@@ -17,11 +17,10 @@ limitations under the License.
1717import { MatrixEvent } from "matrix-js-sdk/src/models/event" ;
1818import { logger } from "matrix-js-sdk/src/logger" ;
1919import { CryptoEvent } from "matrix-js-sdk/src/crypto" ;
20- import { ClientEvent , EventType , RoomStateEvent } from "matrix-js-sdk/src/matrix" ;
20+ import { ClientEvent , EventType , MatrixClient , RoomStateEvent } from "matrix-js-sdk/src/matrix" ;
2121import { SyncState } from "matrix-js-sdk/src/sync" ;
2222import { IKeyBackupInfo } from "matrix-js-sdk/src/crypto/keybackup" ;
2323
24- import { MatrixClientPeg } from "./MatrixClientPeg" ;
2524import dis from "./dispatcher/dispatcher" ;
2625import {
2726 hideToast as hideBulkUnverifiedSessionsToast ,
@@ -67,6 +66,8 @@ export default class DeviceListener {
6766 // The set of device IDs we're currently displaying toasts for
6867 private displayingToastsForDeviceIds = new Set < string > ( ) ;
6968 private running = false ;
69+ // The client with which the instance is running. Only set if `running` is true, otherwise undefined.
70+ private client ?: MatrixClient ;
7071 private shouldRecordClientInformation = false ;
7172 private enableBulkUnverifiedSessionsReminder = true ;
7273 private deviceClientInformationSettingWatcherRef : string | undefined ;
@@ -76,16 +77,17 @@ export default class DeviceListener {
7677 return window . mxDeviceListener ;
7778 }
7879
79- public start ( ) : void {
80+ public start ( matrixClient : MatrixClient ) : void {
8081 this . running = true ;
81- MatrixClientPeg . get ( ) . on ( CryptoEvent . WillUpdateDevices , this . onWillUpdateDevices ) ;
82- MatrixClientPeg . get ( ) . on ( CryptoEvent . DevicesUpdated , this . onDevicesUpdated ) ;
83- MatrixClientPeg . get ( ) . on ( CryptoEvent . DeviceVerificationChanged , this . onDeviceVerificationChanged ) ;
84- MatrixClientPeg . get ( ) . on ( CryptoEvent . UserTrustStatusChanged , this . onUserTrustStatusChanged ) ;
85- MatrixClientPeg . get ( ) . on ( CryptoEvent . KeysChanged , this . onCrossSingingKeysChanged ) ;
86- MatrixClientPeg . get ( ) . on ( ClientEvent . AccountData , this . onAccountData ) ;
87- MatrixClientPeg . get ( ) . on ( ClientEvent . Sync , this . onSync ) ;
88- MatrixClientPeg . get ( ) . on ( RoomStateEvent . Events , this . onRoomStateEvents ) ;
82+ this . client = matrixClient ;
83+ this . client . on ( CryptoEvent . WillUpdateDevices , this . onWillUpdateDevices ) ;
84+ this . client . on ( CryptoEvent . DevicesUpdated , this . onDevicesUpdated ) ;
85+ this . client . on ( CryptoEvent . DeviceVerificationChanged , this . onDeviceVerificationChanged ) ;
86+ this . client . on ( CryptoEvent . UserTrustStatusChanged , this . onUserTrustStatusChanged ) ;
87+ this . client . on ( CryptoEvent . KeysChanged , this . onCrossSingingKeysChanged ) ;
88+ this . client . on ( ClientEvent . AccountData , this . onAccountData ) ;
89+ this . client . on ( ClientEvent . Sync , this . onSync ) ;
90+ this . client . on ( RoomStateEvent . Events , this . onRoomStateEvents ) ;
8991 this . shouldRecordClientInformation = SettingsStore . getValue ( "deviceClientInformationOptIn" ) ;
9092 // only configurable in config, so we don't need to watch the value
9193 this . enableBulkUnverifiedSessionsReminder = SettingsStore . getValue ( UIFeature . BulkUnverifiedSessionsReminder ) ;
@@ -101,18 +103,15 @@ export default class DeviceListener {
101103
102104 public stop ( ) : void {
103105 this . running = false ;
104- if ( MatrixClientPeg . get ( ) ) {
105- MatrixClientPeg . get ( ) . removeListener ( CryptoEvent . WillUpdateDevices , this . onWillUpdateDevices ) ;
106- MatrixClientPeg . get ( ) . removeListener ( CryptoEvent . DevicesUpdated , this . onDevicesUpdated ) ;
107- MatrixClientPeg . get ( ) . removeListener (
108- CryptoEvent . DeviceVerificationChanged ,
109- this . onDeviceVerificationChanged ,
110- ) ;
111- MatrixClientPeg . get ( ) . removeListener ( CryptoEvent . UserTrustStatusChanged , this . onUserTrustStatusChanged ) ;
112- MatrixClientPeg . get ( ) . removeListener ( CryptoEvent . KeysChanged , this . onCrossSingingKeysChanged ) ;
113- MatrixClientPeg . get ( ) . removeListener ( ClientEvent . AccountData , this . onAccountData ) ;
114- MatrixClientPeg . get ( ) . removeListener ( ClientEvent . Sync , this . onSync ) ;
115- MatrixClientPeg . get ( ) . removeListener ( RoomStateEvent . Events , this . onRoomStateEvents ) ;
106+ if ( this . client ) {
107+ this . client . removeListener ( CryptoEvent . WillUpdateDevices , this . onWillUpdateDevices ) ;
108+ this . client . removeListener ( CryptoEvent . DevicesUpdated , this . onDevicesUpdated ) ;
109+ this . client . removeListener ( CryptoEvent . DeviceVerificationChanged , this . onDeviceVerificationChanged ) ;
110+ this . client . removeListener ( CryptoEvent . UserTrustStatusChanged , this . onUserTrustStatusChanged ) ;
111+ this . client . removeListener ( CryptoEvent . KeysChanged , this . onCrossSingingKeysChanged ) ;
112+ this . client . removeListener ( ClientEvent . AccountData , this . onAccountData ) ;
113+ this . client . removeListener ( ClientEvent . Sync , this . onSync ) ;
114+ this . client . removeListener ( RoomStateEvent . Events , this . onRoomStateEvents ) ;
116115 }
117116 if ( this . deviceClientInformationSettingWatcherRef ) {
118117 SettingsStore . unwatchSetting ( this . deviceClientInformationSettingWatcherRef ) ;
@@ -128,6 +127,7 @@ export default class DeviceListener {
128127 this . keyBackupStatusChecked = false ;
129128 this . ourDeviceIdsAtStart = null ;
130129 this . displayingToastsForDeviceIds = new Set ( ) ;
130+ this . client = undefined ;
131131 }
132132
133133 /**
@@ -160,40 +160,44 @@ export default class DeviceListener {
160160 * @returns the set of device IDs
161161 */
162162 private async getDeviceIds ( ) : Promise < Set < string > > {
163- const cli = MatrixClientPeg . get ( ) ;
164- const crypto = cli . getCrypto ( ) ;
163+ const cli = this . client ;
164+ const crypto = cli ? .getCrypto ( ) ;
165165 if ( crypto === undefined ) return new Set ( ) ;
166166
167- const userId = cli . getSafeUserId ( ) ;
167+ const userId = cli ! . getSafeUserId ( ) ;
168168 const devices = await crypto . getUserDeviceInfo ( [ userId ] ) ;
169169 return new Set ( devices . get ( userId ) ?. keys ( ) ?? [ ] ) ;
170170 }
171171
172172 private onWillUpdateDevices = async ( users : string [ ] , initialFetch ?: boolean ) : Promise < void > => {
173+ if ( ! this . client ) return ;
173174 // If we didn't know about *any* devices before (ie. it's fresh login),
174175 // then they are all pre-existing devices, so ignore this and set the
175176 // devicesAtStart list to the devices that we see after the fetch.
176177 if ( initialFetch ) return ;
177178
178- const myUserId = MatrixClientPeg . get ( ) . getUserId ( ) ! ;
179+ const myUserId = this . client . getSafeUserId ( ) ;
179180 if ( users . includes ( myUserId ) ) await this . ensureDeviceIdsAtStartPopulated ( ) ;
180181
181182 // No need to do a recheck here: we just need to get a snapshot of our devices
182183 // before we download any new ones.
183184 } ;
184185
185186 private onDevicesUpdated = ( users : string [ ] ) : void => {
186- if ( ! users . includes ( MatrixClientPeg . get ( ) . getUserId ( ) ! ) ) return ;
187+ if ( ! this . client ) return ;
188+ if ( ! users . includes ( this . client . getSafeUserId ( ) ) ) return ;
187189 this . recheck ( ) ;
188190 } ;
189191
190192 private onDeviceVerificationChanged = ( userId : string ) : void => {
191- if ( userId !== MatrixClientPeg . get ( ) . getUserId ( ) ) return ;
193+ if ( ! this . client ) return ;
194+ if ( userId !== this . client . getUserId ( ) ) return ;
192195 this . recheck ( ) ;
193196 } ;
194197
195198 private onUserTrustStatusChanged = ( userId : string ) : void => {
196- if ( userId !== MatrixClientPeg . get ( ) . getUserId ( ) ) return ;
199+ if ( ! this . client ) return ;
200+ if ( userId !== this . client . getUserId ( ) ) return ;
197201 this . recheck ( ) ;
198202 } ;
199203
@@ -239,13 +243,14 @@ export default class DeviceListener {
239243 // The server doesn't tell us when key backup is set up, so we poll
240244 // & cache the result
241245 private async getKeyBackupInfo ( ) : Promise < IKeyBackupInfo | null > {
246+ if ( ! this . client ) return null ;
242247 const now = new Date ( ) . getTime ( ) ;
243248 if (
244249 ! this . keyBackupInfo ||
245250 ! this . keyBackupFetchedAt ||
246251 this . keyBackupFetchedAt < now - KEY_BACKUP_POLL_INTERVAL
247252 ) {
248- this . keyBackupInfo = await MatrixClientPeg . get ( ) . getKeyBackupVersion ( ) ;
253+ this . keyBackupInfo = await this . client . getKeyBackupVersion ( ) ;
249254 this . keyBackupFetchedAt = now ;
250255 }
251256 return this . keyBackupInfo ;
@@ -256,13 +261,13 @@ export default class DeviceListener {
256261 // modifying the state involved here, so don't add new toasts to setup.
257262 if ( isSecretStorageBeingAccessed ( ) ) return false ;
258263 // Show setup toasts once the user is in at least one encrypted room.
259- const cli = MatrixClientPeg . get ( ) ;
260- return cli && cli . getRooms ( ) . some ( ( r ) => cli . isRoomEncrypted ( r . roomId ) ) ;
264+ const cli = this . client ;
265+ return cli ? .getRooms ( ) . some ( ( r ) => cli . isRoomEncrypted ( r . roomId ) ) ?? false ;
261266 }
262267
263268 private async recheck ( ) : Promise < void > {
264- if ( ! this . running ) return ; // we have been stopped
265- const cli = MatrixClientPeg . get ( ) ;
269+ if ( ! this . running || ! this . client ) return ; // we have been stopped
270+ const cli = this . client ;
266271
267272 // cross-signing support was added to Matrix in MSC1756, which landed in spec v1.1
268273 if ( ! ( await cli . isVersionSupported ( "v1.1" ) ) ) return ;
@@ -285,11 +290,11 @@ export default class DeviceListener {
285290 this . checkKeyBackupStatus ( ) ;
286291 } else if ( this . shouldShowSetupEncryptionToast ( ) ) {
287292 // make sure our keys are finished downloading
288- await crypto . getUserDeviceInfo ( [ cli . getUserId ( ) ! ] ) ;
293+ await crypto . getUserDeviceInfo ( [ cli . getSafeUserId ( ) ] ) ;
289294
290295 // cross signing isn't enabled - nag to enable it
291296 // There are 3 different toasts for:
292- if ( ! ( await crypto . getCrossSigningKeyId ( ) ) && cli . getStoredCrossSigningForUser ( cli . getUserId ( ) ! ) ) {
297+ if ( ! ( await crypto . getCrossSigningKeyId ( ) ) && cli . getStoredCrossSigningForUser ( cli . getSafeUserId ( ) ) ) {
293298 // Cross-signing on account but this device doesn't trust the master key (verify this session)
294299 showSetupEncryptionToast ( SetupKind . VERIFY_THIS_SESSION ) ;
295300 this . checkKeyBackupStatus ( ) ;
@@ -327,7 +332,9 @@ export default class DeviceListener {
327332
328333 const isCurrentDeviceTrusted =
329334 crossSigningReady &&
330- Boolean ( ( await crypto . getDeviceVerificationStatus ( cli . getUserId ( ) ! , cli . deviceId ! ) ) ?. crossSigningVerified ) ;
335+ Boolean (
336+ ( await crypto . getDeviceVerificationStatus ( cli . getSafeUserId ( ) , cli . deviceId ! ) ) ?. crossSigningVerified ,
337+ ) ;
331338
332339 // as long as cross-signing isn't ready,
333340 // you can't see or dismiss any device toasts
@@ -336,7 +343,7 @@ export default class DeviceListener {
336343 for ( const deviceId of devices ) {
337344 if ( deviceId === cli . deviceId ) continue ;
338345
339- const deviceTrust = await crypto . getDeviceVerificationStatus ( cli . getUserId ( ) ! , deviceId ) ;
346+ const deviceTrust = await crypto . getDeviceVerificationStatus ( cli . getSafeUserId ( ) , deviceId ) ;
340347 if ( ! deviceTrust ?. crossSigningVerified && ! this . dismissed . has ( deviceId ) ) {
341348 if ( this . ourDeviceIdsAtStart ?. has ( deviceId ) ) {
342349 oldUnverifiedDeviceIds . add ( deviceId ) ;
@@ -383,11 +390,11 @@ export default class DeviceListener {
383390 }
384391
385392 private checkKeyBackupStatus = async ( ) : Promise < void > => {
386- if ( this . keyBackupStatusChecked ) {
393+ if ( this . keyBackupStatusChecked || ! this . client ) {
387394 return ;
388395 }
389396 // returns null when key backup status hasn't finished being checked
390- const isKeyBackupEnabled = MatrixClientPeg . get ( ) . getKeyBackupEnabled ( ) ;
397+ const isKeyBackupEnabled = this . client . getKeyBackupEnabled ( ) ;
391398 this . keyBackupStatusChecked = isKeyBackupEnabled !== null ;
392399
393400 if ( isKeyBackupEnabled === false ) {
@@ -412,11 +419,12 @@ export default class DeviceListener {
412419 } ;
413420
414421 private updateClientInformation = async ( ) : Promise < void > => {
422+ if ( ! this . client ) return ;
415423 try {
416424 if ( this . shouldRecordClientInformation ) {
417- await recordClientInformation ( MatrixClientPeg . get ( ) , SdkConfig . get ( ) , PlatformPeg . get ( ) ?? undefined ) ;
425+ await recordClientInformation ( this . client , SdkConfig . get ( ) , PlatformPeg . get ( ) ?? undefined ) ;
418426 } else {
419- await removeClientInformation ( MatrixClientPeg . get ( ) ) ;
427+ await removeClientInformation ( this . client ) ;
420428 }
421429 } catch ( error ) {
422430 // this is a best effort operation
0 commit comments