From e970abf6ec25940fef9a01dce01987f74fc1cadc Mon Sep 17 00:00:00 2001 From: Sebastian Streich Date: Mon, 9 Dec 2024 14:09:21 +0100 Subject: [PATCH] FXVPN-12 Allow manipulation of client settings --- package.json | 2 +- src/background/vpncontroller/states.js | 5 +++ src/background/vpncontroller/vpncontroller.js | 18 ++++++++++ .../vpncontroller/vpncontroller.test.mjs | 34 +++++++++++++++++++ 4 files changed, 58 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 0ac4d4dc..fa535830 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "build": "web-ext build --source-dir src --filename mozilla-vpn-extension.xpi", "start-dev": "web-ext run --verbose --source-dir src --pref=ui.popup.disable_autohide=true", "start": "web-ext run --verbose --source-dir src", - "test": "node --experimental-vm-modules node_modules/jest/bin/jest.js --collect-coverage --detectOpenHandles" + "test": "node --experimental-vm-modules node_modules/jest/bin/jest.js --collect-coverage --detectOpenHandles --" }, "repository": { "type": "git", diff --git a/src/background/vpncontroller/states.js b/src/background/vpncontroller/states.js index 52f17e76..acf0230b 100644 --- a/src/background/vpncontroller/states.js +++ b/src/background/vpncontroller/states.js @@ -19,6 +19,7 @@ export const REQUEST_TYPES = [ "telemetry", "session_start", "session_stop", + "settings", ]; export class VPNState { @@ -213,3 +214,7 @@ export class vpnStatusResponse { version: "2.25.0", }; } + +export class VPNSettings { + extensionTelemetryEnabled = false; +} diff --git a/src/background/vpncontroller/vpncontroller.js b/src/background/vpncontroller/vpncontroller.js index 2e7a2eef..d01560f8 100644 --- a/src/background/vpncontroller/vpncontroller.js +++ b/src/background/vpncontroller/vpncontroller.js @@ -27,6 +27,7 @@ import { StateVPNClosed, StateVPNSignedOut, StateVPNNeedsUpdate, + VPNSettings, } from "./states.js"; const log = Logger.logger("TabHandler"); @@ -47,6 +48,7 @@ export class VPNController extends Component { postToApp: PropertyType.Function, isolationKey: PropertyType.Bindable, featureList: PropertyType.Bindable, + settings: PropertyType.Bindable, }; get state() { @@ -62,6 +64,9 @@ export class VPNController extends Component { get featureList() { return this.#mFeaturelist; } + get settings() { + return this.#settings.readOnly; + } initNativeMessaging() { log("initNativeMessaging"); @@ -178,6 +183,17 @@ export class VPNController extends Component { ...new FeatureFlags(), ...response.featurelist, }); + break; + case "settings": + const settings = new VPNSettings(); + // Copy over all values that we expect to be in VPNSettings + Object.keys(settings).forEach((k) => { + if (response.settings[k]) { + settings[k] = response.settings[k]; + } + }); + this.#settings.set(settings); + break; default: console.log("Unexpected Message type: " + response.t); } @@ -200,6 +216,7 @@ export class VPNController extends Component { this.postToApp("status"); this.postToApp("servers"); this.postToApp("disabled_apps"); + this.postToApp("settings"); }); return; } @@ -235,6 +252,7 @@ export class VPNController extends Component { #mFeaturelist = property(new FeatureFlags()); #isExcluded = property(false); + #settings = property(new VPNSettings()); } export function isSplitTunnled( diff --git a/tests/jest/background/vpncontroller/vpncontroller.test.mjs b/tests/jest/background/vpncontroller/vpncontroller.test.mjs index aa987241..5d8e6cae 100644 --- a/tests/jest/background/vpncontroller/vpncontroller.test.mjs +++ b/tests/jest/background/vpncontroller/vpncontroller.test.mjs @@ -8,6 +8,8 @@ import { isSplitTunnled, ServerCity, ServerCountry, + VPNController, + VPNSettings, vpnStatusResponse, } from "../../../../src/background/vpncontroller"; @@ -178,3 +180,35 @@ describe("fromVPNStatusResponse", () => { expect(result.state).toBe("NeedsUpdate"); }); }); + +describe("IPC::Settings", () => { + it("can handle a setting response", async () => { + const target = new VPNController({ registerObserver: () => {} }); + // The Value should be the default one. + expect(target.settings.value.extensionTelemetryEnabled).toBe( + new VPNSettings().extensionTelemetryEnabled + ); + // The VPN Client may at any point push new data + const message = { + t: "settings", + settings: { + extensionTelemetryEnabled: true, + }, + }; + await target.handleResponse(message); + expect(target.settings.value.extensionTelemetryEnabled).toBe( + message.settings.extensionTelemetryEnabled + ); + }); + it("ignores unknown settings", async () => { + const target = new VPNController({ registerObserver: () => {} }); + const message = { + t: "settings", + settings: { + thisSettingDoesNotExist: true, + }, + }; + await target.handleResponse(message); + expect(target.settings.value["thisSettingDoesNotExist"]).toBe(undefined); + }); +});