Skip to content

Commit b39af64

Browse files
authored
Add the ability to disable user tracking. (#794, DEVEX-242)
* Added `setTrackingDisabled` and `trackingDisabled` methods to the Branch class to set and query the tracking state. * Added the `BNCTrackingDisabledError` error code that's returned to callbacks when tracking is disabled. * Added a `clearTrackingInformation` method to the preference helper class that clears user identifiable information from preferences. * Changed some NSDictionaries to NSMutableDictionaries for crash safety: Storing nil to a mutable dictionary is not a crash. * Added a 'Do not track' option to UITestBed. * Fixed some code analyzer warnings. * Updated the SDK so that deep links can be opened even when 'no tracking' is set. * Added open stress test. * Updated documentation. * Added SMS as a link scraper when sharing. * Fixed some unit tests and updated pods.
1 parent b7739fc commit b39af64

38 files changed

+738
-281
lines changed

Branch-SDK/Branch-SDK/BNCEncodingUtils.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
extern NSDate* BNCDateFromWireFormat(id object);
1818
extern NSNumber* BNCWireFormatFromDate(NSDate *date);
19+
extern NSNumber* BNCWireFormatFromBool(BOOL b);
1920

2021
extern NSString* BNCStringFromWireFormat(id object);
2122
extern NSString* BNCWireFormatFromString(NSString *string);

Branch-SDK/Branch-SDK/BNCEncodingUtils.m

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@
3131
return number;
3232
}
3333

34+
NSNumber* BNCWireFormatFromBool(BOOL b) {
35+
return (b) ? (__bridge NSNumber*) kCFBooleanTrue : nil;
36+
}
37+
3438
NSString* BNCStringFromWireFormat(id object) {
3539
if ([object isKindOfClass:NSString.class])
3640
return object;

Branch-SDK/Branch-SDK/BNCError.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ typedef NS_ENUM(NSInteger, BNCErrorCode) {
3030
BNCRedeemZeroCreditsError = 1012,
3131
BNCSpotlightIdentifierError = 1013,
3232
BNCSpotlightPublicIndexError = 1014,
33+
BNCTrackingDisabledError = 1015,
3334
BNCHighestError,
3435
};
3536

Branch-SDK/Branch-SDK/BNCError.m

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,10 @@ + (NSString*) messageForCode:(BNCErrorCode)code {
6666
@"The Spotlight identifier is required to remove indexing from spotlight.",
6767

6868
//BNCSpotlightPublicIndexError
69-
@"Spotlight cannot remove publicly indexed content",
70-
69+
@"Spotlight cannot remove publicly indexed content.",
70+
71+
//BNCTrackingDisabledError
72+
@"User tracking is disabled."
7173
};
7274

7375
#define _countof(array) (sizeof(array)/sizeof(array[0]))

Branch-SDK/Branch-SDK/BNCLinkCache.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,5 @@
1111
@interface BNCLinkCache : NSObject
1212
- (void)setObject:(NSString *)anObject forKey:(BNCLinkData *)aKey;
1313
- (NSString *)objectForKey:(BNCLinkData *)aKey;
14+
- (void) clear;
1415
@end

Branch-SDK/Branch-SDK/BNCLinkCache.m

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,10 @@ - (NSString *)objectForKey:(BNCLinkData *)aKey {
3636
}
3737
}
3838

39+
- (void) clear {
40+
@synchronized (self) {
41+
[self.cache removeAllObjects];
42+
}
43+
}
44+
3945
@end

Branch-SDK/Branch-SDK/BNCLocalization.m

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,8 @@ + (NSDictionary*_Nonnull) en_localized {
191191
@"Could not generate a URL.":
192192
@"Could not generate a URL.",
193193

194+
@"User tracking is disabled.":
195+
@"User tracking is disabled."
194196
};
195197
return en_dict;
196198
}
@@ -280,6 +282,9 @@ + (NSDictionary*_Nonnull) ru_localized {
280282

281283
@"Could not generate a URL.":
282284
@"Не получилось сгенерировать URL.",
285+
286+
@"User tracking is disbabled.":
287+
@"Трекинг пользователя отключен.",
283288
};
284289

285290
return ru_dict;

Branch-SDK/Branch-SDK/BNCPreferenceHelper.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ NSURL* /* _Nonnull */ BNCURLForBranchDirectory(void);
5454
@property (strong, atomic) NSArray<NSString*> *URLBlackList;
5555
@property (assign, atomic) NSInteger URLBlackListVersion;
5656

57+
@property (assign, atomic) BOOL trackingDisabled;
58+
- (void) clearTrackingInformation;
59+
5760
+ (BNCPreferenceHelper *)preferenceHelper;
5861

5962
- (NSString *)getAPIBaseURL;
@@ -88,6 +91,7 @@ NSURL* /* _Nonnull */ BNCURLForBranchDirectory(void);
8891
- (NSDictionary *)getContentAnalyticsManifest;
8992
- (void)saveContentAnalyticsManifest:(NSDictionary *)cdManifest;
9093

94+
- (NSMutableString*) sanitizedMutableBaseURL:(NSString*)baseUrl;
9195
- (void) synchronize; // Flushes preference queue to persistence.
9296

9397
@end

Branch-SDK/Branch-SDK/BNCPreferenceHelper.m

Lines changed: 95 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#import "BNCLog.h"
1414
#import "BNCFabricAnswers.h"
1515
#import "BranchConstants.h"
16+
#import "NSString+Branch.h"
1617

1718
static const NSTimeInterval DEFAULT_TIMEOUT = 5.5;
1819
static const NSTimeInterval DEFAULT_RETRY_INTERVAL = 0;
@@ -173,7 +174,6 @@ - (NSString *)lastRunBranchKey {
173174
if (!_lastRunBranchKey) {
174175
_lastRunBranchKey = [self readStringFromDefaults:BRANCH_PREFS_KEY_LAST_RUN_BRANCH_KEY];
175176
}
176-
177177
return _lastRunBranchKey;
178178
}
179179

@@ -188,12 +188,11 @@ - (NSDate *)lastStrongMatchDate {
188188
if (!_lastStrongMatchDate) {
189189
_lastStrongMatchDate = (NSDate *)[self readObjectFromDefaults:BRANCH_PREFS_KEY_LAST_STRONG_MATCH_DATE];
190190
}
191-
192191
return _lastStrongMatchDate;
193192
}
194193

195194
- (void)setLastStrongMatchDate:(NSDate *)lastStrongMatchDate {
196-
if (![_lastStrongMatchDate isEqualToDate:lastStrongMatchDate]) {
195+
if (lastStrongMatchDate == nil || ![_lastStrongMatchDate isEqualToDate:lastStrongMatchDate]) {
197196
_lastStrongMatchDate = lastStrongMatchDate;
198197
[self writeObjectToDefaults:BRANCH_PREFS_KEY_LAST_STRONG_MATCH_DATE value:lastStrongMatchDate];
199198
}
@@ -203,7 +202,6 @@ - (NSString *)appVersion {
203202
if (!_appVersion) {
204203
_appVersion = [self readStringFromDefaults:BRANCH_PREFS_KEY_APP_VERSION];
205204
}
206-
207205
return _appVersion;
208206
}
209207

@@ -223,7 +221,7 @@ - (NSString *)deviceFingerprintID {
223221
}
224222

225223
- (void)setDeviceFingerprintID:(NSString *)deviceFingerprintID {
226-
if (![_deviceFingerprintID isEqualToString:deviceFingerprintID]) {
224+
if (deviceFingerprintID == nil || ![_deviceFingerprintID isEqualToString:deviceFingerprintID]) {
227225
_deviceFingerprintID = deviceFingerprintID;
228226
[self writeObjectToDefaults:BRANCH_PREFS_KEY_DEVICE_FINGERPRINT_ID value:deviceFingerprintID];
229227
}
@@ -238,70 +236,42 @@ - (NSString *)sessionID {
238236
}
239237

240238
- (void)setSessionID:(NSString *)sessionID {
241-
if (![_sessionID isEqualToString:sessionID]) {
239+
if (sessionID == nil || ![_sessionID isEqualToString:sessionID]) {
242240
_sessionID = sessionID;
243241
[self writeObjectToDefaults:BRANCH_PREFS_KEY_SESSION_ID value:sessionID];
244242
}
245243
}
246244

247245
- (NSString *)identityID {
248-
if (!_identityID) {
249-
_identityID = [self readStringFromDefaults:BRANCH_PREFS_KEY_IDENTITY_ID];
250-
}
251-
252-
return _identityID;
246+
return [self readStringFromDefaults:BRANCH_PREFS_KEY_IDENTITY_ID];
253247
}
254248

255249
- (void)setIdentityID:(NSString *)identityID {
256-
if (![_identityID isEqualToString:identityID]) {
257-
_identityID = identityID;
258-
[self writeObjectToDefaults:BRANCH_PREFS_KEY_IDENTITY_ID value:identityID];
259-
}
250+
[self writeObjectToDefaults:BRANCH_PREFS_KEY_IDENTITY_ID value:identityID];
260251
}
261252

262253
- (NSString *)userIdentity {
263-
if (!_userIdentity) {
264-
_userIdentity = [self readStringFromDefaults:BRANCH_PREFS_KEY_IDENTITY];
265-
}
266-
267-
return _userIdentity;
254+
return [self readStringFromDefaults:BRANCH_PREFS_KEY_IDENTITY];
268255
}
269256

270257
- (void)setUserIdentity:(NSString *)userIdentity {
271-
if (![_userIdentity isEqualToString:userIdentity]) {
272-
_userIdentity = userIdentity;
273-
[self writeObjectToDefaults:BRANCH_PREFS_KEY_IDENTITY value:userIdentity];
274-
}
258+
[self writeObjectToDefaults:BRANCH_PREFS_KEY_IDENTITY value:userIdentity];
275259
}
276260

277261
- (NSString *)linkClickIdentifier {
278-
if (!_linkClickIdentifier) {
279-
_linkClickIdentifier = [self readStringFromDefaults:BRANCH_PREFS_KEY_LINK_CLICK_IDENTIFIER];
280-
}
281-
282-
return _linkClickIdentifier;
262+
return [self readStringFromDefaults:BRANCH_PREFS_KEY_LINK_CLICK_IDENTIFIER];
283263
}
284264

285265
- (void)setLinkClickIdentifier:(NSString *)linkClickIdentifier {
286-
if (![_linkClickIdentifier isEqualToString:linkClickIdentifier]) {
287-
_linkClickIdentifier = linkClickIdentifier;
288-
[self writeObjectToDefaults:BRANCH_PREFS_KEY_LINK_CLICK_IDENTIFIER value:linkClickIdentifier];
289-
}
266+
[self writeObjectToDefaults:BRANCH_PREFS_KEY_LINK_CLICK_IDENTIFIER value:linkClickIdentifier];
290267
}
291268

292269
- (NSString *)spotlightIdentifier {
293-
if (!_spotlightIdentifier) {
294-
_spotlightIdentifier = [self readStringFromDefaults:BRANCH_PREFS_KEY_SPOTLIGHT_IDENTIFIER];
295-
}
296-
297-
return _spotlightIdentifier;
270+
return [self readStringFromDefaults:BRANCH_PREFS_KEY_SPOTLIGHT_IDENTIFIER];
298271
}
299272

300273
- (void)setSpotlightIdentifier:(NSString *)spotlightIdentifier {
301-
if (![_spotlightIdentifier isEqualToString:spotlightIdentifier]) {
302-
_spotlightIdentifier = spotlightIdentifier;
303-
[self writeObjectToDefaults:BRANCH_PREFS_KEY_SPOTLIGHT_IDENTIFIER value:spotlightIdentifier];
304-
}
274+
[self writeObjectToDefaults:BRANCH_PREFS_KEY_SPOTLIGHT_IDENTIFIER value:spotlightIdentifier];
305275
}
306276

307277
- (NSString *)externalIntentURI {
@@ -315,7 +285,7 @@ - (NSString *)externalIntentURI {
315285

316286
- (void)setExternalIntentURI:(NSString *)externalIntentURI {
317287
@synchronized(self) {
318-
if (![_externalIntentURI isEqualToString:externalIntentURI]) {
288+
if (externalIntentURI == nil || ![_externalIntentURI isEqualToString:externalIntentURI]) {
319289
_externalIntentURI = externalIntentURI;
320290
[self writeObjectToDefaults:BRANCH_REQUEST_KEY_EXTERNAL_INTENT_URI value:externalIntentURI];
321291
}
@@ -337,21 +307,11 @@ - (void) setReferringURL:(NSString *)referringURL {
337307
}
338308

339309
- (NSString *)universalLinkUrl {
340-
@synchronized(self) {
341-
if (!_universalLinkUrl) {
342-
_universalLinkUrl = [self readStringFromDefaults:BRANCH_PREFS_KEY_UNIVERSAL_LINK_URL];
343-
}
344-
return _universalLinkUrl;
345-
}
310+
return [self readStringFromDefaults:BRANCH_PREFS_KEY_UNIVERSAL_LINK_URL];
346311
}
347312

348313
- (void)setUniversalLinkUrl:(NSString *)universalLinkUrl {
349-
@synchronized(self) {
350-
if (![_universalLinkUrl isEqualToString:universalLinkUrl]) {
351-
_universalLinkUrl = universalLinkUrl;
352-
[self writeObjectToDefaults:BRANCH_PREFS_KEY_UNIVERSAL_LINK_URL value:universalLinkUrl];
353-
}
354-
}
314+
[self writeObjectToDefaults:BRANCH_PREFS_KEY_UNIVERSAL_LINK_URL value:universalLinkUrl];
355315
}
356316

357317
- (NSString *)sessionParams {
@@ -365,37 +325,39 @@ - (NSString *)sessionParams {
365325

366326
- (void)setSessionParams:(NSString *)sessionParams {
367327
@synchronized (self) {
368-
if (![_sessionParams isEqualToString:sessionParams]) {
328+
if (sessionParams == nil || ![_sessionParams isEqualToString:sessionParams]) {
369329
_sessionParams = sessionParams;
370330
[self writeObjectToDefaults:BRANCH_PREFS_KEY_SESSION_PARAMS value:sessionParams];
371331
}
372332
}
373333
}
374334

375335
- (NSString *)installParams {
376-
if (!_installParams) {
377-
id installParamsFromCache = [self readStringFromDefaults:BRANCH_PREFS_KEY_INSTALL_PARAMS];
378-
if ([installParamsFromCache isKindOfClass:[NSString class]]) {
379-
_installParams = [self readStringFromDefaults:BRANCH_PREFS_KEY_INSTALL_PARAMS];
380-
}
381-
else if ([installParamsFromCache isKindOfClass:[NSDictionary class]]) {
382-
[self writeObjectToDefaults:BRANCH_PREFS_KEY_INSTALL_PARAMS value:nil];
336+
@synchronized(self) {
337+
if (!_installParams) {
338+
id installParamsFromCache = [self readStringFromDefaults:BRANCH_PREFS_KEY_INSTALL_PARAMS];
339+
if ([installParamsFromCache isKindOfClass:[NSString class]]) {
340+
_installParams = [self readStringFromDefaults:BRANCH_PREFS_KEY_INSTALL_PARAMS];
341+
}
342+
else if ([installParamsFromCache isKindOfClass:[NSDictionary class]]) {
343+
[self writeObjectToDefaults:BRANCH_PREFS_KEY_INSTALL_PARAMS value:nil];
344+
}
383345
}
346+
return _installParams;
384347
}
385-
386-
return _installParams;
387348
}
388349

389350
- (void)setInstallParams:(NSString *)installParams {
390-
if ([installParams isKindOfClass:[NSDictionary class]]) {
391-
_installParams = [BNCEncodingUtils encodeDictionaryToJsonString:(NSDictionary *)installParams];
392-
[self writeObjectToDefaults:BRANCH_PREFS_KEY_INSTALL_PARAMS value:_installParams];
393-
return;
394-
}
395-
396-
if (![_installParams isEqualToString:installParams]) {
397-
_installParams = installParams;
398-
[self writeObjectToDefaults:BRANCH_PREFS_KEY_INSTALL_PARAMS value:installParams];
351+
@synchronized(self) {
352+
if ([installParams isKindOfClass:[NSDictionary class]]) {
353+
_installParams = [BNCEncodingUtils encodeDictionaryToJsonString:(NSDictionary *)installParams];
354+
[self writeObjectToDefaults:BRANCH_PREFS_KEY_INSTALL_PARAMS value:_installParams];
355+
return;
356+
}
357+
if (installParams == nil || ![_installParams isEqualToString:installParams]) {
358+
_installParams = installParams;
359+
[self writeObjectToDefaults:BRANCH_PREFS_KEY_INSTALL_PARAMS value:installParams];
360+
}
399361
}
400362
}
401363

@@ -464,6 +426,24 @@ - (void)setUserUrl:(NSString *)userUrl {
464426
}
465427
}
466428

429+
- (NSMutableString*) sanitizedMutableBaseURL:(NSString*)baseUrl_ {
430+
NSMutableString *baseUrl = [baseUrl_ mutableCopy];
431+
if (self.trackingDisabled) {
432+
NSString *id_string = [NSString stringWithFormat:@"%%24identity_id=%@", self.identityID];
433+
NSRange range = [baseUrl rangeOfString:id_string];
434+
if (range.location != NSNotFound) [baseUrl replaceCharactersInRange:range withString:@""];
435+
} else
436+
if ([baseUrl hasSuffix:@"&"] || [baseUrl hasSuffix:@"?"]) {
437+
} else
438+
if ([baseUrl bnc_containsString:@"?"]) {
439+
[baseUrl appendString:@"&"];
440+
}
441+
else {
442+
[baseUrl appendString:@"?"];
443+
}
444+
return baseUrl;
445+
}
446+
467447
- (BOOL)checkedAppleSearchAdAttribution {
468448
_checkedAppleSearchAdAttribution = [self readBoolFromDefaults:BRANCH_PREFS_KEY_CHECKED_APPLE_SEARCH_ADS];
469449
return _checkedAppleSearchAdAttribution;
@@ -591,6 +571,47 @@ - (void) setURLBlackListVersion:(NSInteger)URLBlackListVersion {
591571
}
592572
}
593573

574+
- (BOOL) trackingDisabled {
575+
@synchronized(self) {
576+
NSNumber *b = (id) [self readObjectFromDefaults:@"trackingDisabled"];
577+
if ([b isKindOfClass:NSNumber.class]) return [b boolValue];
578+
return false;
579+
}
580+
}
581+
582+
- (void) setTrackingDisabled:(BOOL)disabled {
583+
@synchronized(self) {
584+
NSNumber *b = [NSNumber numberWithBool:disabled];
585+
[self writeObjectToDefaults:@"trackingDisabled" value:b];
586+
if (disabled) [self clearTrackingInformation];
587+
}
588+
}
589+
590+
- (void) clearTrackingInformation {
591+
@synchronized(self) {
592+
/* Don't clear these:
593+
self.deviceFingerprintID = nil;
594+
self.userIdentity = nil;
595+
self.identityID = nil;
596+
self.installParams = nil;
597+
*/
598+
self.sessionID = nil;
599+
self.linkClickIdentifier = nil;
600+
self.spotlightIdentifier = nil;
601+
self.referringURL = nil;
602+
self.universalLinkUrl = nil;
603+
self.installParams = nil;
604+
self.appleSearchAdDetails = nil;
605+
self.appleSearchAdNeedsSend = NO;
606+
self.sessionParams = nil;
607+
self.externalIntentURI = nil;
608+
self.savedAnalyticsData = nil;
609+
self.previousAppBuildDate = nil;
610+
self.requestMetadataDictionary = nil;
611+
self.lastStrongMatchDate = nil;
612+
}
613+
}
614+
594615
#pragma mark - Credit Storage
595616

596617
- (NSMutableDictionary *)creditsDictionary {

0 commit comments

Comments
 (0)