diff options
author | Ryan Wilson <wilsonryan@google.com> | 2018-05-14 10:02:25 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-05-14 10:02:25 -0700 |
commit | 08f447cd3fffae80748239daada493fcc19c111f (patch) | |
tree | 52049deb6adda8eb87c07d01264bdc2e0be26ac5 /Firebase | |
parent | 281d145dc93d310d1dc21fdff61e004faba3b057 (diff) |
Add global data collection switch. (#1219)
* Addition of global data collection switch.
* Added Messaging conformance to data switch.
Also formatted code.
* Move data collection flag internal until all SDKs conform to it.
* Formatting in response to code review.
Diffstat (limited to 'Firebase')
-rw-r--r-- | Firebase/Core/FIRApp.m | 85 | ||||
-rw-r--r-- | Firebase/Core/Private/FIRAppInternal.h | 28 | ||||
-rw-r--r-- | Firebase/Messaging/FIRMessaging+FIRApp.m | 1 | ||||
-rw-r--r-- | Firebase/Messaging/FIRMessaging.m | 7 | ||||
-rw-r--r-- | Firebase/Messaging/FIRMessaging_Private.h | 4 |
5 files changed, 121 insertions, 4 deletions
diff --git a/Firebase/Core/FIRApp.m b/Firebase/Core/FIRApp.m index 3d05f12..717da4e 100644 --- a/Firebase/Core/FIRApp.m +++ b/Firebase/Core/FIRApp.m @@ -46,6 +46,11 @@ NSString *const kFIRAppIsDefaultAppKey = @"FIRAppIsDefaultAppKey"; NSString *const kFIRAppNameKey = @"FIRAppNameKey"; NSString *const kFIRGoogleAppIDKey = @"FIRGoogleAppIDKey"; +NSString *const kFIRGlobalAppDataCollectionEnabledDefaultsKeyFormat = + @"/google/firebase/global_data_collection_enabled:%@"; +NSString *const kFIRGlobalAppDataCollectionEnabledPlistKey = + @"FirebaseAutomaticDataCollectionEnabled"; + NSString *const kFIRAppDiagnosticsNotification = @"FIRAppDiagnosticsNotification"; NSString *const kFIRAppDiagnosticsConfigurationTypeKey = @"ConfigType"; @@ -227,6 +232,7 @@ static NSMutableDictionary *sLibraryVersions; if (sAllApps && sAllApps[self.name]) { FIRLogDebug(kFIRLoggerCore, @"I-COR000006", @"Deleting app named %@", self.name); [sAllApps removeObjectForKey:self.name]; + [self clearDataCollectionSwitchFromUserDefaults]; if ([self.name isEqualToString:kFIRDefaultAppName]) { sDefaultApp = nil; } @@ -332,6 +338,30 @@ static NSMutableDictionary *sLibraryVersions; return [_options copy]; } +- (void)setAutomaticDataCollectionEnabled:(BOOL)automaticDataCollectionEnabled { + NSString *key = + [NSString stringWithFormat:kFIRGlobalAppDataCollectionEnabledDefaultsKeyFormat, self.name]; + [[NSUserDefaults standardUserDefaults] setBool:automaticDataCollectionEnabled forKey:key]; +} + +- (BOOL)isAutomaticDataCollectionEnabled { + // Check if it's been manually set before in code, and use that as the higher priority value. + NSNumber *defaultsObject = [[self class] readDataCollectionSwitchFromUserDefaultsForApp:self]; + if (defaultsObject) { + return [defaultsObject boolValue]; + } + + // Read the Info.plist to see if the flag is set. If it's not set, it should default to `YES`. + // As per the implementation of `readDataCollectionSwitchFromPlist`, it's a cached value and has + // no performance impact calling multiple times. + NSNumber *collectionEnabledPlistValue = [[self class] readDataCollectionSwitchFromPlist]; + if (collectionEnabledPlistValue) { + return [collectionEnabledPlistValue boolValue]; + } + + return YES; +} + #pragma mark - private + (void)sendNotificationsToSDKs:(FIRApp *)app { @@ -613,11 +643,64 @@ static NSMutableDictionary *sLibraryVersions; } // end App ID validation -#pragma mark + +#pragma mark - Reading From Plist & User Defaults + +/** + * Clears the data collection switch from the standard NSUserDefaults for easier testing and + * readability. + */ +- (void)clearDataCollectionSwitchFromUserDefaults { + NSString *key = + [NSString stringWithFormat:kFIRGlobalAppDataCollectionEnabledDefaultsKeyFormat, self.name]; + [[NSUserDefaults standardUserDefaults] removeObjectForKey:key]; +} + +/** + * Reads the data collection switch from the standard NSUserDefaults for easier testing and + * readability. + */ ++ (nullable NSNumber *)readDataCollectionSwitchFromUserDefaultsForApp:(FIRApp *)app { + // Read the object in user defaults, and only return if it's an NSNumber. + NSString *key = + [NSString stringWithFormat:kFIRGlobalAppDataCollectionEnabledDefaultsKeyFormat, app.name]; + id collectionEnabledDefaultsObject = [[NSUserDefaults standardUserDefaults] objectForKey:key]; + if ([collectionEnabledDefaultsObject isKindOfClass:[NSNumber class]]) { + return collectionEnabledDefaultsObject; + } + + return nil; +} + +/** + * Reads the data collection switch from the Info.plist for easier testing and readability. Will + * only read once from the plist and return the cached value. + */ ++ (nullable NSNumber *)readDataCollectionSwitchFromPlist { + static NSNumber *collectionEnabledPlistObject; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + // Read the data from the `Info.plist`, only assign it if it's there and an NSNumber. + id plistValue = [[NSBundle mainBundle] + objectForInfoDictionaryKey:kFIRGlobalAppDataCollectionEnabledPlistKey]; + if (plistValue && [plistValue isKindOfClass:[NSNumber class]]) { + collectionEnabledPlistObject = (NSNumber *)plistValue; + } + }); + + return collectionEnabledPlistObject; +} + +#pragma mark - Sending Logs - (void)sendLogsWithServiceName:(NSString *)serviceName version:(NSString *)version error:(NSError *)error { + // If the user has manually turned off data collection, return and don't send logs. + if (![self isAutomaticDataCollectionEnabled]) { + return; + } + NSMutableDictionary *userInfo = [[NSMutableDictionary alloc] initWithDictionary:@{ kFIRAppDiagnosticsConfigurationTypeKey : @(FIRConfigTypeSDK), kFIRAppDiagnosticsSDKNameKey : serviceName, diff --git a/Firebase/Core/Private/FIRAppInternal.h b/Firebase/Core/Private/FIRAppInternal.h index b7cf5e8..66979eb 100644 --- a/Firebase/Core/Private/FIRAppInternal.h +++ b/Firebase/Core/Private/FIRAppInternal.h @@ -60,6 +60,22 @@ extern NSString *const kFIRAppIsDefaultAppKey; extern NSString *const kFIRAppNameKey; extern NSString *const kFIRGoogleAppIDKey; +/** + * The format string for the User Defaults key used for storing the data collection enabled flag. + * This includes formatting to append the Firebase App's name. + */ +extern NSString *const kFIRGlobalAppDataCollectionEnabledDefaultsKeyFormat; + +/** + * The plist key used for storing the data collection enabled flag. + */ +extern NSString *const kFIRGlobalAppDataCollectionEnabledPlistKey; + +/** + * A notification fired containing diagnostic information when SDK errors occur. + */ +extern NSString *const kFIRAppDiagnosticsNotification; + /** @var FIRAuthStateDidChangeInternalNotification @brief The name of the @c NSNotificationCenter notification which is posted when the auth state changes (e.g. a new token has been produced, a user logs in or out). The object parameter of @@ -181,6 +197,18 @@ typedef NSString *_Nullable (^FIRAppGetUIDImplementation)(void); */ - (nullable NSString *)getUID; +/** + * WARNING: THIS SETTING DOES NOT WORK YET. IT WILL BE MOVED TO THE PUBLIC HEADER ONCE ALL SDKS + * CONFORM TO THIS PREFERENCE. DO NOT RELY ON IT. + * + * Gets or sets whether automatic data collection is enabled for all products. Defaults to `YES` + * unless `FirebaseAutomaticDataCollectionEnabled` is set to `NO` in your app's Info.plist. This + * value is persisted across runs of the app so that it can be set once when users have consented to + * collection. + */ +@property(nonatomic, readwrite, getter=isAutomaticDataCollectionEnabled) + BOOL automaticDataCollectionEnabled; + @end NS_ASSUME_NONNULL_END diff --git a/Firebase/Messaging/FIRMessaging+FIRApp.m b/Firebase/Messaging/FIRMessaging+FIRApp.m index 58ae3af..d48a3b4 100644 --- a/Firebase/Messaging/FIRMessaging+FIRApp.m +++ b/Firebase/Messaging/FIRMessaging+FIRApp.m @@ -72,6 +72,7 @@ } self.fcmSenderID = [options.GCMSenderID copy]; + self.globalAutomaticDataCollectionEnabled = [app isAutomaticDataCollectionEnabled]; // Swizzle remote-notification-related methods (app delegate and UNUserNotificationCenter) if ([FIRMessagingRemoteNotificationsProxy canSwizzleMethods]) { diff --git a/Firebase/Messaging/FIRMessaging.m b/Firebase/Messaging/FIRMessaging.m index 339bd7d..6222420 100644 --- a/Firebase/Messaging/FIRMessaging.m +++ b/Firebase/Messaging/FIRMessaging.m @@ -75,7 +75,7 @@ NSString *const kFIRMessagingUserDefaultsKeyAutoInitEnabled = NSString *const kFIRMessagingAPNSTokenType = @"APNSTokenType"; // APNS Token type key stored in user info. -static NSString *const kFIRMessagingPlistAutoInitEnabled = +NSString *const kFIRMessagingPlistAutoInitEnabled = @"FirebaseMessagingAutoInitEnabled"; // Auto Init Enabled key stored in Info.plist @interface FIRMessagingMessageInfo () @@ -471,8 +471,9 @@ static NSString *const kFIRMessagingPlistAutoInitEnabled = if (isAutoInitEnabledObject) { return [isAutoInitEnabledObject boolValue]; } - // If none of above exists, we default assume FCM auto init is enabled. - return YES; + + // If none of above exists, we default to the global switch that comes from FIRApp. + return self.isGlobalAutomaticDataCollectionEnabled; } - (void)setAutoInitEnabled:(BOOL)autoInitEnabled { diff --git a/Firebase/Messaging/FIRMessaging_Private.h b/Firebase/Messaging/FIRMessaging_Private.h index 46daee0..6bac99d 100644 --- a/Firebase/Messaging/FIRMessaging_Private.h +++ b/Firebase/Messaging/FIRMessaging_Private.h @@ -25,6 +25,7 @@ typedef NS_ENUM(int8_t, FIRMessagingNetworkStatus) { kFIRMessagingReachabilityReachableViaWWAN, }; +FOUNDATION_EXPORT NSString *const kFIRMessagingPlistAutoInitEnabled; FOUNDATION_EXPORT NSString *const kFIRMessagingUserDefaultsKeyAutoInitEnabled; @interface FIRMessagingRemoteMessage () @@ -37,6 +38,9 @@ FOUNDATION_EXPORT NSString *const kFIRMessagingUserDefaultsKeyAutoInitEnabled; #pragma mark - Private API +// The data collection flag from Core. +@property(nonatomic, readwrite, getter=isGlobalAutomaticDataCollectionEnabled) BOOL globalAutomaticDataCollectionEnabled; + - (NSString *)defaultFcmToken; - (FIRMessagingClient *)client; - (FIRMessagingPubSub *)pubsub; |