Ver Fonte

Check token is different from cache and storage before updating it (#7223)

Chen Liang há 5 anos atrás
pai
commit
6ffc845b05

+ 105 - 5
Example/InstanceID/Tests/FIRInstanceIDTest.m

@@ -51,6 +51,7 @@ static NSString *const kGoogleAppID = @"1:123:ios:123abc";
 @property(nonatomic, readwrite, strong) FIRInstallations *installations;
 @property(nonatomic, readwrite, copy) NSString *fcmSenderID;
 @property(nonatomic, readwrite, copy) NSString *firebaseAppID;
+@property(nonatomic, readwrite, copy) NSString *defaultFCMToken;
 
 - (NSInteger)retryIntervalToFetchDefaultToken;
 - (BOOL)isFCMAutoInitEnabled;
@@ -651,7 +652,6 @@ static NSString *const kGoogleAppID = @"1:123:ios:123abc";
                                  return obj != nil;
                                }]];
 
-  __block NSInteger notificationPostCount = 0;
   __block NSString *notificationToken = nil;
 
   // Fetch token once to store token state
@@ -663,8 +663,6 @@ static NSString *const kGoogleAppID = @"1:123:ios:123abc";
               usingBlock:^(NSNotification *_Nonnull note) {
                 // Should have saved token to cache
                 cachedTokenInfo = sTokenInfo;
-
-                notificationPostCount++;
                 notificationToken = [[self.instanceID token] copy];
                 [defaultTokenExpectation fulfill];
               }];
@@ -721,7 +719,6 @@ static NSString *const kGoogleAppID = @"1:123:ios:123abc";
                                  return obj != nil;
                                }]];
 
-  __block int notificationPostCount = 0;
   __block NSString *notificationToken = nil;
 
   NSString *notificationName = kFIRInstanceIDTokenRefreshNotification;
@@ -733,7 +730,6 @@ static NSString *const kGoogleAppID = @"1:123:ios:123abc";
                 // Should have saved token to cache
                 cachedTokenInfo = sTokenInfo;
 
-                notificationPostCount++;
                 notificationToken = [[self.instanceID token] copy];
                 [defaultTokenExpectation fulfill];
               }];
@@ -800,6 +796,7 @@ static NSString *const kGoogleAppID = @"1:123:ios:123abc";
   __block NSString *notificationToken = nil;
 
   NSString *notificationName = kFIRInstanceIDTokenRefreshNotification;
+
   self.tokenRefreshNotificationObserver = [[NSNotificationCenter defaultCenter]
       addObserverForName:notificationName
                   object:nil
@@ -1328,6 +1325,109 @@ static NSString *const kGoogleAppID = @"1:123:ios:123abc";
   OCMVerifyAll(self.mockTokenManager);
 }
 
+- (void)testRefreshDifferentTokenFromMessaging {
+  _instanceID.defaultFCMToken = kToken;
+  XCTAssertEqualObjects(_instanceID.defaultFCMToken, kToken);
+  NSString *newTokenFromMessaging = @"a_new_token_from_messaging";
+  FIRInstanceIDTokenInfo *cachedTokenInfo =
+      [[FIRInstanceIDTokenInfo alloc] initWithAuthorizedEntity:kAuthorizedEntity
+                                                         scope:kFIRInstanceIDDefaultTokenScope
+                                                         token:kToken
+                                                    appVersion:@""
+                                                 firebaseAppID:kGoogleAppID];
+  OCMStub([self.mockTokenManager
+              cachedTokenInfoWithAuthorizedEntity:kAuthorizedEntity
+                                            scope:kFIRInstanceIDDefaultTokenScope])
+      .andReturn(cachedTokenInfo);
+
+  OCMExpect([self.mockTokenManager saveDefaultToken:newTokenFromMessaging
+                                        withOptions:[OCMArg any]]);
+  [[NSNotificationCenter defaultCenter]
+      postNotificationName:kFIRInstanceIDMessagingUpdateTokenNotification
+                    object:newTokenFromMessaging];
+  OCMVerifyAll(self.mockTokenManager);
+  XCTAssertEqualObjects(_instanceID.defaultFCMToken, newTokenFromMessaging);
+}
+
+- (void)testRefreshTheSameTokenFromMessaging {
+  _instanceID.defaultFCMToken = kToken;
+  XCTAssertEqualObjects(_instanceID.defaultFCMToken, kToken);
+
+  NSString *newTokenFromMessaging = kToken;
+  FIRInstanceIDTokenInfo *cachedTokenInfo =
+      [[FIRInstanceIDTokenInfo alloc] initWithAuthorizedEntity:kAuthorizedEntity
+                                                         scope:kFIRInstanceIDDefaultTokenScope
+                                                         token:kToken
+                                                    appVersion:@""
+                                                 firebaseAppID:kGoogleAppID];
+  OCMStub([self.mockTokenManager
+              cachedTokenInfoWithAuthorizedEntity:kAuthorizedEntity
+                                            scope:kFIRInstanceIDDefaultTokenScope])
+      .andReturn(cachedTokenInfo);
+
+  OCMReject([self.mockTokenManager saveDefaultToken:newTokenFromMessaging
+                                        withOptions:[OCMArg any]]);
+  [[NSNotificationCenter defaultCenter]
+      postNotificationName:kFIRInstanceIDMessagingUpdateTokenNotification
+                    object:newTokenFromMessaging];
+  OCMVerifyAll(self.mockTokenManager);
+  XCTAssertEqualObjects(_instanceID.defaultFCMToken, newTokenFromMessaging);
+}
+
+- (void)testRefreshDifferentTokenInInstanceIDStorage {
+  _instanceID.defaultFCMToken = kToken;
+  XCTAssertEqualObjects(_instanceID.defaultFCMToken, kToken);
+  // New token from messaging is the same as local cache in InstanceID
+  // But the token in InstanceID storage is different
+  NSString *newTokenFromMessaging = kToken;
+
+  FIRInstanceIDTokenInfo *cachedTokenInfo =
+      [[FIRInstanceIDTokenInfo alloc] initWithAuthorizedEntity:kAuthorizedEntity
+                                                         scope:kFIRInstanceIDDefaultTokenScope
+                                                         token:@"a_outdated_token_in_storage"
+                                                    appVersion:@""
+                                                 firebaseAppID:kGoogleAppID];
+  OCMStub([self.mockTokenManager
+              cachedTokenInfoWithAuthorizedEntity:kAuthorizedEntity
+                                            scope:kFIRInstanceIDDefaultTokenScope])
+      .andReturn(cachedTokenInfo);
+
+  OCMExpect([self.mockTokenManager saveDefaultToken:newTokenFromMessaging
+                                        withOptions:[OCMArg any]]);
+  [[NSNotificationCenter defaultCenter]
+      postNotificationName:kFIRInstanceIDMessagingUpdateTokenNotification
+                    object:newTokenFromMessaging];
+  OCMVerifyAll(self.mockTokenManager);
+  XCTAssertEqualObjects(_instanceID.defaultFCMToken, newTokenFromMessaging);
+}
+
+- (void)testRefreshNullTokenFromMessaging {
+  _instanceID.defaultFCMToken = kToken;
+  XCTAssertEqualObjects(_instanceID.defaultFCMToken, kToken);
+  // New token from messaging is the same as local cache in InstanceID
+  // But the token in InstanceID storage is different
+  NSString *newTokenFromMessaging = nil;
+
+  FIRInstanceIDTokenInfo *cachedTokenInfo =
+      [[FIRInstanceIDTokenInfo alloc] initWithAuthorizedEntity:kAuthorizedEntity
+                                                         scope:kFIRInstanceIDDefaultTokenScope
+                                                         token:kToken
+                                                    appVersion:@""
+                                                 firebaseAppID:kGoogleAppID];
+  OCMStub([self.mockTokenManager
+              cachedTokenInfoWithAuthorizedEntity:kAuthorizedEntity
+                                            scope:kFIRInstanceIDDefaultTokenScope])
+      .andReturn(cachedTokenInfo);
+
+  OCMExpect([self.mockTokenManager saveDefaultToken:newTokenFromMessaging
+                                        withOptions:[OCMArg any]]);
+  [[NSNotificationCenter defaultCenter]
+      postNotificationName:kFIRInstanceIDMessagingUpdateTokenNotification
+                    object:newTokenFromMessaging];
+  OCMVerifyAll(self.mockTokenManager);
+  XCTAssertEqualObjects(_instanceID.defaultFCMToken, newTokenFromMessaging);
+}
+
 #pragma mark - Private Helpers
 
 - (void)stubInstallationsToReturnValidID {

+ 4 - 1
Firebase/InstanceID/CHANGELOG.md

@@ -1,4 +1,7 @@
-# Unreleased -- 7.0.0
+# Unreleased
+- [changed] Added a check on whether the default token has been changed from Messaging before writing to storage. (#7223)
+
+# 2020-10 -- 7.0.0
 - [changed] Deprecated private `-[FIRInstanceID appInstanceID:]` method was removed. (#4486)
 - [fixed] Fixed an issue that APNS token is not sent in token request when there's a delay of getting the APNS token from Apple. (#6553)
 

+ 16 - 3
Firebase/InstanceID/FIRInstanceID.m

@@ -1127,9 +1127,22 @@ static FIRInstanceID *gInstanceID;
 - (void)messagingTokenDidChangeNotificationReceived:(NSNotification *)notification {
   NSString *tokenUpdatedFromMessaging = notification.object;
   if (!tokenUpdatedFromMessaging || [tokenUpdatedFromMessaging isKindOfClass:[NSString class]]) {
-    self.defaultFCMToken = tokenUpdatedFromMessaging;
-    [self.tokenManager saveDefaultToken:tokenUpdatedFromMessaging
-                            withOptions:[self defaultTokenOptions]];
+    // Check the token from storage along with local value.
+    FIRInstanceIDTokenInfo *cachedTokenInfo =
+        [self.tokenManager cachedTokenInfoWithAuthorizedEntity:self.fcmSenderID
+                                                         scope:kFIRInstanceIDDefaultTokenScope];
+    NSString *cachedToken = cachedTokenInfo.token;
+
+    if (self.defaultFCMToken.length != tokenUpdatedFromMessaging.length ||
+        cachedToken.length != tokenUpdatedFromMessaging.length ||
+        (self.defaultFCMToken.length && tokenUpdatedFromMessaging.length &&
+         ![self.defaultFCMToken isEqualToString:tokenUpdatedFromMessaging]) ||
+        (cachedToken.length && tokenUpdatedFromMessaging.length &&
+         ![cachedToken isEqualToString:tokenUpdatedFromMessaging])) {
+      self.defaultFCMToken = tokenUpdatedFromMessaging;
+      [self.tokenManager saveDefaultToken:tokenUpdatedFromMessaging
+                              withOptions:[self defaultTokenOptions]];
+    }
   }
 }
 

+ 1 - 0
FirebaseMessaging/Apps/Shared/ContentView.swift

@@ -48,6 +48,7 @@ struct ContentView: View {
               // simulator renders a single truncated line even though the Preview renders it
               // appropriately. Potentially a bug in the simulator?
               .layoutPriority(1)
+              .lineLimit(7)
           }
           NavigationLink(destination: SettingsView()) {
             Text("Settings")

+ 3 - 0
FirebaseMessaging/Apps/Shared/SceneDelegate.swift

@@ -73,5 +73,8 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate, MessagingDelegate {
 
   func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
     identity.token = fcmToken
+    print("=============================\n")
+    print("Did refresh token:\n", identity.token ?? "")
+    print("\n=============================\n")
   }
 }