Skip to content

Commit fef7940

Browse files
Prevent stale configuration data after iOS device restore
1 parent f73ee14 commit fef7940

File tree

7 files changed

+36
-9
lines changed

7 files changed

+36
-9
lines changed

FirebaseRemoteConfig/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
# Unreleased
2+
- [fixed] Fixed a bug where Remote Config does not work after a restore
3+
of a previous backup of the device. (#14459)
4+
- [fixed] Fixed a data race condition on the global database status flag
5+
by synchronizing all read and write operations. (#14715)
6+
17
# 12.3.0
28
- [fixed] Add missing GoogleUtilities dependency to fix SwiftPM builds when
39
building dynamically linked libraries. (#15276)

FirebaseRemoteConfig/Sources/FIRRemoteConfig.m

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,10 @@ - (instancetype)initWithAppName:(NSString *)appName
160160

161161
// Initialize RCConfigContent if not already.
162162
_configContent = configContent;
163+
164+
// We must ensure the DBManager's asynchronous setup (which sets gIsNewDatabase)
165+
// completes before RCNConfigSettings tries to read that state for the resetUserDefaults logic.
166+
[_DBManager waitForDatabaseOperationQueue];
163167
_settings = [[RCNConfigSettings alloc] initWithDatabaseManager:_DBManager
164168
namespace:_FIRNamespace
165169
firebaseAppName:appName

FirebaseRemoteConfig/Sources/RCNConfigDBManager.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,4 +130,8 @@ typedef void (^RCNDBLoadCompletion)(BOOL success,
130130

131131
/// Returns true if this a new install of the Config database.
132132
- (BOOL)isNewDatabase;
133+
134+
/// Blocks the calling thread until all pending database operations on the internal serial queue are
135+
/// completed. Used to enforce initialization order.
136+
- (void)waitForDatabaseOperationQueue;
133137
@end

FirebaseRemoteConfig/Sources/RCNConfigDBManager.m

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@
3838
/// The storage sub-directory that the Remote Config database resides in.
3939
static NSString *const RCNRemoteConfigStorageSubDirectory = @"Google/RemoteConfig";
4040

41+
/// Introduce a dedicated serial queue for gIsNewDatabase access.
42+
static dispatch_queue_t gIsNewDatabaseQueue;
43+
4144
/// Remote Config database path for deprecated V0 version.
4245
static NSString *RemoteConfigPathForOldDatabaseV0(void) {
4346
NSArray *dirPaths =
@@ -80,11 +83,11 @@ static BOOL RemoteConfigCreateFilePathIfNotExist(NSString *filePath) {
8083
@"Failed to create subdirectory for an empty file path.");
8184
return NO;
8285
}
83-
FIRLogDebug(kFIRLoggerRemoteConfig, @"RC-SDK-DEBUG", @"DBManager: DB file does not exists BEFORE create: 0");
8486
NSFileManager *fileManager = [NSFileManager defaultManager];
8587
if (![fileManager fileExistsAtPath:filePath]) {
86-
FIRLogDebug(kFIRLoggerRemoteConfig, @"RC-SDK-DEBUG", @"DBManager: Setting gIsNewDatabase = YES");
87-
gIsNewDatabase = YES;
88+
dispatch_sync(gIsNewDatabaseQueue, ^{
89+
gIsNewDatabase = YES;
90+
});
8891
NSError *error;
8992
[fileManager createDirectoryAtPath:[filePath stringByDeletingLastPathComponent]
9093
withIntermediateDirectories:YES
@@ -121,6 +124,8 @@ + (instancetype)sharedInstance {
121124
static dispatch_once_t onceToken;
122125
static RCNConfigDBManager *sharedInstance;
123126
dispatch_once(&onceToken, ^{
127+
gIsNewDatabaseQueue = dispatch_queue_create("com.google.FirebaseRemoteConfig.gIsNewDatabase",
128+
DISPATCH_QUEUE_SERIAL);
124129
sharedInstance = [[RCNConfigDBManager alloc] init];
125130
});
126131
return sharedInstance;
@@ -1221,7 +1226,20 @@ - (BOOL)logErrorWithSQL:(const char *)SQL
12211226
}
12221227

12231228
- (BOOL)isNewDatabase {
1224-
return gIsNewDatabase;
1229+
__block BOOL isNew;
1230+
dispatch_sync(gIsNewDatabaseQueue, ^{
1231+
isNew = gIsNewDatabase;
1232+
});
1233+
return isNew;
1234+
}
1235+
1236+
- (void)waitForDatabaseOperationQueue {
1237+
// This dispatch_sync call ensures that all blocks queued before it on _databaseOperationQueue
1238+
// (including the createOrOpenDatabase setup block) execute and complete before this method
1239+
// returns.
1240+
dispatch_sync(_databaseOperationQueue, ^{
1241+
// Empty block forces synchronization.
1242+
});
12251243
}
12261244

12271245
@end

FirebaseRemoteConfig/Sources/RCNConfigRealtime.m

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -723,7 +723,6 @@ - (void)pauseRealtimeStream {
723723

724724
- (FIRConfigUpdateListenerRegistration *)addConfigUpdateListener:
725725
(void (^_Nonnull)(FIRRemoteConfigUpdate *configUpdate, NSError *_Nullable error))listener {
726-
FIRLogDebug(kFIRLoggerRemoteConfig, @"RC-SDK-DEBUG", @"Realtime: Check1 local SDK is working");
727726
if (listener == nil) {
728727
return nil;
729728
}

FirebaseRemoteConfig/Sources/RCNConfigSettings.m

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,6 @@ - (instancetype)initWithDatabaseManager:(RCNConfigDBManager *)manager
7272
googleAppID:(NSString *)googleAppID {
7373
self = [super init];
7474
if (self) {
75-
FIRLogDebug(kFIRLoggerRemoteConfig, @"RC-SDK-DEBUG", @"Config Settings: Init for namespace");
7675
_FIRNamespace = FIRNamespace;
7776
_googleAppID = googleAppID;
7877
_bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];
@@ -93,12 +92,10 @@ - (instancetype)initWithDatabaseManager:(RCNConfigDBManager *)manager
9392

9493
// Check if the config database is new. If so, clear the configs saved in userDefaults.
9594
if ([_DBManager isNewDatabase]) {
96-
FIRLogDebug(kFIRLoggerRemoteConfig, @"RC-SDK-DEBUG", @"isNewDatabase returned: 1");
9795
FIRLogNotice(kFIRLoggerRemoteConfig, @"I-RCN000072",
9896
@"New config database created. Resetting user defaults.");
9997
[_userDefaultsManager resetUserDefaults];
10098
}
101-
10299
_isFetchInProgress = NO;
103100
_lastFetchedTemplateVersion = [_userDefaultsManager lastFetchedTemplateVersion];
104101
_lastActiveTemplateVersion = [_userDefaultsManager lastActiveTemplateVersion];

FirebaseRemoteConfig/Sources/RCNUserDefaultsManager.m

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,6 @@ - (void)setInstanceUserDefaultsValue:(NSObject *)value forKey:(NSString *)key {
316316
// Delete any existing userdefaults for this instance.
317317
- (void)resetInstanceUserDefaults {
318318
@synchronized(_userDefaults) {
319-
FIRLogDebug(kFIRLoggerRemoteConfig, @"RC-SDK-DEBUG", @"Defaults Manager: Reset is happening");
320319
NSMutableDictionary *appUserDefaults = [[self appUserDefaults] mutableCopy];
321320
NSMutableDictionary *appNamespaceUserDefaults = [[self instanceUserDefaults] mutableCopy];
322321
[appNamespaceUserDefaults removeAllObjects];

0 commit comments

Comments
 (0)