Skip to content

Commit

Permalink
Merge pull request #894 from OneSignal/fix/iam-userdefaults-crashes
Browse files Browse the repository at this point in the history
Fix IAM redisplay cache userdefaults crashes
  • Loading branch information
emawby committed Mar 5, 2021
2 parents 037fc8c + a51401d commit a9cf615
Show file tree
Hide file tree
Showing 15 changed files with 110 additions and 195 deletions.
6 changes: 0 additions & 6 deletions iOS_SDK/OneSignalSDK/OneSignal.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@
3E66F5821D90A2C600E45A01 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3E08E2701D49A5C8002176DE /* SystemConfiguration.framework */; };
4529DED21FA81EA800CEAB1D /* NSObjectOverrider.m in Sources */ = {isa = PBXBuildFile; fileRef = 4529DED11FA81EA800CEAB1D /* NSObjectOverrider.m */; };
4529DED51FA823B900CEAB1D /* TestHelperFunctions.m in Sources */ = {isa = PBXBuildFile; fileRef = 4529DED41FA823B900CEAB1D /* TestHelperFunctions.m */; };
4529DED81FA8253D00CEAB1D /* NSUserDefaultsOverrider.m in Sources */ = {isa = PBXBuildFile; fileRef = 4529DED71FA8253D00CEAB1D /* NSUserDefaultsOverrider.m */; };
4529DEDB1FA8284E00CEAB1D /* NSDataOverrider.m in Sources */ = {isa = PBXBuildFile; fileRef = 4529DEDA1FA8284E00CEAB1D /* NSDataOverrider.m */; };
4529DEDE1FA828E500CEAB1D /* NSDateOverrider.m in Sources */ = {isa = PBXBuildFile; fileRef = 4529DEDD1FA828E500CEAB1D /* NSDateOverrider.m */; };
4529DEE11FA82AB300CEAB1D /* NSBundleOverrider.m in Sources */ = {isa = PBXBuildFile; fileRef = 4529DEE01FA82AB300CEAB1D /* NSBundleOverrider.m */; };
Expand Down Expand Up @@ -524,8 +523,6 @@
4529DED11FA81EA800CEAB1D /* NSObjectOverrider.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NSObjectOverrider.m; sourceTree = "<group>"; };
4529DED31FA823B900CEAB1D /* TestHelperFunctions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TestHelperFunctions.h; sourceTree = "<group>"; };
4529DED41FA823B900CEAB1D /* TestHelperFunctions.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TestHelperFunctions.m; sourceTree = "<group>"; };
4529DED61FA8253D00CEAB1D /* NSUserDefaultsOverrider.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NSUserDefaultsOverrider.h; sourceTree = "<group>"; };
4529DED71FA8253D00CEAB1D /* NSUserDefaultsOverrider.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NSUserDefaultsOverrider.m; sourceTree = "<group>"; };
4529DED91FA8284E00CEAB1D /* NSDataOverrider.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NSDataOverrider.h; sourceTree = "<group>"; };
4529DEDA1FA8284E00CEAB1D /* NSDataOverrider.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NSDataOverrider.m; sourceTree = "<group>"; };
4529DEDC1FA828E500CEAB1D /* NSDateOverrider.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NSDateOverrider.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -926,8 +923,6 @@
4529DED11FA81EA800CEAB1D /* NSObjectOverrider.m */,
4529DEE21FA82C6200CEAB1D /* NSURLSessionOverrider.h */,
4529DEE31FA82C6200CEAB1D /* NSURLSessionOverrider.m */,
4529DED61FA8253D00CEAB1D /* NSUserDefaultsOverrider.h */,
4529DED71FA8253D00CEAB1D /* NSUserDefaultsOverrider.m */,
4529DEEB1FA83C5D00CEAB1D /* OneSignalHelperOverrider.h */,
4529DEEC1FA83C5D00CEAB1D /* OneSignalHelperOverrider.m */,
CA08FC821FE99BB4004C445F /* OneSignalClientOverrider.h */,
Expand Down Expand Up @@ -1953,7 +1948,6 @@
CA63AF8720211FF800E340FB /* UnitTestCommonMethods.m in Sources */,
CA70E3372023D51300019273 /* OneSignalSetEmailParameters.m in Sources */,
7A5A8185248990CD002E07C8 /* OSIndirectNotification.m in Sources */,
4529DED81FA8253D00CEAB1D /* NSUserDefaultsOverrider.m in Sources */,
4529DEED1FA83C5D00CEAB1D /* OneSignalHelperOverrider.m in Sources */,
7AF98666244975AD00C36EAE /* OSOutcomeSourceBody.m in Sources */,
CA1A6E6C20DC2E31001C41B9 /* OneSignalDialogController.m in Sources */,
Expand Down
2 changes: 1 addition & 1 deletion iOS_SDK/OneSignalSDK/Source/OSMessagingController.m
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ - (void)deleteOldRedisplayedInAppMessages {
[newRedisplayDictionary removeObjectForKey:messageId];
}

[OneSignalUserDefaults.initStandard saveDictionaryForKey:OS_IAM_REDISPLAY_DICTIONARY withValue:newRedisplayDictionary];
[OneSignalUserDefaults.initStandard saveCodeableDataForKey:OS_IAM_REDISPLAY_DICTIONARY withValue:newRedisplayDictionary];
}
}

Expand Down
32 changes: 32 additions & 0 deletions iOS_SDK/OneSignalSDK/Source/OSMigrationController.m
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ of this software and associated documentation files (the "Software"), to deal
#import "OneSignal.h"
#import "OneSignalUserDefaults.h"
#import "OneSignalCommonDefines.h"
#import "OSInAppMessagingDefines.h"
#import "OneSignalHelper.h"

@interface OneSignal ()
Expand All @@ -45,6 +46,7 @@ @implementation OSMigrationController

- (void)migrate {
[self migrateToVersion_02_14_00_AndGreater];
[self migrateIAMRedisplayCache];
[self saveCurrentSDKVersion];
}

Expand Down Expand Up @@ -78,6 +80,36 @@ - (void)migrateToVersion_02_14_00_AndGreater {
}
}

// Devices could potentially have bad data in the OS_IAM_REDISPLAY_DICTIONARY
// that was saved as a dictionary and not CodeableData. Try to detect if that is the case
// and save it is as CodeableData instead.
- (void)migrateIAMRedisplayCache {
let iamRedisplayCacheFixVersion = 30203;
long sdkVersion = [OneSignalUserDefaults.initShared getSavedIntegerForKey:OSUD_CACHED_SDK_VERSION defaultValue:0];
if (sdkVersion >= iamRedisplayCacheFixVersion)
return;

@try {
__unused NSMutableDictionary *redisplayDict =[[NSMutableDictionary alloc] initWithDictionary:[OneSignalUserDefaults.initStandard
getSavedCodeableDataForKey:OS_IAM_REDISPLAY_DICTIONARY
defaultValue:[NSMutableDictionary new]]];
} @catch (NSException *exception) {
@try {
// The redisplay IAMs might have been saved as a dictionary.
// Try to read them as a dictionary and then save them as a codeable.
NSMutableDictionary *redisplayDict = [[NSMutableDictionary alloc] initWithDictionary:[OneSignalUserDefaults.initStandard
getSavedDictionaryForKey:OS_IAM_REDISPLAY_DICTIONARY
defaultValue:[NSMutableDictionary new]]];
[OneSignalUserDefaults.initStandard saveCodeableDataForKey:OS_IAM_REDISPLAY_DICTIONARY
withValue:redisplayDict];
} @catch (NSException *exception) {
//Clear the cached redisplay dictionary of bad data
[OneSignalUserDefaults.initStandard saveCodeableDataForKey:OS_IAM_REDISPLAY_DICTIONARY
withValue:nil];
}
}
}

- (void)saveCurrentSDKVersion {
let currentVersion = [[OneSignal sdkVersionRaw] intValue];
[OneSignalUserDefaults.initShared saveIntegerForKey:OSUD_CACHED_SDK_VERSION withValue:currentVersion];
Expand Down
3 changes: 1 addition & 2 deletions iOS_SDK/OneSignalSDK/UnitTests/BadgeTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ of this software and associated documentation files (the "Software"), to deal
#import <XCTest/XCTest.h>
#import "UnitTestCommonMethods.h"
#import "OneSignalExtensionBadgeHandler.h"
#import "NSUserDefaultsOverrider.h"
#import "UNUserNotificationCenterOverrider.h"
#import "UNUserNotificationCenter+OneSignal.h"
#import "OneSignalHelperOverrider.h"
Expand All @@ -52,7 +51,7 @@ - (void)setUp {

UNUserNotificationCenterOverrider.authorizationStatus = [NSNumber numberWithInteger:UNAuthorizationStatusAuthorized];

[NSUserDefaultsOverrider clearInternalDictionary];
[UnitTestCommonMethods clearUserDefaults];
}

/*
Expand Down
1 change: 0 additions & 1 deletion iOS_SDK/OneSignalSDK/UnitTests/EmailTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ of this software and associated documentation files (the "Software"), to deal
#import "UNUserNotificationCenterOverrider.h"
#import "UNUserNotificationCenter+OneSignal.h"
#import "NSBundleOverrider.h"
#import "NSUserDefaultsOverrider.h"
#import "OneSignalCommonDefines.h"
#import "OneSignalTracker.h"
#import "OneSignalInternal.h"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ of this software and associated documentation files (the "Software"), to deal
#import "UIApplicationOverrider.h"
#import "OneSignalHelperOverrider.h"
#import "UNUserNotificationCenterOverrider.h"
#import "NSUserDefaultsOverrider.h"
#import "NSBundleOverrider.h"
#import "UNUserNotificationCenter+OneSignal.h"
#import "Requests.h"
Expand Down Expand Up @@ -544,7 +543,7 @@ - (void)testIAMWithNoTriggersDisplayOnePerSession_Redisplay {

message.displayStats.lastDisplayTime = firstInterval - delay;
// Save IAM for redisplay
[OneSignalUserDefaults.initStandard saveDictionaryForKey:OS_IAM_REDISPLAY_DICTIONARY withValue:redisplayedInAppMessages];
[OneSignalUserDefaults.initStandard saveCodeableDataForKey:OS_IAM_REDISPLAY_DICTIONARY withValue:redisplayedInAppMessages];
// Set data for redisplay
[OSMessagingControllerOverrider setMessagesForRedisplay:redisplayedInAppMessages];
// Save IAM for dismiss
Expand Down Expand Up @@ -680,11 +679,11 @@ - (void)testIAMRemoveFromCache_Redisplay {
[redisplayedInAppMessages setObject:message2 forKey:message2.messageId];

[OSMessagingControllerOverrider setMessagesForRedisplay:redisplayedInAppMessages];
[standardUserDefaults saveDictionaryForKey:OS_IAM_REDISPLAY_DICTIONARY withValue:redisplayedInAppMessages];
[standardUserDefaults saveCodeableDataForKey:OS_IAM_REDISPLAY_DICTIONARY withValue:redisplayedInAppMessages];

[self initOneSignalWithInAppMessage:message];

let redisplayMessagesCache = [standardUserDefaults getSavedDictionaryForKey:OS_IAM_REDISPLAY_DICTIONARY defaultValue:nil];
NSMutableDictionary *redisplayMessagesCache = [standardUserDefaults getSavedCodeableDataForKey:OS_IAM_REDISPLAY_DICTIONARY defaultValue:nil];
XCTAssertTrue([redisplayMessagesCache objectForKey:message1.messageId]);
XCTAssertFalse([redisplayMessagesCache objectForKey:message2.messageId]);
}
Expand Down
55 changes: 55 additions & 0 deletions iOS_SDK/OneSignalSDK/UnitTests/MigrationTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@
#import "UnitTestCommonMethods.h"
#import "OneSignalUserDefaults.h"
#import "OneSignalCommonDefines.h"
#import "OSInAppMessagingDefines.h"
#import "OneSignalUserDefaults.h"
#import "OSInAppMessage.h"
#import "OSInAppMessagingHelpers.h"
#import "CommonAsserts.h"

@interface MigrationTests : XCTestCase
Expand Down Expand Up @@ -237,4 +241,55 @@ - (void)testCachedUniqueOutcomeToCachedUniqueOutcomeMigration {
XCTAssertEqual([[OneSignal sdkVersionRaw] intValue], sdkVersionAfterMigration);
}

- (void)testIAMCachedEmptyDictionaryToCachedCodeableMigration {
NSDictionary<NSString *, OSInAppMessage *>*emptyDict = [NSMutableDictionary new];
[OneSignalUserDefaults.initStandard saveDictionaryForKey:OS_IAM_REDISPLAY_DICTIONARY withValue:emptyDict];

[migrationController migrate];
}

- (void)testIAMCachedDictionaryToCachedCodeableMigration {
NSMutableDictionary <NSString *, OSInAppMessage *> *emptyDict = [NSMutableDictionary new];

[OneSignalUserDefaults.initStandard saveDictionaryForKey:OS_IAM_REDISPLAY_DICTIONARY withValue:emptyDict];

[migrationController migrate];

NSDictionary<NSString *, OSInAppMessage *>*retrievedDict = [OneSignalUserDefaults.initStandard
getSavedCodeableDataForKey:OS_IAM_REDISPLAY_DICTIONARY defaultValue:nil];
XCTAssertEqualObjects(emptyDict, retrievedDict);
}

- (void)testIAMCachedCodeableMigration {
let limit = 5;
let delay = 60;
let message = [OSInAppMessageTestHelper testMessageWithRedisplayLimit:limit delay:@(delay)];
message.isDisplayedInSession = true;
NSMutableDictionary <NSString *, OSInAppMessage *> *redisplayedInAppMessages = [NSMutableDictionary new];
[redisplayedInAppMessages setObject:message forKey:message.messageId];

[OneSignalUserDefaults.initStandard saveCodeableDataForKey:OS_IAM_REDISPLAY_DICTIONARY withValue:redisplayedInAppMessages];

[migrationController migrate];

NSDictionary<NSString *, OSInAppMessage *>*retrievedDict = [OneSignalUserDefaults.initStandard
getSavedCodeableDataForKey:OS_IAM_REDISPLAY_DICTIONARY defaultValue:nil];
XCTAssertEqualObjects(redisplayedInAppMessages, retrievedDict);
}

- (void)testIAMNilCacheToNilMigration {

[OneSignalUserDefaults.initStandard saveDictionaryForKey:OS_IAM_REDISPLAY_DICTIONARY withValue:nil];

[migrationController migrate];

NSDictionary<NSString *, OSInAppMessage *>*retrievedDict = [OneSignalUserDefaults.initStandard
getSavedCodeableDataForKey:OS_IAM_REDISPLAY_DICTIONARY defaultValue:nil];
XCTAssertNil(retrievedDict);
}





@end
1 change: 0 additions & 1 deletion iOS_SDK/OneSignalSDK/UnitTests/OutcomeIntegrationTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ of this software and associated documentation files (the "Software"), to deal
#import "UNUserNotificationCenterOverrider.h"
#import "RestClientAsserts.h"
#import "CommonAsserts.h"
#import "NSUserDefaultsOverrider.h"
#import "OneSignalClientOverrider.h"
#import "UIApplicationOverrider.h"
#import "OneSignalNotificationServiceExtensionHandler.h"
Expand Down
1 change: 0 additions & 1 deletion iOS_SDK/OneSignalSDK/UnitTests/OutcomeIntegrationV2Tests.m
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@
#import "UNUserNotificationCenterOverrider.h"
#import "RestClientAsserts.h"
#import "CommonAsserts.h"
#import "NSUserDefaultsOverrider.h"
#import "OneSignalClientOverrider.h"
#import "UIApplicationOverrider.h"
#import "OneSignalNotificationServiceExtensionHandler.h"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ of this software and associated documentation files (the "Software"), to deal
#import <XCTest/XCTest.h>
#import "UnitTestCommonMethods.h"
#import "OneSignalExtensionBadgeHandler.h"
#import "NSUserDefaultsOverrider.h"
#import "UNUserNotificationCenterOverrider.h"
#import "UNUserNotificationCenter+OneSignal.h"
#import "OneSignalHelperOverrider.h"
Expand Down
32 changes: 0 additions & 32 deletions iOS_SDK/OneSignalSDK/UnitTests/Shadows/NSUserDefaultsOverrider.h

This file was deleted.

Loading

0 comments on commit a9cf615

Please sign in to comment.