1717static const NSTimeInterval DEFAULT_TIMEOUT = 5.5 ;
1818static const NSTimeInterval DEFAULT_RETRY_INTERVAL = 0 ;
1919static const NSInteger DEFAULT_RETRY_COUNT = 3 ;
20+ static const NSTimeInterval DEFAULT_REFERRER_GBRAID_WINDOW = 2592000 ; // 30 days = 2,592,000 seconds
2021
2122static NSString * const BRANCH_PREFS_FILE = @" BNCPreferences" ;
2223
4344static NSString * const BRANCH_PREFS_KEY_BRANCH_VIEW_USAGE_CNT = @" bnc_branch_view_usage_cnt_" ;
4445static NSString * const BRANCH_PREFS_KEY_ANALYTICAL_DATA = @" bnc_branch_analytical_data" ;
4546static NSString * const BRANCH_PREFS_KEY_ANALYTICS_MANIFEST = @" bnc_branch_analytics_manifest" ;
47+ static NSString * const BRANCH_PREFS_KEY_REFERRER_GBRAID = @" bnc_referrer_gbraid" ;
48+ static NSString * const BRANCH_PREFS_KEY_REFERRER_GBRAID_WINDOW = @" bnc_referrer_gbraid_window" ;
49+ static NSString * const BRANCH_PREFS_KEY_REFERRER_GBRAID_INIT_DATE = @" bnc_referrer_gbraid_init_date" ;
4650
4751NSURL * /* _Nonnull */ BNCURLForBranchDirectory_Unthreaded(void );
4852
@@ -86,7 +90,9 @@ @implementation BNCPreferenceHelper
8690 checkedAppleSearchAdAttribution = _checkedAppleSearchAdAttribution,
8791 appleSearchAdDetails = _appleSearchAdDetails,
8892 requestMetadataDictionary = _requestMetadataDictionary,
89- instrumentationDictionary = _instrumentationDictionary;
93+ instrumentationDictionary = _instrumentationDictionary,
94+ referrerGBRAID = _referrerGBRAID,
95+ referrerGBRAIDValidityWindow = _referrerGBRAIDValidityWindow;
9096
9197+ (BNCPreferenceHelper *)sharedInstance {
9298 static BNCPreferenceHelper *preferenceHelper;
@@ -650,6 +656,53 @@ - (void)setSendCloseRequests:(BOOL)disabled {
650656 }
651657}
652658
659+ - (NSString *) referrerGBRAID {
660+ @synchronized (self) {
661+ if (!_referrerGBRAID) {
662+ _referrerGBRAID = [self readStringFromDefaults: BRANCH_PREFS_KEY_REFERRER_GBRAID];
663+ }
664+ return _referrerGBRAID;
665+ }
666+ }
667+
668+ - (void ) setReferrerGBRAID : (NSString *)referrerGBRAID {
669+ if (![_referrerGBRAID isEqualToString: referrerGBRAID]) {
670+ _referrerGBRAID = referrerGBRAID;
671+ [self writeObjectToDefaults: BRANCH_PREFS_KEY_REFERRER_GBRAID value: referrerGBRAID];
672+ self.referrerGBRAIDInitDate = [NSDate date ];
673+ }
674+ }
675+
676+ - (NSTimeInterval ) referrerGBRAIDValidityWindow {
677+ @synchronized (self) {
678+ _referrerGBRAIDValidityWindow = [self readDoubleFromDefaults: BRANCH_PREFS_KEY_REFERRER_GBRAID_WINDOW];
679+ if (_referrerGBRAIDValidityWindow == NSNotFound ) {
680+ _referrerGBRAIDValidityWindow = DEFAULT_REFERRER_GBRAID_WINDOW;
681+ }
682+ return _referrerGBRAIDValidityWindow;
683+ }
684+ }
685+
686+ - (void ) setReferrerGBRAIDValidityWindow : (NSTimeInterval )validityWindow {
687+ @synchronized (self) {
688+ [self writeObjectToDefaults: BRANCH_PREFS_KEY_REFERRER_GBRAID_WINDOW value: @(validityWindow)];
689+ }
690+ }
691+
692+ - (NSDate *) referrerGBRAIDInitDate {
693+ @synchronized (self) {
694+ NSDate * initdate = (NSDate *)[self readObjectFromDefaults: BRANCH_PREFS_KEY_REFERRER_GBRAID_INIT_DATE];
695+ if ([initdate isKindOfClass: [NSDate class ]]) return initdate;
696+ return nil ;
697+ }
698+ }
699+
700+ - (void )setReferrerGBRAIDInitDate : (NSDate *)initDate {
701+ @synchronized (self) {
702+ [self writeObjectToDefaults: BRANCH_PREFS_KEY_REFERRER_GBRAID_INIT_DATE value: initDate];
703+ }
704+ }
705+
653706- (void ) clearTrackingInformation {
654707 @synchronized (self) {
655708 /*
@@ -742,24 +795,10 @@ - (void)writeObjectToDefaults:(NSString *)key value:(NSObject *)value {
742795- (void )persistPrefsToDisk {
743796 @synchronized (self) {
744797 if (!self.persistenceDict ) return ;
745- NSData *data = nil ;
746- @try {
747- if (@available (iOS 11.0 , tvOS 11.0 , *)) {
748- data = [NSKeyedArchiver archivedDataWithRootObject: self .persistenceDict requiringSecureCoding: YES error: NULL ];
749- } else {
750- #if __IPHONE_OS_VERSION_MIN_REQUIRED < 12000
751- data = [NSKeyedArchiver archivedDataWithRootObject: self .persistenceDict];
752- #endif
753- }
754- }
755- @catch (id exception) {
756- data = nil ;
757- BNCLogWarning ([NSString stringWithFormat: @" Exception creating preferences data: %@ ." , exception]);
758- }
759- if (!data) {
760- BNCLogWarning (@" Can't create preferences data." );
761- return ;
762- }
798+
799+ NSData *data = [self serializePrefDict: self .persistenceDict];
800+ if (!data) return ;
801+
763802 NSURL *prefsURL = [self .class.URLForPrefsFile copy ];
764803 NSBlockOperation *newPersistOp = [NSBlockOperation blockOperationWithBlock: ^ {
765804 NSError *error = nil ;
@@ -772,6 +811,24 @@ - (void)persistPrefsToDisk {
772811 }
773812}
774813
814+ - (NSData *)serializePrefDict : (NSMutableDictionary *)dict {
815+ if (dict == nil ) return nil ;
816+
817+ NSData *data = nil ;
818+ @try {
819+ if (@available (iOS 11.0 , tvOS 11.0 , *)) {
820+ data = [NSKeyedArchiver archivedDataWithRootObject: dict requiringSecureCoding: YES error: NULL ];
821+ } else {
822+ #if __IPHONE_OS_VERSION_MIN_REQUIRED < 12000
823+ data = [NSKeyedArchiver archivedDataWithRootObject: dict];
824+ #endif
825+ }
826+ } @catch (id exception) {
827+ BNCLogWarning ([NSString stringWithFormat: @" Exception serializing preferences dict: %@ ." , exception]);
828+ }
829+ return data;
830+ }
831+
775832+ (void ) clearAll {
776833 NSURL *prefsURL = [self .URLForPrefsFile copy ];
777834 if (prefsURL) [[NSFileManager defaultManager ] removeItemAtURL: prefsURL error: nil ];
@@ -782,31 +839,50 @@ + (void) clearAll {
782839- (NSMutableDictionary *)persistenceDict {
783840 @synchronized (self) {
784841 if (!_persistenceDict) {
785- NSDictionary *persistenceDict = nil ;
786- @try {
787- NSError *error = nil ;
788- NSData *data = [NSData dataWithContentsOfURL: self .class.URLForPrefsFile options: 0 error: &error];
789- if (!error && data) {
790- // if (@available(iOS 11.0, tvOS 11.0, *)) {
791- // persistenceDict = [NSKeyedUnarchiver unarchivedObjectOfClass:[NSMutableDictionary class] fromData:data error:NULL];
792- // } else {
793- // #if __IPHONE_OS_VERSION_MIN_REQUIRED < 12000
794- persistenceDict = [NSKeyedUnarchiver unarchiveObjectWithData: data];
795- // #endif
796- // }
797- }
798- }
799- @catch (NSException *) {
842+ _persistenceDict = [self deserializePrefDictFromData: [self loadPrefData ]];
843+ }
844+ return _persistenceDict;
845+ }
846+ }
847+
848+ - (NSData *)loadPrefData {
849+ NSData *data = nil ;
850+ @try {
851+ NSError *error = nil ;
852+ data = [NSData dataWithContentsOfURL: self .class.URLForPrefsFile options: 0 error: &error];
853+ if (error || !data) {
854+ BNCLogWarning (@" Failed to load preferences from storage." );
855+ }
856+ } @catch (NSException *) {
857+ BNCLogWarning (@" Failed to load preferences from storage." );
858+ }
859+ return data;
860+ }
861+
862+ - (NSMutableDictionary *)deserializePrefDictFromData : (NSData *)data {
863+ NSDictionary *dict = nil ;
864+ if (data) {
865+ if (@available (iOS 11.0 , tvOS 11.0 , *)) {
866+ NSError *error = nil ;
867+ NSSet *classes = [[NSMutableSet alloc ] initWithArray: @[ NSNumber .class, NSString .class, NSDate .class, NSArray .class, NSDictionary .class ]];
868+
869+ dict = [NSKeyedUnarchiver unarchivedObjectOfClasses: classes fromData: data error: &error];
870+ if (error) {
800871 BNCLogWarning (@" Failed to load preferences from storage." );
801872 }
802873
803- if ([persistenceDict isKindOfClass: [NSDictionary class ]]) {
804- _persistenceDict = [persistenceDict mutableCopy ];
805- } else {
806- _persistenceDict = [[NSMutableDictionary alloc ] init ];
807- }
874+ } else {
875+ #if __IPHONE_OS_VERSION_MIN_REQUIRED < 12000
876+ dict = [NSKeyedUnarchiver unarchiveObjectWithData: data];
877+ #endif
808878 }
809- return _persistenceDict;
879+ }
880+
881+ // NSKeyedUnarchiver returns an NSDictionary, convert to NSMutableDictionary
882+ if (dict && [dict isKindOfClass: [NSDictionary class ]]) {
883+ return [dict mutableCopy ];
884+ } else {
885+ return [[NSMutableDictionary alloc ] init ];
810886 }
811887}
812888
@@ -858,6 +934,16 @@ - (NSInteger)readIntegerFromDefaults:(NSString *)key {
858934 }
859935}
860936
937+ - (double )readDoubleFromDefaults : (NSString *)key {
938+ @synchronized (self) {
939+ NSNumber *number = self.persistenceDict [key];
940+ if (number != nil && [number respondsToSelector: @selector (doubleValue )]){
941+ return [number doubleValue ];
942+ }
943+ return NSNotFound ;
944+ }
945+ }
946+
861947#pragma mark - Preferences File URL
862948
863949+ (NSURL * _Nonnull) URLForPrefsFile {
0 commit comments