Skip to content

Commit 1cb6322

Browse files
authored
Merge pull request #890 from OneSignal/fix/reapply_register_user_race_condition
Wait until we have an APNS token before create
2 parents ee389b9 + 19bf021 commit 1cb6322

File tree

3 files changed

+65
-8
lines changed

3 files changed

+65
-8
lines changed

iOS_SDK/OneSignalSDK/Source/OneSignal.m

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1561,12 +1561,15 @@ + (BOOL)shouldRegisterNow {
15611561
return false;
15621562

15631563
// Don't make a 2nd on_session if have in inflight one
1564+
onesignal_Log(ONE_S_LL_VERBOSE, [NSString stringWithFormat:@"shouldRegisterNow:waitingForOneSReg: %d", waitingForOneSReg]);
15641565
if (waitingForOneSReg)
15651566
return false;
15661567

1568+
onesignal_Log(ONE_S_LL_VERBOSE, [NSString stringWithFormat:@"shouldRegisterNow:isImmediatePlayerCreateOrOnSession: %d", [self isImmediatePlayerCreateOrOnSession]]);
15671569
if ([self isImmediatePlayerCreateOrOnSession])
15681570
return true;
15691571

1572+
onesignal_Log(ONE_S_LL_VERBOSE, [NSString stringWithFormat:@"shouldRegisterNow:isOnSessionSuccessfulForCurrentState: %d", isOnSessionSuccessfulForCurrentState]);
15701573
if (isOnSessionSuccessfulForCurrentState)
15711574
return false;
15721575

@@ -1587,6 +1590,7 @@ + (BOOL)shouldRegisterNow {
15871590
}
15881591

15891592
+ (void)registerUserAfterDelay {
1593+
[OneSignal onesignal_Log:ONE_S_LL_VERBOSE message:@"registerUserAfterDelay"];
15901594
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(registerUser) object:nil];
15911595
[OneSignalHelper performSelector:@selector(registerUser) onMainThreadOnObject:self withObject:nil afterDelay:reattemptRegistrationInterval];
15921596
}
@@ -1601,21 +1605,44 @@ + (void)registerUser {
16011605
// return if the user has not granted privacy permissions
16021606
if ([self shouldLogMissingPrivacyConsentErrorWithMethodName:nil])
16031607
return;
1604-
1605-
// We should delay registration if we are waiting on APNS
1606-
// But if APNS hasn't responded within 30 seconds,
1607-
// we should continue and register the user.
1608-
if (waitingForApnsResponse && initializationTime && [[NSDate date] timeIntervalSinceDate:initializationTime] < maxApnsWait) {
1608+
1609+
if ([self shouldRegisterUserAfterDelay]) {
16091610
[self registerUserAfterDelay];
16101611
return;
16111612
}
16121613

16131614
if (!serialQueue)
16141615
serialQueue = dispatch_queue_create("com.onesignal.regiseruser", DISPATCH_QUEUE_SERIAL);
16151616

1616-
dispatch_async(serialQueue, ^{
1617+
[self registerUserNow];
1618+
}
1619+
1620+
+(void)registerUserNow {
1621+
[OneSignal onesignal_Log:ONE_S_LL_VERBOSE message:@"registerUserNow"];
1622+
1623+
if (!serialQueue)
1624+
serialQueue = dispatch_queue_create("com.onesignal.regiseruser", DISPATCH_QUEUE_SERIAL);
1625+
1626+
dispatch_async(serialQueue, ^{
16171627
[self registerUserInternal];
1618-
});
1628+
});
1629+
}
1630+
1631+
// We should delay registration if we are waiting on APNS
1632+
// But if APNS hasn't responded within 30 seconds (maxApnsWait),
1633+
// we should continue and register the user.
1634+
+ (BOOL)shouldRegisterUserAfterDelay {
1635+
[OneSignal onesignal_Log:ONE_S_LL_VERBOSE message:[NSString stringWithFormat:@"registerUser:waitingForApnsResponse: %d", waitingForApnsResponse]];
1636+
[OneSignal onesignal_Log:ONE_S_LL_VERBOSE message:[NSString stringWithFormat:@"registerUser:initializationTime: %@", initializationTime]];
1637+
1638+
// If there isn't an initializationTime yet then the SDK hasn't finished initializing so we should delay
1639+
if (!initializationTime)
1640+
return true;
1641+
1642+
if (!waitingForApnsResponse)
1643+
return false;
1644+
1645+
return [[NSDate date] timeIntervalSinceDate:initializationTime] < maxApnsWait;
16191646
}
16201647

16211648
+ (OSUserState *)createUserState {
@@ -1697,6 +1724,7 @@ + (OSUserState *)createUserState {
16971724
}
16981725

16991726
+ (void)registerUserInternal {
1727+
[OneSignal onesignal_Log:ONE_S_LL_VERBOSE message:@"registerUserInternal"];
17001728
_registerUserFinished = false;
17011729

17021730
// return if the user has not granted privacy permissions

iOS_SDK/OneSignalSDK/UnitTests/Shadows/UIApplicationOverrider.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ + (void)setDidFailRegistarationErrorCode:(NSInteger)value {
101101
}
102102

103103
+ (void)setBlockApnsResponse:(BOOL)block {
104-
blockApnsResponse = true;
104+
blockApnsResponse = block;
105105
}
106106

107107
+ (void)setAPNSTokenLength:(int)tokenLength {

iOS_SDK/OneSignalSDK/UnitTests/UnitTests.m

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -716,6 +716,35 @@ - (void)testPromptedButNeveranswerNotificationPrompt {
716716
XCTAssertEqualObjects(OneSignalClientOverrider.lastHTTPRequest[@"notification_types"], @-19);
717717
}
718718

719+
// This test covers migrating to OneSignal with the following senario;
720+
// 1. App was released publicly to the AppStore with push on with another provider.
721+
// 2. User imports all existing push tokens into OneSignal.
722+
// 3. OneSignal is added to their app.
723+
// 4. Ensure that identifier is always send with the player create, to prevent duplicated players
724+
- (void)testNotificationPermissionsAcceptedBeforeAddingOneSiganl_waitsForAPNSTokenBeforePlayerCreate {
725+
// 1. Set that notification permissions are already enabled.
726+
UNUserNotificationCenterOverrider.notifTypesOverride = 7;
727+
UNUserNotificationCenterOverrider.authorizationStatus = [NSNumber numberWithInteger:UNAuthorizationStatusAuthorized];
728+
729+
// 2. Setup delay of APNs reaponse
730+
[UIApplicationOverrider setBlockApnsResponse:true];
731+
732+
// 3. Init OneSignal
733+
[UnitTestCommonMethods initOneSignal_andThreadWait];
734+
[NSObjectOverrider runPendingSelectors];
735+
736+
// 4. Don't make a network call right away
737+
XCTAssertNil(OneSignalClientOverrider.lastHTTPRequest);
738+
739+
// 5. Simulate APNs now giving us a push token
740+
[UIApplicationOverrider setBlockApnsResponse:false];
741+
[UnitTestCommonMethods runBackgroundThreads];
742+
743+
// 6. Ensure we registered with push token and it has the correct notification_types
744+
XCTAssertEqualObjects(OneSignalClientOverrider.lastHTTPRequest[@"notification_types"], @15);
745+
XCTAssertEqualObjects(OneSignalClientOverrider.lastHTTPRequest[@"identifier"], @"0000000000000000000000000000000000000000000000000000000000000000");
746+
}
747+
719748
- (void)testNotificationTypesWhenAlreadyAcceptedWithAutoPromptOffOnFristStartPreIos10 {
720749
OneSignalHelperOverrider.mockIOSVersion = 9;
721750
[UnitTestCommonMethods setCurrentNotificationPermission:true];

0 commit comments

Comments
 (0)