@ququplay/admob 8.0.7 → 8.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/Package.swift CHANGED
@@ -11,7 +11,7 @@ let package = Package(
11
11
  ],
12
12
  dependencies: [
13
13
  .package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", from: "8.0.0"),
14
- .package(url: "https://github.com/googleads/swift-package-manager-google-mobile-ads.git", .upToNextMinor(from: "12.14.0")),
14
+ .package(url: "https://github.com/googleads/swift-package-manager-google-mobile-ads.git", .upToNextMinor(from: "13.5.0")),
15
15
  .package(url: "https://github.com/googleads/swift-package-manager-google-user-messaging-platform.git", .upToNextMinor(from: "3.1.0"))
16
16
  ],
17
17
  targets: [
@@ -15,6 +15,6 @@ Pod::Spec.new do |s|
15
15
  s.swift_version = '5.1'
16
16
  s.static_framework = true
17
17
  s.dependency 'Capacitor'
18
- s.dependency 'Google-Mobile-Ads-SDK', '~> 12.14'
18
+ s.dependency 'Google-Mobile-Ads-SDK', '~> 13.5'
19
19
  s.dependency 'GoogleUserMessagingPlatform', '~> 3.1'
20
20
  end
@@ -29,7 +29,8 @@ class BannerExecutor: NSObject, BannerViewDelegate {
29
29
  case "MEDIUM_RECTANGLE":
30
30
  bannerSize = AdSizeMediumRectangle
31
31
  case "SMART_BANNER":
32
- bannerSize = kGADAdSizeSmartBannerPortrait
32
+ let smartFrame = rootViewController.view.frame.inset(by: rootViewController.view.safeAreaInsets)
33
+ bannerSize = largePortraitAnchoredAdaptiveBanner(width: smartFrame.size.width)
33
34
  default: // ADAPTIVE_BANNER
34
35
  let frame = { () -> CGRect in
35
36
  // Here safe area is taken into account, hence the view frame is used
@@ -71,6 +71,10 @@ class ConsentExecutor: NSObject {
71
71
  }
72
72
 
73
73
  private func getConsentInfoDictionary() -> [String: Any] {
74
+ // Check (and possibly purge) outdated consent before reading the
75
+ // remaining values, so they reflect the post-cleanup state.
76
+ let isConsentOutdated = isConsentOutdated()
77
+
74
78
  return [
75
79
  "status": getConsentStatusString(ConsentInformation.shared.consentStatus),
76
80
  "isConsentFormAvailable": ConsentInformation.shared.formStatus == FormStatus.available,
@@ -78,7 +82,7 @@ class ConsentExecutor: NSObject {
78
82
  "privacyOptionsRequirementStatus": getPrivacyOptionsRequirementStatus(ConsentInformation.shared.privacyOptionsRequirementStatus),
79
83
  "canShowAds": canShowAds(),
80
84
  "canShowPersonalizedAds": canShowPersonalizedAds(),
81
- "isConsentOutdated": isConsentOutdated()
85
+ "isConsentOutdated": isConsentOutdated
82
86
  ]
83
87
  }
84
88
 
@@ -160,36 +164,66 @@ class ConsentExecutor: NSObject {
160
164
  && hasConsentOrLegitimateInterestFor([2,7,9,10], purposeConsent, purposeLI, hasGoogleVendorConsent, hasGoogleVendorLI)
161
165
  }
162
166
 
167
+ /// Erases ALL core IAB TCF records simultaneously to prevent leaving
168
+ /// orphaned consent data that will crash Google Ad serving.
169
+ private func clearAllTCFPreferences(_ settings: UserDefaults) {
170
+ settings.removeObject(forKey: "IABTCF_TCString")
171
+ settings.removeObject(forKey: "IABTCF_PurposeConsents")
172
+ settings.removeObject(forKey: "IABTCF_VendorConsents")
173
+ settings.removeObject(forKey: "IABTCF_PurposeLegitimateInterests")
174
+ settings.removeObject(forKey: "IABTCF_VendorLegitimateInterests")
175
+ settings.removeObject(forKey: "IABTCF_gdprApplies") // Force SDK to reassess context
176
+ NSLog("AdMob: Successfully purged all IABTCF tracking variables from UserDefaults.")
177
+ }
178
+
163
179
  private func isConsentOutdated() -> Bool {
164
180
  let settings = UserDefaults.standard
165
181
  guard let tcString = settings.string(forKey: "IABTCF_TCString"), !tcString.isEmpty else {
166
182
  return false
167
183
  }
168
184
 
169
- // base64 alphabet used to store data in IABTCF string
185
+ // 1. Safety Boundary Check: If string is way too short, it's corrupted.
186
+ if tcString.count < 7 {
187
+ clearAllTCFPreferences(settings)
188
+ return true
189
+ }
190
+
191
+ // Base64url alphabet used in IAB TCF specifications
170
192
  let base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
171
193
 
172
- // date is stored in digits 1..7 of the IABTCF string
194
+ // 2. Extract and Validate TCF Specification Version (First 6 bits / 1st character)
195
+ let versionChar = tcString[tcString.startIndex]
196
+ let tcfVersion = base64.firstIndex(of: versionChar)?.utf16Offset(in: base64) ?? -1
197
+
198
+ // TCF v2.0 through v2.3 strings all use a '2' value in the version bit field
199
+ if tcfVersion != 2 {
200
+ clearAllTCFPreferences(settings)
201
+ return true
202
+ }
203
+
204
+ // 3. Extract and Parse Timestamp (Characters at indexes 1 through 6 inclusive)
173
205
  let dateSubstring = String(tcString[tcString.index(tcString.startIndex, offsetBy: 1)..<tcString.index(tcString.startIndex, offsetBy: 7)])
174
206
 
175
- // interpret date substring as base64-encoded integer value
176
207
  var timestamp: Int64 = 0
177
-
178
208
  for char in dateSubstring {
179
- if let value = base64.firstIndex(of: char) {
180
- timestamp = timestamp * 64 + Int64(value.utf16Offset(in: base64))
209
+ guard let value = base64.firstIndex(of: char) else {
210
+ clearAllTCFPreferences(settings)
211
+ return true
181
212
  }
213
+ timestamp = timestamp * 64 + Int64(value.utf16Offset(in: base64))
182
214
  }
183
215
 
184
- // timestamp is given in deci-seconds, convert to milliseconds
216
+ // Timestamp is given in deci-seconds, convert to milliseconds
185
217
  timestamp *= 100
186
218
 
187
- // compare with current timestamp to get age in days
219
+ // 4. Calculate Age in Days
188
220
  let daysAgo = (Int64(Date().timeIntervalSince1970 * 1000) - timestamp) / (1000 * 60 * 60 * 24)
189
221
 
190
- // delete TC string if age is over a year
191
- if daysAgo > 365 {
192
- settings.removeObject(forKey: "IABTCF_TCString")
222
+ // 5. Enforce Expiration Hard Limits
223
+ // Google hard-caps ad server acceptance at 395 days (13 months).
224
+ // The IAB TCF policy requires CMP re-checks at 365 days (12 months).
225
+ if daysAgo > 365 || daysAgo < 0 {
226
+ clearAllTCFPreferences(settings)
193
227
  return true
194
228
  }
195
229
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ququplay/admob",
3
- "version": "8.0.7",
3
+ "version": "8.0.8",
4
4
  "description": "A native plugin for AdMob",
5
5
  "main": "dist/plugin.cjs.js",
6
6
  "module": "dist/esm/index.js",