Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Experimental #1854

Closed
wants to merge 25 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
98c94b1
Added method for generating device's `id` and `secret` when needed (o…
maratal Dec 21, 2023
94053aa
Added method for clearing all the device details (RSH3g2a).
maratal Dec 21, 2023
a49061d
Updated tests for the new device details loading behavior.
maratal Dec 21, 2023
be01fb3
Tests for RSH8b, RSH3a2b, RSH3g2a.
maratal Dec 21, 2023
8381e10
Fix for `nil` check.
maratal Dec 21, 2023
2f4b315
Updated func names.
maratal Jan 4, 2024
12521f8
Fixed call order.
maratal Jan 4, 2024
f16491b
Fixed return type for function fetching APNs device token.
maratal Jan 7, 2024
d5a9d82
Updated RSH8b and RSH3g2a tests.
maratal Jan 7, 2024
a6e39f7
Temp remove of other workflows.
maratal Jan 13, 2024
8355274
Avoid resetting deviceId until the new one is needed together with th…
maratal Jan 12, 2024
e54fa35
Temporarily ignore RSH8a/b, see https://github.com/ably/ably-cocoa/pu…
maratal Jan 12, 2024
6d31126
Fixed failing tests because of deviceId.
maratal Jan 13, 2024
10f66ef
Revert "Temp remove of other workflows."
maratal Jan 13, 2024
a2da9d4
Merge remote-tracking branch 'origin/main' into tmp-1177
maratal Jan 13, 2024
7fbbc50
Temp remove of other workflows.
maratal Jan 13, 2024
642e772
Removed unnecessary check for clientId.
maratal Jan 12, 2024
e987310
Setup device with the new clientId after validation.
maratal Jan 13, 2024
e212b05
Save clientId in its own storage value.
maratal Jan 12, 2024
3bde6ef
Updated RSH8a test to check clientId.
maratal Jan 13, 2024
77d6d63
Fixed tests affected by other tests by setting unexpected clientId in…
maratal Jan 13, 2024
510402d
Revert "Temp remove of other workflows."
maratal Jan 14, 2024
fec6580
Moved `registerForAPNS` to `validateAndSync` to keep proper call order.
maratal Jan 14, 2024
1bb7d48
Save clientId in its own storage value (fix).
maratal Jan 14, 2024
ef19492
Updated RSH8d and RSH8f tests.
maratal Jan 14, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Source/ARTAuth.m
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
#import "ARTPushActivationState.h"
#import "ARTFormEncode.h"
#import "ARTInternalLog.h"
#import "ARTLocalDeviceStorage.h"
#import "ARTLocalDevice+Private.h"

@implementation ARTAuth {
ARTQueuedDealloc *_dealloc;
Expand Down Expand Up @@ -824,6 +826,7 @@ - (void)setLocalDeviceClientId_nosync:(NSString *)clientId {
return;
}
[_rest.device_nosync setClientId:clientId];
[_rest.storage setObject:clientId forKey:ARTClientIdKey];
[_rest.push getActivationMachine:^(ARTPushActivationStateMachine *stateMachine) {
if (![stateMachine.current_nosync isKindOfClass:[ARTPushActivationStateNotActivated class]]) {
[stateMachine sendEvent:[[ARTPushActivationEventGotPushDeviceDetails alloc] init]];
Expand Down
65 changes: 47 additions & 18 deletions Source/ARTLocalDevice.m
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
NSString *const ARTDeviceSecretKey = @"ARTDeviceSecret";
NSString *const ARTDeviceIdentityTokenKey = @"ARTDeviceIdentityToken";
NSString *const ARTAPNSDeviceTokenKey = @"ARTAPNSDeviceToken";
NSString *const ARTClientIdKey = @"ARTClientId";

NSString *const ARTAPNSDeviceDefaultTokenType = @"default";
NSString *const ARTAPNSDeviceLocationTokenType = @"location";
Expand All @@ -46,17 +47,16 @@ @interface ARTLocalDevice ()

@implementation ARTLocalDevice

- (instancetype)initWithClientId:(NSString *)clientId storage:(id<ARTDeviceStorage>)storage logger:(nullable ARTInternalLog *)logger {
- (instancetype)initWithStorage:(id<ARTDeviceStorage>)storage logger:(nullable ARTInternalLog *)logger {
if (self = [super init]) {
self.clientId = clientId;
self.storage = storage;
_logger = logger;
}
return self;
}

+ (ARTLocalDevice *)load:(NSString *)clientId storage:(id<ARTDeviceStorage>)storage logger:(nullable ARTInternalLog *)logger {
ARTLocalDevice *device = [[ARTLocalDevice alloc] initWithClientId:clientId storage:storage logger:logger];
+ (instancetype)deviceWithStorage:(id<ARTDeviceStorage>)storage logger:(nullable ARTInternalLog *)logger {
ARTLocalDevice *device = [[ARTLocalDevice alloc] initWithStorage:storage logger:logger];
device.platform = ARTDevicePlatform;
#if TARGET_OS_IOS
switch ([[UIDevice currentDevice] userInterfaceIdiom]) {
Expand All @@ -75,21 +75,20 @@ + (ARTLocalDevice *)load:(NSString *)clientId storage:(id<ARTDeviceStorage>)stor
NSString *deviceId = [storage objectForKey:ARTDeviceIdKey];
NSString *deviceSecret = deviceId == nil ? nil : [storage secretForDevice:deviceId];

if (deviceId == nil || deviceSecret == nil) { // generate both at the same time
deviceId = [self generateId];
deviceSecret = [self generateSecret];

[storage setObject:deviceId forKey:ARTDeviceIdKey];
[storage setSecret:deviceSecret forDevice:deviceId];
}

device.id = deviceId;
device.id = deviceId ?: [self.class generateId]; // temporarily ignore RSH8a/b, see https://github.com/ably/ably-cocoa/pull/1847#discussion_r1441954284 thread
device.secret = deviceSecret;

id identityTokenDetailsInfo = [storage objectForKey:ARTDeviceIdentityTokenKey];
ARTDeviceIdentityTokenDetails *identityTokenDetails = [ARTDeviceIdentityTokenDetails unarchive:identityTokenDetailsInfo withLogger:logger];
device->_identityTokenDetails = identityTokenDetails;

NSString *clientId = [storage objectForKey:ARTClientIdKey];
if (clientId == nil && identityTokenDetails.clientId != nil) {
clientId = identityTokenDetails.clientId;
[storage setObject:clientId forKey:ARTClientIdKey];
}
device.clientId = clientId;

NSArray *supportedTokenTypes = @[
ARTAPNSDeviceDefaultTokenType,
ARTAPNSDeviceLocationTokenType
Expand All @@ -102,6 +101,40 @@ + (ARTLocalDevice *)load:(NSString *)clientId storage:(id<ARTDeviceStorage>)stor
return device;
}

- (void)setupDetailsWithClientId:(NSString *)clientId {
NSString *deviceId = self.id;
NSString *deviceSecret = self.secret;

if (deviceId == nil || deviceSecret == nil) { // generate both at the same time
deviceId = [self.class generateId];
deviceSecret = [self.class generateSecret];

[_storage setObject:deviceId forKey:ARTDeviceIdKey];
[_storage setSecret:deviceSecret forDevice:deviceId];
}

self.id = deviceId;
self.secret = deviceSecret;

self.clientId = clientId;
[_storage setObject:clientId forKey:ARTClientIdKey];
}

- (void)resetDetails {
self.secret = nil;
self.clientId = nil;
[_storage setSecret:nil forDevice:self.id];
[_storage setObject:nil forKey:ARTClientIdKey];
[self setAndPersistIdentityTokenDetails:nil];
NSArray *supportedTokenTypes = @[
ARTAPNSDeviceDefaultTokenType,
ARTAPNSDeviceLocationTokenType
];
for (NSString *tokenType in supportedTokenTypes) {
[self setAndPersistAPNSDeviceToken:nil tokenType:tokenType];
}
}

+ (NSString *)generateId {
return [NSUUID new].UUIDString;
}
Expand Down Expand Up @@ -146,16 +179,12 @@ - (void)setAndPersistIdentityTokenDetails:(ARTDeviceIdentityTokenDetails *)token
_identityTokenDetails = tokenDetails;
if (self.clientId == nil) {
self.clientId = tokenDetails.clientId;
[self.storage setObject:tokenDetails.clientId forKey:ARTClientIdKey];
}
}

- (BOOL)isRegistered {
return _identityTokenDetails != nil;
}

- (void)clearIdentityTokenDetailsAndClientId {
[self setAndPersistIdentityTokenDetails:nil];
self.clientId = nil;
}

@end
10 changes: 5 additions & 5 deletions Source/ARTPushActivationState.m
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,10 @@ @implementation ARTPushActivationPersistentState
#if TARGET_OS_IOS
ARTLocalDevice *const local = machine.rest.device_nosync;

NSString *const presentClientId = machine.rest.auth.clientId_nosync;
if (local.identityTokenDetails) {
// Already registered.
NSString *const instanceClientId = machine.rest.auth.clientId_nosync;
if (local.clientId != nil && instanceClientId && ![local.clientId isEqualToString:instanceClientId]) {
if (local.clientId != nil && presentClientId && ![local.clientId isEqualToString:presentClientId]) {
ARTErrorInfo *const error = [ARTErrorInfo createWithCode:61002 message:@"Activation failed: present clientId is not compatible with existing device registration"];
[machine sendEvent:[ARTPushActivationEventSyncRegistrationFailed newWithError:error]];
} else {
Expand All @@ -102,6 +102,8 @@ @implementation ARTPushActivationPersistentState
} else if ([local apnsDeviceToken]) {
[machine sendEvent:[ARTPushActivationEventGotPushDeviceDetails new]];
}
[local setupDetailsWithClientId:presentClientId];
[machine registerForAPNS];
#endif

return [ARTPushActivationStateWaitingForPushDeviceDetails newWithMachine:machine logger:logger];
Expand All @@ -116,7 +118,6 @@ - (ARTPushActivationState *)transition:(ARTPushActivationEvent *)event {
return self;
}
else if ([event isKindOfClass:[ARTPushActivationEventCalledActivate class]]) {
[self.machine registerForAPNS];
return validateAndSync(self.machine, event, self.logger);
}
return nil;
Expand Down Expand Up @@ -274,8 +275,7 @@ - (ARTPushActivationState *)transition:(ARTPushActivationEvent *)event {
}
else if ([event isKindOfClass:[ARTPushActivationEventDeregistered class]]) {
#if TARGET_OS_IOS
ARTLocalDevice *local = self.machine.rest.device_nosync;
[local clearIdentityTokenDetailsAndClientId];
[self.machine.rest resetLocalDevice_nosync];
#endif
[self.machine callDeactivatedCallback:nil];
return [ARTPushActivationStateNotActivated newWithMachine:self.machine logger:self.logger];
Expand Down
24 changes: 19 additions & 5 deletions Source/ARTRest.m
Original file line number Diff line number Diff line change
Expand Up @@ -744,10 +744,9 @@ - (ARTLocalDevice *)device {
}

- (ARTLocalDevice *)device_nosync {
NSString *clientId = self.auth.clientId_nosync;
__block ARTLocalDevice *ret;
dispatch_sync(ARTRestInternal.deviceAccessQueue, ^{
ret = [self deviceWithClientId_onlyCallOnDeviceAccessQueue:clientId];
dispatch_sync([ARTRestInternal deviceAccessQueue], ^{
ret = [self sharedDevice_onlyCallOnDeviceAccessQueue];
});
return ret;
}
Expand All @@ -765,7 +764,7 @@ + (dispatch_queue_t)deviceAccessQueue {

static BOOL sharedDeviceNeedsLoading_onlyAccessOnDeviceAccessQueue = YES;

- (ARTLocalDevice *)deviceWithClientId_onlyCallOnDeviceAccessQueue:(NSString *)clientId {
- (ARTLocalDevice *)sharedDevice_onlyCallOnDeviceAccessQueue {
// The device is shared in a static variable because it's a reflection
// of what's persisted. Having a device instance per ARTRest instance
// could leave some instances in a stale state, if, through another
Expand All @@ -776,12 +775,27 @@ - (ARTLocalDevice *)deviceWithClientId_onlyCallOnDeviceAccessQueue:(NSString *)c

static id device;
if (sharedDeviceNeedsLoading_onlyAccessOnDeviceAccessQueue) {
device = [ARTLocalDevice load:clientId storage:self.storage logger:self.logger];
device = [ARTLocalDevice deviceWithStorage:self.storage logger:self.logger];
sharedDeviceNeedsLoading_onlyAccessOnDeviceAccessQueue = NO;
}
return device;
}

- (void)setupLocalDevice_nosync {
ARTLocalDevice *device = [self device_nosync];
NSString *clientId = self.auth.clientId_nosync;
dispatch_sync([ARTRestInternal deviceAccessQueue], ^{
[device setupDetailsWithClientId:clientId];
});
}

- (void)resetLocalDevice_nosync {
ARTLocalDevice *device = [self device_nosync];
dispatch_sync([ARTRestInternal deviceAccessQueue], ^{
[device resetDetails];
});
}

- (void)resetDeviceSingleton {
dispatch_sync([ARTRestInternal deviceAccessQueue], ^{
sharedDeviceNeedsLoading_onlyAccessOnDeviceAccessQueue = YES;
Expand Down
8 changes: 5 additions & 3 deletions Source/PrivateHeaders/Ably/ARTLocalDevice+Private.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ extern NSString *const ARTDeviceIdKey;
extern NSString *const ARTDeviceSecretKey;
extern NSString *const ARTDeviceIdentityTokenKey;
extern NSString *const ARTAPNSDeviceTokenKey;
extern NSString *const ARTClientIdKey;

extern NSString *const ARTAPNSDeviceDefaultTokenType;
extern NSString *const ARTAPNSDeviceLocationTokenType;
Expand All @@ -19,18 +20,19 @@ NSString* ARTAPNSDeviceTokenKeyOfType(NSString * _Nullable tokenType);

@property (nonatomic) id<ARTDeviceStorage> storage;

+ (ARTLocalDevice *)load:(NSString *)clientId storage:(id<ARTDeviceStorage>)storage logger:(nullable ARTInternalLog *)logger;
+ (instancetype)deviceWithStorage:(id<ARTDeviceStorage>)storage logger:(nullable ARTInternalLog *)logger;
- (nullable NSString *)apnsDeviceToken;
- (void)setAndPersistAPNSDeviceToken:(nullable NSString *)deviceToken tokenType:(NSString *)tokenType;
- (void)setAndPersistAPNSDeviceToken:(nullable NSString *)deviceToken;
- (void)setAndPersistIdentityTokenDetails:(nullable ARTDeviceIdentityTokenDetails *)tokenDetails;
- (BOOL)isRegistered;
- (void)clearIdentityTokenDetailsAndClientId;
- (void)resetDetails;
- (void)setupDetailsWithClientId:(nullable NSString *)clientId;

+ (NSString *)generateId;
+ (NSString *)generateSecret;

+ (NSString *)apnsDeviceTokenOfType:(nullable NSString *)tokenType fromStorage:(id<ARTDeviceStorage>)storage;
+ (nullable NSString *)apnsDeviceTokenOfType:(nullable NSString *)tokenType fromStorage:(id<ARTDeviceStorage>)storage;

@end

Expand Down
3 changes: 3 additions & 0 deletions Source/PrivateHeaders/Ably/ARTRest+Private.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ NS_ASSUME_NONNULL_BEGIN
- (nullable NSObject<ARTCancellable> *)internetIsUp:(void (^)(BOOL isUp))cb;

#if TARGET_OS_IOS
- (void)setupLocalDevice_nosync;
- (void)resetLocalDevice_nosync;

// This is only intended to be called from test code.
- (void)resetDeviceSingleton;

Expand Down
Loading
Loading