-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Add global data collection switch. #1219
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
8728d20
d98a71f
99c4e0c
9423978
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -46,6 +46,11 @@ | |
| 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 @@ - (void)deleteApp:(FIRAppVoidBoolCallback)completion { | |
| 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 @@ - (FIROptions *)options { | |
| 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]; | ||
| } else { | ||
|
||
| return YES; | ||
| } | ||
| } | ||
|
|
||
| #pragma mark - private | ||
|
|
||
| + (void)sendNotificationsToSDKs:(FIRApp *)app { | ||
|
|
@@ -613,11 +643,61 @@ - (NSString *)expectedBundleID { | |
| } | ||
|
|
||
| // end App ID validation | ||
| #pragma mark | ||
|
|
||
| #pragma mark - Reading From Plist & User Defaults | ||
|
|
||
| /** | ||
| * A wrapper to clear 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]; | ||
| } | ||
|
|
||
| /** | ||
| * A wrapper to read 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; | ||
| } else { | ||
|
||
| return nil; | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * A wrapper to read 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, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -113,6 +113,14 @@ NS_SWIFT_NAME(FirebaseApp) | |
| */ | ||
| @property(nonatomic, copy, readonly) FIROptions *options; | ||
|
|
||
| /** | ||
| * 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 | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
self.name can be nil. We should check it before accessing the dictionary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We throw an exception if a user tries to configure the app with a
nilor empty name, which should catch this. If you're still concerned, we can add it in a separate PR since it's unrelated to this change.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok. I think we should be careful of accessing dictionary when the provided key is nil. I'm concerned that self.name might be nil at some point during the entire app life cycle.