Skip to content

Commit d6af861

Browse files
authored
Fix token fetch not invoking callback for unchanged token (#3251)
1 parent 8ab90e5 commit d6af861

File tree

4 files changed

+76
-3
lines changed

4 files changed

+76
-3
lines changed

Example/InstanceID/Tests/FIRInstanceIDTest.m

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -549,6 +549,76 @@ - (void)testDefaultToken_validCachedToken {
549549
XCTAssertEqualObjects([self.mockInstanceID token], kToken);
550550
}
551551

552+
/**
553+
* Tests that the callback handler will be invoked when the default token is fetched
554+
* despite the token being unchanged.
555+
*/
556+
- (void)testDefaultToken_callbackInvokedForUnchangedToken {
557+
XCTestExpectation *defaultTokenExpectation =
558+
[self expectationWithDescription:@"Token fetch was successful."];
559+
560+
__block FIRInstanceIDTokenInfo *cachedTokenInfo = nil;
561+
562+
[self stubKeyPairStoreToReturnValidKeypair];
563+
564+
[self mockAuthServiceToAlwaysReturnValidCheckin];
565+
566+
// Mock Token manager to always succeed the token fetch, and return
567+
// a particular cached value.
568+
569+
// Return a dynamic cachedToken variable whenever the cached is checked.
570+
// This uses an invocation-based mock because the |cachedToken| pointer
571+
// will change. Normal stubbing will always return the initial pointer,
572+
// which in this case is 0x0 (nil).
573+
[[[self.mockTokenManager stub] andDo:^(NSInvocation *invocation) {
574+
[invocation setReturnValue:&cachedTokenInfo];
575+
}] cachedTokenInfoWithAuthorizedEntity:kAuthorizedEntity scope:kFIRInstanceIDDefaultTokenScope];
576+
577+
[[[self.mockTokenManager stub] andDo:^(NSInvocation *invocation) {
578+
self.newTokenCompletion(kToken, nil);
579+
}] fetchNewTokenWithAuthorizedEntity:kAuthorizedEntity
580+
scope:kFIRInstanceIDDefaultTokenScope
581+
keyPair:[OCMArg any]
582+
options:[OCMArg any]
583+
handler:[OCMArg checkWithBlock:^BOOL(id obj) {
584+
self.newTokenCompletion = obj;
585+
return obj != nil;
586+
}]];
587+
588+
__block NSInteger notificationPostCount = 0;
589+
__block NSString *notificationToken = nil;
590+
591+
// Fetch token once to store token state
592+
NSString *notificationName = kFIRInstanceIDTokenRefreshNotification;
593+
self.tokenRefreshNotificationObserver = [[NSNotificationCenter defaultCenter]
594+
addObserverForName:notificationName
595+
object:nil
596+
queue:nil
597+
usingBlock:^(NSNotification *_Nonnull note) {
598+
// Should have saved token to cache
599+
cachedTokenInfo = sTokenInfo;
600+
601+
notificationPostCount++;
602+
notificationToken = [[self.instanceID token] copy];
603+
[defaultTokenExpectation fulfill];
604+
}];
605+
XCTAssertNil([self.mockInstanceID token]);
606+
[self waitForExpectationsWithTimeout:10.0 handler:nil];
607+
[[NSNotificationCenter defaultCenter] removeObserver:self.tokenRefreshNotificationObserver];
608+
609+
XCTAssertEqualObjects(notificationToken, kToken);
610+
611+
// Fetch default handler again without any token changes
612+
XCTestExpectation *tokenCallback = [self expectationWithDescription:@"Callback was invoked."];
613+
614+
[self.mockInstanceID defaultTokenWithHandler:^(NSString *token, NSError *error) {
615+
notificationToken = token;
616+
[tokenCallback fulfill];
617+
}];
618+
[self waitForExpectationsWithTimeout:10.0 handler:nil];
619+
XCTAssertEqualObjects(notificationToken, kToken);
620+
}
621+
552622
/**
553623
* Test that when we fetch a new default token and cache it successfully we post a
554624
* tokenRefresh notification which allows to fetch the cached token.

Firebase/InstanceID/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
# Unreleased -- 4.2.1
2+
- Fixed an issue where fetching an instance ID wouldn't invoke the callback handler if the instance ID had not changed. (#3229)
3+
14
# 2019-06-18 -- 4.2.0
25
- Added macOS support for InstanceID (#2880)
36
- Corrected timezone proto key (#3132)

Firebase/InstanceID/FIRInstanceID.m

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -946,9 +946,9 @@ - (void)defaultTokenWithRetry:(BOOL)retry handler:(nullable FIRInstanceIDTokenHa
946946
object:[self.defaultFCMToken copy]];
947947
[[NSNotificationQueue defaultQueue] enqueueNotification:tokenRefreshNotification
948948
postingStyle:NSPostASAP];
949-
950-
[self performDefaultTokenHandlerWithToken:token error:nil];
951949
}
950+
951+
[self performDefaultTokenHandlerWithToken:token error:nil];
952952
}
953953
};
954954

Firestore/Swift/Source/Codable/third_party/FirestoreEncoder.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ extension Firestore {
3636
/// API can work with.
3737
public func encode<T: Encodable>(_ value: T) throws -> [String: Any] {
3838
// DocumentReference and FieldValue cannot be encoded directly.
39-
guard T.self != DocumentReference.self && T.self != FieldValue.self else {
39+
guard T.self != DocumentReference.self, T.self != FieldValue.self else {
4040
throw FirestoreEncodingError.encodingIsNotSupported
4141
}
4242
guard let topLevel = try _FirestoreEncoder().box_(value) else {

0 commit comments

Comments
 (0)