Skip to content
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

Fix IAM redisplay cache userdefaults crashes #894

Merged
merged 4 commits into from
Mar 5, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -61,7 +61,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 @@ -521,8 +520,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 @@ -923,8 +920,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 @@ -1948,7 +1943,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