diff --git a/Branch-TestBed/Branch-SDK-Tests/BNCRequestFactoryTests.m b/Branch-TestBed/Branch-SDK-Tests/BNCRequestFactoryTests.m index c185057..c28d3b6 100644 --- a/Branch-TestBed/Branch-SDK-Tests/BNCRequestFactoryTests.m +++ b/Branch-TestBed/Branch-SDK-Tests/BNCRequestFactoryTests.m @@ -8,15 +8,19 @@ #import #import "BNCRequestFactory.h" +#import "BranchConstants.h" +#import "BNCEncodingUtils.h" @interface BNCRequestFactoryTests : XCTestCase - +@property (nonatomic, copy, readwrite) NSString *requestUUID; +@property (nonatomic, copy, readwrite) NSNumber *requestCreationTimeStamp; @end @implementation BNCRequestFactoryTests - (void)setUp { - + _requestUUID = [[NSUUID UUID ] UUIDString]; + _requestCreationTimeStamp = BNCWireFormatFromDate([NSDate date]); } - (void)tearDown { @@ -24,32 +28,40 @@ - (void)tearDown { } - (void)testInitWithBranchKeyNil { - BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:nil]; + BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:nil UUID:_requestUUID TimeStamp:_requestCreationTimeStamp]; NSDictionary *json = [factory dataForInstallWithURLString:@"https://branch.io"]; XCTAssertNotNil(json); // key is omitted when nil XCTAssertNil([json objectForKey:@"branch_key"]); + XCTAssertTrue(self.requestCreationTimeStamp == [json objectForKey:BRANCH_REQUEST_KEY_REQUEST_CREATION_TIME_STAMP]); + XCTAssertTrue([self.requestUUID isEqualToString:[json objectForKey:BRANCH_REQUEST_KEY_REQUEST_UUID]]); } - (void)testInitWithBranchKeyEmpty { - BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:@""]; + BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:@"" UUID:self.requestUUID TimeStamp:self.requestCreationTimeStamp]; NSDictionary *json = [factory dataForInstallWithURLString:@"https://branch.io"]; XCTAssertNotNil(json); // empty string is allowed XCTAssertTrue([@"" isEqualToString:[json objectForKey:@"branch_key"]]); + + XCTAssertTrue(self.requestCreationTimeStamp == [json objectForKey:BRANCH_REQUEST_KEY_REQUEST_CREATION_TIME_STAMP]); + XCTAssertTrue([self.requestUUID isEqualToString:[json objectForKey:BRANCH_REQUEST_KEY_REQUEST_UUID]]); } - (void)testInitWithBranchKey { - BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:@"key_abcd"]; + BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:@"key_abcd" UUID:self.requestUUID TimeStamp:self.requestCreationTimeStamp]; NSDictionary *json = [factory dataForInstallWithURLString:@"https://branch.io"]; XCTAssertNotNil(json); XCTAssertTrue([@"key_abcd" isEqualToString:[json objectForKey:@"branch_key"]]); + + XCTAssertTrue(self.requestCreationTimeStamp == [json objectForKey:BRANCH_REQUEST_KEY_REQUEST_CREATION_TIME_STAMP]); + XCTAssertTrue([self.requestUUID isEqualToString:[json objectForKey:BRANCH_REQUEST_KEY_REQUEST_UUID]]); } - (void)testDataForInstall { - BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:@"key_abcd"]; + BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:@"key_abcd" UUID:self.requestUUID TimeStamp:self.requestCreationTimeStamp]; NSDictionary *json = [factory dataForInstallWithURLString:@"https://branch.io"]; XCTAssertNotNil(json); @@ -60,10 +72,13 @@ - (void)testDataForInstall { // not present on installs XCTAssertNil([json objectForKey:@"randomized_bundle_token"]); + + XCTAssertTrue(self.requestCreationTimeStamp == [json objectForKey:BRANCH_REQUEST_KEY_REQUEST_CREATION_TIME_STAMP]); + XCTAssertTrue([self.requestUUID isEqualToString:[json objectForKey:BRANCH_REQUEST_KEY_REQUEST_UUID]]); } - (void)testDataForOpen { - BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:@"key_abcd"]; + BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:@"key_abcd" UUID:self.requestUUID TimeStamp:self.requestCreationTimeStamp]; NSDictionary *json = [factory dataForOpenWithURLString:@"https://branch.io"]; XCTAssertNotNil(json); @@ -75,12 +90,15 @@ - (void)testDataForOpen { // Present only on opens. Assumes test runs after the host app completes an install. // This is not a reliable assumption on test runners //XCTAssertNotNil([json objectForKey:@"randomized_bundle_token"]); + + XCTAssertTrue(self.requestCreationTimeStamp == [json objectForKey:BRANCH_REQUEST_KEY_REQUEST_CREATION_TIME_STAMP]); + XCTAssertTrue([self.requestUUID isEqualToString:[json objectForKey:BRANCH_REQUEST_KEY_REQUEST_UUID]]); } - (void)testDataForEvent { NSDictionary *event = @{@"name": @"ADD_TO_CART"}; - BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:@"key_abcd"]; + BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:@"key_abcd" UUID:self.requestUUID TimeStamp:self.requestCreationTimeStamp]; NSDictionary *json = [factory dataForEventWithEventDictionary:[event mutableCopy]]; XCTAssertNotNil(json); @@ -89,6 +107,9 @@ - (void)testDataForEvent { NSDictionary *userData = [json objectForKey:@"user_data"]; XCTAssertNotNil(userData); XCTAssertNotNil([userData objectForKey:@"idfv"]); + + XCTAssertTrue(self.requestCreationTimeStamp == [json objectForKey:BRANCH_REQUEST_KEY_REQUEST_CREATION_TIME_STAMP]); + XCTAssertTrue([self.requestUUID isEqualToString:[json objectForKey:BRANCH_REQUEST_KEY_REQUEST_UUID]]); } - (void)testDataForEventWithContentItem { @@ -104,7 +125,7 @@ - (void)testDataForEventWithContentItem { ] }; - BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:@"key_abcd"]; + BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:@"key_abcd" UUID:self.requestUUID TimeStamp:self.requestCreationTimeStamp]; NSDictionary *json = [factory dataForEventWithEventDictionary:[event mutableCopy]]; XCTAssertNotNil(json); @@ -117,6 +138,9 @@ - (void)testDataForEventWithContentItem { NSDictionary *userData = [json objectForKey:@"user_data"]; XCTAssertNotNil(userData); XCTAssertNotNil([userData objectForKey:@"idfv"]); + + XCTAssertTrue(self.requestCreationTimeStamp == [json objectForKey:BRANCH_REQUEST_KEY_REQUEST_CREATION_TIME_STAMP]); + XCTAssertTrue([self.requestUUID isEqualToString:[json objectForKey:BRANCH_REQUEST_KEY_REQUEST_UUID]]); } - (void)testDataForEventWithTwoContentItem { @@ -138,7 +162,7 @@ - (void)testDataForEventWithTwoContentItem { ] }; - BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:@"key_abcd"]; + BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:@"key_abcd" UUID:self.requestUUID TimeStamp:self.requestCreationTimeStamp]; NSDictionary *json = [factory dataForEventWithEventDictionary:[event mutableCopy]]; XCTAssertNotNil(json); @@ -151,12 +175,15 @@ - (void)testDataForEventWithTwoContentItem { NSDictionary *userData = [json objectForKey:@"user_data"]; XCTAssertNotNil(userData); XCTAssertNotNil([userData objectForKey:@"idfv"]); + + XCTAssertTrue(self.requestCreationTimeStamp == [json objectForKey:BRANCH_REQUEST_KEY_REQUEST_CREATION_TIME_STAMP]); + XCTAssertTrue([self.requestUUID isEqualToString:[json objectForKey:BRANCH_REQUEST_KEY_REQUEST_UUID]]); } - (void)testDataForEventEmpty { NSDictionary *event = @{}; - BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:@"key_abcd"]; + BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:@"key_abcd" UUID:self.requestUUID TimeStamp:self.requestCreationTimeStamp]; NSDictionary *json = [factory dataForEventWithEventDictionary:[event mutableCopy]]; XCTAssertNotNil(json); @@ -165,10 +192,13 @@ - (void)testDataForEventEmpty { NSDictionary *userData = [json objectForKey:@"user_data"]; XCTAssertNotNil(userData); XCTAssertNotNil([userData objectForKey:@"idfv"]); + + XCTAssertTrue(self.requestCreationTimeStamp == [json objectForKey:BRANCH_REQUEST_KEY_REQUEST_CREATION_TIME_STAMP]); + XCTAssertTrue([self.requestUUID isEqualToString:[json objectForKey:BRANCH_REQUEST_KEY_REQUEST_UUID]]); } - (void)testDataForEventNil { - BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:@"key_abcd"]; + BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:@"key_abcd" UUID:self.requestUUID TimeStamp:self.requestCreationTimeStamp]; NSDictionary *json = [factory dataForEventWithEventDictionary:nil]; XCTAssertNotNil(json); @@ -177,19 +207,28 @@ - (void)testDataForEventNil { NSDictionary *userData = [json objectForKey:@"user_data"]; XCTAssertNotNil(userData); XCTAssertNotNil([userData objectForKey:@"idfv"]); + + XCTAssertTrue(self.requestCreationTimeStamp == [json objectForKey:BRANCH_REQUEST_KEY_REQUEST_CREATION_TIME_STAMP]); + XCTAssertTrue([self.requestUUID isEqualToString:[json objectForKey:BRANCH_REQUEST_KEY_REQUEST_UUID]]); } - (void)testDataForShortURL { - BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:@"key_abcd"]; + BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:@"key_abcd" UUID:self.requestUUID TimeStamp:self.requestCreationTimeStamp]; NSDictionary *json = [factory dataForShortURLWithLinkDataDictionary:@{}.mutableCopy isSpotlightRequest:NO]; XCTAssertNotNil(json); + + XCTAssertTrue(self.requestCreationTimeStamp == [json objectForKey:BRANCH_REQUEST_KEY_REQUEST_CREATION_TIME_STAMP]); + XCTAssertTrue([self.requestUUID isEqualToString:[json objectForKey:BRANCH_REQUEST_KEY_REQUEST_UUID]]); } - (void)testDataForLATD { - BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:@"key_abcd"]; + BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:@"key_abcd" UUID:self.requestUUID TimeStamp:self.requestCreationTimeStamp]; NSDictionary *json = [factory dataForLATDWithDataDictionary:@{}.mutableCopy]; XCTAssertNotNil(json); + + XCTAssertTrue(self.requestCreationTimeStamp == [json objectForKey:BRANCH_REQUEST_KEY_REQUEST_CREATION_TIME_STAMP]); + XCTAssertTrue([self.requestUUID isEqualToString:[json objectForKey:BRANCH_REQUEST_KEY_REQUEST_UUID]]); } @end diff --git a/Branch-TestBed/Branch-SDK-Tests/BNCServerRequestQueueTests.m b/Branch-TestBed/Branch-SDK-Tests/BNCServerRequestQueueTests.m index d99a1be..3dbbdd4 100644 --- a/Branch-TestBed/Branch-SDK-Tests/BNCServerRequestQueueTests.m +++ b/Branch-TestBed/Branch-SDK-Tests/BNCServerRequestQueueTests.m @@ -14,6 +14,8 @@ #import "BranchInstallRequest.h" #import "BranchOpenRequest.h" #import "BranchEvent.h" +#import "BranchShortURLRequest.h" +#import "BranchLATDRequest.h" @interface BNCServerRequestQueue () - (NSData *)archiveQueue:(NSArray *)queue; @@ -44,6 +46,15 @@ - (void)tearDown { self.queue = nil; } +- (NSArray *)getQueueCachedOnDisk { + NSMutableArray *decodedQueue = nil; + NSData *data = [NSData dataWithContentsOfURL:[BNCServerRequestQueue URLForQueueFile] options:0 error:nil]; + if (data) { + decodedQueue = [_queue unarchiveQueueFromData:data]; + } + return decodedQueue; +} + - (void)testArchiveNil { NSString *object = nil; @@ -168,11 +179,8 @@ - (void)testMultipleRequests { [_queue enqueue: openObject]; [_queue persistImmediately]; - NSMutableArray *decodedQueue = nil; - NSData *data = [NSData dataWithContentsOfURL:[BNCServerRequestQueue URLForQueueFile] options:0 error:nil]; - if (data) { - decodedQueue = [_queue unarchiveQueueFromData:data]; - } + NSArray *decodedQueue = [self getQueueCachedOnDisk]; + XCTAssert([decodedQueue count] == 2); [_queue clearQueue]; XCTAssert([_queue queueDepth] == 0); @@ -183,4 +191,182 @@ - (void)testMultipleRequests { XCTAssert([NSFileManager.defaultManager fileExistsAtPath:[[BNCServerRequestQueue URLForQueueFile] path]] == NO); } +- (void)testUUIDANDTimeStampPersistence { + BranchEventRequest *eventObject = [BranchEventRequest new]; + BranchOpenRequest *openObject = [BranchOpenRequest new]; + NSString *uuidFromEventObject = eventObject.requestUUID; + NSNumber *timeStampFromEventObject = eventObject.requestCreationTimeStamp; + NSString *uuidFromOpenObject = openObject.requestUUID; + NSNumber *timeStampFromOpenObject = openObject.requestCreationTimeStamp; + + XCTAssertTrue(![uuidFromEventObject isEqualToString:uuidFromOpenObject]); + + [_queue enqueue: eventObject]; + [_queue enqueue: openObject]; + [_queue persistImmediately]; + + NSArray *decodedQueue = [self getQueueCachedOnDisk]; + + for (id requestObject in decodedQueue) { + if ([requestObject isKindOfClass:BranchEventRequest.class]) { + XCTAssertTrue([uuidFromEventObject isEqualToString:[(BranchEventRequest *)requestObject requestUUID]]); + XCTAssertTrue([timeStampFromEventObject isEqualToNumber:[(BranchEventRequest *)requestObject requestCreationTimeStamp]]); + } + if ([requestObject isKindOfClass:BranchOpenRequest.class]) { + XCTAssertTrue([uuidFromOpenObject isEqualToString:[(BranchOpenRequest *)requestObject requestUUID]]); + XCTAssertTrue([timeStampFromOpenObject isEqualToNumber:[(BranchOpenRequest *)requestObject requestCreationTimeStamp]]); + } + } +} + +- (void)testUUIDANDTimeStampPersistenceForOpen { + BranchOpenRequest *openObject = [[BranchOpenRequest alloc] init]; + BranchOpenRequest *openWithCallbackObject = [[BranchOpenRequest alloc] initWithCallback:^(BOOL changed, NSError * _Nullable error) {}]; + openObject.urlString = @"https://www.branch.io"; + openWithCallbackObject.urlString = @"https://www.branch.testWithCallback.io"; + [_queue enqueue: openObject]; + [_queue enqueue: openWithCallbackObject]; + [_queue persistImmediately]; + + NSArray *decodedQueue = [self getQueueCachedOnDisk]; + + for (id requestObject in decodedQueue) { + if ([requestObject isKindOfClass:BranchOpenRequest.class]) { + BranchOpenRequest *tmpCopy = (BranchOpenRequest *)requestObject; + if ([tmpCopy.urlString isEqualToString:openObject.urlString]) { + XCTAssertTrue([tmpCopy.requestUUID isEqualToString:openObject.requestUUID]); + XCTAssertTrue([tmpCopy.requestCreationTimeStamp isEqualToNumber:openObject.requestCreationTimeStamp]); + } else if ([tmpCopy.urlString isEqualToString:openWithCallbackObject.urlString]) { + XCTAssertTrue([tmpCopy.requestUUID isEqualToString:openWithCallbackObject.requestUUID]); + XCTAssertTrue([tmpCopy.requestCreationTimeStamp isEqualToNumber:openWithCallbackObject.requestCreationTimeStamp]); + } else { + XCTFail("Invalid URL found"); + } + + } else { + XCTFail("Invalid Object type found"); + } + } +} + +- (void)testUUIDANDTimeStampPersistenceForInstall { + BranchInstallRequest *installObject = [[BranchInstallRequest alloc] init]; + BranchInstallRequest *installWithCallbackObject = [[BranchInstallRequest alloc] initWithCallback:^(BOOL changed, NSError * _Nullable error) {}]; + installObject.urlString = @"https://www.branch.io"; + installWithCallbackObject.urlString = @"https://www.branch.testWithCallback.io"; + [_queue enqueue: installObject]; + [_queue enqueue: installWithCallbackObject]; + [_queue persistImmediately]; + + NSArray *decodedQueue = [self getQueueCachedOnDisk]; + + for (id requestObject in decodedQueue) { + if ([requestObject isKindOfClass:BranchInstallRequest.class]) { + BranchInstallRequest *tmpCopy = (BranchInstallRequest *)requestObject; + if ([tmpCopy.urlString isEqualToString:installObject.urlString]) { + XCTAssertTrue([tmpCopy.requestUUID isEqualToString:installObject.requestUUID]); + XCTAssertTrue([tmpCopy.requestCreationTimeStamp isEqualToNumber:installObject.requestCreationTimeStamp]); + } else if ([tmpCopy.urlString isEqualToString:installWithCallbackObject.urlString]) { + XCTAssertTrue([tmpCopy.requestUUID isEqualToString:installWithCallbackObject.requestUUID]); + XCTAssertTrue([tmpCopy.requestCreationTimeStamp isEqualToNumber:installWithCallbackObject.requestCreationTimeStamp]); + } else { + XCTFail("Invalid URL found"); + } + } else { + XCTFail("Invalid Object type found"); + } + } +} + +- (void)testUUIDANDTimeStampPersistenceForEvent { + BranchEventRequest *eventObject = [[BranchEventRequest alloc] init]; + [_queue enqueue: eventObject]; + [_queue persistImmediately]; + + NSArray *decodedQueue = [self getQueueCachedOnDisk]; + + for (id requestObject in decodedQueue) { + if ([requestObject isKindOfClass:BranchEventRequest.class]) { + XCTAssertTrue([eventObject.requestUUID isEqualToString:((BranchEventRequest *)requestObject).requestUUID]); + XCTAssertTrue([eventObject.requestCreationTimeStamp isEqualToNumber:((BranchEventRequest *)requestObject).requestCreationTimeStamp]); + } else { + XCTFail("Invalid Object type found"); + } + } +} + +- (void)testUUIDANDTimeStampPersistenceForEventWithCallback { + + NSURL *url = [NSURL URLWithString:@"https://api3.branch.io/v2/event/standard"]; + BranchEventRequest *eventObject = [[BranchEventRequest alloc] initWithServerURL:url eventDictionary:nil completion:nil]; + + [_queue enqueue: eventObject]; + [_queue persistImmediately]; + + NSArray *decodedQueue = [self getQueueCachedOnDisk]; + + for (id requestObject in decodedQueue) { + if ([requestObject isKindOfClass:BranchEventRequest.class]) { + XCTAssertTrue([eventObject.requestUUID isEqualToString:((BranchEventRequest *)requestObject).requestUUID]); + XCTAssertTrue([eventObject.requestCreationTimeStamp isEqualToNumber:((BranchEventRequest *)requestObject).requestCreationTimeStamp]); + } else { + XCTFail("Invalid Object type found"); + } + } +} + +- (void)testUUIDANDTimeStampPersistenceForShortURL { + BranchShortUrlRequest *shortURLObject = [BranchShortUrlRequest new]; + [_queue enqueue: shortURLObject]; + [_queue persistImmediately]; + + NSArray *decodedQueue = [self getQueueCachedOnDisk]; + + for (id requestObject in decodedQueue) { + if ([requestObject isKindOfClass:BranchShortUrlRequest.class]) { + XCTAssertTrue([shortURLObject.requestUUID isEqualToString:((BranchShortUrlRequest *)requestObject).requestUUID]); + XCTAssertTrue([shortURLObject.requestCreationTimeStamp isEqualToNumber:((BranchShortUrlRequest *)requestObject).requestCreationTimeStamp]); + } else { + XCTFail("Invalid Object type found"); + } + } +} + +- (void)testUUIDANDTimeStampPersistenceForShortURLWithParams { + + BranchShortUrlRequest *shortURLObject = [[BranchShortUrlRequest alloc] initWithTags:nil alias:nil type:BranchLinkTypeUnlimitedUse matchDuration:0 channel:nil feature:nil stage:nil campaign:nil params:nil linkData:nil linkCache:nil callback:^(NSString * _Nullable url, NSError * _Nullable error) {}]; + [_queue enqueue: shortURLObject]; + [_queue persistImmediately]; + + NSArray *decodedQueue = [self getQueueCachedOnDisk]; + + for (id requestObject in decodedQueue) { + if ([requestObject isKindOfClass:BranchShortUrlRequest.class]) { + XCTAssertTrue([shortURLObject.requestUUID isEqualToString:((BranchShortUrlRequest *)requestObject).requestUUID]); + XCTAssertTrue([shortURLObject.requestCreationTimeStamp isEqualToNumber:((BranchShortUrlRequest *)requestObject).requestCreationTimeStamp]); + } else { + XCTFail("Invalid Object type found"); + } + } +} + +- (void)testUUIDANDTimeStampPersistenceForLATD { + + BranchLATDRequest *latdObject = [BranchLATDRequest new]; + [_queue enqueue: latdObject]; + [_queue persistImmediately]; + + NSArray *decodedQueue = [self getQueueCachedOnDisk]; + + for (id requestObject in decodedQueue) { + if ([requestObject isKindOfClass:BranchLATDRequest.class]) { + XCTAssertTrue([latdObject.requestUUID isEqualToString:((BranchLATDRequest *)requestObject).requestUUID]); + XCTAssertTrue([latdObject.requestCreationTimeStamp isEqualToNumber:((BranchLATDRequest *)requestObject).requestCreationTimeStamp]); + } else { + XCTFail("Invalid Object type found"); + } + } +} + + @end diff --git a/BranchSDK.podspec b/BranchSDK.podspec index de2775d..992acfa 100644 --- a/BranchSDK.podspec +++ b/BranchSDK.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "BranchSDK" - s.version = "3.6.3" + s.version = "3.6.4" s.summary = "Create an HTTP URL for any piece of content in your app" s.description = <<-DESC - Want the highest possible conversions on your sharing feature? diff --git a/BranchSDK.xcodeproj/project.pbxproj b/BranchSDK.xcodeproj/project.pbxproj index 528cd9c..7219bec 100644 --- a/BranchSDK.xcodeproj/project.pbxproj +++ b/BranchSDK.xcodeproj/project.pbxproj @@ -1974,7 +1974,7 @@ "@executable_path/Frameworks", "@loader_path/Frameworks", ); - MARKETING_VERSION = 3.6.3; + MARKETING_VERSION = 3.6.4; OTHER_LDFLAGS = ( "-weak_framework", LinkPresentation, @@ -2009,7 +2009,7 @@ "@executable_path/Frameworks", "@loader_path/Frameworks", ); - MARKETING_VERSION = 3.6.3; + MARKETING_VERSION = 3.6.4; OTHER_LDFLAGS = ( "-weak_framework", LinkPresentation, @@ -2215,7 +2215,7 @@ "@loader_path/Frameworks", ); MACH_O_TYPE = staticlib; - MARKETING_VERSION = 3.6.3; + MARKETING_VERSION = 3.6.4; OTHER_LDFLAGS = ( "-weak_framework", LinkPresentation, @@ -2254,7 +2254,7 @@ "@loader_path/Frameworks", ); MACH_O_TYPE = staticlib; - MARKETING_VERSION = 3.6.3; + MARKETING_VERSION = 3.6.4; OTHER_LDFLAGS = ( "-weak_framework", LinkPresentation, @@ -2291,7 +2291,7 @@ "@executable_path/Frameworks", "@loader_path/Frameworks", ); - MARKETING_VERSION = 3.6.3; + MARKETING_VERSION = 3.6.4; OTHER_LDFLAGS = ( "-weak_framework", LinkPresentation, @@ -2326,7 +2326,7 @@ "@executable_path/Frameworks", "@loader_path/Frameworks", ); - MARKETING_VERSION = 3.6.3; + MARKETING_VERSION = 3.6.4; OTHER_LDFLAGS = ( "-weak_framework", LinkPresentation, diff --git a/ChangeLog.md b/ChangeLog.md index 0b3065d..e18e514 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,5 +1,8 @@ Branch iOS SDK Change Log +v.3.6.4 +- Added 'branch_sdk_request_unique_id' and 'branch_sdk_request_timestamp' to post params of all the SDK requests. + v.3.6.3 - Fix for duplicate events created from archived request queue on disk. diff --git a/Sources/BranchSDK/BNCConfig.m b/Sources/BranchSDK/BNCConfig.m index 2b661ef..a2c0f23 100644 --- a/Sources/BranchSDK/BNCConfig.m +++ b/Sources/BranchSDK/BNCConfig.m @@ -8,7 +8,7 @@ #include "BNCConfig.h" -NSString * const BNC_SDK_VERSION = @"3.6.3"; +NSString * const BNC_SDK_VERSION = @"3.6.4"; NSString * const BNC_LINK_URL = @"https://bnc.lt"; NSString * const BNC_CDN_URL = @"https://cdn.branch.io"; diff --git a/Sources/BranchSDK/BNCQRCodeCache.m b/Sources/BranchSDK/BNCQRCodeCache.m index b77723e..eb23f2e 100644 --- a/Sources/BranchSDK/BNCQRCodeCache.m +++ b/Sources/BranchSDK/BNCQRCodeCache.m @@ -7,6 +7,7 @@ // #import "BNCQRCodeCache.h" +#import "BranchConstants.h" @interface BNCQRCodeCache() @property (nonatomic, strong) NSMutableDictionary *cache; @@ -35,6 +36,8 @@ - (void)addQRCodeToCache:(NSData *)qrCodeData withParams:(NSMutableDictionary *) @synchronized (self) { [self.cache removeAllObjects]; NSMutableDictionary *tempParams = [parameters mutableCopy]; + [tempParams removeObjectForKey:BRANCH_REQUEST_KEY_REQUEST_CREATION_TIME_STAMP]; + [tempParams removeObjectForKey:BRANCH_REQUEST_KEY_REQUEST_UUID]; [tempParams[@"data"] removeObjectForKey:@"$creation_timestamp"]; self.cache[tempParams] = qrCodeData; } @@ -45,6 +48,8 @@ - (NSData *)checkQRCodeCache:(NSMutableDictionary *)parameters { @synchronized (self) { NSMutableDictionary *tempParams = [parameters mutableCopy]; [tempParams[@"data"] removeObjectForKey:@"$creation_timestamp"]; + [tempParams removeObjectForKey:BRANCH_REQUEST_KEY_REQUEST_CREATION_TIME_STAMP]; + [tempParams removeObjectForKey:BRANCH_REQUEST_KEY_REQUEST_UUID]; qrCode = self.cache[tempParams]; } return qrCode; diff --git a/Sources/BranchSDK/BNCRequestFactory.m b/Sources/BranchSDK/BNCRequestFactory.m index a7d79b2..12ad738 100644 --- a/Sources/BranchSDK/BNCRequestFactory.m +++ b/Sources/BranchSDK/BNCRequestFactory.m @@ -47,12 +47,14 @@ @interface BNCRequestFactory() @property (nonatomic, strong, readwrite) BNCSKAdNetwork *skAdNetwork; @property (nonatomic, strong, readwrite) BNCAppleReceipt *appleReceipt; @property (nonatomic, strong, readwrite) BNCPasteboard *pasteboard; +@property (nonatomic, strong, readwrite) NSNumber *requestCreationTimeStamp; +@property (nonatomic, strong, readwrite) NSString *requestUUID; @end @implementation BNCRequestFactory -- (instancetype)initWithBranchKey:(NSString *)key { +- (instancetype)initWithBranchKey:(NSString *)key UUID:(NSString *)requestUUID TimeStamp:(NSNumber *)requestTimeStamp { self = [super init]; if (self) { self.branchKey = key; @@ -65,6 +67,8 @@ - (instancetype)initWithBranchKey:(NSString *)key { self.skAdNetwork = [BNCSKAdNetwork sharedInstance]; self.appleReceipt = [BNCAppleReceipt sharedInstance]; self.pasteboard = [BNCPasteboard sharedInstance]; + self.requestUUID = requestUUID; + self.requestCreationTimeStamp = requestTimeStamp; } return self; } @@ -426,6 +430,8 @@ - (void)addAppClipDataToJSON:(NSMutableDictionary *)json { - (void)addDefaultRequestDataToJSON:(NSMutableDictionary *)json { json[@"branch_key"] = self.branchKey; + json[BRANCH_REQUEST_KEY_REQUEST_UUID] = self.requestUUID; + json[BRANCH_REQUEST_KEY_REQUEST_CREATION_TIME_STAMP] = self.requestCreationTimeStamp; // omit field if value is NO if ([self isTrackingDisabled]) { diff --git a/Sources/BranchSDK/BNCServerRequest.m b/Sources/BranchSDK/BNCServerRequest.m index decdf92..d176755 100644 --- a/Sources/BranchSDK/BNCServerRequest.m +++ b/Sources/BranchSDK/BNCServerRequest.m @@ -8,9 +8,19 @@ #import "BNCServerRequest.h" #import "BranchLogger.h" +#import "BNCEncodingUtils.h" @implementation BNCServerRequest +- (id) init { + if ((self = [super init])) { + NSDate *timeStamp = [NSDate date]; + _requestUUID = [BNCServerRequest generateRequestUUIDFromDate:timeStamp]; + _requestCreationTimeStamp = BNCWireFormatFromDate(timeStamp); + } + return self; +} + - (void)makeRequest:(BNCServerInterface *)serverInterface key:(NSString *)key callback:(BNCServerCallback)callback { [[BranchLogger shared] logError:@"BNCServerRequest subclasses must implement makeRequest:key:callback:." error:nil]; } @@ -20,11 +30,17 @@ - (void)processResponse:(BNCServerResponse *)response error:(NSError *)error { } - (id)initWithCoder:(NSCoder *)aDecoder { - return self = [super init]; + self = [super init]; + if (self) { + self.requestUUID = [aDecoder decodeObjectOfClass:NSString.class forKey:@"requestUUID"]; + self.requestCreationTimeStamp = [aDecoder decodeObjectOfClass:NSNumber.class forKey:@"requestCreationTimeStamp"]; + } + return self; } - (void)encodeWithCoder:(NSCoder *)coder { - // Nothing going on here + [coder encodeObject:self.requestUUID forKey:@"requestUUID"]; + [coder encodeObject:self.requestCreationTimeStamp forKey:@"requestCreationTimeStamp"]; } - (void)safeSetValue:(NSObject *)value forKey:(NSString *)key onDict:(NSMutableDictionary *)dict { @@ -37,4 +53,15 @@ + (BOOL)supportsSecureCoding { return YES; } ++ (NSString *) generateRequestUUIDFromDate:(NSDate *) localDate { + NSString *uuid = [[NSUUID UUID ] UUIDString]; + + NSTimeZone *gmt = [NSTimeZone timeZoneWithAbbreviation:@"GMT"]; + NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; + dateFormatter.dateFormat = @"'-'yyyyMMddHH"; + [dateFormatter setTimeZone:gmt]; + + return [uuid stringByAppendingString:[dateFormatter stringFromDate:localDate]]; +} + @end diff --git a/Sources/BranchSDK/BranchConstants.m b/Sources/BranchSDK/BranchConstants.m index 9674937..290e930 100644 --- a/Sources/BranchSDK/BranchConstants.m +++ b/Sources/BranchSDK/BranchConstants.m @@ -166,3 +166,6 @@ NSString * const BRANCH_REQUEST_KEY_DMA_AD_PEROSALIZATION = @"dma_ad_personalization"; NSString * const BRANCH_REQUEST_KEY_DMA_AD_USER_DATA = @"dma_ad_user_data"; +NSString * const BRANCH_REQUEST_KEY_REQUEST_UUID = @"branch_sdk_request_unique_id"; +NSString * const BRANCH_REQUEST_KEY_REQUEST_CREATION_TIME_STAMP = @"branch_sdk_request_timestamp"; + diff --git a/Sources/BranchSDK/BranchEvent.m b/Sources/BranchSDK/BranchEvent.m index e763417..b16c813 100644 --- a/Sources/BranchSDK/BranchEvent.m +++ b/Sources/BranchSDK/BranchEvent.m @@ -77,7 +77,7 @@ - (void)makeRequest:(BNCServerInterface *)serverInterface key:(NSString *)key callback:(BNCServerCallback)callback { - BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:key]; + BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:key UUID:self.requestUUID TimeStamp:self.requestCreationTimeStamp]; NSDictionary *json = [factory dataForEventWithEventDictionary:[self.eventDictionary mutableCopy]]; [serverInterface postRequest:json url:[self.serverURL absoluteString] key:key callback:callback]; diff --git a/Sources/BranchSDK/BranchInstallRequest.m b/Sources/BranchSDK/BranchInstallRequest.m index f4aa50f..1c3c0a5 100644 --- a/Sources/BranchSDK/BranchInstallRequest.m +++ b/Sources/BranchSDK/BranchInstallRequest.m @@ -19,7 +19,7 @@ - (id)initWithCallback:(callbackWithStatus)callback { } - (void)makeRequest:(BNCServerInterface *)serverInterface key:(NSString *)key callback:(BNCServerCallback)callback { - BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:key]; + BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:key UUID:self.requestUUID TimeStamp:self.requestCreationTimeStamp]; NSDictionary *params = [factory dataForInstallWithURLString:self.urlString]; [serverInterface postRequest:params url:[[BNCServerAPI sharedInstance] installServiceURL] key:key callback:callback]; diff --git a/Sources/BranchSDK/BranchLATDRequest.m b/Sources/BranchSDK/BranchLATDRequest.m index 330cf3c..c22fd88 100644 --- a/Sources/BranchSDK/BranchLATDRequest.m +++ b/Sources/BranchSDK/BranchLATDRequest.m @@ -33,7 +33,7 @@ - (NSMutableDictionary *)dataDictionary { } - (void)makeRequest:(BNCServerInterface *)serverInterface key:(NSString *)key callback:(BNCServerCallback)callback { - BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:key]; + BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:key UUID:self.requestUUID TimeStamp:self.requestCreationTimeStamp]; NSDictionary *json = [factory dataForLATDWithDataDictionary:[self dataDictionary]]; [serverInterface postRequest:json url:[self serverURL] key:key callback:callback]; } diff --git a/Sources/BranchSDK/BranchOpenRequest.m b/Sources/BranchSDK/BranchOpenRequest.m index d817d9a..a05c5bf 100644 --- a/Sources/BranchSDK/BranchOpenRequest.m +++ b/Sources/BranchSDK/BranchOpenRequest.m @@ -47,7 +47,7 @@ - (id)initWithCallback:(callbackWithStatus)callback isInstall:(BOOL)isInstall { } - (void)makeRequest:(BNCServerInterface *)serverInterface key:(NSString *)key callback:(BNCServerCallback)callback { - BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:key]; + BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:key UUID:self.requestUUID TimeStamp:self.requestCreationTimeStamp]; NSDictionary *params = [factory dataForOpenWithURLString:self.urlString]; [serverInterface postRequest:params diff --git a/Sources/BranchSDK/BranchQRCode.m b/Sources/BranchSDK/BranchQRCode.m index c42319f..32182de 100644 --- a/Sources/BranchSDK/BranchQRCode.m +++ b/Sources/BranchSDK/BranchQRCode.m @@ -15,6 +15,8 @@ #import "UIViewController+Branch.h" #import "BranchLogger.h" #import "BNCServerAPI.h" +#import "BranchConstants.h" +#import "BNCEncodingUtils.h" @interface BranchQRCode() @property (nonatomic, copy, readwrite) NSString *buoTitle; @@ -91,6 +93,10 @@ - (void)getQRCodeAsData:(nullable BranchUniversalObject *)buo parameters[@"data"] = [buo dictionary]; parameters[@"branch_key"] = [Branch branchKey]; + NSDate *timestamp = [NSDate date]; + parameters[BRANCH_REQUEST_KEY_REQUEST_CREATION_TIME_STAMP] = BNCWireFormatFromDate(timestamp); + parameters[BRANCH_REQUEST_KEY_REQUEST_UUID] = [BNCServerRequest generateRequestUUIDFromDate:timestamp]; + NSData *cachedQRCode = [[BNCQRCodeCache sharedInstance] checkQRCodeCache:parameters]; if (cachedQRCode) { completion(cachedQRCode, nil); @@ -136,8 +142,7 @@ - (void)callQRCodeAPI:(nullable NSDictionary *)params NSData *postData = [NSJSONSerialization dataWithJSONObject:params options:0 error:&error]; [request setHTTPBody:postData]; - - [[BranchLogger shared] logDebug:[NSString stringWithFormat:@"Network start operation %@.", request.URL.absoluteString] error:nil]; + [[BranchLogger shared] logDebug:[NSString stringWithFormat:@"Network start operation %@.\n Body %@", request.URL.absoluteString, [BNCEncodingUtils prettyPrintJSON:params]] error:nil]; NSDate *startDate = [NSDate date]; NSURLSessionDataTask *postDataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { diff --git a/Sources/BranchSDK/BranchShortUrlRequest.m b/Sources/BranchSDK/BranchShortUrlRequest.m index 7ce0400..90f41dd 100644 --- a/Sources/BranchSDK/BranchShortUrlRequest.m +++ b/Sources/BranchSDK/BranchShortUrlRequest.m @@ -57,7 +57,7 @@ - (void)makeRequest:(BNCServerInterface *)serverInterface key:(NSString *)key callback:(BNCServerCallback)callback { - BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:key]; + BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:key UUID:self.requestUUID TimeStamp:self.requestCreationTimeStamp]; NSDictionary *json = [factory dataForShortURLWithLinkDataDictionary:[self.linkData.data mutableCopy] isSpotlightRequest:self.isSpotlightRequest]; [serverInterface postRequest:json diff --git a/Sources/BranchSDK/BranchShortUrlSyncRequest.m b/Sources/BranchSDK/BranchShortUrlSyncRequest.m index 3cbf8da..0850df8 100644 --- a/Sources/BranchSDK/BranchShortUrlSyncRequest.m +++ b/Sources/BranchSDK/BranchShortUrlSyncRequest.m @@ -28,7 +28,8 @@ @interface BranchShortUrlSyncRequest () @property (strong, nonatomic) NSDictionary *params; @property (strong, nonatomic) BNCLinkCache *linkCache; @property (strong, nonatomic) BNCLinkData *linkData; - +@property (nonatomic, copy, readwrite) NSString *requestUUID; +@property (nonatomic, copy, readwrite) NSNumber *requestCreationTimeStamp; @end @implementation BranchShortUrlSyncRequest @@ -46,13 +47,15 @@ - (id)initWithTags:(NSArray *)tags alias:(NSString *)alias type:(BranchLinkType) _params = params; _linkCache = linkCache; _linkData = linkData; + _requestUUID = [[NSUUID UUID ] UUIDString]; + _requestCreationTimeStamp = BNCWireFormatFromDate([NSDate date]); } return self; } - (BNCServerResponse *)makeRequest:(BNCServerInterface *)serverInterface key:(NSString *)key { - BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:key]; + BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:key UUID:self.requestUUID TimeStamp:self.requestCreationTimeStamp]; NSDictionary *json = [factory dataForShortURLWithLinkDataDictionary:[self.linkData.data mutableCopy] isSpotlightRequest:NO]; return [serverInterface postRequestSynchronous:json diff --git a/Sources/BranchSDK/Private/BNCRequestFactory.h b/Sources/BranchSDK/Private/BNCRequestFactory.h index 0732aee..697154b 100644 --- a/Sources/BranchSDK/Private/BNCRequestFactory.h +++ b/Sources/BranchSDK/Private/BNCRequestFactory.h @@ -20,7 +20,7 @@ NS_ASSUME_NONNULL_BEGIN */ @interface BNCRequestFactory : NSObject -- (instancetype)initWithBranchKey:(NSString *)key NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithBranchKey:(NSString *)key UUID:(NSString *)requestUUID TimeStamp:(NSNumber *)requestTimeStamp NS_DESIGNATED_INITIALIZER; - (instancetype)init NS_UNAVAILABLE; - (NSDictionary *)dataForInstallWithURLString:(nullable NSString *)urlString; diff --git a/Sources/BranchSDK/Private/BranchConstants.h b/Sources/BranchSDK/Private/BranchConstants.h index da64586..a366ee1 100644 --- a/Sources/BranchSDK/Private/BranchConstants.h +++ b/Sources/BranchSDK/Private/BranchConstants.h @@ -167,3 +167,6 @@ extern NSString * const BRANCH_REQUEST_KEY_VALUE_POSTBACK_SEQUENCE_INDEX_2; extern NSString * const BRANCH_REQUEST_KEY_DMA_EEA; extern NSString * const BRANCH_REQUEST_KEY_DMA_AD_PEROSALIZATION; extern NSString * const BRANCH_REQUEST_KEY_DMA_AD_USER_DATA; + +extern NSString * const BRANCH_REQUEST_KEY_REQUEST_UUID; +extern NSString * const BRANCH_REQUEST_KEY_REQUEST_CREATION_TIME_STAMP; diff --git a/Sources/BranchSDK/Public/BNCServerRequest.h b/Sources/BranchSDK/Public/BNCServerRequest.h index 5da9f76..9b65ff5 100644 --- a/Sources/BranchSDK/Public/BNCServerRequest.h +++ b/Sources/BranchSDK/Public/BNCServerRequest.h @@ -10,7 +10,11 @@ @interface BNCServerRequest : NSObject +@property (nonatomic, copy, readwrite) NSString *requestUUID; +@property (nonatomic, copy, readwrite) NSNumber *requestCreationTimeStamp; + - (void)makeRequest:(BNCServerInterface *)serverInterface key:(NSString *)key callback:(BNCServerCallback)callback; - (void)processResponse:(BNCServerResponse *)response error:(NSError *)error; - (void)safeSetValue:(NSObject *)value forKey:(NSString *)key onDict:(NSMutableDictionary *)dict; ++ (NSString *) generateRequestUUIDFromDate:(NSDate *) localDate; @end diff --git a/scripts/version.sh b/scripts/version.sh index 70c4ee2..f1ba477 100755 --- a/scripts/version.sh +++ b/scripts/version.sh @@ -30,7 +30,7 @@ Options: USAGE } -version=3.6.3 +version=3.6.4 prev_version="$version" if (( $# == 0 )); then