From 756b1c3d1da17047b9ad3a421e7070bd1a2b0105 Mon Sep 17 00:00:00 2001 From: David Langley Date: Thu, 6 Jan 2022 20:35:37 +0000 Subject: [PATCH] Split MXKAccount from Data so just data can be loaded from disk without side effects. Also change force reload of accounts to stop double load on init. --- .../AuthenticationViewController.m | 2 +- .../MXKAuthenticationViewController.m | 2 + .../MatrixKit/Models/Account/MXKAccount.h | 77 +----- .../MatrixKit/Models/Account/MXKAccount.m | 229 +++++------------- .../MatrixKit/Models/Account/MXKAccountData.h | 141 +++++++++++ .../MatrixKit/Models/Account/MXKAccountData.m | 150 ++++++++++++ .../Models/Account/MXKAccountManager.h | 9 +- .../Models/Account/MXKAccountManager.m | 87 +++++-- RiotNSE/NotificationService.swift | 10 +- RiotShareExtension/Shared/ShareDataSource.m | 4 +- RiotShareExtension/Shared/ShareManager.m | 6 +- 11 files changed, 445 insertions(+), 272 deletions(-) create mode 100644 Riot/Modules/MatrixKit/Models/Account/MXKAccountData.h create mode 100644 Riot/Modules/MatrixKit/Models/Account/MXKAccountData.m diff --git a/Riot/Modules/Authentication/AuthenticationViewController.m b/Riot/Modules/Authentication/AuthenticationViewController.m index 188e33268..6bc35a5b0 100644 --- a/Riot/Modules/Authentication/AuthenticationViewController.m +++ b/Riot/Modules/Authentication/AuthenticationViewController.m @@ -340,7 +340,7 @@ static const CGFloat kAuthInputContainerViewMinHeightConstraintConstant = 150.0; didCheckFalseAuthScreenDisplay = YES; MXLogDebug(@"[AuthenticationVC] viewDidAppear: Checking false logout"); - [[MXKAccountManager sharedManager] forceReloadAccounts]; + [MXKAccountManager sharedManagerWithReload: YES]; if ([MXKAccountManager sharedManager].activeAccounts.count) { // For now, we do not have better solution than forcing the user to restart the app diff --git a/Riot/Modules/MatrixKit/Controllers/MXKAuthenticationViewController.m b/Riot/Modules/MatrixKit/Controllers/MXKAuthenticationViewController.m index 91a1eda04..acccd6a29 100644 --- a/Riot/Modules/MatrixKit/Controllers/MXKAuthenticationViewController.m +++ b/Riot/Modules/MatrixKit/Controllers/MXKAuthenticationViewController.m @@ -1451,6 +1451,8 @@ MXRestClient *mxRestClient = [[MXRestClient alloc] initWithCredentials:credentials andOnUnrecognizedCertificateBlock:^BOOL(NSData *certificate) { return NO; + } andPersistentTokenDataHandler:^(void (^handler)(NSArray *credentials, void (^completion)(BOOL didUpdateCredentials))) { + [[MXKAccountManager sharedManager] readAndWriteCredentials:handler]; }]; MXWeakify(self); diff --git a/Riot/Modules/MatrixKit/Models/Account/MXKAccount.h b/Riot/Modules/MatrixKit/Models/Account/MXKAccount.h index 8d21f6e72..5e928299c 100644 --- a/Riot/Modules/MatrixKit/Models/Account/MXKAccount.h +++ b/Riot/Modules/MatrixKit/Models/Account/MXKAccount.h @@ -17,6 +17,7 @@ */ #import +#import "MXKAccountData.h" @class MXKAccount; @@ -56,29 +57,7 @@ typedef BOOL (^MXKAccountOnCertificateChange)(MXKAccount *mxAccount, NSData *cer `MXKAccount` object contains the credentials of a logged matrix user. It is used to handle matrix session and presence for this user. */ -@interface MXKAccount : NSObject - -/** - The account's credentials: homeserver, access token, user id. - */ -@property (nonatomic, readonly) MXCredentials *mxCredentials; - -/** - The identity server URL. - */ -@property (nonatomic) NSString *identityServerURL; - -/** - The antivirus server URL, if any (nil by default). - Set a non-null url to configure the antivirus scanner use. - */ -@property (nonatomic) NSString *antivirusServerURL; - -/** - The Push Gateway URL used to send event notifications to (nil by default). - This URL should be over HTTPS and never over HTTP. - */ -@property (nonatomic) NSString *pushGatewayURL; +@interface MXKAccount : MXKAccountData /** The matrix REST client used to make matrix API requests. @@ -107,12 +86,6 @@ typedef BOOL (^MXKAccountOnCertificateChange)(MXKAccount *mxAccount, NSData *cer */ @property (nonatomic, readonly) NSString *fullDisplayName; -/** - The 3PIDs linked to this account. - [self load3PIDs] must be called to update the property. - */ -@property (nonatomic, readonly) NSArray *threePIDs; - /** The email addresses linked to this account. This is a subset of self.threePIDs. @@ -125,12 +98,6 @@ typedef BOOL (^MXKAccountOnCertificateChange)(MXKAccount *mxAccount, NSData *cer */ @property (nonatomic, readonly) NSArray *linkedPhoneNumbers; -/** - The account user's device. - [self loadDeviceInformation] must be called to update the property. - */ -@property (nonatomic, readonly) MXDevice *device; - /** The account user's presence (`MXPresenceUnknown` by default, available if matrix session `mxSession` is opened). The notification `kMXKAccountUserInfoDidChangeNotification` is posted in case of change of this property. @@ -148,11 +115,6 @@ typedef BOOL (^MXKAccountOnCertificateChange)(MXKAccount *mxAccount, NSData *cer */ @property (nonatomic, readonly) BOOL pushNotificationServiceIsActive; -/** - Transient information storage. - */ -@property (nonatomic, strong, readonly) NSMutableDictionary> *others; - /** Enable Push notification based on Apple Push Notification Service (APNS). @@ -166,11 +128,6 @@ typedef BOOL (^MXKAccountOnCertificateChange)(MXKAccount *mxAccount, NSData *cer success:(void (^)(void))success failure:(void (^)(NSError *))failure; -/** - Flag to indicate that an APNS pusher has been set on the homeserver for this device. - */ -@property (nonatomic, readonly) BOOL hasPusherForPushNotifications; - /** The Push notification activity (based on PushKit) for this account. YES when Push is turned on (locally available and enabled homeserver side). @@ -190,26 +147,6 @@ typedef BOOL (^MXKAccountOnCertificateChange)(MXKAccount *mxAccount, NSData *cer success:(void (^)(void))success failure:(void (^)(NSError *))failure; -/** - Flag to indicate that a PushKit pusher has been set on the homeserver for this device. - */ -@property (nonatomic, readonly) BOOL hasPusherForPushKitNotifications; - - -/** - Enable In-App notifications based on Remote notifications rules. - NO by default. - */ -@property (nonatomic) BOOL enableInAppNotifications; - -/** - Disable the account without logging out (NO by default). - - A matrix session is automatically opened for the account when this property is toggled from YES to NO. - The session is closed when this property is set to YES. - */ -@property (nonatomic,getter=isDisabled) BOOL disabled; - /** Manage the online presence event. @@ -217,11 +154,6 @@ typedef BOOL (^MXKAccountOnCertificateChange)(MXKAccount *mxAccount, NSData *cer */ @property (nonatomic) BOOL hideUserPresence; -/** - Flag indicating if the end user has been warned about encryption and its limitations. - */ -@property (nonatomic,getter=isWarnedAboutEncryption) BOOL warnedAboutEncryption; - /** Register the MXKAccountOnCertificateChange block that will be used to handle certificate change during account use. This block is nil by default, any new certificate is ignored/untrusted (this will abort the connection to the server). @@ -284,11 +216,6 @@ typedef BOOL (^MXKAccountOnCertificateChange)(MXKAccount *mxAccount, NSData *cer #pragma mark - Soft logout -/** - Flag to indicate if the account has been logged out by the homeserver admin. - */ -@property (nonatomic, readonly) BOOL isSoftLogout; - /** Soft logout the account. diff --git a/Riot/Modules/MatrixKit/Models/Account/MXKAccount.m b/Riot/Modules/MatrixKit/Models/Account/MXKAccount.m index 359cf9ff4..25482b6b5 100644 --- a/Riot/Modules/MatrixKit/Models/Account/MXKAccount.m +++ b/Riot/Modules/MatrixKit/Models/Account/MXKAccount.m @@ -92,13 +92,10 @@ static NSArray *initialSyncSilentErrorsHTTPStatusCodes; @property (nonatomic, strong) id backgroundTask; @property (nonatomic, strong) id backgroundSyncBgTask; -@property (nonatomic, strong) NSMutableDictionary> *others; - @end @implementation MXKAccount -@synthesize mxCredentials, mxSession, mxRestClient; -@synthesize threePIDs; +@synthesize mxSession, mxRestClient; @synthesize userPresence; @synthesize userTintColor; @synthesize hideUserPresence; @@ -144,7 +141,7 @@ static NSArray *initialSyncSilentErrorsHTTPStatusCodes; notifyOpenSessionFailure = YES; // Report credentials and alloc REST client. - mxCredentials = credentials; + _mxCredentials = credentials; [self prepareRESTClient]; userPresence = MXPresenceUnknown; @@ -171,67 +168,19 @@ static NSArray *initialSyncSilentErrorsHTTPStatusCodes; - (id)initWithCoder:(NSCoder *)coder { - self = [super init]; + self = [super initWithCoder:coder]; if (self) { notifyOpenSessionFailure = YES; - NSString *homeServerURL = [coder decodeObjectForKey:@"homeserverurl"]; - NSString *userId = [coder decodeObjectForKey:@"userid"]; - NSString *accessToken = [coder decodeObjectForKey:@"accesstoken"]; - _identityServerURL = [coder decodeObjectForKey:@"identityserverurl"]; - NSString *identityServerAccessToken = [coder decodeObjectForKey:@"identityserveraccesstoken"]; - - mxCredentials = [[MXCredentials alloc] initWithHomeServer:homeServerURL - userId:userId - accessToken:accessToken]; - - mxCredentials.accessTokenExpiresAt = [coder decodeInt64ForKey:@"accessTokenExpiresAt"]; - mxCredentials.refreshToken = [coder decodeObjectForKey:@"refreshToken"]; - mxCredentials.identityServer = _identityServerURL; - mxCredentials.identityServerAccessToken = identityServerAccessToken; - mxCredentials.deviceId = [coder decodeObjectForKey:@"deviceId"]; - mxCredentials.allowedCertificate = [coder decodeObjectForKey:@"allowedCertificate"]; - [self prepareRESTClient]; [self registerAccountDataDidChangeIdentityServerNotification]; [self registerIdentityServiceDidChangeAccessTokenNotification]; - if ([coder decodeObjectForKey:@"threePIDs"]) - { - threePIDs = [coder decodeObjectForKey:@"threePIDs"]; - } - - if ([coder decodeObjectForKey:@"device"]) - { - _device = [coder decodeObjectForKey:@"device"]; - } - userPresence = MXPresenceUnknown; - if ([coder decodeObjectForKey:@"antivirusserverurl"]) - { - _antivirusServerURL = [coder decodeObjectForKey:@"antivirusserverurl"]; - } - - if ([coder decodeObjectForKey:@"pushgatewayurl"]) - { - _pushGatewayURL = [coder decodeObjectForKey:@"pushgatewayurl"]; - } - - _hasPusherForPushNotifications = [coder decodeBoolForKey:@"_enablePushNotifications"]; - _hasPusherForPushKitNotifications = [coder decodeBoolForKey:@"enablePushKitNotifications"]; - _enableInAppNotifications = [coder decodeBoolForKey:@"enableInAppNotifications"]; - - _disabled = [coder decodeBoolForKey:@"disabled"]; - _isSoftLogout = [coder decodeBoolForKey:@"isSoftLogout"]; - - _warnedAboutEncryption = [coder decodeBoolForKey:@"warnedAboutEncryption"]; - - _others = [coder decodeObjectForKey:@"others"]; - // Refresh device information [self loadDeviceInformation:nil failure:nil]; } @@ -239,66 +188,6 @@ static NSArray *initialSyncSilentErrorsHTTPStatusCodes; return self; } -- (void)encodeWithCoder:(NSCoder *)coder -{ - [coder encodeObject:mxCredentials.homeServer forKey:@"homeserverurl"]; - [coder encodeObject:mxCredentials.userId forKey:@"userid"]; - [coder encodeObject:mxCredentials.accessToken forKey:@"accesstoken"]; - if (mxCredentials.accessTokenExpiresAt) { - [coder encodeInt64:mxCredentials.accessTokenExpiresAt forKey:@"accessTokenExpiresAt"]; - } - if (mxCredentials.refreshToken) { - [coder encodeObject:mxCredentials.refreshToken forKey:@"refreshToken"]; - } - [coder encodeObject:mxCredentials.identityServerAccessToken forKey:@"identityserveraccesstoken"]; - - if (mxCredentials.deviceId) - { - [coder encodeObject:mxCredentials.deviceId forKey:@"deviceId"]; - } - - if (mxCredentials.allowedCertificate) - { - [coder encodeObject:mxCredentials.allowedCertificate forKey:@"allowedCertificate"]; - } - - if (self.threePIDs) - { - [coder encodeObject:threePIDs forKey:@"threePIDs"]; - } - - if (self.device) - { - [coder encodeObject:_device forKey:@"device"]; - } - - if (self.identityServerURL) - { - [coder encodeObject:_identityServerURL forKey:@"identityserverurl"]; - } - - if (self.antivirusServerURL) - { - [coder encodeObject:_antivirusServerURL forKey:@"antivirusserverurl"]; - } - - if (self.pushGatewayURL) - { - [coder encodeObject:_pushGatewayURL forKey:@"pushgatewayurl"]; - } - - [coder encodeBool:_hasPusherForPushNotifications forKey:@"_enablePushNotifications"]; - [coder encodeBool:_hasPusherForPushKitNotifications forKey:@"enablePushKitNotifications"]; - [coder encodeBool:_enableInAppNotifications forKey:@"enableInAppNotifications"]; - - [coder encodeBool:_disabled forKey:@"disabled"]; - [coder encodeBool:_isSoftLogout forKey:@"isSoftLogout"]; - - [coder encodeBool:_warnedAboutEncryption forKey:@"warnedAboutEncryption"]; - - [coder encodeObject:_others forKey:@"others"]; -} - #pragma mark - Properties - (void)setIdentityServerURL:(NSString *)identityServerURL @@ -306,10 +195,10 @@ static NSArray *initialSyncSilentErrorsHTTPStatusCodes; if (identityServerURL.length) { _identityServerURL = identityServerURL; - mxCredentials.identityServer = identityServerURL; + self.mxCredentials.identityServer = identityServerURL; // Update services used in MXSession - [mxSession setIdentityServer:mxCredentials.identityServer andAccessToken:mxCredentials.identityServerAccessToken]; + [mxSession setIdentityServer:self.mxCredentials.identityServer andAccessToken:self.mxCredentials.identityServerAccessToken]; } else { @@ -363,24 +252,24 @@ static NSArray *initialSyncSilentErrorsHTTPStatusCodes; { if (self.userDisplayName.length) { - return [NSString stringWithFormat:@"%@ (%@)", self.userDisplayName, mxCredentials.userId]; + return [NSString stringWithFormat:@"%@ (%@)", self.userDisplayName, self.mxCredentials.userId]; } else { - return mxCredentials.userId; + return self.mxCredentials.userId; } } -- (NSArray *)threePIDs -{ - return threePIDs; -} +//- (NSArray *)threePIDs +//{ +// return _threePIDs; +//} - (NSArray *)linkedEmails { NSMutableArray *linkedEmails = [NSMutableArray array]; - for (MXThirdPartyIdentifier *threePID in threePIDs) + for (MXThirdPartyIdentifier *threePID in self.threePIDs) { if ([threePID.medium isEqualToString:kMX3PIDMediumEmail]) { @@ -395,7 +284,7 @@ static NSArray *initialSyncSilentErrorsHTTPStatusCodes; { NSMutableArray *linkedPhoneNumbers = [NSMutableArray array]; - for (MXThirdPartyIdentifier *threePID in threePIDs) + for (MXThirdPartyIdentifier *threePID in self.threePIDs) { if ([threePID.medium isEqualToString:kMX3PIDMediumMSISDN]) { @@ -410,7 +299,7 @@ static NSArray *initialSyncSilentErrorsHTTPStatusCodes; { if (!userTintColor) { - userTintColor = [MXKTools colorWithRGBValue:[mxCredentials.userId hash]]; + userTintColor = [MXKTools colorWithRGBValue:[self.mxCredentials.userId hash]]; } return userTintColor; @@ -418,7 +307,7 @@ static NSArray *initialSyncSilentErrorsHTTPStatusCodes; - (BOOL)pushNotificationServiceIsActive { - BOOL pushNotificationServiceIsActive = ([[MXKAccountManager sharedManager] isAPNSAvailable] && _hasPusherForPushNotifications && mxSession); + BOOL pushNotificationServiceIsActive = ([[MXKAccountManager sharedManager] isAPNSAvailable] && self.hasPusherForPushNotifications && mxSession); MXLogDebug(@"[MXKAccount][Push] pushNotificationServiceIsActive: %@", @(pushNotificationServiceIsActive)); return pushNotificationServiceIsActive; @@ -469,7 +358,7 @@ static NSArray *initialSyncSilentErrorsHTTPStatusCodes; } } } - else if (_hasPusherForPushNotifications) + else if (self.hasPusherForPushNotifications) { MXLogDebug(@"[MXKAccount][Push] enablePushNotifications: Disable APNS for %@ account", self.mxCredentials.userId); @@ -495,7 +384,7 @@ static NSArray *initialSyncSilentErrorsHTTPStatusCodes; - (BOOL)isPushKitNotificationActive { - BOOL isPushKitNotificationActive = ([[MXKAccountManager sharedManager] isPushAvailable] && _hasPusherForPushKitNotifications && mxSession); + BOOL isPushKitNotificationActive = ([[MXKAccountManager sharedManager] isPushAvailable] && self.hasPusherForPushKitNotifications && mxSession); MXLogDebug(@"[MXKAccount][Push] isPushKitNotificationActive: %@", @(isPushKitNotificationActive)); return isPushKitNotificationActive; @@ -543,7 +432,7 @@ static NSArray *initialSyncSilentErrorsHTTPStatusCodes; failure (error); } } - else if (_hasPusherForPushKitNotifications) + else if (self.hasPusherForPushKitNotifications) { MXLogDebug(@"[MXKAccount][Push] enablePushKitNotifications: Disable Push for %@ account", self.mxCredentials.userId); @@ -641,7 +530,7 @@ static NSArray *initialSyncSilentErrorsHTTPStatusCodes; success(); } - [[NSNotificationCenter defaultCenter] postNotificationName:kMXKAccountUserInfoDidChangeNotification object:self->mxCredentials.userId]; + [[NSNotificationCenter defaultCenter] postNotificationName:kMXKAccountUserInfoDidChangeNotification object:self.mxCredentials.userId]; } failure:failure]; } @@ -661,7 +550,7 @@ static NSArray *initialSyncSilentErrorsHTTPStatusCodes; success(); } - [[NSNotificationCenter defaultCenter] postNotificationName:kMXKAccountUserInfoDidChangeNotification object:self->mxCredentials.userId]; + [[NSNotificationCenter defaultCenter] postNotificationName:kMXKAccountUserInfoDidChangeNotification object:self.mxCredentials.userId]; } failure:failure]; } @@ -694,9 +583,9 @@ static NSArray *initialSyncSilentErrorsHTTPStatusCodes; - (void)load3PIDs:(void (^)(void))success failure:(void (^)(NSError *))failure { + [mxRestClient threePIDs:^(NSArray *threePIDs2) { - - self->threePIDs = threePIDs2; + self->_threePIDs = threePIDs2; // Archive updated field [[MXKAccountManager sharedManager] saveAccounts]; @@ -716,9 +605,9 @@ static NSArray *initialSyncSilentErrorsHTTPStatusCodes; - (void)loadDeviceInformation:(void (^)(void))success failure:(void (^)(NSError *error))failure { - if (mxCredentials.deviceId) + if (self.mxCredentials.deviceId) { - [mxRestClient deviceByDeviceId:mxCredentials.deviceId success:^(MXDevice *device) { + [mxRestClient deviceByDeviceId:self.mxCredentials.deviceId success:^(MXDevice *device) { self->_device = device; @@ -759,21 +648,21 @@ static NSArray *initialSyncSilentErrorsHTTPStatusCodes; [mxSession.myUser setPresence:userPresence andStatusMessage:statusMessage success:^{ - MXLogDebug(@"[MXKAccount] %@: set user presence (%lu) succeeded", self->mxCredentials.userId, (unsigned long)self->userPresence); + MXLogDebug(@"[MXKAccount] %@: set user presence (%lu) succeeded", self.mxCredentials.userId, (unsigned long)self->userPresence); if (completion) { completion(); } - [[NSNotificationCenter defaultCenter] postNotificationName:kMXKAccountUserInfoDidChangeNotification object:self->mxCredentials.userId]; + [[NSNotificationCenter defaultCenter] postNotificationName:kMXKAccountUserInfoDidChangeNotification object:self.mxCredentials.userId]; } failure:^(NSError *error) { - MXLogDebug(@"[MXKAccount] %@: set user presence (%lu) failed", self->mxCredentials.userId, (unsigned long)self->userPresence); + MXLogDebug(@"[MXKAccount] %@: set user presence (%lu) failed", self.mxCredentials.userId, (unsigned long)self->userPresence); }]; } else if (hideUserPresence) { - MXLogDebug(@"[MXKAccount] %@: set user presence is disabled.", mxCredentials.userId); + MXLogDebug(@"[MXKAccount] %@: set user presence is disabled.", self.mxCredentials.userId); } } @@ -791,7 +680,7 @@ static NSArray *initialSyncSilentErrorsHTTPStatusCodes; -(void)openSessionWithStore:(id)store { // Sanity check - if (!mxCredentials || !mxRestClient) + if (!self.mxCredentials || !mxRestClient) { MXLogDebug(@"[MXKAccount] Matrix session cannot be created without credentials"); return; @@ -1056,9 +945,9 @@ static NSArray *initialSyncSilentErrorsHTTPStatusCodes; - (void)hydrateWithCredentials:(MXCredentials*)credentials { // Sanity check - if ([mxCredentials.userId isEqualToString:credentials.userId]) + if ([self.mxCredentials.userId isEqualToString:credentials.userId]) { - mxCredentials = credentials; + _mxCredentials = credentials; _isSoftLogout = NO; [[MXKAccountManager sharedManager] saveAccounts]; @@ -1066,11 +955,13 @@ static NSArray *initialSyncSilentErrorsHTTPStatusCodes; } else { - MXLogDebug(@"[MXKAccount] hydrateWithCredentials: Error: users ids mismatch: %@ vs %@", credentials.userId, mxCredentials.userId); + MXLogDebug(@"[MXKAccount] hydrateWithCredentials: Error: users ids mismatch: %@ vs %@", credentials.userId, self.mxCredentials.userId); } } + + - (void)deletePusher { if (self.pushNotificationServiceIsActive) @@ -1267,7 +1158,7 @@ static NSArray *initialSyncSilentErrorsHTTPStatusCodes; success(); } - [[NSNotificationCenter defaultCenter] postNotificationName:kMXKAccountAPNSActivityDidChangeNotification object:self->mxCredentials.userId]; + [[NSNotificationCenter defaultCenter] postNotificationName:kMXKAccountAPNSActivityDidChangeNotification object:self.mxCredentials.userId]; } failure:^(NSError *error) { @@ -1286,7 +1177,7 @@ static NSArray *initialSyncSilentErrorsHTTPStatusCodes; success(); } - [[NSNotificationCenter defaultCenter] postNotificationName:kMXKAccountAPNSActivityDidChangeNotification object:self->mxCredentials.userId]; + [[NSNotificationCenter defaultCenter] postNotificationName:kMXKAccountAPNSActivityDidChangeNotification object:self.mxCredentials.userId]; return; } @@ -1303,7 +1194,7 @@ static NSArray *initialSyncSilentErrorsHTTPStatusCodes; failure(error); } - [[NSNotificationCenter defaultCenter] postNotificationName:kMXKAccountAPNSActivityDidChangeNotification object:self->mxCredentials.userId]; + [[NSNotificationCenter defaultCenter] postNotificationName:kMXKAccountAPNSActivityDidChangeNotification object:self.mxCredentials.userId]; }]; } @@ -1330,7 +1221,7 @@ static NSArray *initialSyncSilentErrorsHTTPStatusCodes; MXLogDebug(@"[MXKAccount][Push] refreshPushKitPusher: Error: %@", error); }]; } - else if (_hasPusherForPushKitNotifications) + else if (self.hasPusherForPushKitNotifications) { if ([MXKAccountManager sharedManager].pushDeviceToken) { @@ -1344,7 +1235,7 @@ static NSArray *initialSyncSilentErrorsHTTPStatusCodes; else { MXLogDebug(@"[MXKAccount][Push] refreshPushKitPusher: PushKit pusher for %@ account is already disabled. Reset _hasPusherForPushKitNotifications", self.mxCredentials.userId); - _hasPusherForPushKitNotifications = NO; + self->_hasPusherForPushKitNotifications = NO; [[MXKAccountManager sharedManager] saveAccounts]; } } @@ -1406,7 +1297,7 @@ static NSArray *initialSyncSilentErrorsHTTPStatusCodes; success(); } - [[NSNotificationCenter defaultCenter] postNotificationName:kMXKAccountPushKitActivityDidChangeNotification object:self->mxCredentials.userId]; + [[NSNotificationCenter defaultCenter] postNotificationName:kMXKAccountPushKitActivityDidChangeNotification object:self.mxCredentials.userId]; } failure:^(NSError *error) { @@ -1425,7 +1316,7 @@ static NSArray *initialSyncSilentErrorsHTTPStatusCodes; success(); } - [[NSNotificationCenter defaultCenter] postNotificationName:kMXKAccountPushKitActivityDidChangeNotification object:self->mxCredentials.userId]; + [[NSNotificationCenter defaultCenter] postNotificationName:kMXKAccountPushKitActivityDidChangeNotification object:self.mxCredentials.userId]; return; } @@ -1442,7 +1333,7 @@ static NSArray *initialSyncSilentErrorsHTTPStatusCodes; failure(error); } - [[NSNotificationCenter defaultCenter] postNotificationName:kMXKAccountPushKitActivityDidChangeNotification object:self->mxCredentials.userId]; + [[NSNotificationCenter defaultCenter] postNotificationName:kMXKAccountPushKitActivityDidChangeNotification object:self.mxCredentials.userId]; }]; } @@ -1451,7 +1342,7 @@ static NSArray *initialSyncSilentErrorsHTTPStatusCodes; MXLogDebug(@"[MXKAccount][Push] enablePusher: %@", @(enabled)); // Refuse to try & turn push on if we're not logged in, it's nonsensical. - if (!mxCredentials) + if (!self.mxCredentials) { MXLogDebug(@"[MXKAccount][Push] enablePusher: Not setting push token because we're not logged in"); return; @@ -1618,7 +1509,7 @@ static NSArray *initialSyncSilentErrorsHTTPStatusCodes; [self.mxSession startWithSyncFilter:syncFilter onServerSyncDone:^{ MXStrongifyAndReturnIfNil(self); - MXLogDebug(@"[MXKAccount] %@: The session is ready. Matrix SDK session has been started in %0.fms.", self->mxCredentials.userId, [[NSDate date] timeIntervalSinceDate:self->openSessionStartDate] * 1000); + MXLogDebug(@"[MXKAccount] %@: The session is ready. Matrix SDK session has been started in %0.fms.", self.mxCredentials.userId, [[NSDate date] timeIntervalSinceDate:self->openSessionStartDate] * 1000); [self setUserPresence:MXPresenceOnline andStatusMessage:nil completion:nil]; @@ -1753,11 +1644,11 @@ static NSArray *initialSyncSilentErrorsHTTPStatusCodes; } // Here displayname or other information have been updated, post update notification. - [[NSNotificationCenter defaultCenter] postNotificationName:kMXKAccountUserInfoDidChangeNotification object:self->mxCredentials.userId]; + [[NSNotificationCenter defaultCenter] postNotificationName:kMXKAccountUserInfoDidChangeNotification object:self.mxCredentials.userId]; }]; // User information are just up-to-date (`mxSession` is running), post update notification. - [[NSNotificationCenter defaultCenter] postNotificationName:kMXKAccountUserInfoDidChangeNotification object:mxCredentials.userId]; + [[NSNotificationCenter defaultCenter] postNotificationName:kMXKAccountUserInfoDidChangeNotification object:self.mxCredentials.userId]; } } else if (mxSession.state == MXSessionStateStoreDataReady || mxSession.state == MXSessionStateSyncInProgress) @@ -1772,7 +1663,7 @@ static NSArray *initialSyncSilentErrorsHTTPStatusCodes; { // Here the initial server sync is in progress. The session is not running yet, but some user's information are available (from local storage). // We post update notification to let observer take into account this user's information even if they may not be up-to-date. - [[NSNotificationCenter defaultCenter] postNotificationName:kMXKAccountUserInfoDidChangeNotification object:mxCredentials.userId]; + [[NSNotificationCenter defaultCenter] postNotificationName:kMXKAccountUserInfoDidChangeNotification object:self.mxCredentials.userId]; } } else if (mxSession.state == MXSessionStatePaused) @@ -1782,7 +1673,7 @@ static NSArray *initialSyncSilentErrorsHTTPStatusCodes; else if (mxSession.state == MXSessionStateUnauthenticated) { // Logout this account - [[MXKAccountManager sharedManager] removeAccount:self completion:nil]; + [[MXKAccountManager sharedManager] removeAccount:self sendLogoutRequest:NO completion:nil]; } else if (mxSession.state == MXSessionStateSoftLogout) { @@ -1793,19 +1684,19 @@ static NSArray *initialSyncSilentErrorsHTTPStatusCodes; - (void)prepareRESTClient { - if (!mxCredentials) + if (!self.mxCredentials) { return; } - mxRestClient = [[MXRestClient alloc] initWithCredentials:mxCredentials andOnUnrecognizedCertificateBlock:^BOOL(NSData *certificate) { + mxRestClient = [[MXRestClient alloc] initWithCredentials:self.mxCredentials andOnUnrecognizedCertificateBlock:^BOOL(NSData *certificate) { if (_onCertificateChangeBlock) { if (_onCertificateChangeBlock (self, certificate)) { // Update the certificate in credentials - self->mxCredentials.allowedCertificate = certificate; + self.mxCredentials.allowedCertificate = certificate; // Archive updated field [[MXKAccountManager sharedManager] saveAccounts]; @@ -1813,13 +1704,15 @@ static NSArray *initialSyncSilentErrorsHTTPStatusCodes; return YES; } - self->mxCredentials.ignoredCertificate = certificate; + self.mxCredentials.ignoredCertificate = certificate; // Archive updated field [[MXKAccountManager sharedManager] saveAccounts]; } return NO; + } andPersistentTokenDataHandler:^(void (^handler)(NSArray *credentials, void (^completion)(BOOL didUpdateCredentials))) { + [MXKAccountManager.sharedManager readAndWriteCredentials:handler]; }]; } @@ -1875,7 +1768,7 @@ static NSArray *initialSyncSilentErrorsHTTPStatusCodes; #pragma mark - Crypto - (void)resetDeviceId { - mxCredentials.deviceId = nil; + self.mxCredentials.deviceId = nil; // Archive updated field [[MXKAccountManager sharedManager] saveAccounts]; @@ -2191,11 +2084,11 @@ static NSArray *initialSyncSilentErrorsHTTPStatusCodes; MXSession *mxSession = notification.object; if (mxSession == self.mxSession) { - if (![mxCredentials.identityServer isEqualToString:self.mxSession.accountDataIdentityServer]) + if (![self.mxCredentials.identityServer isEqualToString:self.mxSession.accountDataIdentityServer]) { _identityServerURL = self.mxSession.accountDataIdentityServer; - mxCredentials.identityServer = _identityServerURL; - mxCredentials.identityServerAccessToken = nil; + self.mxCredentials.identityServer = _identityServerURL; + self.mxCredentials.identityServerAccessToken = nil; // Archive updated field [[MXKAccountManager sharedManager] saveAccounts]; @@ -2208,7 +2101,7 @@ static NSArray *initialSyncSilentErrorsHTTPStatusCodes; - (void)identityService:(MXIdentityService *)identityService didUpdateAccessToken:(NSString *)accessToken { - mxCredentials.identityServerAccessToken = accessToken; + self.mxCredentials.identityServerAccessToken = accessToken; } - (void)registerIdentityServiceDidChangeAccessTokenNotification @@ -2224,9 +2117,9 @@ static NSArray *initialSyncSilentErrorsHTTPStatusCodes; NSString *identityServer = userInfo[MXIdentityServiceNotificationIdentityServerKey]; NSString *accessToken = userInfo[MXIdentityServiceNotificationAccessTokenKey]; - if (userId && identityServer && accessToken && [mxCredentials.identityServer isEqualToString:identityServer]) + if (userId && identityServer && accessToken && [self.mxCredentials.identityServer isEqualToString:identityServer]) { - mxCredentials.identityServerAccessToken = accessToken; + self.mxCredentials.identityServerAccessToken = accessToken; // Archive updated field [[MXKAccountManager sharedManager] saveAccounts]; diff --git a/Riot/Modules/MatrixKit/Models/Account/MXKAccountData.h b/Riot/Modules/MatrixKit/Models/Account/MXKAccountData.h new file mode 100644 index 000000000..b5cc5512b --- /dev/null +++ b/Riot/Modules/MatrixKit/Models/Account/MXKAccountData.h @@ -0,0 +1,141 @@ +// +// Copyright 2021 New Vector Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#import + +@class MXKAccountData; + +@interface MXKAccountData : NSObject { + +@protected MXCredentials *_mxCredentials; +@protected NSString *_identityServerURL; +@protected NSString *_antivirusServerURL; +@protected NSString *_pushGatewayURL; +@protected MXDevice *_device; +@protected BOOL _disabled; +@protected BOOL _enableInAppNotifications; +@protected BOOL _warnedAboutEncryption; +@protected NSMutableDictionary> *_others; +@protected NSArray *_threePIDs; +@protected BOOL _isSoftLogout; +@protected BOOL _hasPusherForPushNotifications; +@protected BOOL _hasPusherForPushKitNotifications; +} + +/** + The account's credentials: homeserver, access token, user id. + */ +@property (nonatomic, readonly) MXCredentials *mxCredentials; + +/** + The identity server URL. + */ +@property (nonatomic) NSString *identityServerURL; + +/** + The antivirus server URL, if any (nil by default). + Set a non-null url to configure the antivirus scanner use. + */ +@property (nonatomic) NSString *antivirusServerURL; + +/** + The Push Gateway URL used to send event notifications to (nil by default). + This URL should be over HTTPS and never over HTTP. + */ +@property (nonatomic) NSString *pushGatewayURL; + +/** + The 3PIDs linked to this account. + [self load3PIDs] must be called to update the property. + */ +@property (nonatomic, readonly) NSArray *threePIDs; + +/** + The email addresses linked to this account. + This is a subset of self.threePIDs. + */ +@property (nonatomic, readonly) NSArray *linkedEmails; + +/** + The phone numbers linked to this account. + This is a subset of self.threePIDs. + */ +@property (nonatomic, readonly) NSArray *linkedPhoneNumbers; + +/** + The account user's device. + [self loadDeviceInformation] must be called to update the property. + */ +@property (nonatomic, readonly) MXDevice *device; + +/** + The account user's tint color: a unique color fixed by the user id. This tint color may be used to highlight + rooms which belong to this account's user. + */ +@property (nonatomic, readonly) UIColor *userTintColor; + +/** + The Apple Push Notification Service activity for this account. YES when APNS is turned on (locally available and synced with server). + */ +@property (nonatomic, readonly) BOOL pushNotificationServiceIsActive; + +/** + Transient information storage. + */ +@property (nonatomic, strong, readonly) NSMutableDictionary> *others; + +/** + Flag to indicate that an APNS pusher has been set on the homeserver for this device. + */ +@property (nonatomic, readonly) BOOL hasPusherForPushNotifications; + +/** + The Push notification activity (based on PushKit) for this account. + YES when Push is turned on (locally available and enabled homeserver side). + */ +@property (nonatomic, readonly) BOOL isPushKitNotificationActive; + +/** + Flag to indicate that a PushKit pusher has been set on the homeserver for this device. + */ +@property (nonatomic, readonly) BOOL hasPusherForPushKitNotifications; + + +/** + Enable In-App notifications based on Remote notifications rules. + NO by default. + */ +@property (nonatomic) BOOL enableInAppNotifications; + +/** + Disable the account without logging out (NO by default). + + A matrix session is automatically opened for the account when this property is toggled from YES to NO. + The session is closed when this property is set to YES. + */ +@property (nonatomic,getter=isDisabled) BOOL disabled; + +/** + Flag indicating if the end user has been warned about encryption and its limitations. + */ +@property (nonatomic,getter=isWarnedAboutEncryption) BOOL warnedAboutEncryption; + +#pragma mark - Soft logout + +/** + Flag to indicate if the account has been logged out by the homeserver admin. + */ +@property (nonatomic, readonly) BOOL isSoftLogout; +@end diff --git a/Riot/Modules/MatrixKit/Models/Account/MXKAccountData.m b/Riot/Modules/MatrixKit/Models/Account/MXKAccountData.m new file mode 100644 index 000000000..4d59e2a4b --- /dev/null +++ b/Riot/Modules/MatrixKit/Models/Account/MXKAccountData.m @@ -0,0 +1,150 @@ +// +// Copyright 2021 New Vector Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import +#import "MXKAccountData.h" + +@interface MXKAccountData () + +@end + +@implementation MXKAccountData + +@synthesize mxCredentials = _mxCredentials; + +#pragma mark - NSCoding + +- (id)initWithCoder:(NSCoder *)coder +{ + self = [super init]; + + if (self) + { + + NSString *homeServerURL = [coder decodeObjectForKey:@"homeserverurl"]; + NSString *userId = [coder decodeObjectForKey:@"userid"]; + NSString *accessToken = [coder decodeObjectForKey:@"accesstoken"]; + _identityServerURL = [coder decodeObjectForKey:@"identityserverurl"]; + NSString *identityServerAccessToken = [coder decodeObjectForKey:@"identityserveraccesstoken"]; + + _mxCredentials = [[MXCredentials alloc] initWithHomeServer:homeServerURL + userId:userId + accessToken:accessToken]; + + _mxCredentials.accessTokenExpiresAt = [coder decodeInt64ForKey:@"accessTokenExpiresAt"]; + _mxCredentials.refreshToken = [coder decodeObjectForKey:@"refreshToken"]; + _mxCredentials.identityServer = _identityServerURL; + _mxCredentials.identityServerAccessToken = identityServerAccessToken; + _mxCredentials.deviceId = [coder decodeObjectForKey:@"deviceId"]; + _mxCredentials.allowedCertificate = [coder decodeObjectForKey:@"allowedCertificate"]; + + if ([coder decodeObjectForKey:@"threePIDs"]) + { + _threePIDs = [coder decodeObjectForKey:@"threePIDs"]; + } + + if ([coder decodeObjectForKey:@"device"]) + { + _device = [coder decodeObjectForKey:@"device"]; + } + + if ([coder decodeObjectForKey:@"antivirusserverurl"]) + { + _antivirusServerURL = [coder decodeObjectForKey:@"antivirusserverurl"]; + } + + if ([coder decodeObjectForKey:@"pushgatewayurl"]) + { + _pushGatewayURL = [coder decodeObjectForKey:@"pushgatewayurl"]; + } + + _hasPusherForPushNotifications = [coder decodeBoolForKey:@"_enablePushNotifications"]; + _hasPusherForPushKitNotifications = [coder decodeBoolForKey:@"enablePushKitNotifications"]; + _enableInAppNotifications = [coder decodeBoolForKey:@"enableInAppNotifications"]; + + _disabled = [coder decodeBoolForKey:@"disabled"]; + _isSoftLogout = [coder decodeBoolForKey:@"isSoftLogout"]; + + _warnedAboutEncryption = [coder decodeBoolForKey:@"warnedAboutEncryption"]; + + _others = [coder decodeObjectForKey:@"others"]; + } + + return self; +} + +- (void)encodeWithCoder:(NSCoder *)coder +{ + [coder encodeObject:_mxCredentials.homeServer forKey:@"homeserverurl"]; + [coder encodeObject:_mxCredentials.userId forKey:@"userid"]; + [coder encodeObject:_mxCredentials.accessToken forKey:@"accesstoken"]; + if (self.mxCredentials.accessTokenExpiresAt) { + [coder encodeInt64:_mxCredentials.accessTokenExpiresAt forKey:@"accessTokenExpiresAt"]; + } + if (self.mxCredentials.refreshToken) { + [coder encodeObject:_mxCredentials.refreshToken forKey:@"refreshToken"]; + } + [coder encodeObject:_mxCredentials.identityServerAccessToken forKey:@"identityserveraccesstoken"]; + + if (self.mxCredentials.deviceId) + { + [coder encodeObject:_mxCredentials.deviceId forKey:@"deviceId"]; + } + + if (self.mxCredentials.allowedCertificate) + { + [coder encodeObject:_mxCredentials.allowedCertificate forKey:@"allowedCertificate"]; + } + + if (self.threePIDs) + { + [coder encodeObject:_threePIDs forKey:@"threePIDs"]; + } + + if (self.device) + { + [coder encodeObject:_device forKey:@"device"]; + } + + if (self.identityServerURL) + { + [coder encodeObject:_identityServerURL forKey:@"identityserverurl"]; + } + + if (self.antivirusServerURL) + { + [coder encodeObject:_antivirusServerURL forKey:@"antivirusserverurl"]; + } + + if (self.pushGatewayURL) + { + [coder encodeObject:_pushGatewayURL forKey:@"pushgatewayurl"]; + } + + [coder encodeBool:_hasPusherForPushNotifications forKey:@"_enablePushNotifications"]; + [coder encodeBool:_hasPusherForPushKitNotifications forKey:@"enablePushKitNotifications"]; + [coder encodeBool:_enableInAppNotifications forKey:@"enableInAppNotifications"]; + + [coder encodeBool:_disabled forKey:@"disabled"]; + [coder encodeBool:_isSoftLogout forKey:@"isSoftLogout"]; + + [coder encodeBool:_warnedAboutEncryption forKey:@"warnedAboutEncryption"]; + + [coder encodeObject:_others forKey:@"others"]; +} + + +@end diff --git a/Riot/Modules/MatrixKit/Models/Account/MXKAccountManager.h b/Riot/Modules/MatrixKit/Models/Account/MXKAccountManager.h index 70c4857c9..cfbec2a9a 100644 --- a/Riot/Modules/MatrixKit/Models/Account/MXKAccountManager.h +++ b/Riot/Modules/MatrixKit/Models/Account/MXKAccountManager.h @@ -110,6 +110,8 @@ extern NSString *const MXKAccountManagerDataType; */ + (MXKAccountManager *)sharedManager; ++ (MXKAccountManager *)sharedManagerWithReload:(BOOL)reload; + /** Check for each enabled account if a matrix session is already opened. Open a matrix session for each enabled account which doesn't have a session. @@ -208,11 +210,6 @@ extern NSString *const MXKAccountManagerDataType; */ - (MXKAccount *)accountKnowingUserWithUserId:(NSString *)userId; -/** - Force the account manager to reload existing accounts from the local storage. - The account manager is supposed to handle itself the list of the accounts. - Call this method only when an account has been changed from an other application from the same group. - */ -- (void)forceReloadAccounts; +- (void)readAndWriteCredentials:(void (^)(NSArray * _Nullable readData, void (^completion)(BOOL didUpdateCredentials)))readAnWriteHandler; @end diff --git a/Riot/Modules/MatrixKit/Models/Account/MXKAccountManager.m b/Riot/Modules/MatrixKit/Models/Account/MXKAccountManager.m index 080a7ace4..a8947f4ef 100644 --- a/Riot/Modules/MatrixKit/Models/Account/MXKAccountManager.m +++ b/Riot/Modules/MatrixKit/Models/Account/MXKAccountManager.m @@ -21,6 +21,8 @@ #import "MXKAppSettings.h" #import "MXKTools.h" +#import "MXKAccountData.h" +#import "MXRefreshTokenData.h" static NSString *const kMXKAccountsKeyOld = @"accounts"; static NSString *const kMXKAccountsKey = @"accountsV2"; @@ -43,13 +45,23 @@ NSString *const MXKAccountManagerDataType = @"org.matrix.kit.MXKAccountManagerDa @implementation MXKAccountManager + (MXKAccountManager *)sharedManager +{ + return [MXKAccountManager sharedManagerWithReload:NO]; +} + ++ (MXKAccountManager *)sharedManagerWithReload:(BOOL)reload { static MXKAccountManager *sharedAccountManager = nil; static dispatch_once_t onceToken; + __block BOOL didLoad = false; dispatch_once(&onceToken, ^{ + didLoad = true; sharedAccountManager = [[super allocWithZone:NULL] init]; }); + if (reload && !didLoad) { + [sharedAccountManager loadAccounts]; + } return sharedAccountManager; } @@ -66,8 +78,6 @@ NSString *const MXKAccountManagerDataType = @"org.matrix.kit.MXKAccountManagerDa // Load existing accounts from local storage [self loadAccounts]; - - [self registerRestClientDidRefreshTokensNotification]; } return self; } @@ -601,7 +611,6 @@ NSString *const MXKAccountManagerDataType = @"org.matrix.kit.MXKAccountManagerDa - (void)loadAccounts { MXLogDebug(@"[MXKAccountManager] loadAccounts"); - NSString *accountFile = [self accountFile]; if ([[NSFileManager defaultManager] fileExistsAtPath:accountFile]) { @@ -667,12 +676,6 @@ NSString *const MXKAccountManagerDataType = @"org.matrix.kit.MXKAccountManagerDa } } -- (void)forceReloadAccounts -{ - MXLogDebug(@"[MXKAccountManager] Force reload existing accounts from local storage"); - [self loadAccounts]; -} - - (NSData*)encryptData:(NSData*)data { // Exceptions are not caught as the key is always needed if the KeyProviderDelegate @@ -725,17 +728,69 @@ NSString *const MXKAccountManagerDataType = @"org.matrix.kit.MXKAccountManagerDa } } -#pragma mark - Homeserver Access/Refresh Token updates - -- (void)registerRestClientDidRefreshTokensNotification +- (void)readAndWriteCredentials:(void (^)(NSArray * _Nullable readData, void (^completion)(BOOL didUpdateCredentials)))readAnWriteHandler { - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleRestClientDidRefreshTokensNotification:) name:MXRestClientDidRefreshTokensNotification object:nil]; + NSError *error; + NSFileCoordinator *fileCoordinator = [[NSFileCoordinator alloc] init]; + __block BOOL coordinatorSuccess = NO; + NSLog(@"[MXKAccountManager] readAndWriteCredentials: purposeIdentifier = %@", fileCoordinator.purposeIdentifier); + NSDate *coordinateStartTime = [NSDate date]; + [fileCoordinator coordinateReadingItemAtURL:[self accountFileUrl] + options:0 + writingItemAtURL:[self accountFileUrl] + options:NSFileCoordinatorWritingForMerging + error:&error + byAccessor:^(NSURL * _Nonnull newReadingURL, NSURL * _Nonnull newWritingURL) { + + NSDate *accessorStartTime = [NSDate date]; + NSTimeInterval acquireInterval = [accessorStartTime timeIntervalSinceDate:coordinateStartTime]; + NSLog(@"[MXKAccountManager] readAndWriteCredentials: acquireInterval = %f", acquireInterval); + NSError *error = nil; + NSData* data = [NSData dataWithContentsOfURL:newReadingURL options:(NSDataReadingMappedAlways | NSDataReadingUncached) error:&error]; + + // Decrypt data if encryption method is provided + NSData *unciphered = [self decryptData:data]; + NSKeyedUnarchiver *decoder = [[NSKeyedUnarchiver alloc] initForReadingFromData:unciphered error:&error]; + decoder.requiresSecureCoding = false; + [decoder setClass:[MXKAccountData class] forClassName:@"MXKAccount"]; + NSMutableArray* mxAccountsData = [decoder decodeObjectForKey:@"mxAccounts"]; + NSMutableArray* mxAccountCredentials = [NSMutableArray arrayWithCapacity:mxAccounts.count]; + for(MXKAccountData *account in mxAccountsData){ + [mxAccountCredentials addObject:account.mxCredentials]; + } + + dispatch_group_t dispatchGroup = dispatch_group_create(); + dispatch_group_enter(dispatchGroup); + + __block BOOL didUpdate = NO; + readAnWriteHandler(mxAccountCredentials, ^(BOOL didUpdateCredentials) { + didUpdate = didUpdateCredentials; + dispatch_group_leave(dispatchGroup); + }); + + dispatch_group_wait(dispatchGroup, DISPATCH_TIME_FOREVER); + + if (didUpdate) { + NSLog(@"[MXKAccountManager] readAndWriteCredentials: did update saving credential data"); + NSKeyedArchiver *encoder = [[NSKeyedArchiver alloc] initRequiringSecureCoding: NO]; + [encoder setClassName:@"MXKAccount" forClass:[MXKAccountData class]]; + [encoder encodeObject:mxAccountsData forKey:@"mxAccounts"]; + NSData *writeData = [self encryptData:[encoder encodedData]]; + coordinatorSuccess = [writeData writeToURL:newWritingURL atomically:YES]; + } else { + NSLog(@"[MXKAccountManager] readAndWriteCredentials: did not update not saving credential data"); + coordinatorSuccess = YES; + } + NSDate *accessorEndTime = [NSDate date]; + NSTimeInterval lockedTime = [accessorEndTime timeIntervalSinceDate:accessorStartTime]; + NSLog(@"[MXKAccountManager] readAndWriteCredentials: lockedTime = %f", lockedTime); + }]; + NSLog(@"[MXKAccountManager] readAndWriteCredentials:exit"); } -- (void)handleRestClientDidRefreshTokensNotification:(NSNotification*)notification +- (NSURL *)accountFileUrl { - [self saveAccounts]; + return [NSURL fileURLWithPath: [self accountFile]]; } - @end diff --git a/RiotNSE/NotificationService.swift b/RiotNSE/NotificationService.swift index f669b9593..cd8494f24 100644 --- a/RiotNSE/NotificationService.swift +++ b/RiotNSE/NotificationService.swift @@ -56,7 +56,9 @@ class NotificationService: UNNotificationServiceExtension { guard let userAccount = userAccount else { return nil } - let restClient = MXRestClient(credentials: userAccount.mxCredentials, unrecognizedCertificateHandler: nil) + let restClient = MXRestClient(credentials: userAccount.mxCredentials, unrecognizedCertificateHandler: nil) { persistTokenDataHandler in + MXKAccountManager.shared().readAndWriteCredentials(persistTokenDataHandler) + } restClient.refreshTokensFailedHandler = { mxError in MXLog.debug("[NotificationService] mxRestClient: The rest client is no longer authenticated.") if let mxError = mxError, @@ -180,14 +182,16 @@ class NotificationService: UNNotificationServiceExtension { } private func setup(withRoomId roomId: String, eventId: String, completion: @escaping () -> Void) { - MXKAccountManager.shared()?.forceReloadAccounts() + MXKAccountManager.sharedManager(withReload: true) self.userAccount = MXKAccountManager.shared()?.activeAccounts.first if let userAccount = userAccount { Self.backgroundServiceInitQueue.sync { if NotificationService.backgroundSyncService?.credentials != userAccount.mxCredentials { MXLog.debug("[NotificationService] setup: MXBackgroundSyncService init: BEFORE") self.logMemory() - NotificationService.backgroundSyncService = MXBackgroundSyncService(withCredentials: userAccount.mxCredentials) + NotificationService.backgroundSyncService = MXBackgroundSyncService(withCredentials: userAccount.mxCredentials, persistTokenDataHandler: { persistTokenDataHandler in + MXKAccountManager.shared().readAndWriteCredentials(persistTokenDataHandler) + }) MXLog.debug("[NotificationService] setup: MXBackgroundSyncService init: AFTER") self.logMemory() } diff --git a/RiotShareExtension/Shared/ShareDataSource.m b/RiotShareExtension/Shared/ShareDataSource.m index aa064c5a5..7bfcfab73 100644 --- a/RiotShareExtension/Shared/ShareDataSource.m +++ b/RiotShareExtension/Shared/ShareDataSource.m @@ -82,7 +82,9 @@ NSMutableArray *cellData = [NSMutableArray array]; // Add a fake matrix session to each room summary to provide it a REST client (used to handle correctly the room avatar). - MXSession *session = [[MXSession alloc] initWithMatrixRestClient:[[MXRestClient alloc] initWithCredentials:self.credentials andOnUnrecognizedCertificateBlock:nil]]; + MXSession *session = [[MXSession alloc] initWithMatrixRestClient:[[MXRestClient alloc] initWithCredentials:self.credentials andOnUnrecognizedCertificateBlock:nil andPersistentTokenDataHandler:^(void (^handler)(NSArray *credentials, void (^completion)(BOOL didUpdateCredentials))) { + [[MXKAccountManager sharedManager] readAndWriteCredentials:handler]; + }]]; for (MXRoomSummary *roomSummary in roomsSummaries) { diff --git a/RiotShareExtension/Shared/ShareManager.m b/RiotShareExtension/Shared/ShareManager.m index d955f9da1..ee306286d 100644 --- a/RiotShareExtension/Shared/ShareManager.m +++ b/RiotShareExtension/Shared/ShareManager.m @@ -78,7 +78,9 @@ - (void)shareViewController:(ShareViewController *)shareViewController didRequestShareForRoomIdentifiers:(NSSet *)roomIdentifiers { - MXSession *session = [[MXSession alloc] initWithMatrixRestClient:[[MXRestClient alloc] initWithCredentials:self.userAccount.mxCredentials andOnUnrecognizedCertificateBlock:nil]]; + MXSession *session = [[MXSession alloc] initWithMatrixRestClient:[[MXRestClient alloc] initWithCredentials:self.userAccount.mxCredentials andOnUnrecognizedCertificateBlock:nil andPersistentTokenDataHandler:^(void (^handler)(NSArray *credentials, void (^completion)(BOOL didUpdateCredentials))) { + [[MXKAccountManager sharedManager] readAndWriteCredentials:handler]; + }]]; [MXFileStore setPreloadOptions:0]; MXWeakify(session); @@ -147,7 +149,7 @@ - (void)checkUserAccount { // Force account manager to reload account from the local storage. - [[MXKAccountManager sharedManager] forceReloadAccounts]; + [MXKAccountManager sharedManagerWithReload:YES]; if (self.userAccount) {