Skip to content

Commit 434be68

Browse files
committed
INTENG-7729 race condition with search ads or slow init. Needs cleanup badly
1 parent 75c2e1b commit 434be68

File tree

1 file changed

+84
-22
lines changed

1 file changed

+84
-22
lines changed

Branch-SDK/Branch-SDK/Branch.m

Lines changed: 84 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,6 @@ @interface Branch() <BranchDeepLinkingControllerCompletionDelegate> {
130130
@property (strong, nonatomic) BNCServerRequestQueue *requestQueue;
131131
@property (strong, nonatomic) dispatch_semaphore_t processing_sema;
132132
@property (assign, atomic) NSInteger networkCount;
133-
@property (assign, nonatomic) NSInteger asyncRequestCount;
134133
@property (assign, nonatomic) BNCInitStatus initializationStatus;
135134
@property (assign, nonatomic) BOOL shouldCallSessionInitCallback;
136135
@property (assign, nonatomic) BOOL shouldAutomaticallyDeepLink;
@@ -147,9 +146,16 @@ @interface Branch() <BranchDeepLinkingControllerCompletionDelegate> {
147146
@property (strong, nonatomic) NSMutableArray *whiteListedSchemeList;
148147
@property (strong, nonatomic) BNCURLBlackList *URLBlackList;
149148

150-
// dedicated object for locking asyncRequestCount
149+
// tracks async setup calls required before Branch init
150+
@property (assign, nonatomic) NSInteger asyncRequestCount;
151151
@property (strong, nonatomic, readwrite) NSObject *asyncRequestCountLock;
152152

153+
// tracks if continueUserActivity was called
154+
@property (assign, nonatomic, readwrite) BOOL continueUserActivityCalled;
155+
@property (strong, nonatomic, readwrite) NSObject *continueUserActivityCalledLock;
156+
157+
@property (strong, nonatomic, readwrite) NSObject *shouldWaitForInitLock;
158+
153159
@end
154160

155161
@implementation Branch
@@ -241,6 +247,8 @@ - (id)initWithInterface:(BNCServerInterface *)interface
241247
if (!self) return self;
242248

243249
self.asyncRequestCountLock = [NSObject new];
250+
self.continueUserActivityCalledLock = [NSObject new];
251+
self.shouldWaitForInitLock = [NSObject new];
244252

245253
// Initialize instance variables
246254

@@ -255,14 +263,19 @@ - (id)initWithInterface:(BNCServerInterface *)interface
255263
_shouldCallSessionInitCallback = YES;
256264
_processing_sema = dispatch_semaphore_create(1);
257265
_networkCount = 0;
258-
@synchronized (self.asyncRequestCountLock) {
259-
_asyncRequestCount = 0;
260-
}
261266
_deepLinkControllers = [[NSMutableDictionary alloc] init];
262267
_whiteListedSchemeList = [[NSMutableArray alloc] init];
263268
_useCookieBasedMatching = YES;
264269
self.class.branchKey = key;
265270
self.URLBlackList = [BNCURLBlackList new];
271+
272+
@synchronized (self.asyncRequestCountLock) {
273+
_asyncRequestCount = 0;
274+
}
275+
@synchronized (self.continueUserActivityCalledLock) {
276+
_continueUserActivityCalled = NO;
277+
}
278+
266279
[BranchOpenRequest setWaitNeededForOpenResponseLock];
267280

268281
// Register for notifications
@@ -508,21 +521,27 @@ - (void)setRequestMetadataKey:(NSString *)key value:(NSObject *)value {
508521
}
509522

510523
- (void)enableDelayedInit {
511-
self.preferenceHelper.shouldWaitForInit = YES;
524+
@synchronized (self.shouldWaitForInitLock) {
525+
self.preferenceHelper.shouldWaitForInit = YES;
526+
}
512527

513528
self.useCookieBasedMatching = NO; // Developers delaying init should implement their own SFSafariViewController
514529
}
515530

516531
- (void)disableDelayedInit {
517-
self.preferenceHelper.shouldWaitForInit = NO;
532+
@synchronized (self.shouldWaitForInitLock) {
533+
self.preferenceHelper.shouldWaitForInit = NO;
534+
}
518535
}
519536

520537
- (NSURL *)getUrlForOnboardingWithRedirectUrl:(NSString *)redirectUrl {
521538
return [BNCStrongMatchHelper getUrlForCookieBasedMatchingWithBranchKey:self.class.branchKey redirectUrl:redirectUrl];
522539
}
523540

524541
- (void)resumeInit {
525-
self.preferenceHelper.shouldWaitForInit = NO;
542+
@synchronized (self.shouldWaitForInitLock) {
543+
self.preferenceHelper.shouldWaitForInit = NO;
544+
}
526545
if (self.initializationStatus == BNCInitStatusInitialized) {
527546
BNCLogError(@"User session has already been initialized, so resumeInit is aborting.");
528547
}
@@ -695,8 +714,18 @@ - (void)initSessionWithLaunchOptions:(NSDictionary *)options
695714
return;
696715
}
697716
}
698-
// Wait for continueUserActivity Branch AppDelegate call to come through
699-
self.preferenceHelper.shouldWaitForInit = YES;
717+
// Wait for continueUserActivity Branch AppDelegate call to come through. This may have already happened...
718+
@synchronized (self.continueUserActivityCalledLock) {
719+
if (self.continueUserActivityCalled) {
720+
@synchronized (self.shouldWaitForInitLock) {
721+
self.preferenceHelper.shouldWaitForInit = NO;
722+
}
723+
} else {
724+
@synchronized (self.shouldWaitForInitLock) {
725+
self.preferenceHelper.shouldWaitForInit = YES;
726+
}
727+
}
728+
}
700729
}
701730
}
702731
else if (![options.allKeys containsObject:UIApplicationLaunchOptionsURLKey]) {
@@ -844,7 +873,9 @@ - (BOOL)handleUniversalDeepLink_private:(NSString*)urlString fromSelf:(BOOL)isFr
844873
self.preferenceHelper.universalLinkUrl = urlString;
845874
self.preferenceHelper.referringURL = urlString;
846875
}
847-
self.preferenceHelper.shouldWaitForInit = NO;
876+
@synchronized (self.shouldWaitForInitLock) {
877+
self.preferenceHelper.shouldWaitForInit = NO;
878+
}
848879
[self initUserSessionAndCallCallback:YES];
849880

850881
id branchUniversalLinkDomains = [self.preferenceHelper getBranchUniversalLinkDomains];
@@ -902,9 +933,16 @@ - (BOOL)continueUserActivity:(NSUserActivity *)userActivity {
902933
self.preferenceHelper.spotlightIdentifier = nonBranchSpotlightIdentifier;
903934
}
904935
}
905-
self.preferenceHelper.shouldWaitForInit = NO;
936+
@synchronized (self.shouldWaitForInitLock) {
937+
self.preferenceHelper.shouldWaitForInit = NO;
938+
}
906939
[self initUserSessionAndCallCallback:YES];
907940

941+
// update that continueUserActivity was called
942+
@synchronized (self.continueUserActivityCalledLock) {
943+
_continueUserActivityCalled = YES;
944+
}
945+
908946
return spotlightIdentifier != nil;
909947
}
910948

@@ -952,6 +990,8 @@ - (void)handlePushNotification:(NSDictionary *)userInfo {
952990
}
953991
}
954992

993+
#pragma mark - async data collection
994+
955995
- (void)loadUserAgent {
956996
@synchronized (self.asyncRequestCountLock) {
957997
self.asyncRequestCount++;
@@ -962,7 +1002,9 @@ - (void)loadUserAgent {
9621002
self.asyncRequestCount--;
9631003
if (self.asyncRequestCount > 0) return;
9641004

965-
self.preferenceHelper.shouldWaitForInit = NO;
1005+
@synchronized (self.shouldWaitForInitLock) {
1006+
self.preferenceHelper.shouldWaitForInit = NO;
1007+
}
9661008
dispatch_async(dispatch_get_main_queue(), ^{
9671009
[self initUserSessionAndCallCallback:(self.initializationStatus != BNCInitStatusInitialized)];
9681010
});
@@ -979,8 +1021,10 @@ - (void)loadApplicationData {
9791021
@synchronized (self.asyncRequestCountLock) {
9801022
self.asyncRequestCount--;
9811023
if (self.asyncRequestCount > 0) return;
982-
983-
self.preferenceHelper.shouldWaitForInit = NO;
1024+
1025+
@synchronized (self.shouldWaitForInitLock) {
1026+
self.preferenceHelper.shouldWaitForInit = NO;
1027+
}
9841028
dispatch_async(dispatch_get_main_queue(), ^{
9851029
[self initUserSessionAndCallCallback:(self.initializationStatus != BNCInitStatusInitialized)];
9861030
});
@@ -1025,7 +1069,9 @@ - (BOOL)checkAppleSearchAdsAttribution {
10251069

10261070
id sharedClientInstance = ((id (*)(id, SEL))[ADClientClass methodForSelector:sharedClient])(ADClientClass, sharedClient);
10271071

1028-
self.preferenceHelper.shouldWaitForInit = YES;
1072+
@synchronized (self.shouldWaitForInitLock) {
1073+
self.preferenceHelper.shouldWaitForInit = YES;
1074+
}
10291075
self.preferenceHelper.checkedAppleSearchAdAttribution = YES;
10301076
@synchronized (self.asyncRequestCountLock) {
10311077
self.asyncRequestCount++;
@@ -1065,7 +1111,9 @@ - (BOOL)checkAppleSearchAdsAttribution {
10651111
self.asyncRequestCount--;
10661112
if (self.asyncRequestCount > 0) return;
10671113

1068-
self.preferenceHelper.shouldWaitForInit = NO;
1114+
@synchronized (self.shouldWaitForInitLock) {
1115+
self.preferenceHelper.shouldWaitForInit = NO;
1116+
}
10691117
dispatch_async(dispatch_get_main_queue(), ^{
10701118
[self initUserSessionAndCallCallback:(self.initializationStatus != BNCInitStatusInitialized)];
10711119
});
@@ -1103,8 +1151,10 @@ - (BOOL)checkFacebookAppLinks {
11031151
self.asyncRequestCount--;
11041152

11051153
if (self.asyncRequestCount > 0) { return; }
1106-
self.preferenceHelper.shouldWaitForInit = NO;
1107-
1154+
1155+
@synchronized (self.shouldWaitForInitLock) {
1156+
self.preferenceHelper.shouldWaitForInit = NO;
1157+
}
11081158
dispatch_async(dispatch_get_main_queue(), ^{
11091159
[self handleDeepLink:appLink];
11101160
});
@@ -1115,7 +1165,9 @@ - (BOOL)checkFacebookAppLinks {
11151165
self.asyncRequestCount++;
11161166
}
11171167
self.preferenceHelper.checkedFacebookAppLinks = YES;
1118-
self.preferenceHelper.shouldWaitForInit = YES;
1168+
@synchronized (self.shouldWaitForInitLock) {
1169+
self.preferenceHelper.shouldWaitForInit = YES;
1170+
}
11191171

11201172
((void (*)(id, SEL, void (^ __nullable)(NSURL *__nullable appLink, NSError * __nullable error)))[self.FBSDKAppLinkUtility methodForSelector:fetchDeferredAppLink])(self.FBSDKAppLinkUtility, fetchDeferredAppLink, completionBlock);
11211173

@@ -1955,9 +2007,14 @@ - (void)registerViewWithParams:(NSDictionary *)params andCallback:(callbackWithP
19552007
#pragma mark - Application State Change methods
19562008

19572009
- (void)applicationDidBecomeActive {
2010+
BOOL shouldWaitForInitCopy = NO;
2011+
@synchronized (self.shouldWaitForInitLock) {
2012+
shouldWaitForInitCopy = self.preferenceHelper.shouldWaitForInit;
2013+
}
2014+
19582015
if (!Branch.trackingDisabled) {
19592016
if ((self.initializationStatus != BNCInitStatusInitialized) &&
1960-
!self.preferenceHelper.shouldWaitForInit &&
2017+
!shouldWaitForInitCopy &&
19612018
![self.requestQueue containsInstallOrOpen]) {
19622019
[self initUserSessionAndCallCallback:YES];
19632020
}
@@ -2137,8 +2194,13 @@ - (void) clearNetworkQueue {
21372194
#pragma mark - Session Initialization
21382195

21392196
- (void)initSessionIfNeededAndNotInProgress {
2197+
BOOL shouldWaitForInitCopy = NO;
2198+
@synchronized (self.shouldWaitForInitLock) {
2199+
shouldWaitForInitCopy = self.preferenceHelper.shouldWaitForInit;
2200+
}
2201+
21402202
if (self.initializationStatus == BNCInitStatusUninitialized &&
2141-
!self.preferenceHelper.shouldWaitForInit &&
2203+
!shouldWaitForInitCopy &&
21422204
![self.requestQueue containsInstallOrOpen]) {
21432205
[self initUserSessionAndCallCallback:NO];
21442206
}

0 commit comments

Comments
 (0)