DeviceListener: Remove usage of deprecated keybackup API (#11614)

Primarily this means calling `CryptoApi.getActiveSessionBackupVersion` instead
of `MatrixClisnt.getKeyBackupEnabled`
This commit is contained in:
Richard van der Hoff 2023-09-20 13:34:18 +02:00 committed by GitHub
parent 8ac25758b3
commit 51ec7f04b4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 29 additions and 35 deletions

View file

@ -25,7 +25,7 @@ import {
} from "matrix-js-sdk/src/matrix";
import { logger } from "matrix-js-sdk/src/logger";
import { CryptoEvent } from "matrix-js-sdk/src/crypto";
import { IKeyBackupInfo } from "matrix-js-sdk/src/crypto/keybackup";
import { KeyBackupInfo } from "matrix-js-sdk/src/crypto-api";
import dis from "./dispatcher/dispatcher";
import {
@ -62,10 +62,10 @@ export default class DeviceListener {
private dismissed = new Set<string>();
// has the user dismissed any of the various nag toasts to setup encryption on this device?
private dismissedThisDeviceToast = false;
// cache of the key backup info
private keyBackupInfo: IKeyBackupInfo | null = null;
/** Cache of the info about the current key backup on the server. */
private keyBackupInfo: KeyBackupInfo | null = null;
/** When `keyBackupInfo` was last updated */
private keyBackupFetchedAt: number | null = null;
private keyBackupStatusChecked = false;
// We keep a list of our own device IDs so we can batch ones that were already
// there the last time the app launched into a single toast, but display new
// ones in their own toasts.
@ -243,9 +243,14 @@ export default class DeviceListener {
this.updateClientInformation();
};
// The server doesn't tell us when key backup is set up, so we poll
// & cache the result
private async getKeyBackupInfo(): Promise<IKeyBackupInfo | null> {
/**
* Fetch the key backup information from the server.
*
* The result is cached for `KEY_BACKUP_POLL_INTERVAL` ms to avoid repeated API calls.
*
* @returns The key backup info from the server, or `null` if there is no key backup.
*/
private async getKeyBackupInfo(): Promise<KeyBackupInfo | null> {
if (!this.client) return null;
const now = new Date().getTime();
if (
@ -402,18 +407,23 @@ export default class DeviceListener {
this.displayingToastsForDeviceIds = newUnverifiedDeviceIds;
}
/**
* Check if key backup is enabled, and if not, raise an `Action.ReportKeyBackupNotEnabled` event (which will
* trigger an auto-rageshake).
*/
private checkKeyBackupStatus = async (): Promise<void> => {
if (this.keyBackupStatusChecked || !this.client) {
return;
}
// returns null when key backup status hasn't finished being checked
const isKeyBackupEnabled = this.client.getKeyBackupEnabled();
this.keyBackupStatusChecked = isKeyBackupEnabled !== null;
const activeKeyBackupVersion = await this.client.getCrypto()?.getActiveSessionBackupVersion();
// if key backup is enabled, no need to check this ever again (XXX: why only when it is enabled?)
this.keyBackupStatusChecked = !!activeKeyBackupVersion;
if (isKeyBackupEnabled === false) {
if (!activeKeyBackupVersion) {
dis.dispatch({ action: Action.ReportKeyBackupNotEnabled });
}
};
private keyBackupStatusChecked = false;
private onRecordClientInformationSettingChange: CallbackFn = (
_originalSettingName,

View file

@ -92,6 +92,7 @@ describe("DeviceListener", () => {
isCrossSigningReady: jest.fn().mockResolvedValue(true),
isSecretStorageReady: jest.fn().mockResolvedValue(true),
userHasCrossSigningKeys: jest.fn(),
getActiveSessionBackupVersion: jest.fn(),
} as unknown as Mocked<CryptoApi>;
mockClient = getMockClientWithEventEmitter({
isGuest: jest.fn(),
@ -101,7 +102,6 @@ describe("DeviceListener", () => {
getRooms: jest.fn().mockReturnValue([]),
isVersionSupported: jest.fn().mockResolvedValue(true),
isInitialSyncComplete: jest.fn().mockReturnValue(true),
getKeyBackupEnabled: jest.fn(),
waitForClientWellKnown: jest.fn(),
isRoomEncrypted: jest.fn(),
getClientWellKnown: jest.fn(),
@ -337,7 +337,7 @@ describe("DeviceListener", () => {
mockCrypto!.userHasCrossSigningKeys.mockResolvedValue(true);
await createAndStart();
expect(mockClient!.getKeyBackupEnabled).toHaveBeenCalled();
expect(mockCrypto!.getActiveSessionBackupVersion).toHaveBeenCalled();
});
});
@ -362,8 +362,7 @@ describe("DeviceListener", () => {
it("checks keybackup status when cross signing and secret storage are ready", async () => {
// default mocks set cross signing and secret storage to ready
await createAndStart();
expect(mockClient!.getKeyBackupEnabled).toHaveBeenCalled();
expect(mockDispatcher.dispatch).not.toHaveBeenCalled();
expect(mockCrypto.getActiveSessionBackupVersion).toHaveBeenCalled();
});
it("checks keybackup status when setup encryption toast has been dismissed", async () => {
@ -373,40 +372,25 @@ describe("DeviceListener", () => {
instance.dismissEncryptionSetup();
await flushPromises();
expect(mockClient!.getKeyBackupEnabled).toHaveBeenCalled();
});
it("does not dispatch keybackup event when key backup check is not finished", async () => {
// returns null when key backup status hasn't finished being checked
mockClient!.getKeyBackupEnabled.mockReturnValue(null);
await createAndStart();
expect(mockDispatcher.dispatch).not.toHaveBeenCalled();
expect(mockCrypto.getActiveSessionBackupVersion).toHaveBeenCalled();
});
it("dispatches keybackup event when key backup is not enabled", async () => {
mockClient!.getKeyBackupEnabled.mockReturnValue(false);
mockCrypto.getActiveSessionBackupVersion.mockResolvedValue(null);
await createAndStart();
expect(mockDispatcher.dispatch).toHaveBeenCalledWith({ action: Action.ReportKeyBackupNotEnabled });
});
it("does not check key backup status again after check is complete", async () => {
mockClient!.getKeyBackupEnabled.mockReturnValue(null);
mockCrypto.getActiveSessionBackupVersion.mockResolvedValue("1");
const instance = await createAndStart();
expect(mockClient!.getKeyBackupEnabled).toHaveBeenCalled();
// keyback check now complete
mockClient!.getKeyBackupEnabled.mockReturnValue(true);
expect(mockCrypto.getActiveSessionBackupVersion).toHaveBeenCalled();
// trigger a recheck
instance.dismissEncryptionSetup();
await flushPromises();
expect(mockClient!.getKeyBackupEnabled).toHaveBeenCalledTimes(2);
// trigger another recheck
instance.dismissEncryptionSetup();
await flushPromises();
// not called again, check was complete last time
expect(mockClient!.getKeyBackupEnabled).toHaveBeenCalledTimes(2);
expect(mockCrypto.getActiveSessionBackupVersion).toHaveBeenCalledTimes(1);
});
});