Ver Fonte

Decode old fcmToken format (#12246)

Paul Beusterien há 2 anos atrás
pai
commit
75f52822d0

+ 4 - 0
FirebaseMessaging/CHANGELOG.md

@@ -1,3 +1,7 @@
+# 10.20.0
+- [fixed] Fix 10.19.0 regression where the FCM registration token was nil at first app start
+  after update from 10.19.0 or earlier. (#12245)
+
 # 10.19.0
 - [changed] Adopt NSSecureCoding for internal classes. (#12075)
 

+ 3 - 0
FirebaseMessaging/Sources/Token/FIRMessagingTokenInfo.h

@@ -50,6 +50,9 @@ NS_ASSUME_NONNULL_BEGIN
 /// the cacheTime would be updated.
 @property(nonatomic, copy, nullable) NSDate *cacheTime;
 
+/// Indicates the info was stored on the keychain by version 10.18.0 or earlier.
+@property(nonatomic, readonly) BOOL needsMigration;
+
 /**
  *  Initializes a FIRMessagingTokenInfo object with the required parameters. These
  *  parameters represent all the relevant associated data with a token.

+ 21 - 1
FirebaseMessaging/Sources/Token/FIRMessagingTokenInfo.m

@@ -140,6 +140,7 @@ static const NSTimeInterval kDefaultFetchTokenInterval = 7 * 24 * 60 * 60;  // 7
 }
 
 - (nullable instancetype)initWithCoder:(NSCoder *)aDecoder {
+  BOOL needsMigration = NO;
   // These value cannot be nil
 
   id authorizedEntity = [aDecoder decodeObjectForKey:kFIRInstanceIDAuthorizedEntityKey];
@@ -172,7 +173,25 @@ static const NSTimeInterval kDefaultFetchTokenInterval = 7 * 24 * 60 * 60;  // 7
   FIRMessagingAPNSInfo *rawAPNSInfo = [aDecoder decodeObjectOfClasses:classes
                                                                forKey:kFIRInstanceIDAPNSInfoKey];
   if (rawAPNSInfo && ![rawAPNSInfo isKindOfClass:[FIRMessagingAPNSInfo class]]) {
-    return nil;
+    // If the decoder fails to decode a FIRMessagingAPNSInfo, check if this was archived by a
+    // FirebaseMessaging 10.18.0 or earlier.
+    // TODO(#12246) This block may be replaced with `rawAPNSInfo = nil` once we're confident all
+    // users have upgraded to at least 10.19.0. Perhaps, after privacy manifests have been required
+    // for awhile?
+    @try {
+      [NSKeyedUnarchiver setClass:[FIRMessagingAPNSInfo class]
+                     forClassName:@"FIRInstanceIDAPNSInfo"];
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+      rawAPNSInfo = [NSKeyedUnarchiver unarchiveObjectWithData:(NSData *)rawAPNSInfo];
+      needsMigration = YES;
+#pragma clang diagnostic pop
+    } @catch (NSException *exception) {
+      FIRMessagingLoggerInfo(kFIRMessagingMessageCodeTokenInfoBadAPNSInfo,
+                             @"Could not parse raw APNS Info while parsing archived token info.");
+      rawAPNSInfo = nil;
+    } @finally {
+    }
   }
 
   id cacheTime = [aDecoder decodeObjectForKey:kFIRInstanceIDCacheTimeKey];
@@ -189,6 +208,7 @@ static const NSTimeInterval kDefaultFetchTokenInterval = 7 * 24 * 60 * 60;  // 7
     _firebaseAppID = [firebaseAppID copy];
     _APNSInfo = [rawAPNSInfo copy];
     _cacheTime = cacheTime;
+    _needsMigration = needsMigration;
   }
   return self;
 }

+ 16 - 0
FirebaseMessaging/Sources/Token/FIRMessagingTokenStore.m

@@ -63,6 +63,21 @@ static NSString *const kFIRMessagingTokenKeychainId = @"com.google.iid-tokens";
   }
   // Token infos created from legacy storage don't have appVersion, firebaseAppID, or APNSInfo.
   FIRMessagingTokenInfo *tokenInfo = [[self class] tokenInfoFromKeychainItem:item];
+  if ([tokenInfo needsMigration]) {
+    [self
+        saveTokenInfo:tokenInfo
+              handler:^(NSError *error) {
+                if (error) {
+                  FIRMessagingLoggerDebug(kFIRMessagingMessageCodeTokenManager001,
+                                          @"Failed to migrate token: %@ account: %@ service %@",
+                                          tokenInfo, account, service);
+                } else {
+                  FIRMessagingLoggerDebug(kFIRMessagingMessageCodeTokenManager001,
+                                          @"Successful token migration: %@ account: %@ service %@",
+                                          tokenInfo, account, service);
+                }
+              }];
+  }
   return tokenInfo;
 }
 
@@ -94,6 +109,7 @@ static NSString *const kFIRMessagingTokenKeychainId = @"com.google.iid-tokens";
       [NSKeyedUnarchiver setClass:[FIRMessagingTokenInfo class]
                      forClassName:@"FIRInstanceIDTokenInfo"];
       tokenInfo = [NSKeyedUnarchiver unarchiveObjectWithData:item];
+
 #pragma clang diagnostic pop
 
     } @catch (NSException *exception) {