From a240961239e9bab77eddf31cb8cd6402fe8378fe Mon Sep 17 00:00:00 2001 From: Marat Al Date: Thu, 9 Dec 2021 21:32:09 +0100 Subject: [PATCH 1/8] Full reset of the device instead of nullify identity token details --- Source/ARTLocalDevice.h | 2 ++ Source/ARTLocalDevice.m | 15 +++++++++++++++ Source/ARTPushActivationState.m | 4 ++-- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/Source/ARTLocalDevice.h b/Source/ARTLocalDevice.h index 1c7e4a726..b14bce94a 100644 --- a/Source/ARTLocalDevice.h +++ b/Source/ARTLocalDevice.h @@ -16,6 +16,8 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)init NS_UNAVAILABLE; +- (void)reset; + @end NS_ASSUME_NONNULL_END diff --git a/Source/ARTLocalDevice.m b/Source/ARTLocalDevice.m index e0df4c325..c14f2d16d 100644 --- a/Source/ARTLocalDevice.m +++ b/Source/ARTLocalDevice.m @@ -110,4 +110,19 @@ - (BOOL)isRegistered { return _identityTokenDetails != nil; } +- (void)clearStorage { + for (NSString *key in @[ ARTDeviceIdKey, ARTDeviceIdentityTokenKey ]) { + [self.storage setObject:nil forKey:key]; + } +} + +- (void)reset { + self.id = @""; + self.secret = nil; + self.clientId = nil; + _identityTokenDetails = nil; + [self.push.recipient removeAllObjects]; + [self clearStorage]; +} + @end diff --git a/Source/ARTPushActivationState.m b/Source/ARTPushActivationState.m index 0e57f7378..04ea131a2 100644 --- a/Source/ARTPushActivationState.m +++ b/Source/ARTPushActivationState.m @@ -259,8 +259,8 @@ - (ARTPushActivationState *)transition:(ARTPushActivationEvent *)event { } else if ([event isKindOfClass:[ARTPushActivationEventDeregistered class]]) { #if TARGET_OS_IOS - ARTLocalDevice *local = self.machine.rest.device_nosync; - [local setAndPersistIdentityTokenDetails:nil]; + ARTLocalDevice *device = self.machine.rest.device_nosync; + [device reset]; #endif [self.machine callDeactivatedCallback:nil]; return [ARTPushActivationStateNotActivated newWithMachine:self.machine]; From c863d0133ddfdd1f9e4791c283621de052fae4f7 Mon Sep 17 00:00:00 2001 From: Marat Al Date: Thu, 9 Dec 2021 21:45:51 +0100 Subject: [PATCH 2/8] Tests updated for `reset` method --- .../PushActivationStateMachineTests.swift | 35 +++++++++---------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/Spec/Tests/PushActivationStateMachineTests.swift b/Spec/Tests/PushActivationStateMachineTests.swift index c944708c8..d135c5bb7 100644 --- a/Spec/Tests/PushActivationStateMachineTests.swift +++ b/Spec/Tests/PushActivationStateMachineTests.swift @@ -859,16 +859,16 @@ class PushActivationStateMachineTests: XCTestCase { } defer { hook.remove() } - var setAndPersistIdentityTokenDetailsCalled = false - let hookDevice = stateMachine.rest.device.testSuite_injectIntoMethod(after: NSSelectorFromString("setAndPersistIdentityTokenDetails:")) { - setAndPersistIdentityTokenDetailsCalled = true + var resetDeviceCalled = false + let hookDevice = stateMachine.rest.device.testSuite_injectIntoMethod(after: NSSelectorFromString("reset")) { + resetDeviceCalled = true } defer { hookDevice.remove() } stateMachine.send(ARTPushActivationEventDeregistered()) expect(stateMachine.current).to(beAKindOf(ARTPushActivationStateNotActivated.self)) expect(deactivatedCallbackCalled).to(beTrue()) - expect(setAndPersistIdentityTokenDetailsCalled).to(beTrue()) + expect(resetDeviceCalled).to(beTrue()) // RSH3g2a expect(stateMachine.rest.device.identityTokenDetails).to(beNil()) } @@ -1192,7 +1192,10 @@ class PushActivationStateMachineTests: XCTestCase { let delegate = StateMachineDelegate() stateMachine.delegate = delegate - + + let deviceId = rest.device.id + let deviceSecret = rest.device.secret + waitUntil(timeout: testTimeout) { done in let partialDone = AblyTests.splitDone(2, done: done) stateMachine.transitions = { event, _, currentState in @@ -1210,19 +1213,16 @@ class PushActivationStateMachineTests: XCTestCase { expect(stateMachine.current).to(beAKindOf(ARTPushActivationStateNotActivated.self)) expect(httpExecutor.requests.count) == 1 - let requests = httpExecutor.requests.compactMap { $0.url?.path }.filter { $0 == "/push/deviceRegistrations/\(rest.device.id)" } + let requests = httpExecutor.requests.filter({ $0.url?.path == "/push/deviceRegistrations/\(deviceId)" }) expect(requests).to(haveCount(1)) - guard let request = httpExecutor.requests.first else { - fail("should have a \"/push/deviceRegistrations\" request"); return - } - guard let url = request.url else { - fail("should have a \"/push/deviceRegistrations\" URL"); return + guard let request = requests.first, let url = request.url else { + fail("should have a '/push/deviceRegistrations/\(deviceId)' request"); return } expect(url.host).to(equal(rest.internal.options.restUrl().host)) expect(request.httpMethod) == "DELETE" expect(request.allHTTPHeaderFields?["Authorization"]).toNot(beNil()) let deviceAuthorization = request.allHTTPHeaderFields?["X-Ably-DeviceSecret"] - expect(deviceAuthorization).to(equal(rest.device.secret)) + expect(deviceAuthorization).to(equal(deviceSecret)) contextAfterEach?() } @@ -1241,6 +1241,8 @@ class PushActivationStateMachineTests: XCTestCase { capability: "", clientId: "" ) + + let deviceId = rest.device.id expect(rest.device.identityTokenDetails).to(beNil()) rest.device.setAndPersistIdentityTokenDetails(testIdentityTokenDetails) @@ -1264,13 +1266,10 @@ class PushActivationStateMachineTests: XCTestCase { expect(stateMachine.current).to(beAKindOf(ARTPushActivationStateNotActivated.self)) expect(httpExecutor.requests.count) == 1 - let requests = httpExecutor.requests.compactMap { $0.url?.path }.filter { $0 == "/push/deviceRegistrations/\(rest.device.id)" } + let requests = httpExecutor.requests.filter({ $0.url?.path == "/push/deviceRegistrations/\(deviceId)" }) expect(requests).to(haveCount(1)) - guard let request = httpExecutor.requests.first else { - fail("should have a \"/push/deviceRegistrations\" request"); return - } - guard let url = request.url else { - fail("should have a \"/push/deviceRegistrations\" URL"); return + guard let request = requests.first, let url = request.url else { + fail("should have a '/push/deviceRegistrations/\(deviceId)' request"); return } expect(url.host).to(equal(rest.internal.options.restUrl().host)) expect(request.httpMethod) == "DELETE" From 2fd80074289ec9d893d3cb765a88318108c1fcbb Mon Sep 17 00:00:00 2001 From: Marat Al Date: Sun, 12 Dec 2021 21:27:52 +0100 Subject: [PATCH 3/8] Global static shared device variable instead of local --- Source/ARTRest.m | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/Source/ARTRest.m b/Source/ARTRest.m index 7b34c57fc..cd3d155b0 100644 --- a/Source/ARTRest.m +++ b/Source/ARTRest.m @@ -716,6 +716,9 @@ - (void)setCurrentFallbackHost:(NSString *)value { } #if TARGET_OS_IOS + +static ARTLocalDevice *_sharedDevice; + - (ARTLocalDevice *)device { __block ARTLocalDevice *ret; dispatch_sync(_queue, ^{ @@ -724,9 +727,6 @@ - (ARTLocalDevice *)device { return ret; } -// Store address of once_token to access it in debug function. -static dispatch_once_t *device_once_token; - - (ARTLocalDevice *)device_nosync { // The device is shared in a static variable because it's a reflection // of what's persisted. Having a device instance per ARTRest instance @@ -736,17 +736,14 @@ - (ARTLocalDevice *)device_nosync { // As a side effect, the first instance "wins" at setting the device's // client ID. - static dispatch_once_t once; - device_once_token = &once; - static id device; - dispatch_once(&once, ^{ - device = [ARTLocalDevice load:self.auth.clientId_nosync storage:self.storage]; - }); - return device; + if (_sharedDevice == nil) { + _sharedDevice = [ARTLocalDevice load:self.auth.clientId_nosync storage:self.storage]; + } + return _sharedDevice; } - (void)resetDeviceSingleton { - if (device_once_token) *device_once_token = 0; + _sharedDevice = nil; } #endif From 1294191f20774355604c460d8802ddcd29c71931 Mon Sep 17 00:00:00 2001 From: Marat Al Date: Sat, 11 Dec 2021 17:58:00 +0100 Subject: [PATCH 4/8] Returning functioning local device object after `reset` was called --- Source/ARTAuth.m | 2 +- Source/ARTLocalDevice.h | 2 ++ Source/ARTLocalDevice.m | 4 ++++ Source/ARTPushActivationState.m | 8 ++++---- Source/ARTPushActivationStateMachine.m | 10 +++++----- Source/ARTPushChannel.m | 2 +- Source/ARTPushChannelSubscriptions.m | 4 ++-- Source/ARTPushDeviceRegistrations.m | 6 +++--- Source/ARTRest+Private.h | 1 + Source/ARTRest.m | 13 +++++++++++++ 10 files changed, 36 insertions(+), 16 deletions(-) diff --git a/Source/ARTAuth.m b/Source/ARTAuth.m index 1ecd8a534..7ab3d117a 100644 --- a/Source/ARTAuth.m +++ b/Source/ARTAuth.m @@ -809,7 +809,7 @@ - (NSString *_Nullable)appId { #if TARGET_OS_IOS - (void)setLocalDeviceClientId_nosync:(NSString *)clientId { - if (clientId == nil || [clientId isEqualToString:@"*"] || [clientId isEqualToString:_rest.device_nosync.clientId]) { + if (clientId == nil || [clientId isEqualToString:@"*"] || [clientId isEqualToString:[_rest loadDevice].clientId]) { return; } [_rest.device_nosync setClientId:clientId]; diff --git a/Source/ARTLocalDevice.h b/Source/ARTLocalDevice.h index b14bce94a..47d73a4f9 100644 --- a/Source/ARTLocalDevice.h +++ b/Source/ARTLocalDevice.h @@ -18,6 +18,8 @@ NS_ASSUME_NONNULL_BEGIN - (void)reset; +- (BOOL)isReset; + @end NS_ASSUME_NONNULL_END diff --git a/Source/ARTLocalDevice.m b/Source/ARTLocalDevice.m index c14f2d16d..da0d6b707 100644 --- a/Source/ARTLocalDevice.m +++ b/Source/ARTLocalDevice.m @@ -125,4 +125,8 @@ - (void)reset { [self clearStorage]; } +- (BOOL)isReset { + return [self.id isEqualToString:@""]; +} + @end diff --git a/Source/ARTPushActivationState.m b/Source/ARTPushActivationState.m index 04ea131a2..04d3186bd 100644 --- a/Source/ARTPushActivationState.m +++ b/Source/ARTPushActivationState.m @@ -74,7 +74,7 @@ @implementation ARTPushActivationPersistentState ARTPushActivationState *validateAndSync(ARTPushActivationStateMachine *machine, ARTPushActivationEvent *event) { #if TARGET_OS_IOS - ARTLocalDevice *const local = machine.rest.device_nosync; + ARTLocalDevice *const local = machine.rest.loadDevice; if (local.identityTokenDetails) { // Already registered. @@ -121,7 +121,7 @@ - (ARTPushActivationState *)transition:(ARTPushActivationEvent *)event { else if ([event isKindOfClass:[ARTPushActivationEventGotDeviceRegistration class]]) { #if TARGET_OS_IOS ARTPushActivationEventGotDeviceRegistration *gotDeviceRegistrationEvent = (ARTPushActivationEventGotDeviceRegistration *)event; - ARTLocalDevice *local = self.machine.rest.device_nosync; + ARTLocalDevice *local = self.machine.rest.loadDevice; [local setAndPersistIdentityTokenDetails:gotDeviceRegistrationEvent.identityTokenDetails]; #endif [self.machine callActivatedCallback:nil]; @@ -206,7 +206,7 @@ - (ARTPushActivationState *)transition:(ARTPushActivationEvent *)event { #if TARGET_OS_IOS ARTPushActivationEventRegistrationSynced *registrationUpdatedEvent = (ARTPushActivationEventRegistrationSynced *)event; if (registrationUpdatedEvent.identityTokenDetails) { - ARTLocalDevice *local = self.machine.rest.device_nosync; + ARTLocalDevice *local = self.machine.rest.loadDevice; [local setAndPersistIdentityTokenDetails:registrationUpdatedEvent.identityTokenDetails]; } #endif @@ -259,7 +259,7 @@ - (ARTPushActivationState *)transition:(ARTPushActivationEvent *)event { } else if ([event isKindOfClass:[ARTPushActivationEventDeregistered class]]) { #if TARGET_OS_IOS - ARTLocalDevice *device = self.machine.rest.device_nosync; + ARTLocalDevice *device = self.machine.rest.loadDevice; [device reset]; #endif [self.machine callDeactivatedCallback:nil]; diff --git a/Source/ARTPushActivationStateMachine.m b/Source/ARTPushActivationStateMachine.m index 49bb422c0..7dd7bf8f6 100644 --- a/Source/ARTPushActivationStateMachine.m +++ b/Source/ARTPushActivationStateMachine.m @@ -53,7 +53,7 @@ - (instancetype)initWithRest:(ARTRestInternal *const)rest // Due to bug #966, old versions of the library might have led us to an illegal // persisted state: we have a deviceToken, but the persisted push state is WaitingForPushDeviceDetails. // So we need to re-emit the GotPushDeviceDetails event that led us there. - if ([_current isKindOfClass:[ARTPushActivationStateWaitingForPushDeviceDetails class]] && rest.device_nosync.apnsDeviceToken != nil) { + if ([_current isKindOfClass:[ARTPushActivationStateWaitingForPushDeviceDetails class]] && [rest loadDevice].apnsDeviceToken != nil) { [rest.logger debug:@"ARTPush: re-emitting stored device details for stuck state machine"]; [self handleEvent:[ARTPushActivationEventGotPushDeviceDetails new]]; } @@ -137,7 +137,7 @@ - (void)persist { - (void)deviceRegistration:(ARTErrorInfo *)error { #if TARGET_OS_IOS - ARTLocalDevice *local = _rest.device_nosync; + ARTLocalDevice *local = _rest.loadDevice; const id delegate = self.delegate; @@ -200,7 +200,7 @@ - (void)deviceRegistration:(ARTErrorInfo *)error { - (void)deviceUpdateRegistration:(ARTErrorInfo *)error { #if TARGET_OS_IOS - ARTLocalDevice *local = _rest.device_nosync; + ARTLocalDevice *local = _rest.loadDevice; const id delegate = self.delegate; @@ -249,7 +249,7 @@ - (void)deviceUpdateRegistration:(ARTErrorInfo *)error { - (void)syncDevice { #if TARGET_OS_IOS - ARTLocalDevice *const local = _rest.device_nosync; + ARTLocalDevice *const local = _rest.loadDevice; const id delegate = self.delegate; @@ -306,7 +306,7 @@ - (void)syncDevice { - (void)deviceUnregistration:(ARTErrorInfo *)error { #if TARGET_OS_IOS - ARTLocalDevice *local = _rest.device_nosync; + ARTLocalDevice *local = _rest.loadDevice; __block id delegate = self.delegate; diff --git a/Source/ARTPushChannel.m b/Source/ARTPushChannel.m index 0729c5298..071515a4f 100644 --- a/Source/ARTPushChannel.m +++ b/Source/ARTPushChannel.m @@ -299,7 +299,7 @@ - (BOOL)listSubscriptions:(NSStringDictionary *)params - (ARTLocalDevice *)getDevice:(ARTCallback)callback { #if TARGET_OS_IOS - ARTLocalDevice *device = [_rest device_nosync]; + ARTLocalDevice *device = [_rest loadDevice]; #else ARTLocalDevice *device = nil; #endif diff --git a/Source/ARTPushChannelSubscriptions.m b/Source/ARTPushChannelSubscriptions.m index d38aacb50..3d97a70a8 100644 --- a/Source/ARTPushChannelSubscriptions.m +++ b/Source/ARTPushChannelSubscriptions.m @@ -73,7 +73,7 @@ - (void)save:(ARTPushChannelSubscription *)channelSubscription callback:(ARTCall } #if TARGET_OS_IOS - ARTLocalDevice *local = _rest.device; + ARTLocalDevice *local = _rest.loadDevice; #else ARTLocalDevice *local = nil; #endif @@ -203,7 +203,7 @@ - (void)_removeWhere:(NSStringDictionary *)params callback:(ARTCallback)callback NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[components URL]]; request.HTTPMethod = @"DELETE"; #if TARGET_OS_IOS - [request setDeviceAuthentication:[params objectForKey:@"deviceId"] localDevice:_rest.device_nosync]; + [request setDeviceAuthentication:[params objectForKey:@"deviceId"] localDevice:_rest.loadDevice]; #endif [_logger debug:__FILE__ line:__LINE__ message:@"remove channel subscription with request %@", request]; diff --git a/Source/ARTPushDeviceRegistrations.m b/Source/ARTPushDeviceRegistrations.m index da7d2acd4..8854a4b74 100644 --- a/Source/ARTPushDeviceRegistrations.m +++ b/Source/ARTPushDeviceRegistrations.m @@ -74,7 +74,7 @@ - (void)save:(ARTDeviceDetails *)deviceDetails callback:(ARTCallback)callback { } #if TARGET_OS_IOS - ARTLocalDevice *local = _rest.device; + ARTLocalDevice *local = _rest.loadDevice; #else ARTLocalDevice *local = nil; #endif @@ -128,7 +128,7 @@ - (void)get:(ARTDeviceId *)deviceId callback:(void (^)(ARTDeviceDetails *, ARTEr } #if TARGET_OS_IOS - ARTLocalDevice *local = _rest.device; + ARTLocalDevice *local = _rest.loadDevice; #else ARTLocalDevice *local = nil; #endif @@ -241,7 +241,7 @@ - (void)removeWhere:(NSStringDictionary *)params callback:(ARTCallback)callback } #if TARGET_OS_IOS - ARTLocalDevice *local = _rest.device; + ARTLocalDevice *local = _rest.loadDevice; #else ARTLocalDevice *local = nil; #endif diff --git a/Source/ARTRest+Private.h b/Source/ARTRest+Private.h index 0066d1a85..558e60b84 100644 --- a/Source/ARTRest+Private.h +++ b/Source/ARTRest+Private.h @@ -65,6 +65,7 @@ NS_ASSUME_NONNULL_BEGIN #if TARGET_OS_IOS - (void)resetDeviceSingleton; +- (ARTLocalDevice *)loadDevice; #endif @end diff --git a/Source/ARTRest.m b/Source/ARTRest.m index cd3d155b0..40b57f13c 100644 --- a/Source/ARTRest.m +++ b/Source/ARTRest.m @@ -742,6 +742,19 @@ - (ARTLocalDevice *)device_nosync { return _sharedDevice; } +/* + This function is needed to return functioning local device, since after `reset` call + you will end up with empty string as a device's `id` on the server. + */ +- (ARTLocalDevice *)loadDevice { + ARTLocalDevice *device = [self device_nosync]; + if (device.isReset) { + [self resetDeviceSingleton]; + device = [self device_nosync]; + } + return device; +} + - (void)resetDeviceSingleton { _sharedDevice = nil; } From 3db8d952d732b21d2835b38182357bfa4078e856 Mon Sep 17 00:00:00 2001 From: Marat Al Date: Fri, 10 Dec 2021 20:04:40 +0100 Subject: [PATCH 5/8] Moved APNS string from NSData creation into category --- Source/ARTPush+Private.h | 6 ++++++ Source/ARTPush.m | 24 ++++++++++++++++-------- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/Source/ARTPush+Private.h b/Source/ARTPush+Private.h index e78bbeb77..d08818da2 100644 --- a/Source/ARTPush+Private.h +++ b/Source/ARTPush+Private.h @@ -36,4 +36,10 @@ NS_ASSUME_NONNULL_BEGIN @end +@interface NSData (APNSToken) + +- (NSString *)apnsTokenString; + +@end + NS_ASSUME_NONNULL_END diff --git a/Source/ARTPush.m b/Source/ARTPush.m index f8f8ef585..e3b40ed48 100644 --- a/Source/ARTPush.m +++ b/Source/ARTPush.m @@ -169,14 +169,7 @@ - (ARTPushActivationStateMachine *)activationMachine { + (void)didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceTokenData restInternal:(ARTRestInternal *)rest { [rest.logger debug:@"ARTPush: device token data received: %@", [deviceTokenData base64EncodedStringWithOptions:0]]; - NSUInteger dataLength = deviceTokenData.length; - const unsigned char *dataBuffer = deviceTokenData.bytes; - NSMutableString *hexString = [NSMutableString stringWithCapacity:(dataLength * 2)]; - for (int i = 0; i < dataLength; ++i) { - [hexString appendFormat:@"%02x", dataBuffer[i]]; - } - - NSString *deviceToken = [hexString copy]; + NSString *deviceToken = [deviceTokenData apnsTokenString]; [rest.logger info:@"ARTPush: device token: %@", deviceToken]; NSString *currentDeviceToken = [rest.storage objectForKey:ARTAPNSDeviceTokenKey]; @@ -238,3 +231,18 @@ - (void)deactivate { #endif @end + + +@implementation NSData (APNSToken) + +- (NSString *)apnsTokenString { + NSUInteger dataLength = self.length; + const unsigned char *dataBuffer = self.bytes; + NSMutableString *hexString = [NSMutableString stringWithCapacity:(dataLength * 2)]; + for (int i = 0; i < dataLength; ++i) { + [hexString appendFormat:@"%02x", dataBuffer[i]]; + } + return [hexString copy]; +} + +@end From a414baa0dae8b5ebcf81fcd04f204e15f2ef7c7c Mon Sep 17 00:00:00 2001 From: Marat Al Date: Sun, 12 Dec 2021 21:17:15 +0100 Subject: [PATCH 6/8] ARTRestInternal now has static storage dispatch queue. --- Source/ARTPush.m | 5 +++-- Source/ARTRest+Private.h | 9 +++++++++ Source/ARTRest.m | 28 ++++++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/Source/ARTPush.m b/Source/ARTPush.m index e3b40ed48..9dbbe9b7a 100644 --- a/Source/ARTPush.m +++ b/Source/ARTPush.m @@ -172,13 +172,14 @@ + (void)didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceTokenDa NSString *deviceToken = [deviceTokenData apnsTokenString]; [rest.logger info:@"ARTPush: device token: %@", deviceToken]; - NSString *currentDeviceToken = [rest.storage objectForKey:ARTAPNSDeviceTokenKey]; + + NSString *currentDeviceToken = [rest apnsDeviceToken]; if ([currentDeviceToken isEqualToString:deviceToken]) { // Already stored. return; } - [rest.device_nosync setAndPersistAPNSDeviceToken:deviceToken]; + [rest setAndPersistAPNSDeviceToken:deviceToken]; [rest.logger debug:@"ARTPush: device token stored"]; [rest.push getActivationMachine:^(ARTPushActivationStateMachine *stateMachine) { [stateMachine sendEvent:[ARTPushActivationEventGotPushDeviceDetails new]]; diff --git a/Source/ARTRest+Private.h b/Source/ARTRest+Private.h index 558e60b84..7daa443d1 100644 --- a/Source/ARTRest+Private.h +++ b/Source/ARTRest+Private.h @@ -78,4 +78,13 @@ NS_ASSUME_NONNULL_BEGIN @end +@interface ARTRestInternal (Storage) + ++ (dispatch_queue_t)storageQueue; + +- (nullable NSString *)apnsDeviceToken; +- (void)setAndPersistAPNSDeviceToken:(nullable NSString *)deviceToken; + +@end + NS_ASSUME_NONNULL_END diff --git a/Source/ARTRest.m b/Source/ARTRest.m index 40b57f13c..d4f561664 100644 --- a/Source/ARTRest.m +++ b/Source/ARTRest.m @@ -761,3 +761,31 @@ - (void)resetDeviceSingleton { #endif @end + + +@implementation ARTRestInternal (Storage) + ++ (dispatch_queue_t)storageQueue { + static dispatch_queue_t queue; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + queue = dispatch_queue_create("io.ably.device-storage", DISPATCH_QUEUE_SERIAL); + }); + return queue; +} + +- (NSString *)apnsDeviceToken { + __block NSString *value; + dispatch_sync(ARTRestInternal.storageQueue, ^{ + value = [[self device_nosync] apnsDeviceToken]; + }); + return value; +} + +- (void)setAndPersistAPNSDeviceToken:(NSString *)deviceToken { + dispatch_sync(ARTRestInternal.storageQueue, ^{ + [[self device_nosync] setAndPersistAPNSDeviceToken:deviceToken]; + }); +} + +@end From ae91af882af872ec2167e47fc77bff93e0dd4ae0 Mon Sep 17 00:00:00 2001 From: Marat Al Date: Mon, 13 Dec 2021 00:06:45 +0100 Subject: [PATCH 7/8] ARTRestInternal Storage category visibility for iOS only --- Source/ARTRest+Private.h | 2 ++ Source/ARTRest.m | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Source/ARTRest+Private.h b/Source/ARTRest+Private.h index 7daa443d1..a0d7a9414 100644 --- a/Source/ARTRest+Private.h +++ b/Source/ARTRest+Private.h @@ -78,6 +78,7 @@ NS_ASSUME_NONNULL_BEGIN @end +#if TARGET_OS_IOS @interface ARTRestInternal (Storage) + (dispatch_queue_t)storageQueue; @@ -86,5 +87,6 @@ NS_ASSUME_NONNULL_BEGIN - (void)setAndPersistAPNSDeviceToken:(nullable NSString *)deviceToken; @end +#endif NS_ASSUME_NONNULL_END diff --git a/Source/ARTRest.m b/Source/ARTRest.m index d4f561664..45632f1c6 100644 --- a/Source/ARTRest.m +++ b/Source/ARTRest.m @@ -762,7 +762,7 @@ - (void)resetDeviceSingleton { @end - +#if TARGET_OS_IOS @implementation ARTRestInternal (Storage) + (dispatch_queue_t)storageQueue { @@ -789,3 +789,4 @@ - (void)setAndPersistAPNSDeviceToken:(NSString *)deviceToken { } @end +#endif From a88c282c0b88e58eb22adf7b272c49b6e649e264 Mon Sep 17 00:00:00 2001 From: Marat Al Date: Thu, 16 Dec 2021 17:35:32 +0100 Subject: [PATCH 8/8] Resetting device within storage queue --- Source/ARTPushActivationState.m | 3 +-- Source/ARTRest+Private.h | 1 + Source/ARTRest.m | 7 +++++++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/Source/ARTPushActivationState.m b/Source/ARTPushActivationState.m index 04d3186bd..e959fe751 100644 --- a/Source/ARTPushActivationState.m +++ b/Source/ARTPushActivationState.m @@ -259,8 +259,7 @@ - (ARTPushActivationState *)transition:(ARTPushActivationEvent *)event { } else if ([event isKindOfClass:[ARTPushActivationEventDeregistered class]]) { #if TARGET_OS_IOS - ARTLocalDevice *device = self.machine.rest.loadDevice; - [device reset]; + [self.machine.rest resetDevice]; #endif [self.machine callDeactivatedCallback:nil]; return [ARTPushActivationStateNotActivated newWithMachine:self.machine]; diff --git a/Source/ARTRest+Private.h b/Source/ARTRest+Private.h index a0d7a9414..c3c4b1f65 100644 --- a/Source/ARTRest+Private.h +++ b/Source/ARTRest+Private.h @@ -85,6 +85,7 @@ NS_ASSUME_NONNULL_BEGIN - (nullable NSString *)apnsDeviceToken; - (void)setAndPersistAPNSDeviceToken:(nullable NSString *)deviceToken; +- (void)resetDevice; @end #endif diff --git a/Source/ARTRest.m b/Source/ARTRest.m index 45632f1c6..d267fad55 100644 --- a/Source/ARTRest.m +++ b/Source/ARTRest.m @@ -788,5 +788,12 @@ - (void)setAndPersistAPNSDeviceToken:(NSString *)deviceToken { }); } +- (void)resetDevice { + dispatch_sync(ARTRestInternal.storageQueue, ^{ + ARTLocalDevice *device = [self device_nosync]; + [device reset]; + }); +} + @end #endif