Skip to content

Commit d9e19cd

Browse files
[Messaging] - Fix crash for strongSelf dereference (#10740)
Fix crash for strongSelf dereference
1 parent 4171a3b commit d9e19cd

File tree

2 files changed

+83
-57
lines changed

2 files changed

+83
-57
lines changed

FirebaseMessaging/Sources/NSError+FIRMessaging.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ NS_ASSUME_NONNULL_BEGIN
2121
// FIRMessaging Internal Error Code
2222
typedef NS_ENUM(NSUInteger, FIRMessagingErrorCode) {
2323
kFIRMessagingErrorCodeUnknown = 0,
24+
kFIRMessagingErrorCodeInternal = 1,
2425

2526
kFIRMessagingErrorCodeNetwork = 4,
2627

FirebaseMessaging/Sources/Token/FIRMessagingTokenManager.m

Lines changed: 82 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -239,17 +239,25 @@ - (void)tokenWithAuthorizedEntity:(NSString *)authorizedEntity
239239
}
240240

241241
FIRMessaging_WEAKIFY(self);
242-
[_authService
243-
fetchCheckinInfoWithHandler:^(FIRMessagingCheckinPreferences *preferences, NSError *error) {
244-
FIRMessaging_STRONGIFY(self);
245-
if (error) {
246-
newHandler(nil, error);
247-
return;
248-
}
242+
[_authService fetchCheckinInfoWithHandler:^(FIRMessagingCheckinPreferences *preferences,
243+
NSError *error) {
244+
FIRMessaging_STRONGIFY(self);
245+
if (error) {
246+
newHandler(nil, error);
247+
return;
248+
}
249+
250+
if (!self) {
251+
NSError *derefErr =
252+
[NSError messagingErrorWithCode:kFIRMessagingErrorCodeInternal
253+
failureReason:@"Unable to fetch token. Lost Reference to TokenManager"];
254+
handler(nil, derefErr);
255+
return;
256+
}
249257

250-
FIRMessaging_WEAKIFY(self);
251-
[self->_installations installationIDWithCompletion:^(NSString *_Nullable identifier,
252-
NSError *_Nullable error) {
258+
FIRMessaging_WEAKIFY(self);
259+
[self->_installations
260+
installationIDWithCompletion:^(NSString *_Nullable identifier, NSError *_Nullable error) {
253261
FIRMessaging_STRONGIFY(self);
254262

255263
if (error) {
@@ -275,7 +283,7 @@ - (void)tokenWithAuthorizedEntity:(NSString *)authorizedEntity
275283
handler:newHandler];
276284
}
277285
}];
278-
}];
286+
}];
279287
}
280288

281289
- (void)fetchNewTokenWithAuthorizedEntity:(NSString *)authorizedEntity
@@ -292,52 +300,60 @@ - (void)fetchNewTokenWithAuthorizedEntity:(NSString *)authorizedEntity
292300
options:options
293301
instanceID:instanceID];
294302
FIRMessaging_WEAKIFY(self);
295-
FIRMessagingTokenOperationCompletion completion =
296-
^(FIRMessagingTokenOperationResult result, NSString *_Nullable token,
297-
NSError *_Nullable error) {
298-
FIRMessaging_STRONGIFY(self);
299-
if (error) {
300-
handler(nil, error);
301-
return;
302-
}
303-
if ([self isDefaultTokenWithAuthorizedEntity:authorizedEntity scope:scope]) {
304-
[self postTokenRefreshNotificationWithDefaultFCMToken:token];
305-
}
306-
NSString *firebaseAppID = options[kFIRMessagingTokenOptionsFirebaseAppIDKey];
307-
FIRMessagingTokenInfo *tokenInfo =
308-
[[FIRMessagingTokenInfo alloc] initWithAuthorizedEntity:authorizedEntity
309-
scope:scope
310-
token:token
311-
appVersion:FIRMessagingCurrentAppVersion()
312-
firebaseAppID:firebaseAppID];
313-
tokenInfo.APNSInfo = [[FIRMessagingAPNSInfo alloc] initWithTokenOptionsDictionary:options];
314-
315-
[self->_tokenStore
316-
saveTokenInfo:tokenInfo
317-
handler:^(NSError *error) {
318-
if (!error) {
319-
// Do not send the token back in case the save was unsuccessful. Since with
320-
// the new asychronous fetch mechanism this can lead to infinite loops, for
321-
// example, we will return a valid token even though we weren't able to store
322-
// it in our cache. The first token will lead to a onTokenRefresh callback
323-
// wherein the user again calls `getToken` but since we weren't able to save
324-
// it we won't hit the cache but hit the server again leading to an infinite
325-
// loop.
326-
FIRMessagingLoggerDebug(
327-
kFIRMessagingMessageCodeTokenManager001,
328-
@"Token fetch successful, token: %@, authorizedEntity: %@, scope:%@",
329-
token, authorizedEntity, scope);
330-
331-
if (handler) {
332-
handler(token, nil);
333-
}
334-
} else {
335-
if (handler) {
336-
handler(nil, error);
337-
}
338-
}
339-
}];
340-
};
303+
FIRMessagingTokenOperationCompletion completion = ^(FIRMessagingTokenOperationResult result,
304+
NSString *_Nullable token,
305+
NSError *_Nullable error) {
306+
FIRMessaging_STRONGIFY(self);
307+
if (error) {
308+
handler(nil, error);
309+
return;
310+
}
311+
312+
if (!self) {
313+
NSError *lostRefError = [NSError messagingErrorWithCode:kFIRMessagingErrorCodeInternal
314+
failureReason:@"Lost Reference to TokenManager"];
315+
handler(nil, lostRefError);
316+
return;
317+
}
318+
319+
if ([self isDefaultTokenWithAuthorizedEntity:authorizedEntity scope:scope]) {
320+
[self postTokenRefreshNotificationWithDefaultFCMToken:token];
321+
}
322+
NSString *firebaseAppID = options[kFIRMessagingTokenOptionsFirebaseAppIDKey];
323+
FIRMessagingTokenInfo *tokenInfo =
324+
[[FIRMessagingTokenInfo alloc] initWithAuthorizedEntity:authorizedEntity
325+
scope:scope
326+
token:token
327+
appVersion:FIRMessagingCurrentAppVersion()
328+
firebaseAppID:firebaseAppID];
329+
tokenInfo.APNSInfo = [[FIRMessagingAPNSInfo alloc] initWithTokenOptionsDictionary:options];
330+
331+
[self->_tokenStore
332+
saveTokenInfo:tokenInfo
333+
handler:^(NSError *error) {
334+
if (!error) {
335+
// Do not send the token back in case the save was unsuccessful. Since with
336+
// the new asychronous fetch mechanism this can lead to infinite loops, for
337+
// example, we will return a valid token even though we weren't able to store
338+
// it in our cache. The first token will lead to a onTokenRefresh callback
339+
// wherein the user again calls `getToken` but since we weren't able to save
340+
// it we won't hit the cache but hit the server again leading to an infinite
341+
// loop.
342+
FIRMessagingLoggerDebug(
343+
kFIRMessagingMessageCodeTokenManager001,
344+
@"Token fetch successful, token: %@, authorizedEntity: %@, scope:%@", token,
345+
authorizedEntity, scope);
346+
347+
if (handler) {
348+
handler(token, nil);
349+
}
350+
} else {
351+
if (handler) {
352+
handler(nil, error);
353+
}
354+
}
355+
}];
356+
};
341357
// Add completion handler, and ensure it's called on the main queue
342358
[operation addCompletionHandler:^(FIRMessagingTokenOperationResult result,
343359
NSString *_Nullable token, NSError *_Nullable error) {
@@ -456,6 +472,15 @@ - (void)deleteWithHandler:(void (^)(NSError *))handler {
456472
handler(error);
457473
return;
458474
}
475+
476+
if (!self) {
477+
NSError *lostRefError =
478+
[NSError messagingErrorWithCode:kFIRMessagingErrorCodeInternal
479+
failureReason:@"Cannot delete token. Lost reference to TokenManager"];
480+
handler(lostRefError);
481+
return;
482+
}
483+
459484
[self deleteAllTokensLocallyWithHandler:^(NSError *localError) {
460485
[self postTokenRefreshNotificationWithDefaultFCMToken:nil];
461486
self->_defaultFCMToken = nil;

0 commit comments

Comments
 (0)