Skip to content
This repository was archived by the owner on Sep 11, 2024. It is now read-only.

Commit b6364a4

Browse files
authored
Enable the rust-crypto labs button (#12114)
* `LabsUserSettingsTab-test.tsx`: use a real `SdkConfig` ... instead of mocking it out. Doing so allows us more flexibility, and gives a more realistic test. * Enable the rust-crypto labs button * fix up a test
1 parent b64d2e7 commit b6364a4

File tree

7 files changed

+139
-20
lines changed

7 files changed

+139
-20
lines changed

src/MatrixClientPeg.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ import ErrorDialog from "./components/views/dialogs/ErrorDialog";
5252
import PlatformPeg from "./PlatformPeg";
5353
import { formatList } from "./utils/FormattingUtils";
5454
import SdkConfig from "./SdkConfig";
55+
import { Features } from "./settings/Settings";
5556

5657
export interface IMatrixClientCreds {
5758
homeserverUrl: string;
@@ -301,7 +302,7 @@ class MatrixClientPegClass implements IMatrixClientPeg {
301302
throw new Error("createClient must be called first");
302303
}
303304

304-
const useRustCrypto = SettingsStore.getValue("feature_rust_crypto");
305+
const useRustCrypto = SettingsStore.getValue(Features.RustCrypto);
305306

306307
// we want to make sure that the same crypto implementation is used throughout the lifetime of a device,
307308
// so persist the setting at the device layer

src/i18n/strings/en_EN.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1447,7 +1447,10 @@
14471447
"report_to_moderators": "Report to moderators",
14481448
"report_to_moderators_description": "In rooms that support moderation, the “Report” button will let you report abuse to room moderators.",
14491449
"rust_crypto": "Rust cryptography implementation",
1450-
"rust_crypto_disabled_notice": "Can currently only be enabled via config.json",
1450+
"rust_crypto_in_config": "Rust cryptography cannot be disabled on this deployment of %(brand)s",
1451+
"rust_crypto_in_config_description": "Switching to the Rust cryptography requires a migration process that may take several minutes. It cannot be disabled; use with caution!",
1452+
"rust_crypto_optin_warning": "Switching to the Rust cryptography requires a migration process that may take several minutes. To disable you will need to log out and back in; use with caution!",
1453+
"rust_crypto_requires_logout": "Once enabled, Rust cryptography can only be disabled by logging out and in again",
14511454
"sliding_sync": "Sliding Sync mode",
14521455
"sliding_sync_checking": "Checking…",
14531456
"sliding_sync_configuration": "Sliding Sync configuration",

src/settings/Settings.tsx

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ import RustCryptoSdkController from "./controllers/RustCryptoSdkController";
4646
import ServerSupportUnstableFeatureController from "./controllers/ServerSupportUnstableFeatureController";
4747
import { WatchManager } from "./WatchManager";
4848
import { CustomTheme } from "../theme";
49+
import SettingsStore from "./SettingsStore";
4950

5051
export const defaultWatchManager = new WatchManager();
5152

@@ -94,6 +95,7 @@ export enum Features {
9495
VoiceBroadcastForceSmallChunks = "feature_voice_broadcast_force_small_chunks",
9596
NotificationSettings2 = "feature_notification_settings2",
9697
OidcNativeFlow = "feature_oidc_native_flow",
98+
RustCrypto = "feature_rust_crypto",
9799
}
98100

99101
export const labGroupNames: Record<LabGroup, TranslationKey> = {
@@ -480,15 +482,22 @@ export const SETTINGS: { [setting: string]: ISetting } = {
480482
description: _td("labs|oidc_native_flow_description"),
481483
default: false,
482484
},
483-
"feature_rust_crypto": {
484-
// use the rust matrix-sdk-crypto-js for crypto.
485+
[Features.RustCrypto]: {
486+
// use the rust matrix-sdk-crypto-wasm for crypto.
485487
isFeature: true,
486488
labsGroup: LabGroup.Developer,
487-
configDisablesSetting: true,
489+
// unlike most features, `configDisablesSetting` is false here.
488490
supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG,
489491
displayName: _td("labs|rust_crypto"),
490-
description: _td("labs|under_active_development"),
491-
// shouldWarn: true,
492+
description: () => {
493+
if (SettingsStore.getValueAt(SettingLevel.CONFIG, Features.RustCrypto)) {
494+
// It's enabled in the config, so you can't get rid of it even by logging out.
495+
return _t("labs|rust_crypto_in_config_description");
496+
} else {
497+
return _t("labs|rust_crypto_optin_warning");
498+
}
499+
},
500+
shouldWarn: true,
492501
default: false,
493502
controller: new RustCryptoSdkController(),
494503
},

src/settings/controllers/RustCryptoSdkController.ts

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,35 @@ limitations under the License.
1515
*/
1616

1717
import { _t } from "../../languageHandler";
18+
import SettingsStore from "../SettingsStore";
19+
import { SettingLevel } from "../SettingLevel";
20+
import PlatformPeg from "../../PlatformPeg";
1821
import SettingController from "./SettingController";
22+
import { Features } from "../Settings";
23+
import { MatrixClientPeg } from "../../MatrixClientPeg";
24+
import SdkConfig from "../../SdkConfig";
1925

2026
export default class RustCryptoSdkController extends SettingController {
27+
public onChange(level: SettingLevel, roomId: string | null, newValue: any): void {
28+
// If the crypto stack has already been initialized, we'll need to reload the app to make it take effect.
29+
if (MatrixClientPeg.get()?.getCrypto()) {
30+
PlatformPeg.get()?.reload();
31+
}
32+
}
33+
2134
public get settingDisabled(): boolean | string {
22-
// Currently this can only be changed via config.json. In future, we'll allow the user to *enable* this setting
23-
// via labs, which will migrate their existing device to the rust-sdk implementation.
24-
return _t("labs|rust_crypto_disabled_notice");
35+
if (!SettingsStore.getValueAt(SettingLevel.DEVICE, Features.RustCrypto)) {
36+
// If rust crypto has not yet been enabled for this device, you can turn it on, IF YOU DARE
37+
return false;
38+
}
39+
40+
if (SettingsStore.getValueAt(SettingLevel.CONFIG, Features.RustCrypto)) {
41+
// It's enabled in the config, so you can't get rid of it even by logging out.
42+
return _t("labs|rust_crypto_in_config", { brand: SdkConfig.get().brand });
43+
}
44+
45+
// The setting is enabled at the device level, but not mandated at the config level.
46+
// You can only turn it off by logging out and in again.
47+
return _t("labs|rust_crypto_requires_logout");
2548
}
2649
}

test/MatrixClientPeg-test.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ describe("MatrixClientPeg", () => {
3838
afterEach(() => {
3939
localStorage.clear();
4040
jest.restoreAllMocks();
41+
42+
// some of the tests assign `MatrixClientPeg.matrixClient`: clear it, to prevent leakage between tests
43+
peg.unset();
4144
});
4245

4346
it("setJustRegisteredUserId", () => {

test/components/views/settings/tabs/user/LabsUserSettingsTab-test.tsx

Lines changed: 85 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,14 @@ limitations under the License.
1515
*/
1616

1717
import React from "react";
18-
import { render, screen } from "@testing-library/react";
18+
import { fireEvent, render, screen } from "@testing-library/react";
1919

2020
import LabsUserSettingsTab from "../../../../../../src/components/views/settings/tabs/user/LabsUserSettingsTab";
2121
import SettingsStore from "../../../../../../src/settings/SettingsStore";
2222
import SdkConfig from "../../../../../../src/SdkConfig";
23+
import { SettingLevel } from "../../../../../../src/settings/SettingLevel";
2324

2425
describe("<LabsUserSettingsTab />", () => {
25-
const sdkConfigSpy = jest.spyOn(SdkConfig, "get");
26-
2726
const defaultProps = {
2827
closeSettingsFn: jest.fn(),
2928
};
@@ -34,7 +33,9 @@ describe("<LabsUserSettingsTab />", () => {
3433
beforeEach(() => {
3534
jest.clearAllMocks();
3635
settingsValueSpy.mockReturnValue(false);
37-
sdkConfigSpy.mockReturnValue(false);
36+
SdkConfig.reset();
37+
SdkConfig.add({ brand: "BrandedClient" });
38+
localStorage.clear();
3839
});
3940

4041
it("renders settings marked as beta as beta cards", () => {
@@ -43,6 +44,7 @@ describe("<LabsUserSettingsTab />", () => {
4344
});
4445

4546
it("does not render non-beta labs settings when disabled in config", () => {
47+
const sdkConfigSpy = jest.spyOn(SdkConfig, "get");
4648
render(getComponent());
4749
expect(sdkConfigSpy).toHaveBeenCalledWith("show_labs_settings");
4850

@@ -52,12 +54,90 @@ describe("<LabsUserSettingsTab />", () => {
5254

5355
it("renders non-beta labs settings when enabled in config", () => {
5456
// enable labs
55-
sdkConfigSpy.mockImplementation((configName) => configName === "show_labs_settings");
57+
SdkConfig.add({ show_labs_settings: true });
5658
const { container } = render(getComponent());
5759

5860
// non-beta labs section
5961
expect(screen.getByText("Early previews")).toBeInTheDocument();
6062
const labsSections = container.getElementsByClassName("mx_SettingsSubsection");
6163
expect(labsSections).toHaveLength(9);
6264
});
65+
66+
describe("Rust crypto setting", () => {
67+
const SETTING_NAME = "Rust cryptography implementation";
68+
69+
beforeEach(() => {
70+
SdkConfig.add({ show_labs_settings: true });
71+
});
72+
73+
describe("Not enabled in config", () => {
74+
it("can be turned on if not already", async () => {
75+
// By the time the settings panel is shown, `MatrixClientPeg.initClientCrypto` has saved the current
76+
// value to the settings store.
77+
await SettingsStore.setValue("feature_rust_crypto", null, SettingLevel.DEVICE, false);
78+
79+
const rendered = render(getComponent());
80+
const toggle = rendered.getByRole("switch", { name: SETTING_NAME });
81+
expect(toggle.getAttribute("aria-disabled")).toEqual("false");
82+
expect(toggle.getAttribute("aria-checked")).toEqual("false");
83+
84+
const description = toggle.closest(".mx_SettingsFlag")?.querySelector(".mx_SettingsFlag_microcopy");
85+
expect(description).toHaveTextContent(/To disable you will need to log out and back in/);
86+
});
87+
88+
it("cannot be turned off once enabled", async () => {
89+
await SettingsStore.setValue("feature_rust_crypto", null, SettingLevel.DEVICE, true);
90+
91+
const rendered = render(getComponent());
92+
const toggle = rendered.getByRole("switch", { name: SETTING_NAME });
93+
expect(toggle.getAttribute("aria-disabled")).toEqual("true");
94+
expect(toggle.getAttribute("aria-checked")).toEqual("true");
95+
96+
// Hover over the toggle to make it show the tooltip
97+
fireEvent.mouseOver(toggle);
98+
99+
const tooltip = rendered.getByRole("tooltip");
100+
expect(tooltip).toHaveTextContent(
101+
"Once enabled, Rust cryptography can only be disabled by logging out and in again",
102+
);
103+
});
104+
});
105+
106+
describe("Enabled in config", () => {
107+
beforeEach(() => {
108+
SdkConfig.add({ features: { feature_rust_crypto: true } });
109+
});
110+
111+
it("can be turned on if not already", async () => {
112+
// By the time the settings panel is shown, `MatrixClientPeg.initClientCrypto` has saved the current
113+
// value to the settings store.
114+
await SettingsStore.setValue("feature_rust_crypto", null, SettingLevel.DEVICE, false);
115+
116+
const rendered = render(getComponent());
117+
const toggle = rendered.getByRole("switch", { name: SETTING_NAME });
118+
expect(toggle.getAttribute("aria-disabled")).toEqual("false");
119+
expect(toggle.getAttribute("aria-checked")).toEqual("false");
120+
121+
const description = toggle.closest(".mx_SettingsFlag")?.querySelector(".mx_SettingsFlag_microcopy");
122+
expect(description).toHaveTextContent(/It cannot be disabled/);
123+
});
124+
125+
it("cannot be turned off once enabled", async () => {
126+
await SettingsStore.setValue("feature_rust_crypto", null, SettingLevel.DEVICE, true);
127+
128+
const rendered = render(getComponent());
129+
const toggle = rendered.getByRole("switch", { name: SETTING_NAME });
130+
expect(toggle.getAttribute("aria-disabled")).toEqual("true");
131+
expect(toggle.getAttribute("aria-checked")).toEqual("true");
132+
133+
// Hover over the toggle to make it show the tooltip
134+
fireEvent.mouseOver(toggle);
135+
136+
const tooltip = rendered.getByRole("tooltip");
137+
expect(tooltip).toHaveTextContent(
138+
"Rust cryptography cannot be disabled on this deployment of BrandedClient",
139+
);
140+
});
141+
});
142+
});
63143
});

test/components/views/settings/tabs/user/__snapshots__/LabsUserSettingsTab-test.tsx.snap

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ exports[`<LabsUserSettingsTab /> renders settings marked as beta as beta cards 1
1515
<div
1616
class="mx_SettingsSubsection_text"
1717
>
18-
What's next for false? Labs are the best way to get things early, test out new features and help shape them before they actually launch.
18+
What's next for BrandedClient? Labs are the best way to get things early, test out new features and help shape them before they actually launch.
1919
</div>
2020
<div
2121
class="mx_BetaCard"
@@ -42,10 +42,10 @@ exports[`<LabsUserSettingsTab /> renders settings marked as beta as beta cards 1
4242
class="mx_BetaCard_caption"
4343
>
4444
<p>
45-
A new way to chat over voice and video in .
45+
A new way to chat over voice and video in BrandedClient.
4646
</p>
4747
<p>
48-
Video rooms are always-on VoIP channels embedded within a room in .
48+
Video rooms are always-on VoIP channels embedded within a room in BrandedClient.
4949
</p>
5050
</div>
5151
<div
@@ -62,7 +62,7 @@ exports[`<LabsUserSettingsTab /> renders settings marked as beta as beta cards 1
6262
<div
6363
class="mx_BetaCard_refreshWarning"
6464
>
65-
Joining the beta will reload .
65+
Joining the beta will reload BrandedClient.
6666
</div>
6767
<div
6868
class="mx_BetaCard_faq"
@@ -104,7 +104,7 @@ exports[`<LabsUserSettingsTab /> renders settings marked as beta as beta cards 1
104104
class="mx_BetaCard_caption"
105105
>
106106
<p>
107-
Introducing a simpler way to change your notification settings. Customize your , just the way you like.
107+
Introducing a simpler way to change your notification settings. Customize your BrandedClient, just the way you like.
108108
</p>
109109
</div>
110110
<div

0 commit comments

Comments
 (0)