Skip to content

Commit

Permalink
Reset RC per-instance userdefaults if config database was not found. (#…
Browse files Browse the repository at this point in the history
…4896)

* Reset the RC per-instance user defaults if the config database was not found.

* Add unit test.

* Ignore the non-object arguments when stubbing the fetchWithExpirationDuration method.

* Update changelog.
  • Loading branch information
dmandar committed Feb 14, 2020
1 parent 884455c commit 90235b5
Show file tree
Hide file tree
Showing 8 changed files with 52 additions and 1 deletion.
2 changes: 2 additions & 0 deletions FirebaseRemoteConfig/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# v4.4.8
- [fixed] Fixed a bug (#4677, #4734) where Remote Config does not work after a restore of a previous backup of the device. (#4896).
# v4.4.7
- [fixed] Fixed a crash that could occur when attempting a remote config fetch before a valid Instance ID was available. (#4622)
- [fixed] Fixed an issue where config fetch would sometimes fail with a duplicate fetch error when no other fetches were in progress. (#3802)
Expand Down
3 changes: 3 additions & 0 deletions FirebaseRemoteConfig/Sources/RCNConfigDBManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,4 +115,7 @@ typedef void (^RCNDBLoadCompletion)(BOOL success,
/// Remove all the records from experiment table with given key.
/// @param key The key of experiment data belongs to, which are defined in RCNConfigDefines.h.
- (void)deleteExperimentTableForKey:(NSString *)key;

/// Returns true if this a new install of the Config database.
- (BOOL)isNewDatabase;
@end
7 changes: 7 additions & 0 deletions FirebaseRemoteConfig/Sources/RCNConfigDBManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#define RCNTableNameInternalMetadata "internal_metadata"
#define RCNTableNameExperiment "experiment"

static BOOL gIsNewDatabase;
/// SQLite file name in versions 0, 1 and 2.
static NSString *const RCNDatabaseName = @"RemoteConfig.sqlite3";
/// The application support sub-directory that the Remote Config database resides in.
Expand Down Expand Up @@ -77,6 +78,7 @@ static BOOL RemoteConfigCreateFilePathIfNotExist(NSString *filePath) {
}
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath:filePath]) {
gIsNewDatabase = YES;
NSError *error;
[fileManager createDirectoryAtPath:[filePath stringByDeletingLastPathComponent]
withIntermediateDirectories:YES
Expand Down Expand Up @@ -203,6 +205,7 @@ - (void)createOrOpenDatabase {
NSString *dbPath = [RCNConfigDBManager remoteConfigPathForDatabase];
FIRLogInfo(kFIRLoggerRemoteConfig, @"I-RCN000062", @"Loading database at path %@", dbPath);
const char *databasePath = dbPath.UTF8String;

// Create or open database path.
if (!RemoteConfigCreateFilePathIfNotExist(dbPath)) {
return;
Expand Down Expand Up @@ -1036,4 +1039,8 @@ - (BOOL)logErrorWithSQL:(const char *)SQL
return returnValue;
}

- (BOOL)isNewDatabase {
return gIsNewDatabase;
}

@end
8 changes: 8 additions & 0 deletions FirebaseRemoteConfig/Sources/RCNConfigSettings.m
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,14 @@ - (instancetype)initWithDatabaseManager:(RCNConfigDBManager *)manager
_userDefaultsManager = [[RCNUserDefaultsManager alloc] initWithAppName:appName
bundleID:_bundleIdentifier
namespace:_FIRNamespace];

// Check if the config database is new. If so, clear the configs saved in userDefaults.
if ([_DBManager isNewDatabase]) {
FIRLogNotice(kFIRLoggerRemoteConfig, @"I-RCN000072",
@"New config database created. Resetting user defaults.");
[_userDefaultsManager resetUserDefaults];
}

_isFetchInProgress = NO;
}
return self;
Expand Down
2 changes: 2 additions & 0 deletions FirebaseRemoteConfig/Sources/RCNUserDefaultsManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ NS_ASSUME_NONNULL_BEGIN
__attribute__((unavailable("Use `initWithAppName:bundleID:namespace:` instead.")));
// NOLINTEND

/// Delete all saved userdefaults for this instance.
- (void)resetUserDefaults;
@end

NS_ASSUME_NONNULL_END
18 changes: 18 additions & 0 deletions FirebaseRemoteConfig/Sources/RCNUserDefaultsManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,11 @@ - (void)setCurrentThrottlingRetryIntervalSeconds:(NSTimeInterval)throttlingRetry
forKey:kRCNUserDefaultsKeyNamecurrentThrottlingRetryInterval];
}

#pragma mark Public methods.
- (void)resetUserDefaults {
[self resetInstanceUserDefaults];
}

#pragma mark Private methods.

// There is a nested hierarchy for the userdefaults as follows:
Expand Down Expand Up @@ -212,4 +217,17 @@ - (void)setInstanceUserDefaultsValue:(NSObject *)value forKey:(NSString *)key {
}
}

// Delete any existing userdefaults for this instance.
- (void)resetInstanceUserDefaults {
@synchronized(_userDefaults) {
NSMutableDictionary *appUserDefaults = [[self appUserDefaults] mutableCopy];
NSMutableDictionary *appNamespaceUserDefaults = [[self instanceUserDefaults] mutableCopy];
[appNamespaceUserDefaults removeAllObjects];
[appUserDefaults setObject:appNamespaceUserDefaults forKey:_firebaseNamespace];
[_userDefaults setObject:appUserDefaults forKey:_firebaseAppName];
// We need to synchronize to have this value updated for the extension.
[_userDefaults synchronize];
}
}

@end
3 changes: 2 additions & 1 deletion FirebaseRemoteConfig/Tests/Unit/RCNRemoteConfigTest.m
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,8 @@ - (void)setUp {
namespace:fullyQualifiedNamespace
options:currentOptions]);

OCMStub([_configFetch[i] fetchConfigWithExpirationDuration:43200 completionHandler:OCMOCK_ANY])
OCMStub([_configFetch[i] fetchConfigWithExpirationDuration:0 completionHandler:OCMOCK_ANY])
.ignoringNonObjectArgs()
.andDo(^(NSInvocation *invocation) {
void (^handler)(FIRRemoteConfigFetchStatus status, NSError *_Nullable error) = nil;
[invocation getArgument:&handler atIndex:3];
Expand Down
10 changes: 10 additions & 0 deletions FirebaseRemoteConfig/Tests/Unit/RCNUserDefaultsManagerTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -170,4 +170,14 @@ - (void)testUserDefaultsForMultipleNamespaces {
RCNUserDefaultsSampleTimeStamp - 2.0);
}

- (void)testUserDefaultsReset {
RCNUserDefaultsManager* manager =
[[RCNUserDefaultsManager alloc] initWithAppName:@"TESTING"
bundleID:[NSBundle mainBundle].bundleIdentifier
namespace:@"testNamespace1"];
[manager setLastETag:@"testETag"];
[manager resetUserDefaults];
XCTAssertNil([manager lastETag]);
}

@end

0 comments on commit 90235b5

Please sign in to comment.