diff --git a/iOS_SDK/OneSignalSDK/OneSignal.xcodeproj/project.pbxproj b/iOS_SDK/OneSignalSDK/OneSignal.xcodeproj/project.pbxproj index edf9dae0c..fcc20d7c0 100644 --- a/iOS_SDK/OneSignalSDK/OneSignal.xcodeproj/project.pbxproj +++ b/iOS_SDK/OneSignalSDK/OneSignal.xcodeproj/project.pbxproj @@ -144,6 +144,11 @@ 7AECE59E23675F6300537907 /* OSFocusTimeProcessorFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AECE59D23675F6300537907 /* OSFocusTimeProcessorFactory.m */; }; 7AECE59F23675F6300537907 /* OSFocusTimeProcessorFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AECE59D23675F6300537907 /* OSFocusTimeProcessorFactory.m */; }; 7AECE5A023675F6300537907 /* OSFocusTimeProcessorFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AECE59D23675F6300537907 /* OSFocusTimeProcessorFactory.m */; }; + 7AF5174524FDC2AA00B076BC /* OSRemoteParamController.h in Headers */ = {isa = PBXBuildFile; fileRef = 7AF5174424FDC2A100B076BC /* OSRemoteParamController.h */; }; + 7AF5174724FDC2C500B076BC /* OSRemoteParamController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AF5174624FDC2C500B076BC /* OSRemoteParamController.m */; }; + 7AF5174824FDC2C500B076BC /* OSRemoteParamController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AF5174624FDC2C500B076BC /* OSRemoteParamController.m */; }; + 7AF5174924FDC2C500B076BC /* OSRemoteParamController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AF5174624FDC2C500B076BC /* OSRemoteParamController.m */; }; + 7AF5174C24FE980400B076BC /* RemoteParamsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AF5174B24FE980400B076BC /* RemoteParamsTests.m */; }; 7AF8FDBB2332A58900A19245 /* OSSessionManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 7A12EBD523060A6F005C4FA5 /* OSSessionManager.m */; }; 7AF8FDBD2332A5C200A19245 /* OSIndirectInfluence.m in Sources */ = {isa = PBXBuildFile; fileRef = 7A12EBDC23060B37005C4FA5 /* OSIndirectInfluence.m */; }; 7AF986352444C41A00C36EAE /* OSChannelTracker.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AF986342444C41A00C36EAE /* OSChannelTracker.m */; }; @@ -385,9 +390,9 @@ CAB269E021B2038B00F8A43C /* OSInAppMessageBridgeEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = CAB269DE21B2038B00F8A43C /* OSInAppMessageBridgeEvent.m */; }; CAB269E121B2038B00F8A43C /* OSInAppMessageBridgeEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = CAB269DE21B2038B00F8A43C /* OSInAppMessageBridgeEvent.m */; }; CAB269E221B2038B00F8A43C /* OSInAppMessageBridgeEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = CAB269DE21B2038B00F8A43C /* OSInAppMessageBridgeEvent.m */; }; - CAB4112920852E48005A70D1 /* DelayedInitializationParameters.m in Sources */ = {isa = PBXBuildFile; fileRef = CAB4112820852E48005A70D1 /* DelayedInitializationParameters.m */; }; - CAB4112A20852E4C005A70D1 /* DelayedInitializationParameters.m in Sources */ = {isa = PBXBuildFile; fileRef = CAB4112820852E48005A70D1 /* DelayedInitializationParameters.m */; }; - CAB4112B20852E4C005A70D1 /* DelayedInitializationParameters.m in Sources */ = {isa = PBXBuildFile; fileRef = CAB4112820852E48005A70D1 /* DelayedInitializationParameters.m */; }; + CAB4112920852E48005A70D1 /* DelayedConsentInitializationParameters.m in Sources */ = {isa = PBXBuildFile; fileRef = CAB4112820852E48005A70D1 /* DelayedConsentInitializationParameters.m */; }; + CAB4112A20852E4C005A70D1 /* DelayedConsentInitializationParameters.m in Sources */ = {isa = PBXBuildFile; fileRef = CAB4112820852E48005A70D1 /* DelayedConsentInitializationParameters.m */; }; + CAB4112B20852E4C005A70D1 /* DelayedConsentInitializationParameters.m in Sources */ = {isa = PBXBuildFile; fileRef = CAB4112820852E48005A70D1 /* DelayedConsentInitializationParameters.m */; }; CAB411AE208931EE005A70D1 /* DummyNotificationCenterDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = CAB411AD208931EE005A70D1 /* DummyNotificationCenterDelegate.m */; }; CACBAA96218A6243000ACAA5 /* OSInAppMessageViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = CACBAA8D218A6242000ACAA5 /* OSInAppMessageViewController.h */; }; CACBAA97218A6243000ACAA5 /* OSMessagingController.m in Sources */ = {isa = PBXBuildFile; fileRef = CACBAA8E218A6242000ACAA5 /* OSMessagingController.m */; }; @@ -535,6 +540,9 @@ 7AECE59923674ADC00537907 /* OSUnattributedFocusTimeProcessor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OSUnattributedFocusTimeProcessor.h; sourceTree = ""; }; 7AECE59B23675F5700537907 /* OSFocusTimeProcessorFactory.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OSFocusTimeProcessorFactory.h; sourceTree = ""; }; 7AECE59D23675F6300537907 /* OSFocusTimeProcessorFactory.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OSFocusTimeProcessorFactory.m; sourceTree = ""; }; + 7AF5174424FDC2A100B076BC /* OSRemoteParamController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OSRemoteParamController.h; sourceTree = ""; }; + 7AF5174624FDC2C500B076BC /* OSRemoteParamController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OSRemoteParamController.m; sourceTree = ""; }; + 7AF5174B24FE980400B076BC /* RemoteParamsTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RemoteParamsTests.m; sourceTree = ""; }; 7AF986342444C41A00C36EAE /* OSChannelTracker.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OSChannelTracker.m; sourceTree = ""; }; 7AF986382444C42700C36EAE /* OSChannelTracker.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OSChannelTracker.h; sourceTree = ""; }; 7AF9863A2444C43900C36EAE /* OSInAppMessageTracker.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OSInAppMessageTracker.m; sourceTree = ""; }; @@ -674,8 +682,8 @@ CAB269D821B0B6F000F8A43C /* OSInAppMessageAction.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OSInAppMessageAction.m; sourceTree = ""; }; CAB269DD21B2038B00F8A43C /* OSInAppMessageBridgeEvent.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OSInAppMessageBridgeEvent.h; sourceTree = ""; }; CAB269DE21B2038B00F8A43C /* OSInAppMessageBridgeEvent.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OSInAppMessageBridgeEvent.m; sourceTree = ""; }; - CAB4112720852E48005A70D1 /* DelayedInitializationParameters.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DelayedInitializationParameters.h; sourceTree = ""; }; - CAB4112820852E48005A70D1 /* DelayedInitializationParameters.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DelayedInitializationParameters.m; sourceTree = ""; }; + CAB4112720852E48005A70D1 /* DelayedConsentInitializationParameters.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DelayedConsentInitializationParameters.h; sourceTree = ""; }; + CAB4112820852E48005A70D1 /* DelayedConsentInitializationParameters.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DelayedConsentInitializationParameters.m; sourceTree = ""; }; CAB411AC208931EE005A70D1 /* DummyNotificationCenterDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DummyNotificationCenterDelegate.h; sourceTree = ""; }; CAB411AD208931EE005A70D1 /* DummyNotificationCenterDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DummyNotificationCenterDelegate.m; sourceTree = ""; }; CACBAA8D218A6242000ACAA5 /* OSInAppMessageViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OSInAppMessageViewController.h; sourceTree = ""; }; @@ -914,6 +922,15 @@ name = OutcomeEvents; sourceTree = ""; }; + 7AF5174A24FDC2D000B076BC /* RemoteParams */ = { + isa = PBXGroup; + children = ( + 7AF5174424FDC2A100B076BC /* OSRemoteParamController.h */, + 7AF5174624FDC2C500B076BC /* OSRemoteParamController.m */, + ); + name = RemoteParams; + sourceTree = ""; + }; 7AF98632243F84AC00C36EAE /* Influence */ = { isa = PBXGroup; children = ( @@ -983,6 +1000,7 @@ 4529DECD1FA81DE000CEAB1D /* Shadows */, CA8E19012193C6B0009DA223 /* InAppMessagingIntegrationTests.m */, 911E2CBC1E398AB3003112A4 /* UnitTests.m */, + 7AF5174B24FE980400B076BC /* RemoteParamsTests.m */, CACBAAA9218A65AE000ACAA5 /* InAppMessagingTests.m */, CA85C15220604AEA003AB529 /* RequestTests.m */, CAA4ED0020646762005BD59B /* BadgeTests.m */, @@ -1017,6 +1035,7 @@ 912411EE1E73342200E41FD7 /* Source */ = { isa = PBXGroup; children = ( + 7AF5174A24FDC2D000B076BC /* RemoteParams */, 7AAA606B2485D0D70004FADE /* Migration */, 7AF98632243F84AC00C36EAE /* Influence */, 7A674F172360D7DB001F9ACD /* OnFocus */, @@ -1034,8 +1053,8 @@ 912411F11E73342200E41FD7 /* OneSignal.m */, DE16C14624D3727200670EFA /* OneSignalLifecycleObserver.h */, DE16C14324D3724700670EFA /* OneSignalLifecycleObserver.m */, - CAB4112720852E48005A70D1 /* DelayedInitializationParameters.h */, - CAB4112820852E48005A70D1 /* DelayedInitializationParameters.m */, + CAB4112720852E48005A70D1 /* DelayedConsentInitializationParameters.h */, + CAB4112820852E48005A70D1 /* DelayedConsentInitializationParameters.m */, CA70E3332023D51000019273 /* OneSignalSetEmailParameters.h */, CA70E3342023D51000019273 /* OneSignalSetEmailParameters.m */, 9D1BD96B237B57B400A064F7 /* OneSignalCacheCleaner.h */, @@ -1263,6 +1282,7 @@ 7AF98690244A566F00C36EAE /* OSOutcomeEventsCache.h in Headers */, 9DDFEEF223189C0800EAE0BB /* OneSignalViewHelper.h in Headers */, 9124124B1E7337A800E41FD7 /* OneSignal.h in Headers */, + 7AF5174524FDC2AA00B076BC /* OSRemoteParamController.h in Headers */, CA08FC781FE99B13004C445F /* OneSignalRequest.h in Headers */, CACBAAA8218A6280000ACAA5 /* OSJSONHandling.h in Headers */, 912412211E73342200E41FD7 /* OneSignalLocation.h in Headers */, @@ -1517,13 +1537,13 @@ CACBAA97218A6243000ACAA5 /* OSMessagingController.m in Sources */, CA36F35921C33A2500300C77 /* OSInAppMessageController.m in Sources */, CA08FC731FE99AFD004C445F /* OneSignalClient.m in Sources */, - 7AF76E91234252210085F926 /* OSSessionResult.m in Sources */, 91F58D831E7C80DA0017D24D /* OneSignalNotificationSettingsIOS9.m in Sources */, CAAEA68721ED68A40049CF15 /* OneSignalNotificationCategoryController.m in Sources */, 7AF98686244A32EF00C36EAE /* OSOutcomeEventsV2Repository.m in Sources */, 7AF9866A244975CF00C36EAE /* OSOutcomeSource.m in Sources */, 7A1F2D8F2406EFC5007799A9 /* OSInAppMessageTag.m in Sources */, 9D1BD9602379E7C300A064F7 /* OSOutcomeEvent.m in Sources */, + 7AF5174724FDC2C500B076BC /* OSRemoteParamController.m in Sources */, 7AF9865124451F2800C36EAE /* OSInAppMessageTracker.m in Sources */, 7A600B442453790700514A53 /* OSFocusInfluenceParam.m in Sources */, 7AF986352444C41A00C36EAE /* OSChannelTracker.m in Sources */, @@ -1555,7 +1575,7 @@ 7AF9865824452A9600C36EAE /* OSInfluence.m in Sources */, 7AF98692244A567B00C36EAE /* OSOutcomeEventsCache.m in Sources */, 912412261E73342200E41FD7 /* OneSignalMobileProvision.m in Sources */, - CAB4112920852E48005A70D1 /* DelayedInitializationParameters.m in Sources */, + CAB4112920852E48005A70D1 /* DelayedConsentInitializationParameters.m in Sources */, 454F94F21FAD218000D74CCF /* OneSignalNotificationServiceExtensionHandler.m in Sources */, 7AF9867A24497A4D00C36EAE /* OSOutcomeEventsRepository.m in Sources */, CA1A6E7020DC2E73001C41B9 /* OneSignalDialogRequest.m in Sources */, @@ -1613,6 +1633,7 @@ 7AF9866B244975CF00C36EAE /* OSOutcomeSource.m in Sources */, 7AA2848A2406FC6400C25D76 /* OSInAppMessageTag.m in Sources */, CA08FC7A1FE99B13004C445F /* OneSignalRequest.m in Sources */, + 7AF5174824FDC2C500B076BC /* OSRemoteParamController.m in Sources */, 7AF986362444C41A00C36EAE /* OSChannelTracker.m in Sources */, 7A600B452453790700514A53 /* OSFocusInfluenceParam.m in Sources */, 7A72EB0F23E252C700B4D50F /* OSInAppMessageDisplayStats.m in Sources */, @@ -1639,10 +1660,10 @@ 912412431E73342200E41FD7 /* UNUserNotificationCenter+OneSignal.m in Sources */, CA47439F2190FEA80020DC8C /* OSTrigger.m in Sources */, 9124123B1E73342200E41FD7 /* OneSignalWebView.m in Sources */, - CAB4112A20852E4C005A70D1 /* DelayedInitializationParameters.m in Sources */, 7A1232A6235E17A1002B6CE3 /* OSIndirectInfluence.m in Sources */, 7AF9865924452A9600C36EAE /* OSInfluence.m in Sources */, 7AF98693244A567B00C36EAE /* OSOutcomeEventsCache.m in Sources */, + CAB4112A20852E4C005A70D1 /* DelayedConsentInitializationParameters.m in Sources */, 9124123F1E73342200E41FD7 /* UIApplicationDelegate+OneSignal.m in Sources */, 7AECE59F23675F6300537907 /* OSFocusTimeProcessorFactory.m in Sources */, CA1A6E7120DC2E73001C41B9 /* OneSignalDialogRequest.m in Sources */, @@ -1746,7 +1767,7 @@ 5B58E4F8237CE7B4009401E0 /* UIDeviceOverrider.m in Sources */, CA8E19022193C6B0009DA223 /* InAppMessagingIntegrationTests.m in Sources */, 7AA2848B2406FC6500C25D76 /* OSInAppMessageTag.m in Sources */, - CAB4112B20852E4C005A70D1 /* DelayedInitializationParameters.m in Sources */, + CAB4112B20852E4C005A70D1 /* DelayedConsentInitializationParameters.m in Sources */, 7AECE59223674A9700537907 /* OSAttributedFocusTimeProcessor.m in Sources */, 912412341E73342200E41FD7 /* OneSignalTracker.m in Sources */, 7AF98694244A567B00C36EAE /* OSOutcomeEventsCache.m in Sources */, @@ -1772,10 +1793,12 @@ 4529DEDE1FA828E500CEAB1D /* NSDateOverrider.m in Sources */, CA08FC871FE99BB4004C445F /* OneSignalClientOverrider.m in Sources */, CACBAAA3218A6243000ACAA5 /* OSInAppMessage.m in Sources */, + 7AF5174C24FE980400B076BC /* RemoteParamsTests.m in Sources */, CACBAAA6218A6243000ACAA5 /* OSInAppMessageViewController.m in Sources */, 912412401E73342200E41FD7 /* UIApplicationDelegate+OneSignal.m in Sources */, 1AF75EAF1E8569710097B315 /* NSString+OneSignal.m in Sources */, CACBAAAA218A65AE000ACAA5 /* InAppMessagingTests.m in Sources */, + 7AF5174924FDC2C500B076BC /* OSRemoteParamController.m in Sources */, 4529DEE71FA82CDC00CEAB1D /* UNUserNotificationCenterOverrider.m in Sources */, 4529DEDB1FA8284E00CEAB1D /* NSDataOverrider.m in Sources */, 7AD1723A2416D53B00A78B19 /* OSInAppMessageLocationPrompt.m in Sources */, diff --git a/iOS_SDK/OneSignalSDK/Source/DelayedConsentInitializationParameters.h b/iOS_SDK/OneSignalSDK/Source/DelayedConsentInitializationParameters.h new file mode 100644 index 000000000..98f2e97e9 --- /dev/null +++ b/iOS_SDK/OneSignalSDK/Source/DelayedConsentInitializationParameters.h @@ -0,0 +1,38 @@ +/** + * Modified MIT License + * + * Copyright 2017 OneSignal + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * 1. The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * 2. All copies of substantial portions of the Software may only be used in connection + * with services provided by OneSignal. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#import +#import "OneSignal.h" + +@interface DelayedConsentInitializationParameters : NSObject + +@property (strong, nonatomic, nullable) NSDictionary *launchOptions; +@property (strong, nonatomic, nonnull) NSString *appId; + +- (nonnull instancetype)initWithLaunchOptions:(nullable NSDictionary *)launchOptions withAppId:(nonnull NSString *)appId; + +@end diff --git a/iOS_SDK/OneSignalSDK/Source/DelayedConsentInitializationParameters.m b/iOS_SDK/OneSignalSDK/Source/DelayedConsentInitializationParameters.m new file mode 100644 index 000000000..32e485047 --- /dev/null +++ b/iOS_SDK/OneSignalSDK/Source/DelayedConsentInitializationParameters.m @@ -0,0 +1,38 @@ +/** + * Modified MIT License + * + * Copyright 2017 OneSignal + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * 1. The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * 2. All copies of substantial portions of the Software may only be used in connection + * with services provided by OneSignal. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#import "DelayedConsentInitializationParameters.h" + +@implementation DelayedConsentInitializationParameters + +- (instancetype)initWithLaunchOptions:(NSDictionary *)launchOptions withAppId:(NSString *)appId { + self.launchOptions = launchOptions; + self.appId = appId; + return self; +} + +@end diff --git a/iOS_SDK/OneSignalSDK/Source/DelayedInitializationParameters.h b/iOS_SDK/OneSignalSDK/Source/DelayedInitializationParameters.h deleted file mode 100644 index 3ab62c07d..000000000 --- a/iOS_SDK/OneSignalSDK/Source/DelayedInitializationParameters.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - Modified MIT License - - Copyright 2017 OneSignal - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - 1. The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - 2. All copies of substantial portions of the Software may only be used in connection - with services provided by OneSignal. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - */ - -#import -#import "OneSignal.h" - -@interface DelayedInitializationParameters : NSObject - -@property (strong, nonatomic, nullable) NSDictionary *launchOptions; -@property (strong, nonatomic, nonnull) NSString *appId; - -- (nonnull instancetype)initWithLaunchOptions:(nullable NSDictionary *)launchOptions withAppId:(nonnull NSString *)appId; - -@end diff --git a/iOS_SDK/OneSignalSDK/Source/OSRemoteParamController.h b/iOS_SDK/OneSignalSDK/Source/OSRemoteParamController.h new file mode 100644 index 000000000..d885509ea --- /dev/null +++ b/iOS_SDK/OneSignalSDK/Source/OSRemoteParamController.h @@ -0,0 +1,46 @@ +/** +Modified MIT License + +Copyright 2020 OneSignal + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +1. The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +2. All copies of substantial portions of the Software may only be used in connection +with services provided by OneSignal. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#ifndef OSRemoteParamController_h +#define OSRemoteParamController_h + +@interface OSRemoteParamController : NSObject + +@property (strong, nonatomic, readonly, nonnull) NSDictionary *remoteParams; + +- (void)saveRemoteParams:(NSDictionary *)params; +- (BOOL)hasLocationKey; +- (BOOL)hasPrivacyConsentKey; + +- (BOOL)isLocationShared; +- (void)saveLocationShared:(BOOL)shared; +- (BOOL)isPrivacyConsentRequired; +- (void)savePrivacyConsentRequired:(BOOL)shared; + +@end + +#endif /* OSRemoteParamController_h */ diff --git a/iOS_SDK/OneSignalSDK/Source/OSRemoteParamController.m b/iOS_SDK/OneSignalSDK/Source/OSRemoteParamController.m new file mode 100644 index 000000000..672132fb1 --- /dev/null +++ b/iOS_SDK/OneSignalSDK/Source/OSRemoteParamController.m @@ -0,0 +1,82 @@ +/** +Modified MIT License + +Copyright 2020 OneSignal + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +1. The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +2. All copies of substantial portions of the Software may only be used in connection +with services provided by OneSignal. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#import +#import "OSRemoteParamController.h" +#import "OneSignalCommonDefines.h" +#import "OneSignalUserDefaults.h" +#import "OneSignalHelper.h" +#import "OneSignal.h" + +@interface OneSignal () + ++ (void)startLocationSharedWithFlag:(BOOL)enable; + +@end + +@implementation OSRemoteParamController + +- (void)saveRemoteParams:(NSDictionary *)params { + _remoteParams = params; + + if ([self hasLocationKey]) { + let shared = [params[IOS_LOCATION_SHARED] boolValue]; + [OneSignal startLocationSharedWithFlag:shared]; + } + + if ([self hasPrivacyConsentKey]) { + let required = [params[IOS_REQUIRES_USER_PRIVACY_CONSENT] boolValue]; + [self savePrivacyConsentRequired:required]; + [OneSignal setRequiresUserPrivacyConsent:required]; + } +} + +- (BOOL)hasLocationKey { + return _remoteParams && _remoteParams[IOS_LOCATION_SHARED]; +} + +- (BOOL)hasPrivacyConsentKey { + return _remoteParams && _remoteParams[IOS_REQUIRES_USER_PRIVACY_CONSENT]; +} + +- (BOOL)isLocationShared { + return [OneSignalUserDefaults.initShared getSavedBoolForKey:OSUD_LOCATION_ENABLED defaultValue:YES]; +} + +- (void)saveLocationShared:(BOOL)shared { + [OneSignalUserDefaults.initShared saveBoolForKey:OSUD_LOCATION_ENABLED withValue:shared]; +} + +- (BOOL)isPrivacyConsentRequired { + return [OneSignalUserDefaults.initShared getSavedBoolForKey:OSUD_REQUIRES_USER_PRIVACY_CONSENT defaultValue:NO]; +} + +- (void)savePrivacyConsentRequired:(BOOL)required { + [OneSignalUserDefaults.initShared saveBoolForKey:OSUD_REQUIRES_USER_PRIVACY_CONSENT withValue:required]; +} + +@end diff --git a/iOS_SDK/OneSignalSDK/Source/OneSignal.m b/iOS_SDK/OneSignalSDK/Source/OneSignal.m index b2d712492..ee99d5f0f 100755 --- a/iOS_SDK/OneSignalSDK/Source/OneSignal.m +++ b/iOS_SDK/OneSignalSDK/Source/OneSignal.m @@ -47,6 +47,7 @@ #import "OneSignalUserDefaults.h" #import "OneSignalCacheCleaner.h" #import "OSMigrationController.h" +#import "OSRemoteParamController.h" #import "OneSignalNotificationSettings.h" #import "OneSignalNotificationSettingsIOS10.h" @@ -70,7 +71,7 @@ #import #import "OneSignalSetEmailParameters.h" -#import "DelayedInitializationParameters.h" +#import "DelayedConsentInitializationParameters.h" #import "OneSignalDialogController.h" #import "OSInfluenceDataDefines.h" @@ -159,7 +160,10 @@ @implementation OneSignal // If initialization is delayed, this object holds params such as the app ID so that the init() // method can be called the moment the user provides privacy consent. -DelayedInitializationParameters *delayedInitParameters; +DelayedConsentInitializationParameters *_delayedInitParameters; ++ (DelayedConsentInitializationParameters *)delayedInitParameters { + return _delayedInitParameters; +} static NSString* appId; static NSDictionary* launchOptions; @@ -180,11 +184,6 @@ @implementation OneSignal // Set when the app is launched static NSDate *sessionLaunchTime; -//the iOS Native SDK will use the plist flag to enable privacy consent -//however wrapper SDK's will use a method call before initialization -//this boolean flag is switched on to enable this behavior -static BOOL shouldRequireUserConsent = false; - static OneSignalTrackIAP* trackIAPPurchase; NSString* emailToSet; NSMutableDictionary* tagsToSend; @@ -193,7 +192,6 @@ @implementation OneSignal static int mSubscriptionStatus = -1; BOOL disableBadgeClearing = NO; -BOOL mShareLocation = YES; BOOL requestedProvisionalAuthorization = false; BOOL usesAutoPrompt = false; @@ -319,6 +317,13 @@ + (OSDevice *)getUserDevice { return _userDevice; } +static OSRemoteParamController* _remoteParamController; ++ (OSRemoteParamController *)getRemoteParamController { + if (!_remoteParamController) + _remoteParamController = [OSRemoteParamController new]; + return _remoteParamController; +} + /* Indicates if the iOS params request has started Set to true when the method is called and set false if the request's failure callback is triggered @@ -586,7 +591,7 @@ + (void)init { if ([self requiresUserPrivacyConsent]) { [self onesignal_Log:ONE_S_LL_VERBOSE message:@"Delayed initialization of the OneSignal SDK until the user provides privacy consent using the consentGranted() method"]; delayedInitializationForPrivacyConsent = true; - delayedInitParameters = [[DelayedInitializationParameters alloc] initWithLaunchOptions:launchOptions withAppId:appId]; + _delayedInitParameters = [[DelayedConsentInitializationParameters alloc] initWithLaunchOptions:launchOptions withAppId:appId]; // Init was not successful, set appId back to nil appId = nil; return; @@ -615,7 +620,7 @@ + (void)init { _outcomeEventFactory = [[OSOutcomeEventsFactory alloc] initWithCache:OneSignal.outcomeEventsCache]; _outcomeEventsController = [[OneSignalOutcomeEventsController alloc] initWithSessionManager:OneSignal.sessionManager outcomeEventsFactory:_outcomeEventFactory]; - if (appId && mShareLocation) + if (appId && [self isLocationShared]) [OneSignalLocation getLocation:false fallbackToSettings:false withCompletionHandler:nil]; /* @@ -656,13 +661,14 @@ + (BOOL)handleAppIdChange:(NSString*)appId { let standardUserDefaults = OneSignalUserDefaults.initStandard; let prevAppId = [standardUserDefaults getSavedStringForKey:OSUD_APP_ID defaultValue:nil]; - + // Handle changes to the app id, this might happen on a developer's device when testing // Will also run the first time OneSignal is initialized if (appId && ![appId isEqualToString:prevAppId]) { initDone = false; _downloadedParameters = false; _didCallDownloadParameters = false; + let sharedUserDefaults = OneSignalUserDefaults.initShared; [standardUserDefaults saveStringForKey:OSUD_APP_ID withValue:appId]; @@ -764,11 +770,23 @@ + (BOOL)shouldLogMissingPrivacyConsentErrorWithMethodName:(NSString *)methodName } + (void)setRequiresUserPrivacyConsent:(BOOL)required { - shouldRequireUserConsent = required; + let remoteParamController = [self getRemoteParamController]; + + // Already set by remote params + if ([remoteParamController hasPrivacyConsentKey]) + return; + + if ([self requiresUserPrivacyConsent] && !required) { + [OneSignal onesignal_Log:ONE_S_LL_ERROR message:@"Cannot change requiresUserPrivacyConsent() from TRUE to FALSE"]; + return; + } + + [remoteParamController savePrivacyConsentRequired:required]; } + (BOOL)requiresUserPrivacyConsent { - + let remoteParamController = [self getRemoteParamController]; + let shouldRequireUserConsent = [remoteParamController isPrivacyConsentRequired]; // if the plist key does not exist default to true // the plist value specifies whether GDPR privacy consent is required for this app // if required and consent has not been previously granted, return false @@ -782,15 +800,14 @@ + (BOOL)requiresUserPrivacyConsent { + (void)consentGranted:(BOOL)granted { [OneSignalUserDefaults.initStandard saveBoolForKey:GDPR_CONSENT_GRANTED withValue:granted]; - if (!granted || !delayedInitializationForPrivacyConsent || delayedInitParameters == nil) + if (!granted || !delayedInitializationForPrivacyConsent || _delayedInitParameters == nil) return; - // Try to init again using delayed params (order does not matter) - [self setAppId:delayedInitParameters.appId]; - [self setLaunchOptions:delayedInitParameters.launchOptions]; + [self setAppId:_delayedInitParameters.appId]; + [self setLaunchOptions:_delayedInitParameters.launchOptions]; delayedInitializationForPrivacyConsent = false; - delayedInitParameters = nil; + _delayedInitParameters = nil; } // the iOS SDK used to call these selectors as a convenience but has stopped due to concerns about private API usage @@ -826,6 +843,10 @@ + (void)downloadIOSParamsWithAppId:(NSString *)appId { if (result[IOS_RECEIVE_RECEIPTS_ENABLE] != (id)[NSNull null]) [OneSignalUserDefaults.initShared saveBoolForKey:OSUD_RECEIVE_RECEIPTS_ENABLED withValue:[result[IOS_RECEIVE_RECEIPTS_ENABLE] boolValue]]; + + + //TODO: move all remote param logic to new OSRemoteParamController + [[self getRemoteParamController] saveRemoteParams:result]; if (result[OUTCOMES_PARAM] && result[OUTCOMES_PARAM][IOS_OUTCOMES_V2_SERVICE_ENABLE]) [_outcomeEventsCache saveOutcomesV2ServiceEnabled:result[OUTCOMES_PARAM][IOS_OUTCOMES_V2_SERVICE_ENABLE]]; @@ -1381,13 +1402,24 @@ + (void)setSubscription:(BOOL)enable { [OneSignal sendNotificationTypesUpdate]; } - + (void)setLocationShared:(BOOL)enable { - mShareLocation = enable; - [OneSignal onesignal_Log:ONE_S_LL_VERBOSE message:[NSString stringWithFormat:@"setLocationShared called with status: %d", (int) enable]]; + let remoteController = [self getRemoteParamController]; + // Already set by remote params + if ([remoteController hasLocationKey]) + return; + + [self startLocationSharedWithFlag:enable]; +} + ++ (void)startLocationSharedWithFlag:(BOOL)enable { + [OneSignal onesignal_Log:ONE_S_LL_VERBOSE message:[NSString stringWithFormat:@"startLocationSharedWithFlag called with status: %d", (int) enable]]; + + let remoteController = [self getRemoteParamController]; + [remoteController saveLocationShared:enable]; + if (!enable) { - [OneSignal onesignal_Log:ONE_S_LL_VERBOSE message:@"setLocationShared set false, clearing last location!"]; + [OneSignal onesignal_Log:ONE_S_LL_VERBOSE message:@"startLocationSharedWithFlag set false, clearing last location!"]; [OneSignalLocation clearLastLocation]; } } @@ -1405,7 +1437,7 @@ + (void)promptLocationFallbackToSettings:(BOOL)fallback completionHandler:(void } + (BOOL)isLocationShared { - return mShareLocation; + return [[self getRemoteParamController] isLocationShared]; } + (void)handleDidFailRegisterForRemoteNotification:(NSError*)err { @@ -1651,7 +1683,7 @@ + (void)registerUserInternal { [OneSignal onesignal_Log:ONE_S_LL_VERBOSE message:@"Calling OneSignal create/on_session"]; - if (mShareLocation && [OneSignalLocation lastLocation]) { + if ([self isLocationShared] && [OneSignalLocation lastLocation]) { [OneSignal onesignal_Log:ONE_S_LL_VERBOSE message:@"Attaching device location to 'on_session' request payload"]; dataDic[@"lat"] = [NSNumber numberWithDouble:[OneSignalLocation lastLocation]->cords.latitude]; dataDic[@"long"] = [NSNumber numberWithDouble:[OneSignalLocation lastLocation]->cords.longitude]; diff --git a/iOS_SDK/OneSignalSDK/Source/OneSignalCommonDefines.h b/iOS_SDK/OneSignalSDK/Source/OneSignalCommonDefines.h index 69405f7ab..be7947ecb 100644 --- a/iOS_SDK/OneSignalSDK/Source/OneSignalCommonDefines.h +++ b/iOS_SDK/OneSignalSDK/Source/OneSignalCommonDefines.h @@ -77,7 +77,10 @@ #define OSUD_LAST_MESSAGE_OPENED @"GT_LAST_MESSAGE_OPENED_" // * OSUD_MOST_RECENT_NOTIFICATION_OPENED #define OSUD_NOTIFICATION_OPEN_LAUNCH_URL @"ONESIGNAL_INAPP_LAUNCH_URL" // * OSUD_NOTIFICATION_OPEN_LAUNCH_URL #define OSUD_TEMP_CACHED_NOTIFICATION_MEDIA @"OSUD_TEMP_CACHED_NOTIFICATION_MEDIA" // OSUD_TEMP_CACHED_NOTIFICATION_MEDIA -// Receive Receipts +// Remote Params +#define OSUD_LOCATION_ENABLED @"OSUD_LOCATION_ENABLED" +#define OSUD_REQUIRES_USER_PRIVACY_CONSENT @"OSUD_REQUIRES_USER_PRIVACY_CONSENT" +// Remote Params - Receive Receipts #define OSUD_RECEIVE_RECEIPTS_ENABLED @"OS_ENABLE_RECEIVE_RECEIPTS" // * OSUD_RECEIVE_RECEIPTS_ENABLED // Outcomes #define OSUD_OUTCOMES_V2 @"OSUD_OUTCOMES_V2" @@ -119,10 +122,13 @@ #define DEFAULT_UNAUTHORIZATIONOPTIONS (UNAuthorizationOptionSound + UNAuthorizationOptionBadge + UNAuthorizationOptionAlert) // iOS Parameter Names +#define IOS_FBA @"fba" #define IOS_USES_PROVISIONAL_AUTHORIZATION @"uses_provisional_auth" #define IOS_REQUIRES_EMAIL_AUTHENTICATION @"require_email_auth" #define IOS_RECEIVE_RECEIPTS_ENABLE @"receive_receipts_enable" #define IOS_OUTCOMES_V2_SERVICE_ENABLE @"v2_enabled" +#define IOS_LOCATION_SHARED @"location_shared" +#define IOS_REQUIRES_USER_PRIVACY_CONSENT @"requires_user_privacy_consent" // Info.plist key #define FALLBACK_TO_SETTINGS_MESSAGE @"Onesignal_settings_fallback_message" diff --git a/iOS_SDK/OneSignalSDK/Source/UNUserNotificationCenter+OneSignal.m b/iOS_SDK/OneSignalSDK/Source/UNUserNotificationCenter+OneSignal.m index d4aa26476..c9c926d4d 100644 --- a/iOS_SDK/OneSignalSDK/Source/UNUserNotificationCenter+OneSignal.m +++ b/iOS_SDK/OneSignalSDK/Source/UNUserNotificationCenter+OneSignal.m @@ -257,11 +257,11 @@ - (void)onesignalUserNotificationCenter:(UNUserNotificationCenter *)center completionHandler(); } -+ (BOOL) isDismissEvent:(UNNotificationResponse *)response { ++ (BOOL)isDismissEvent:(UNNotificationResponse *)response { return [@"com.apple.UNNotificationDismissActionIdentifier" isEqual:response.actionIdentifier]; } -+ (void) processiOS10Open:(UNNotificationResponse*)response { ++ (void)processiOS10Open:(UNNotificationResponse*)response { if (![OneSignal appId]) return; diff --git a/iOS_SDK/OneSignalSDK/UnitTests/RemoteParamsTests.m b/iOS_SDK/OneSignalSDK/UnitTests/RemoteParamsTests.m new file mode 100644 index 000000000..6cc78e051 --- /dev/null +++ b/iOS_SDK/OneSignalSDK/UnitTests/RemoteParamsTests.m @@ -0,0 +1,300 @@ +/** + * Modified MIT License + * + * Copyright 2020 OneSignal + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * 1. The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * 2. All copies of substantial portions of the Software may only be used in connection + * with services provided by OneSignal. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#import +#import "UnitTestCommonMethods.h" +#import "OneSignalLocation.h" +#import "OneSignalLocationOverrider.h" +#import "OneSignalHelper.h" +#import "OneSignalHelperOverrider.h" +#import "UIDeviceOverrider.h" +#import "NSBundleOverrider.h" +#import "OneSignalClientOverrider.h" +#import "OneSignalCommonDefines.h" + +@interface RemoteParamsTests : XCTestCase +@end + +@implementation RemoteParamsTests + +/* + Put setup code here + This method is called before the invocation of each test method in the class + */ +- (void)setUp { + [super setUp]; + [UnitTestCommonMethods beforeEachTest:self]; + + // Clear last location stored + [OneSignalLocation clearLastLocation]; + + OneSignalHelperOverrider.mockIOSVersion = 10; + + [OneSignalHelperOverrider reset]; + [UIDeviceOverrider reset]; +} + +/* + Put teardown code here + This method is called after the invocation of each test method in the class + */ +- (void)tearDown { + [super tearDown]; +} + +- (void)testLocationPromptAcceptedWithSetLocationShared_iOS9_WhenInUseUsage { + OneSignalHelperOverrider.mockIOSVersion = 9; + + NSBundleOverrider.nsbundleDictionary = @{@"UIBackgroundModes": @[@"remote-notification"], + @"NSLocationWhenInUseUsageDescription" : @YES + }; + + NSMutableDictionary *params = [[OneSignalClientOverrider remoteParamsResponse] mutableCopy]; + [params removeObjectForKey:IOS_LOCATION_SHARED]; + [OneSignalClientOverrider setRemoteParamsResponse:params]; + + [UnitTestCommonMethods initOneSignal_andThreadWait]; + + // Set location shared false + [OneSignal setLocationShared:false]; + // Simulate user granting location services + [OneSignalLocationOverrider grantLocationServices]; + // Last location should not exist since we are not sharing location + XCTAssertFalse([OneSignalLocation lastLocation]); + + // Set location shared true + [OneSignal setLocationShared:true]; + // Simulate user granting location services + [OneSignalLocationOverrider grantLocationServices]; + // Last location should exist since we are sharing location + XCTAssertTrue([OneSignalLocation lastLocation]); +} + +- (void)testLocationPromptAcceptedWithSetLocationSharedTrueFromRemoteParams_iOS9_WhenInUseUsage { + OneSignalHelperOverrider.mockIOSVersion = 9; + + NSBundleOverrider.nsbundleDictionary = @{@"UIBackgroundModes": @[@"remote-notification"], + @"NSLocationWhenInUseUsageDescription" : @YES + }; + + [UnitTestCommonMethods initOneSignal_andThreadWait]; + // location_shared set as true on remote params + XCTAssertTrue([OneSignal isLocationShared]); + // Last location should not exist since we didn't grant permission + XCTAssertFalse([OneSignalLocation lastLocation]); + // Simulate user granting location services + [OneSignalLocationOverrider grantLocationServices]; + // Last location should exist since we are sharing location + XCTAssertTrue([OneSignalLocation lastLocation]); +} + +- (void)testLocationPromptAcceptedWithSetLocationSharedFalseFromRemoteParams_iOS9_WhenInUseUsage { + OneSignalHelperOverrider.mockIOSVersion = 9; + + NSBundleOverrider.nsbundleDictionary = @{@"UIBackgroundModes": @[@"remote-notification"], + @"NSLocationWhenInUseUsageDescription" : @YES + }; + + NSMutableDictionary *params = [[OneSignalClientOverrider remoteParamsResponse] mutableCopy]; + [params setObject:@NO forKey:IOS_LOCATION_SHARED]; + [OneSignalClientOverrider setRemoteParamsResponse:params]; + [UnitTestCommonMethods initOneSignal_andThreadWait]; + // location_shared set as false on remote params + XCTAssertFalse([OneSignal isLocationShared]); + // Last location should not exist since we didn't grant permission + XCTAssertFalse([OneSignalLocation lastLocation]); + // Simulate user granting location services + [OneSignalLocationOverrider grantLocationServices]; + // Last location should not exist since we are not sharing location + XCTAssertFalse([OneSignalLocation lastLocation]); +} + +- (void)testLocationSharedTrueFromRemoteParams { + NSBundleOverrider.nsbundleDictionary = @{ + @"NSLocationWhenInUseUsageDescription" : @YES + }; + [UnitTestCommonMethods initOneSignal_andThreadWait]; + // location_shared set as true on remote params + XCTAssertTrue([OneSignal isLocationShared]); + // Last location should not exist since we didn't grant permission + XCTAssertFalse([OneSignalLocation lastLocation]); + // Simulate user granting location services + [OneSignalLocationOverrider grantLocationServices]; + // Last location should exist since we are sharing location + XCTAssertTrue([OneSignalLocation lastLocation]); +} + +- (void)testLocationSharedFalseFromRemoteParams { + NSBundleOverrider.nsbundleDictionary = @{ + @"NSLocationWhenInUseUsageDescription" : @YES + }; + NSMutableDictionary *params = [[OneSignalClientOverrider remoteParamsResponse] mutableCopy]; + [params setObject:@NO forKey:IOS_LOCATION_SHARED]; + [OneSignalClientOverrider setRemoteParamsResponse:params]; + [UnitTestCommonMethods initOneSignal_andThreadWait]; + // location_shared set as false on remote params + XCTAssertFalse([OneSignal isLocationShared]); + // Last location should not exist since we didn't grant permission + XCTAssertFalse([OneSignalLocation lastLocation]); + // Simulate user granting location services + [OneSignalLocationOverrider grantLocationServices]; + // Last location should not exist since we are not sharing location + XCTAssertFalse([OneSignalLocation lastLocation]); +} + +- (void)testLocationSharedEnable_UserConfigurationOverrideByRemoteParams { + [OneSignal setLocationShared:false]; + [UnitTestCommonMethods initOneSignal_andThreadWait]; + // location_shared set as true on remote params + XCTAssertTrue([OneSignal isLocationShared]); +} + +- (void)testLocationSharedDisable_UserConfigurationOverrideByRemoteParams { + [OneSignal setLocationShared:true]; + NSMutableDictionary *params = [[OneSignalClientOverrider remoteParamsResponse] mutableCopy]; + [params setObject:@NO forKey:IOS_LOCATION_SHARED]; + [OneSignalClientOverrider setRemoteParamsResponse:params]; + [UnitTestCommonMethods initOneSignal_andThreadWait]; + // location_shared set as false on remote params + XCTAssertFalse([OneSignal isLocationShared]); +} + +- (void)testLocationSharedEnable_UserConfigurationNotOverrideRemoteParams { + [UnitTestCommonMethods initOneSignal_andThreadWait]; + // location_shared set as true on remote params + XCTAssertTrue([OneSignal isLocationShared]); + + [OneSignal setLocationShared:false]; + XCTAssertTrue([OneSignal isLocationShared]); +} + +- (void)testLocationSharedDisable_UserConfigurationNotOverrideRemoteParams { + NSMutableDictionary *params = [[OneSignalClientOverrider remoteParamsResponse] mutableCopy]; + [params setObject:@NO forKey:IOS_LOCATION_SHARED]; + [OneSignalClientOverrider setRemoteParamsResponse:params]; + [UnitTestCommonMethods initOneSignal_andThreadWait]; + // location_shared set as false on remote params + XCTAssertFalse([OneSignal isLocationShared]); + + [OneSignal setLocationShared:true]; + XCTAssertFalse([OneSignal isLocationShared]); +} + +/* + Tests the privacy functionality to comply with the GDPR +*/ +- (void)testPrivacyState { + [NSBundleOverrider setPrivacyState:true]; + + [self assertUserConsent]; + + [NSBundleOverrider setPrivacyState:false]; +} + +- (void)assertUserConsent { + [OneSignal setAppSettings:@{kOSSettingsKeyAutoPrompt: @false}]; + [OneSignal setAppId:@"b2f7f966-d8cc-11e4-bed1-df8f05be55ba"]; + [OneSignal setLaunchOptions:nil]; + + //indicates initialization was delayed + XCTAssertNil(OneSignal.appId); + + XCTAssertTrue([OneSignal requiresUserPrivacyConsent]); + + let latestHttpRequest = OneSignalClientOverrider.lastUrl; + + [OneSignal sendTags:@{@"test" : @"test"}]; + + //if lastUrl is null, isEqualToString: will return false, so perform an equality check as well + XCTAssertTrue([OneSignalClientOverrider.lastUrl isEqualToString:latestHttpRequest] || latestHttpRequest == OneSignalClientOverrider.lastUrl); + + [OneSignal consentGranted:true]; + + XCTAssertTrue([@"b2f7f966-d8cc-11e4-bed1-df8f05be55ba" isEqualToString:OneSignal.appId]); + + XCTAssertFalse([OneSignal requiresUserPrivacyConsent]); +} + +- (void)testUserPrivacyConsentRequired_ByRemoteParams { + NSMutableDictionary *params = [[OneSignalClientOverrider remoteParamsResponse] mutableCopy]; + [params setObject:@YES forKey:IOS_REQUIRES_USER_PRIVACY_CONSENT]; + [OneSignalClientOverrider setRemoteParamsResponse:params]; + [UnitTestCommonMethods initOneSignal_andThreadWait]; + + // requires_user_privacy_consent set as true on remote params + XCTAssertTrue([OneSignal requiresUserPrivacyConsent]); + [NSBundleOverrider setPrivacyState:false]; +} + +- (void)testUserPrivacyConsentNotRequired_ByRemoteParams { + [UnitTestCommonMethods initOneSignal_andThreadWait]; + + // requires_user_privacy_consent set as false on remote params + XCTAssertFalse([OneSignal requiresUserPrivacyConsent]); + [NSBundleOverrider setPrivacyState:false]; +} + +- (void)testUserPrivacyConsentRequired_UserConfigurationOverrideByRemoteParams { + [OneSignal setRequiresUserPrivacyConsent:false]; + + NSMutableDictionary *params = [[OneSignalClientOverrider remoteParamsResponse] mutableCopy]; + [params setObject:@YES forKey:IOS_REQUIRES_USER_PRIVACY_CONSENT]; + [OneSignalClientOverrider setRemoteParamsResponse:params]; + [UnitTestCommonMethods initOneSignal_andThreadWait]; + + // requires_user_privacy_consent set as true on remote params + XCTAssertTrue([OneSignal requiresUserPrivacyConsent]); + [NSBundleOverrider setPrivacyState:false]; +} + +- (void)testUserPrivacyConsentRequired_UserConfigurationNotOverrideRemoteParams { + NSMutableDictionary *params = [[OneSignalClientOverrider remoteParamsResponse] mutableCopy]; + [params setObject:@YES forKey:IOS_REQUIRES_USER_PRIVACY_CONSENT]; + [OneSignalClientOverrider setRemoteParamsResponse:params]; + [UnitTestCommonMethods initOneSignal_andThreadWait]; + + // requires_user_privacy_consent set as true on remote params + XCTAssertTrue([OneSignal requiresUserPrivacyConsent]); + + [OneSignal setRequiresUserPrivacyConsent:false]; + XCTAssertTrue([OneSignal requiresUserPrivacyConsent]); + [NSBundleOverrider setPrivacyState:false]; +} + + +- (void)testUserPrivacyConsentNotRequired_UserConfigurationNotOverrideRemoteParams { + [UnitTestCommonMethods initOneSignal_andThreadWait]; + + // requires_user_privacy_consent set as false on remote params + XCTAssertFalse([OneSignal requiresUserPrivacyConsent]); + + [OneSignal setRequiresUserPrivacyConsent:true]; + XCTAssertFalse([OneSignal requiresUserPrivacyConsent]); + [NSBundleOverrider setPrivacyState:false]; +} + +@end diff --git a/iOS_SDK/OneSignalSDK/UnitTests/Shadows/OneSignalClientOverrider.h b/iOS_SDK/OneSignalSDK/UnitTests/Shadows/OneSignalClientOverrider.h index 6ecab0a1b..73caccb98 100644 --- a/iOS_SDK/OneSignalSDK/UnitTests/Shadows/OneSignalClientOverrider.h +++ b/iOS_SDK/OneSignalSDK/UnitTests/Shadows/OneSignalClientOverrider.h @@ -48,5 +48,7 @@ + (void)disableExecuteRequestOverride:(BOOL)disable; + (NSArray *)executedRequests; + (void)setMockResponseForRequest:(NSString *)request withResponse:(NSDictionary *)response; ++ (NSDictionary*)remoteParamsResponse; ++ (void)setRemoteParamsResponse:(NSDictionary *)params; @end diff --git a/iOS_SDK/OneSignalSDK/UnitTests/Shadows/OneSignalClientOverrider.m b/iOS_SDK/OneSignalSDK/UnitTests/Shadows/OneSignalClientOverrider.m index bb9cabc43..2ceb06cbe 100644 --- a/iOS_SDK/OneSignalSDK/UnitTests/Shadows/OneSignalClientOverrider.m +++ b/iOS_SDK/OneSignalSDK/UnitTests/Shadows/OneSignalClientOverrider.m @@ -56,7 +56,8 @@ @implementation OneSignalClientOverrider static BOOL disableOverride = false; static NSMutableArray *executedRequests; static NSMutableDictionary *mockResponses; -static NSDictionary* iOSParamsOutcomes; +static NSDictionary* remoteParamsOutcomes; +static NSDictionary* remoteParams; + (void)load { serialMockMainLooper = dispatch_queue_create("com.onesignal.unittest", DISPATCH_QUEUE_SERIAL); @@ -71,17 +72,20 @@ + (void)load { mockResponses = [NSMutableDictionary new]; } -+ (NSDictionary*)iosParamsResponse { - return @{ - @"fba": @true, - IOS_REQUIRES_EMAIL_AUTHENTICATION : @(requiresEmailAuth), - IOS_USES_PROVISIONAL_AUTHORIZATION : @(shouldUseProvisionalAuthorization), - OUTCOMES_PARAM : iOSParamsOutcomes - }; ++ (NSDictionary*)remoteParamsResponse { + return remoteParams ? remoteParams : + @{ + IOS_FBA: @true, + IOS_REQUIRES_EMAIL_AUTHENTICATION : @(requiresEmailAuth), + IOS_USES_PROVISIONAL_AUTHORIZATION : @(shouldUseProvisionalAuthorization), + OUTCOMES_PARAM : remoteParamsOutcomes, + IOS_LOCATION_SHARED : @true, + IOS_REQUIRES_USER_PRIVACY_CONSENT : @false + }; } + (void)enableOutcomes { - iOSParamsOutcomes = @{ + remoteParamsOutcomes = @{ DIRECT_PARAM: @{ ENABLED_PARAM: @YES }, @@ -98,6 +102,10 @@ + (void)enableOutcomes { }; } ++ (void)setRemoteParamsResponse:(NSDictionary *)params { + remoteParams = params; +} + // Calling this function twice results in reversing the swizzle + (void)disableExecuteRequestOverride:(BOOL)disable { disableOverride = disable; @@ -189,7 +197,7 @@ + (void)finishExecutingRequest:(OneSignalRequest *)request onSuccess:(OSResultSu if (successBlock) { if ([request isKindOfClass:[OSRequestGetIosParams class]]) { - successBlock(self.iosParamsResponse); + successBlock(self.remoteParamsResponse); } else if (mockResponses[NSStringFromClass([request class])]) { successBlock(mockResponses[NSStringFromClass([request class])]); @@ -256,7 +264,8 @@ + (void)reset:(XCTestCase*)testInstance { lastHTTPRequestType = nil; [executedRequests removeAllObjects]; mockResponses = [NSMutableDictionary new]; - iOSParamsOutcomes = @{}; + remoteParamsOutcomes = @{}; + remoteParams = nil; } + (void)setLastHTTPRequest:(NSDictionary*)value { diff --git a/iOS_SDK/OneSignalSDK/UnitTests/UnitTests.m b/iOS_SDK/OneSignalSDK/UnitTests/UnitTests.m index 732833e76..b5eea953b 100644 --- a/iOS_SDK/OneSignalSDK/UnitTests/UnitTests.m +++ b/iOS_SDK/OneSignalSDK/UnitTests/UnitTests.m @@ -48,6 +48,8 @@ #import "OSNotificationPayload+Internal.h" #import "OneSignalUserDefaults.h" #import "OSInAppMessagingHelpers.h" +#import "DelayedConsentInitializationParameters.h" + #import "TestHelperFunctions.h" #import "UnitTestAppDelegate.h" #import "OneSignalExtensionBadgeHandler.h" @@ -79,13 +81,14 @@ #import "OneSignalClientOverrider.h" #import "OneSignalCommonDefines.h" - +@interface OneSignal (TestHelper) ++ (DelayedConsentInitializationParameters *)delayedInitParameters; +@end @interface OneSignalHelper (TestHelper) + (NSString*)downloadMediaAndSaveInBundle:(NSString*)urlString; @end - @interface UnitTests : XCTestCase @property NSString* CALLBACK_EXTERNAL_USER_ID; @@ -225,34 +228,6 @@ - (void)testSymanticVersioning { }]; } -- (void)testLocationPromptAcceptedWithSetLocationShared_iOS9_WhenInUseUsage { - OneSignalHelperOverrider.mockIOSVersion = 9; - - NSBundleOverrider.nsbundleDictionary = @{@"UIBackgroundModes": @[@"remote-notification"], - @"NSLocationWhenInUseUsageDescription" : @YES - }; - - [UnitTestCommonMethods initOneSignal_andThreadWait]; - - [self assertLocationShared_withGrantLocationServices]; -} - -- (void)assertLocationShared_withGrantLocationServices { - // Set location shared false - [OneSignal setLocationShared:false]; - // Simulate user granting location services - [OneSignalLocationOverrider grantLocationServices]; - // Last location should not exist since we are not sharing location - XCTAssertFalse([OneSignalLocation lastLocation]); - - // Set location shared true - [OneSignal setLocationShared:true]; - // Simulate user granting location services - [OneSignalLocationOverrider grantLocationServices]; - // Last location should not exist since we are not sharing location - XCTAssertTrue([OneSignalLocation lastLocation]); -} - // Test exists since we've seen a few rare crash reports where // [NSLocale preferredLanguages] resturns an empty array - (void)testInitWithEmptyPreferredLanguages { @@ -394,7 +369,6 @@ - (void)testPermissionChangeObserverFireAfterAppRestart { XCTAssertEqual(observer->last.to.accepted, false); } - - (void)testPermissionObserverDontFireIfNothingChangedAfterAppRestartiOS10 { OneSignalHelperOverrider.mockIOSVersion = 10; [self sharedPermissionObserverDontFireIfNothingChangedAfterAppRestart]; @@ -482,7 +456,6 @@ - (void)testSubscriptionChangeObserverFireAfterAppRestart { XCTAssertEqual(observer->last.to.subscribed, false); } - - (void)testPermissionChangeObserverWithNativeiOS10PromptCall { [UnitTestCommonMethods setCurrentNotificationPermissionAsUnanswered]; [OneSignal setAppSettings:@{kOSSettingsKeyAutoPrompt: @false}]; @@ -1419,7 +1392,6 @@ - (void)testPostNotification { XCTAssertEqualObjects(OneSignalClientOverrider.lastHTTPRequest[@"app_id"], @"override_app_UUID"); } - - (void)testFirstInitWithNotificationsAlreadyDeclined { [self backgroundModesDisabledInXcode]; UNUserNotificationCenterOverrider.notifTypesOverride = 0; @@ -1499,7 +1471,7 @@ - (void)testPermissionChangedOutsideOfAppOverWithNewSession { XCTAssertEqual(OneSignalClientOverrider.networkRequestCount, 3); } -- (void) testOnSessionWhenResuming { +- (void)testOnSessionWhenResuming { [UnitTestCommonMethods initOneSignal_andThreadWait]; // Don't make an on_session call if only out of the app for 20 secounds @@ -1520,7 +1492,7 @@ - (void) testOnSessionWhenResuming { } -- (void) testOnSessionOnColdStart { +- (void)testOnSessionOnColdStart { // 1. Open app [UnitTestCommonMethods initOneSignal_andThreadWait]; @@ -1826,51 +1798,6 @@ - (void)testHandlingMediaUrlExtensions { XCTAssertNotNil(cacheName); } -/* - Tests the privacy functionality to comply with the GDPR -*/ -- (void)testPrivacyState { - [NSBundleOverrider setPrivacyState:true]; - - [self assertUserConsent]; - - [NSBundleOverrider setPrivacyState:false]; -} - -- (void)testOverridePrivacyState { - //since some wrapper SDK's wont use an info.plist, the SDK also provides a method that can also set the privacy consent setting - - [OneSignal setRequiresUserPrivacyConsent:true]; - - [self assertUserConsent]; - - [OneSignal setRequiresUserPrivacyConsent:false]; -} - -- (void)assertUserConsent { - [OneSignal setAppSettings:@{kOSSettingsKeyAutoPrompt: @false}]; - [OneSignal setAppId:@"b2f7f966-d8cc-11e4-bed1-df8f05be55ba"]; - [OneSignal setLaunchOptions:nil]; - - //indicates initialization was delayed - XCTAssertNil(OneSignal.appId); - - XCTAssertTrue([OneSignal requiresUserPrivacyConsent]); - - let latestHttpRequest = OneSignalClientOverrider.lastUrl; - - [OneSignal sendTags:@{@"test" : @"test"}]; - - //if lastUrl is null, isEqualToString: will return false, so perform an equality check as well - XCTAssertTrue([OneSignalClientOverrider.lastUrl isEqualToString:latestHttpRequest] || latestHttpRequest == OneSignalClientOverrider.lastUrl); - - [OneSignal consentGranted:true]; - - XCTAssertTrue([@"b2f7f966-d8cc-11e4-bed1-df8f05be55ba" isEqualToString:OneSignal.appId]); - - XCTAssertFalse([OneSignal requiresUserPrivacyConsent]); -} - //since apps may manually request push permission while OneSignal privacy consent is not granted, //the SDK should not do anything with this token while permission is pending //checks to make sure that, for example, OneSignal does not register the push token with the backend