From 181f80dacf1946970c08c62abb744b976fb89a77 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Tue, 19 May 2026 19:58:47 +0200 Subject: [PATCH 1/2] feat(electron): support object-based electronSwitches Adds js/electron_helper.js with applyElectronSwitches(), which handles both string and object entries in the electronSwitches config array and logs each activated switch. The hardcoded autoplay-policy default switch is moved into the helper so all switch logic lives in one place. Fixes #4159 --- js/electron.js | 6 +- js/electron_helper.js | 33 +++++++++ tests/unit/functions/electron_helper_spec.js | 78 ++++++++++++++++++++ 3 files changed, 113 insertions(+), 4 deletions(-) create mode 100644 js/electron_helper.js create mode 100644 tests/unit/functions/electron_helper_spec.js diff --git a/js/electron.js b/js/electron.js index 3105966801..1714eab579 100644 --- a/js/electron.js +++ b/js/electron.js @@ -3,6 +3,7 @@ const electron = require("electron"); const core = require("./app"); const Log = require("./logger"); +const { applyElectronSwitches } = require("./electron_helper"); // Config let config = process.env.config ? JSON.parse(process.env.config) : {}; @@ -43,10 +44,7 @@ function createWindow () { Log.warn("Could not get display size, using defaults ..."); } - app.commandLine.appendSwitch("autoplay-policy", "no-user-gesture-required"); - for (const electronSwitch of (config.electronSwitches || [])) { - app.commandLine.appendSwitch(electronSwitch); - } + applyElectronSwitches(app.commandLine, config.electronSwitches); let electronOptionsDefaults = { width: electronSize.width, height: electronSize.height, diff --git a/js/electron_helper.js b/js/electron_helper.js new file mode 100644 index 0000000000..a80b62e81c --- /dev/null +++ b/js/electron_helper.js @@ -0,0 +1,33 @@ +const Log = require("./logger"); + +/** + * Applies Electron command-line switches (defaults + from config). + * @param {object} commandLine Electron commandLine API + * @param {Array} [electronSwitches] User-configured switches + */ +function applyElectronSwitches (commandLine, electronSwitches) { + commandLine.appendSwitch("autoplay-policy", "no-user-gesture-required"); + Log.debug("Activated default switch: autoplay-policy=no-user-gesture-required"); + + if (electronSwitches === undefined) return; + if (!Array.isArray(electronSwitches)) { + Log.error(`electronSwitches must be an array of strings or objects, got: ${JSON.stringify(electronSwitches)}`); + return; + } + + for (const sw of electronSwitches) { + if (typeof sw === "string") { + commandLine.appendSwitch(sw); + Log.debug(`Activated switch: ${sw}`); + } else if (sw && typeof sw === "object" && !Array.isArray(sw)) { + for (const [name, value] of Object.entries(sw)) { + commandLine.appendSwitch(name, String(value)); + Log.debug(`Activated switch: ${name}=${value}`); + } + } else { + Log.error(`Invalid electronSwitches entry: ${JSON.stringify(sw)}`); + } + } +} + +module.exports = { applyElectronSwitches }; diff --git a/tests/unit/functions/electron_helper_spec.js b/tests/unit/functions/electron_helper_spec.js new file mode 100644 index 0000000000..e6be6f13bd --- /dev/null +++ b/tests/unit/functions/electron_helper_spec.js @@ -0,0 +1,78 @@ +const Log = require("logger"); +const { applyElectronSwitches } = require("../../../js/electron_helper"); + +describe("electron switches", () => { + let commandLine; + + beforeEach(() => { + commandLine = { + appendSwitch: vi.fn() + }; + vi.spyOn(Log, "error").mockImplementation(() => {}); + }); + + it("always applies the autoplay-policy default switch", () => { + applyElectronSwitches(commandLine, undefined); + + expect(commandLine.appendSwitch).toHaveBeenCalledTimes(1); + expect(commandLine.appendSwitch).toHaveBeenCalledWith("autoplay-policy", "no-user-gesture-required"); + expect(Log.error).not.toHaveBeenCalled(); + }); + + it("applies string entries as switches without values", () => { + applyElectronSwitches(commandLine, ["no-sandbox", "disable-http-cache"]); + + expect(commandLine.appendSwitch).toHaveBeenCalledTimes(3); + expect(commandLine.appendSwitch).toHaveBeenNthCalledWith(1, "autoplay-policy", "no-user-gesture-required"); + expect(commandLine.appendSwitch).toHaveBeenNthCalledWith(2, "no-sandbox"); + expect(commandLine.appendSwitch).toHaveBeenNthCalledWith(3, "disable-http-cache"); + expect(Log.error).not.toHaveBeenCalled(); + }); + + it("applies object entries as switches with values", () => { + applyElectronSwitches(commandLine, [ + { "js-flags": "--max-old-space-size=8192" }, + { "password-store": "basic" } + ]); + + expect(commandLine.appendSwitch).toHaveBeenCalledTimes(3); + expect(commandLine.appendSwitch).toHaveBeenNthCalledWith(1, "autoplay-policy", "no-user-gesture-required"); + expect(commandLine.appendSwitch).toHaveBeenNthCalledWith(2, "js-flags", "--max-old-space-size=8192"); + expect(commandLine.appendSwitch).toHaveBeenNthCalledWith(3, "password-store", "basic"); + expect(Log.error).not.toHaveBeenCalled(); + }); + + it("allows one object entry to define multiple switches with values", () => { + applyElectronSwitches(commandLine, [ + "no-sandbox", + { + "js-flags": "--max-old-space-size=8192", + "password-store": "basic" + } + ]); + + expect(commandLine.appendSwitch).toHaveBeenCalledTimes(4); + expect(commandLine.appendSwitch).toHaveBeenNthCalledWith(1, "autoplay-policy", "no-user-gesture-required"); + expect(commandLine.appendSwitch).toHaveBeenNthCalledWith(2, "no-sandbox"); + expect(commandLine.appendSwitch).toHaveBeenNthCalledWith(3, "js-flags", "--max-old-space-size=8192"); + expect(commandLine.appendSwitch).toHaveBeenNthCalledWith(4, "password-store", "basic"); + expect(Log.error).not.toHaveBeenCalled(); + }); + + it("logs an error for invalid entries", () => { + applyElectronSwitches(commandLine, ["no-sandbox", ["js-flags", "--max-old-space-size=8192"], null]); + + expect(commandLine.appendSwitch).toHaveBeenCalledTimes(2); + expect(commandLine.appendSwitch).toHaveBeenNthCalledWith(1, "autoplay-policy", "no-user-gesture-required"); + expect(commandLine.appendSwitch).toHaveBeenNthCalledWith(2, "no-sandbox"); + expect(Log.error).toHaveBeenCalledTimes(2); + }); + + it("logs an error when electronSwitches is not an array", () => { + applyElectronSwitches(commandLine, { "js-flags": "--max-old-space-size=8192" }); + + expect(commandLine.appendSwitch).toHaveBeenCalledTimes(1); + expect(commandLine.appendSwitch).toHaveBeenCalledWith("autoplay-policy", "no-user-gesture-required"); + expect(Log.error).toHaveBeenCalledWith(expect.stringContaining("electronSwitches must be an array of strings or objects")); + }); +}); From ab8e20a31c31e0228665c442684cfa537fafea09 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Tue, 19 May 2026 22:30:07 +0200 Subject: [PATCH 2/2] refactor(electron): remove redundant autoplay-policy CLI switch Electron's webPreferences.autoplayPolicy already defaults to "no-user-gesture-required", making the commandLine switch redundant. --- js/electron_helper.js | 5 +-- tests/unit/functions/electron_helper_spec.js | 36 ++++++++------------ 2 files changed, 16 insertions(+), 25 deletions(-) diff --git a/js/electron_helper.js b/js/electron_helper.js index a80b62e81c..6eca6e9178 100644 --- a/js/electron_helper.js +++ b/js/electron_helper.js @@ -1,14 +1,11 @@ const Log = require("./logger"); /** - * Applies Electron command-line switches (defaults + from config). + * Applies Electron command-line switches from config. * @param {object} commandLine Electron commandLine API * @param {Array} [electronSwitches] User-configured switches */ function applyElectronSwitches (commandLine, electronSwitches) { - commandLine.appendSwitch("autoplay-policy", "no-user-gesture-required"); - Log.debug("Activated default switch: autoplay-policy=no-user-gesture-required"); - if (electronSwitches === undefined) return; if (!Array.isArray(electronSwitches)) { Log.error(`electronSwitches must be an array of strings or objects, got: ${JSON.stringify(electronSwitches)}`); diff --git a/tests/unit/functions/electron_helper_spec.js b/tests/unit/functions/electron_helper_spec.js index e6be6f13bd..ff2c09231f 100644 --- a/tests/unit/functions/electron_helper_spec.js +++ b/tests/unit/functions/electron_helper_spec.js @@ -11,21 +11,19 @@ describe("electron switches", () => { vi.spyOn(Log, "error").mockImplementation(() => {}); }); - it("always applies the autoplay-policy default switch", () => { + it("does nothing when electronSwitches is undefined", () => { applyElectronSwitches(commandLine, undefined); - expect(commandLine.appendSwitch).toHaveBeenCalledTimes(1); - expect(commandLine.appendSwitch).toHaveBeenCalledWith("autoplay-policy", "no-user-gesture-required"); + expect(commandLine.appendSwitch).not.toHaveBeenCalled(); expect(Log.error).not.toHaveBeenCalled(); }); it("applies string entries as switches without values", () => { applyElectronSwitches(commandLine, ["no-sandbox", "disable-http-cache"]); - expect(commandLine.appendSwitch).toHaveBeenCalledTimes(3); - expect(commandLine.appendSwitch).toHaveBeenNthCalledWith(1, "autoplay-policy", "no-user-gesture-required"); - expect(commandLine.appendSwitch).toHaveBeenNthCalledWith(2, "no-sandbox"); - expect(commandLine.appendSwitch).toHaveBeenNthCalledWith(3, "disable-http-cache"); + expect(commandLine.appendSwitch).toHaveBeenCalledTimes(2); + expect(commandLine.appendSwitch).toHaveBeenNthCalledWith(1, "no-sandbox"); + expect(commandLine.appendSwitch).toHaveBeenNthCalledWith(2, "disable-http-cache"); expect(Log.error).not.toHaveBeenCalled(); }); @@ -35,10 +33,9 @@ describe("electron switches", () => { { "password-store": "basic" } ]); - expect(commandLine.appendSwitch).toHaveBeenCalledTimes(3); - expect(commandLine.appendSwitch).toHaveBeenNthCalledWith(1, "autoplay-policy", "no-user-gesture-required"); - expect(commandLine.appendSwitch).toHaveBeenNthCalledWith(2, "js-flags", "--max-old-space-size=8192"); - expect(commandLine.appendSwitch).toHaveBeenNthCalledWith(3, "password-store", "basic"); + expect(commandLine.appendSwitch).toHaveBeenCalledTimes(2); + expect(commandLine.appendSwitch).toHaveBeenNthCalledWith(1, "js-flags", "--max-old-space-size=8192"); + expect(commandLine.appendSwitch).toHaveBeenNthCalledWith(2, "password-store", "basic"); expect(Log.error).not.toHaveBeenCalled(); }); @@ -51,28 +48,25 @@ describe("electron switches", () => { } ]); - expect(commandLine.appendSwitch).toHaveBeenCalledTimes(4); - expect(commandLine.appendSwitch).toHaveBeenNthCalledWith(1, "autoplay-policy", "no-user-gesture-required"); - expect(commandLine.appendSwitch).toHaveBeenNthCalledWith(2, "no-sandbox"); - expect(commandLine.appendSwitch).toHaveBeenNthCalledWith(3, "js-flags", "--max-old-space-size=8192"); - expect(commandLine.appendSwitch).toHaveBeenNthCalledWith(4, "password-store", "basic"); + expect(commandLine.appendSwitch).toHaveBeenCalledTimes(3); + expect(commandLine.appendSwitch).toHaveBeenNthCalledWith(1, "no-sandbox"); + expect(commandLine.appendSwitch).toHaveBeenNthCalledWith(2, "js-flags", "--max-old-space-size=8192"); + expect(commandLine.appendSwitch).toHaveBeenNthCalledWith(3, "password-store", "basic"); expect(Log.error).not.toHaveBeenCalled(); }); it("logs an error for invalid entries", () => { applyElectronSwitches(commandLine, ["no-sandbox", ["js-flags", "--max-old-space-size=8192"], null]); - expect(commandLine.appendSwitch).toHaveBeenCalledTimes(2); - expect(commandLine.appendSwitch).toHaveBeenNthCalledWith(1, "autoplay-policy", "no-user-gesture-required"); - expect(commandLine.appendSwitch).toHaveBeenNthCalledWith(2, "no-sandbox"); + expect(commandLine.appendSwitch).toHaveBeenCalledTimes(1); + expect(commandLine.appendSwitch).toHaveBeenCalledWith("no-sandbox"); expect(Log.error).toHaveBeenCalledTimes(2); }); it("logs an error when electronSwitches is not an array", () => { applyElectronSwitches(commandLine, { "js-flags": "--max-old-space-size=8192" }); - expect(commandLine.appendSwitch).toHaveBeenCalledTimes(1); - expect(commandLine.appendSwitch).toHaveBeenCalledWith("autoplay-policy", "no-user-gesture-required"); + expect(commandLine.appendSwitch).not.toHaveBeenCalled(); expect(Log.error).toHaveBeenCalledWith(expect.stringContaining("electronSwitches must be an array of strings or objects")); }); });