diff --git a/CHANGELOG.md b/CHANGELOG.md index e3d96eb1..9454e70b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Change Log All notable changes to this project will be documented in this file. +### [Version 7.0.2](https://github.com/CleverTap/clevertap-ios-sdk/releases/tag/7.0.2) (October 10, 2024) + +#### Added +- Adds support for custom handshake domains. + ### [Version 7.0.1](https://github.com/CleverTap/clevertap-ios-sdk/releases/tag/7.0.1) (August 22, 2024) #### Fixed diff --git a/CleverTapSDK.xcodeproj/project.pbxproj b/CleverTapSDK.xcodeproj/project.pbxproj index ea4c003c..37b8dfed 100644 --- a/CleverTapSDK.xcodeproj/project.pbxproj +++ b/CleverTapSDK.xcodeproj/project.pbxproj @@ -252,6 +252,8 @@ 4E872969277CDF9000A7A618 /* inapp_alert.json in Resources */ = {isa = PBXBuildFile; fileRef = 4E1F1561277090D6009387AE /* inapp_alert.json */; }; 4E87296E277CE8EB00A7A618 /* StubHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 4E87296D277CE8EB00A7A618 /* StubHelper.m */; }; 4E872973277CEE6700A7A618 /* TestConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = 4E872972277CEE6700A7A618 /* TestConstants.m */; }; + 4E87397B2C92223C00FDFDFD /* CTDomainFactoryTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4E8739772C921D9000FDFDFD /* CTDomainFactoryTests.m */; }; + 4E87397E2C9223B300FDFDFD /* CTDomainFactory+Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4E87397D2C9223B300FDFDFD /* CTDomainFactory+Tests.m */; }; 4E8B81662AD2ADAE00714BB4 /* CTSwizzleManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 4E8B81642AD2ADAE00714BB4 /* CTSwizzleManager.m */; }; 4E8B81672AD2ADAE00714BB4 /* CTSwizzleManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 4E8B81642AD2ADAE00714BB4 /* CTSwizzleManager.m */; }; 4E8B81682AD2ADAE00714BB4 /* CTSwizzleManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 4E8B81652AD2ADAE00714BB4 /* CTSwizzleManager.h */; }; @@ -822,6 +824,9 @@ 4E87296D277CE8EB00A7A618 /* StubHelper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = StubHelper.m; sourceTree = ""; }; 4E872971277CEE6700A7A618 /* TestConstants.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TestConstants.h; sourceTree = ""; }; 4E872972277CEE6700A7A618 /* TestConstants.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TestConstants.m; sourceTree = ""; }; + 4E8739772C921D9000FDFDFD /* CTDomainFactoryTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CTDomainFactoryTests.m; sourceTree = ""; }; + 4E87397C2C9223B300FDFDFD /* CTDomainFactory+Tests.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "CTDomainFactory+Tests.h"; sourceTree = ""; }; + 4E87397D2C9223B300FDFDFD /* CTDomainFactory+Tests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "CTDomainFactory+Tests.m"; sourceTree = ""; }; 4E8B81642AD2ADAE00714BB4 /* CTSwizzleManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CTSwizzleManager.m; sourceTree = ""; }; 4E8B81652AD2ADAE00714BB4 /* CTSwizzleManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CTSwizzleManager.h; sourceTree = ""; }; 4E8B816A2AD2B2FD00714BB4 /* CleverTapInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CleverTapInternal.h; sourceTree = ""; }; @@ -1609,6 +1614,9 @@ 6BD851C82B45CD1800FA5298 /* CTMultiDelegateManager+Tests.h */, 0B5564552C25946C00B87284 /* CTUserInfoMigratorTest.m */, 0B995A492C36AEDC00AF6006 /* CTLocalDataStoreTests.m */, + 4E8739772C921D9000FDFDFD /* CTDomainFactoryTests.m */, + 4E87397C2C9223B300FDFDFD /* CTDomainFactory+Tests.h */, + 4E87397D2C9223B300FDFDFD /* CTDomainFactory+Tests.m */, ); path = CleverTapSDKTests; sourceTree = ""; @@ -2510,6 +2518,7 @@ 32394C2529FA272600956058 /* CTValidatorTest.m in Sources */, 6BB778CE2BEE48C300A41628 /* CTCustomTemplateInAppDataTest.m in Sources */, 6BA3B2E82B07E207004E834B /* CTTriggersMatcher+Tests.m in Sources */, + 4E87397E2C9223B300FDFDFD /* CTDomainFactory+Tests.m in Sources */, 6BBF05CE2C58E3FB0047E3D9 /* NSURLSessionMock.m in Sources */, 6B32A0A52B9A0F17009ADC57 /* CTCustomTemplateTest.m in Sources */, 4E1F155B276B662C009387AE /* EventDetail.m in Sources */, @@ -2550,6 +2559,7 @@ 0B995A4A2C36AEDC00AF6006 /* CTLocalDataStoreTests.m in Sources */, 6A4427C52AA6515A0098866F /* CTTriggersMatcherTest.m in Sources */, 6B32A0B02B9DC374009ADC57 /* CTTemplateArgumentTest.m in Sources */, + 4E87397B2C92223C00FDFDFD /* CTDomainFactoryTests.m in Sources */, 0B5564562C25946C00B87284 /* CTUserInfoMigratorTest.m in Sources */, 4E2CF1442AC56D8F00441E8B /* CTEncryptionTests.m in Sources */, 32394C2729FA278C00956058 /* CTUriHelperTest.m in Sources */, diff --git a/CleverTapSDK/CTConstants.h b/CleverTapSDK/CTConstants.h index 8e18b435..c1f91ae1 100644 --- a/CleverTapSDK/CTConstants.h +++ b/CleverTapSDK/CTConstants.h @@ -3,6 +3,12 @@ extern NSString *const kCTApiDomain; extern NSString *const kCTNotifViewedApiDomain; extern NSString *const kHANDSHAKE_URL; +extern NSString *const kHANDSHAKE_DOMAIN_HEADER; +extern NSString *const ACCOUNT_ID_HEADER; +extern NSString *const ACCOUNT_TOKEN_HEADER; + +extern NSString *const REDIRECT_DOMAIN_KEY; +extern NSString *const REDIRECT_NOTIF_VIEWED_DOMAIN_KEY; extern NSString *const kLastSessionPing; extern NSString *const kLastSessionTime; @@ -33,6 +39,7 @@ extern NSString *const kSessionId; #define CLTAP_USE_CUSTOM_CLEVERTAP_ID_LABEL @"CleverTapUseCustomId" #define CLTAP_DISABLE_IDFV_LABEL @"CleverTapDisableIDFV" #define CLTAP_ENABLE_FILE_PROTECTION @"CleverTapEnableFileProtection" +#define CLTAP_HANDSHAKE_DOMAIN @"CleverTapHandshakeDomain" #define CLTAP_BETA_LABEL @"CleverTapBeta" #define CLTAP_SESSION_LENGTH_MINS 20 #define CLTAP_SESSION_LAST_VC_TRAIL @"last_session_vc_trail" diff --git a/CleverTapSDK/CTConstants.m b/CleverTapSDK/CTConstants.m index 4a61e130..b7f5ef46 100644 --- a/CleverTapSDK/CTConstants.m +++ b/CleverTapSDK/CTConstants.m @@ -3,6 +3,12 @@ NSString *const kCTApiDomain = @"clevertap-prod.com"; NSString *const kCTNotifViewedApiDomain = @"spiky.clevertap-prod.com"; NSString *const kHANDSHAKE_URL = @"https://clevertap-prod.com/hello"; +NSString *const kHANDSHAKE_DOMAIN_HEADER =@"X-CleverTap-Handshake-Domain"; +NSString *const ACCOUNT_ID_HEADER = @"X-CleverTap-Account-Id"; +NSString *const ACCOUNT_TOKEN_HEADER = @"X-CleverTap-Token"; + +NSString *const REDIRECT_DOMAIN_KEY = @"CLTAP_REDIRECT_DOMAIN_KEY"; +NSString *const REDIRECT_NOTIF_VIEWED_DOMAIN_KEY = @"CLTAP_REDIRECT_NOTIF_VIEWED_DOMAIN_KEY"; NSString *const kLastSessionPing = @"last_session_ping"; NSString *const kLastSessionTime = @"lastSessionTime"; diff --git a/CleverTapSDK/CTDomainFactory.m b/CleverTapSDK/CTDomainFactory.m index 64a3615f..b18c0b99 100644 --- a/CleverTapSDK/CTDomainFactory.m +++ b/CleverTapSDK/CTDomainFactory.m @@ -11,10 +11,6 @@ #import "CTConstants.h" #import "CleverTapInstanceConfigPrivate.h" - -NSString *const REDIRECT_DOMAIN_KEY = @"CLTAP_REDIRECT_DOMAIN_KEY"; -NSString *const REDIRECT_NOTIF_VIEWED_DOMAIN_KEY = @"CLTAP_REDIRECT_NOTIF_VIEWED_DOMAIN_KEY"; - @interface CTDomainFactory () @property (nonatomic, strong) CleverTapInstanceConfig *config; @@ -75,6 +71,7 @@ - (NSString *)loadRedirectDomain { return self.explictEndpointDomain; } } + NSString *domain = nil; if (self.config.isDefaultInstance) { domain = [CTPreferences getStringForKey:[CTPreferences storageKeyWithSuffix:REDIRECT_DOMAIN_KEY config: self.config] withResetValue:[CTPreferences getStringForKey:REDIRECT_DOMAIN_KEY withResetValue:nil]]; diff --git a/CleverTapSDK/CTPlistInfo.h b/CleverTapSDK/CTPlistInfo.h index ffa177a6..3c2b322e 100644 --- a/CleverTapSDK/CTPlistInfo.h +++ b/CleverTapSDK/CTPlistInfo.h @@ -14,6 +14,7 @@ @property (nonatomic, assign, readonly) BOOL beta; @property (nonatomic, assign, readonly) BOOL disableIDFV; @property (nonatomic, assign) BOOL enableFileProtection; +@property (nonatomic, strong, readonly, nullable) NSString *handshakeDomain; @property (nonatomic, readonly) CleverTapEncryptionLevel encryptionLevel; + (instancetype _Nullable)sharedInstance; diff --git a/CleverTapSDK/CTPlistInfo.m b/CleverTapSDK/CTPlistInfo.m index c660c08d..5c67dfa2 100644 --- a/CleverTapSDK/CTPlistInfo.m +++ b/CleverTapSDK/CTPlistInfo.m @@ -94,6 +94,8 @@ - (instancetype)init { NSString *enableFileProtection = [CTPlistInfo getMetaDataForAttribute:CLTAP_ENABLE_FILE_PROTECTION]; _enableFileProtection = (enableFileProtection && [enableFileProtection isEqualToString:@"1"]); + _handshakeDomain = [CTPlistInfo getMetaDataForAttribute:CLTAP_HANDSHAKE_DOMAIN]; + NSString *encryptionLevel = [CTPlistInfo getMetaDataForAttribute:CLTAP_ENCRYPTION_LEVEL]; [self setEncryption:encryptionLevel]; } diff --git a/CleverTapSDK/CTRequest.m b/CleverTapSDK/CTRequest.m index b8734910..e3aed06a 100644 --- a/CleverTapSDK/CTRequest.m +++ b/CleverTapSDK/CTRequest.m @@ -10,9 +10,6 @@ #import "CTConstants.h" #import "CTUtils.h" -NSString *const ACCOUNT_ID_HEADER = @"X-CleverTap-Account-Id"; -NSString *const ACCOUNT_TOKEN_HEADER = @"X-CleverTap-Token"; - @interface CTRequest() @property (nonatomic, strong, nullable) id params; diff --git a/CleverTapSDK/CTRequestFactory.m b/CleverTapSDK/CTRequestFactory.m index 9edc1c49..251fe57e 100644 --- a/CleverTapSDK/CTRequestFactory.m +++ b/CleverTapSDK/CTRequestFactory.m @@ -12,7 +12,15 @@ @implementation CTRequestFactory + (CTRequest *_Nonnull)helloRequestWithConfig:(CleverTapInstanceConfig *_Nonnull)config { - return [[CTRequest alloc] initWithHttpMethod:@"GET" config:config params:nil url:kHANDSHAKE_URL]; + NSString *helloUrl = kHANDSHAKE_URL; + if (config.handshakeDomain) { + helloUrl = [NSString stringWithFormat:@"https://%@/hello",config.handshakeDomain]; + } + CTRequest *request = [[CTRequest alloc] initWithHttpMethod:@"GET" config:config params:nil url:helloUrl]; + if (config.handshakeDomain) { + [request.urlRequest setValue:config.handshakeDomain forHTTPHeaderField:kHANDSHAKE_DOMAIN_HEADER]; + } + return request; } + (CTRequest *_Nonnull)eventRequestWithConfig:(CleverTapInstanceConfig *_Nonnull)config params:(id _Nullable)params url:(NSString *_Nonnull)url { diff --git a/CleverTapSDK/CleverTap.m b/CleverTapSDK/CleverTap.m index ac9aaa79..806a7244 100644 --- a/CleverTapSDK/CleverTap.m +++ b/CleverTapSDK/CleverTap.m @@ -403,6 +403,7 @@ + (nullable instancetype)_sharedInstanceWithCleverTapID:(NSString *)cleverTapID _defaultInstanceConfig.enablePersonalization = [CleverTap isPersonalizationEnabled]; _defaultInstanceConfig.logLevel = [self getDebugLevel]; _defaultInstanceConfig.enableFileProtection = _plistInfo.enableFileProtection; + _defaultInstanceConfig.handshakeDomain = _plistInfo.handshakeDomain; NSString *regionLog = (!_plistInfo.accountRegion || _plistInfo.accountRegion.length < 1) ? @"default" : _plistInfo.accountRegion; NSString *proxyDomainLog = (!_plistInfo.proxyDomain || _plistInfo.proxyDomain.length < 1) ? @"" : _plistInfo.proxyDomain; NSString *spikyProxyDomainLog = (!_plistInfo.spikyProxyDomain || _plistInfo.spikyProxyDomain.length < 1) ? @"" : _plistInfo.spikyProxyDomain; diff --git a/CleverTapSDK/CleverTapBuildInfo.h b/CleverTapSDK/CleverTapBuildInfo.h index ff6f62bb..2c056645 100644 --- a/CleverTapSDK/CleverTapBuildInfo.h +++ b/CleverTapSDK/CleverTapBuildInfo.h @@ -1 +1 @@ -#define WR_SDK_REVISION @"70001" +#define WR_SDK_REVISION @"70002" diff --git a/CleverTapSDK/CleverTapInstanceConfig.h b/CleverTapSDK/CleverTapInstanceConfig.h index 1f78cbe8..c351f444 100644 --- a/CleverTapSDK/CleverTapInstanceConfig.h +++ b/CleverTapSDK/CleverTapInstanceConfig.h @@ -16,6 +16,8 @@ @property (nonatomic, assign) BOOL useCustomCleverTapId; @property (nonatomic, assign) BOOL disableIDFV; @property (nonatomic, assign) BOOL enableFileProtection; +@property (nonatomic, strong, nullable) NSString *handshakeDomain; + @property (nonatomic, assign) CleverTapLogLevel logLevel; @property (nonatomic, strong, nullable) NSArray *identityKeys; @property (nonatomic, assign) CleverTapEncryptionLevel encryptionLevel; @@ -56,4 +58,5 @@ */ - (void)setEncryptionLevel:(CleverTapEncryptionLevel)encryptionLevel; - (void)setEnableFileProtection:(BOOL)enableFileProtection; +- (void)setHandshakeDomain:(NSString * _Nonnull)handshakeDomain; @end diff --git a/CleverTapSDK/CleverTapInstanceConfig.m b/CleverTapSDK/CleverTapInstanceConfig.m index 8a3144b5..4bd9c770 100644 --- a/CleverTapSDK/CleverTapInstanceConfig.m +++ b/CleverTapSDK/CleverTapInstanceConfig.m @@ -29,6 +29,7 @@ - (void)encodeWithCoder:(NSCoder *)coder [coder encodeInt: _encryptionLevel forKey:@"encryptionLevel"]; [coder encodeObject: _aesCrypt forKey:@"aesCrypt"]; [coder encodeBool:_enableFileProtection forKey:@"enableFileProtection"]; + [coder encodeObject:_handshakeDomain forKey:@"handshakeDomain"]; } - (nullable instancetype)initWithCoder:(nonnull NSCoder *)coder { @@ -54,6 +55,7 @@ - (nullable instancetype)initWithCoder:(nonnull NSCoder *)coder { _encryptionLevel = [coder decodeIntForKey:@"encryptionLevel"]; _aesCrypt = [coder decodeObjectForKey:@"aesCrypt"]; _enableFileProtection = [coder decodeBoolForKey:@"enableFileProtection"]; + _handshakeDomain = [coder decodeObjectForKey:@"handshakeDomain"]; } return self; } @@ -186,6 +188,7 @@ - (instancetype)copyWithZone:(NSZone*)zone { copy.encryptionLevel = self.encryptionLevel; copy.aesCrypt = self.aesCrypt; copy.enableFileProtection = self.enableFileProtection; + copy.handshakeDomain = self.handshakeDomain; return copy; } @@ -209,6 +212,7 @@ - (void) setupPlistData:(BOOL)isDefault { _beta = plist.beta; _encryptionLevel = isDefault ? plist.encryptionLevel : CleverTapEncryptionNone; _enableFileProtection = isDefault ? plist.enableFileProtection : NO; + _handshakeDomain = isDefault ? plist.handshakeDomain : nil; if (isDefault) { _aesCrypt = [[CTAES alloc] initWithAccountID:_accountId encryptionLevel:_encryptionLevel isDefaultInstance:isDefault]; } @@ -241,4 +245,12 @@ - (void)setEnableFileProtection:(BOOL)enableFileProtection { CleverTapLogStaticInfo("CleverTap enable file protection for default instance can't be updated from setEnableFileProtection method"); } } + +- (void)setHandshakeDomain:(NSString *)handshakeDomain { + if (!_isDefaultInstance) { + _handshakeDomain = handshakeDomain; + } else { + CleverTapLogStaticInfo("CleverTap handshake domain for default instance can't be updated from setHandshakeDomain method"); + } +} @end diff --git a/CleverTapSDKTests/CTDomainFactory+Tests.h b/CleverTapSDKTests/CTDomainFactory+Tests.h new file mode 100644 index 00000000..4d828936 --- /dev/null +++ b/CleverTapSDKTests/CTDomainFactory+Tests.h @@ -0,0 +1,14 @@ +// +// CTDomainFactory+Tests.h +// CleverTapSDKTests +// +// Created by Akash Malhotra on 12/09/24. +// Copyright © 2024 CleverTap. All rights reserved. +// + +#import "CleverTapInstanceConfig.h" +#import "CTDomainFactory.h" + +@interface CTDomainFactory (Tests) +- (NSString *)loadRedirectDomain; +@end diff --git a/CleverTapSDKTests/CTDomainFactoryTests.m b/CleverTapSDKTests/CTDomainFactoryTests.m new file mode 100644 index 00000000..4fcdabb6 --- /dev/null +++ b/CleverTapSDKTests/CTDomainFactoryTests.m @@ -0,0 +1,70 @@ +// +// CTDomainFactoryTests.m +// CleverTapSDKTests +// +// Created by Akash Malhotra on 12/09/24. +// Copyright © 2024 CleverTap. All rights reserved. +// +#import +#import +#import "CleverTapInstanceConfig.h" +#import "CTDomainFactory.h" +#import "CTDomainFactory+Tests.h" +#import "CTConstants.h" +#import "CTPreferences.h" + +@interface CTDomainFactoryTests: XCTestCase +@property (nonatomic, strong) NSString *region; +@property (nonatomic, strong) CleverTapInstanceConfig *config; +@property (nonatomic, strong) CTDomainFactory *domainFactory; +@end + +@implementation CTDomainFactoryTests + +- (void)setUp { + [super setUp]; + self.region = @"testRegion"; + self.config = [[CleverTapInstanceConfig alloc] initWithAccountId:@"testAccount" accountToken:@"testToken" accountRegion:self.region]; + self.domainFactory = [[CTDomainFactory alloc]initWithConfig:self.config]; +} + +- (void)tearDown { + [self.domainFactory clearRedirectDomain]; + self.domainFactory = nil; + self.region = nil; + [super tearDown]; +} + +- (void)testLoadRedirectDomainRegion { + NSString *domain = [self.domainFactory loadRedirectDomain]; + NSString *result = [NSString stringWithFormat:@"%@.%@", self.region, kCTApiDomain].lowercaseString; + XCTAssertEqualObjects(domain, result); +} + +- (void)testLoadRedirectDomainCached { + [self.domainFactory persistRedirectDomain]; + NSString *domain = [CTPreferences getStringForKey:[CTPreferences storageKeyWithSuffix:REDIRECT_DOMAIN_KEY config: self.config] withResetValue:nil]; + NSString *result = [self.domainFactory loadRedirectDomain]; + XCTAssertEqualObjects(domain, result); +} + +- (void)testLoadRedirectDomainCustomHandShake { + CleverTapInstanceConfig *config = [[CleverTapInstanceConfig alloc] initWithAccountId:@"testAccount" accountToken:@"testToken"]; + config.handshakeDomain = @"testCustomDomain"; + CTDomainFactory *domainFactory = [[CTDomainFactory alloc]initWithConfig:config]; + domainFactory.redirectDomain = config.handshakeDomain; + [domainFactory persistRedirectDomain]; + + NSString *domain = [domainFactory loadRedirectDomain];; + XCTAssertEqualObjects(domain, config.handshakeDomain); +} + +- (void)testLoadRedirectDomainProxy { + CleverTapInstanceConfig *config = [[CleverTapInstanceConfig alloc] initWithAccountId:@"testAccount" accountToken:@"testToken" proxyDomain:@"testProxydomain"]; + CTDomainFactory *domainFactory = [[CTDomainFactory alloc]initWithConfig:config]; + + NSString *domain = [domainFactory loadRedirectDomain]; + XCTAssertEqualObjects(domain, config.proxyDomain.lowercaseString); +} + +@end diff --git a/sdk-version.txt b/sdk-version.txt index 73a86b19..2f963cd6 100644 --- a/sdk-version.txt +++ b/sdk-version.txt @@ -1 +1 @@ -7.0.1 \ No newline at end of file +7.0.2 \ No newline at end of file