From 97bbceab907870952cd6f293f61ecb9c1ad7f615 Mon Sep 17 00:00:00 2001 From: David Thievon Date: Wed, 31 Dec 2025 01:26:00 +0100 Subject: [PATCH 1/3] feat(settings): add ability to configure settings via policies Setting can now be set via policies. They are not currently locked to these values. If a user changes them in the UI, their changes will be lost on refresh. --- lib/settings.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/lib/settings.js b/lib/settings.js index 569ba4f5d..2b84c3af1 100644 --- a/lib/settings.js +++ b/lib/settings.js @@ -122,9 +122,13 @@ const Settings = { ); } + const managed_settings = this.pruneToOptions(await chrome.storage.managed.get(null)); + let result = await chrome.storage.sync.get(null); // Get every key. result = this.migrateSettingsIfNecessary(result); result["settingsVersion"] = Utils.getCurrentVersion(); + + result = Object.assign(result, managed_settings); this._settings = Object.assign(globalThis.structuredClone(defaultOptions), result); }, @@ -240,6 +244,19 @@ const Settings = { return clonedSettings; }, + // Remove all keys not found in the default options. + pruneToOptions(settings) { + const prunedSettings = {}; + for (const k of Object.keys(defaultOptions)) { + let setting = settings[k]; + + if (setting !== undefined) { + prunedSettings[k] = setting; + } + } + return prunedSettings; + }, + // Used only by tests. async clear() { this._settings = null; From c831d3a942a7fda291522c91b44c9b56ed8442a4 Mon Sep 17 00:00:00 2001 From: David Thievon Date: Wed, 31 Dec 2025 13:14:58 +0100 Subject: [PATCH 2/3] fix(chrome): add managed_schema file for chrome policies --- managed_schema.json | 83 +++++++++++++++++++++++++++++++++++++++++++++ manifest.json | 3 ++ 2 files changed, 86 insertions(+) create mode 100644 managed_schema.json diff --git a/managed_schema.json b/managed_schema.json new file mode 100644 index 000000000..02568a5c9 --- /dev/null +++ b/managed_schema.json @@ -0,0 +1,83 @@ +{ + "type": "object", + "properties": { + "scrollStepSize": { + "type": "integer" + }, + "smoothScroll": { + "type": "boolean" + }, + "keyMappings": { + "type": "string" + }, + "linkHintCharacters": { + "type": "string" + }, + "linkHintNumbers": { + "type": "string" + }, + "filterLinkHints": { + "type": "boolean" + }, + "hideHud": { + "type": "boolean" + }, + "hideUpdateNotifications": { + "type": "boolean" + }, + "userDefinedLinkHintCss": { + "type": "string" + }, + "exclusionRules": { + "type": "array", + "items": { + "type": "object", + "properties": { + "passKeys": { + "type": "string" + }, + "pattern": { + "type": "string" + } + } + } + }, + "previousPatterns": { + "type": "string" + }, + "nextPatterns": { + "type": "string" + }, + "searchUrl": { + "type": "string" + }, + "searchEngines": { + "type": "string" + }, + "newTabDestination": { + "type": "string", + "enum": ["vimiumNewTabPage", "customUrl"] + }, + "newTabCustomUrl": { + "type": "string" + }, + "openVomnibarOnNewTabPage": { + "type": "boolean" + }, + "grabBackFocus": { + "type": "boolean" + }, + "regexFindMode": { + "type": "boolean" + }, + "waitForEnterForFilteredHints": { + "type": "boolean" + }, + "helpDialog_showAdvancedCommands": { + "type": "boolean" + }, + "ignoreKeyboardLayout": { + "type": "boolean" + } + } +} diff --git a/manifest.json b/manifest.json index af4e22412..d17468609 100644 --- a/manifest.json +++ b/manifest.json @@ -5,6 +5,9 @@ "description": "The Hacker's Browser. Vimium provides keyboard shortcuts for navigation and control in the spirit of Vim.", "icons": { "16": "icons/icon16.png", "48": "icons/icon48.png", "128": "icons/icon128.png" }, "minimum_chrome_version": "117.0", + "storage": { + "managed_schema": "managed_schema.json" + }, "background": { "service_worker": "background_scripts/main.js", "type": "module" From 48196ccfc7ca8d98464b37d12706233040e2c3e3 Mon Sep 17 00:00:00 2001 From: David Thievon Date: Wed, 31 Dec 2025 17:50:36 +0100 Subject: [PATCH 3/3] feat(options-page): disable settings fields set via policies --- lib/settings.js | 7 +++++++ pages/options.js | 6 ++++++ 2 files changed, 13 insertions(+) diff --git a/lib/settings.js b/lib/settings.js index 2b84c3af1..09a2690a3 100644 --- a/lib/settings.js +++ b/lib/settings.js @@ -91,6 +91,8 @@ const Settings = { _settings: null, _chromeStorageListenerInstalled: false, + _managedSettingsKeys: [], + defaultOptions, newTabDestinations, vimiumNewTabPageUrl, @@ -123,6 +125,7 @@ const Settings = { } const managed_settings = this.pruneToOptions(await chrome.storage.managed.get(null)); + this._managedSettingsKeys = Object.keys(managed_settings); let result = await chrome.storage.sync.get(null); // Get every key. result = this.migrateSettingsIfNecessary(result); @@ -155,6 +158,10 @@ const Settings = { return globalThis.structuredClone(this._settings); }, + getManagedSettingsKeys() { + return globalThis.structuredClone(this._managedSettingsKeys); + }, + migratePre2_0(settings) { // Prior to Vimium version 2.0.0: // - In chrome.storages.sync, the value of each setting was encoded as a JSON string using diff --git a/pages/options.js b/pages/options.js index eafc6c99d..fb2fd5a01 100644 --- a/pages/options.js +++ b/pages/options.js @@ -98,6 +98,12 @@ const OptionsPage = { const settings = Settings.getSettings(); this.setFormFromSettings(settings); + + for (const option of Settings.getManagedSettingsKeys()) { + let elem = this.getOptionEl(option); + + elem.setAttribute("disabled", "true"); + } }, getOptionEl(optionName) {