summaryrefslogtreecommitdiffstats
path: root/toolkit/components/extensions/parent/ext-browserSettings.js
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/extensions/parent/ext-browserSettings.js')
-rw-r--r--toolkit/components/extensions/parent/ext-browserSettings.js592
1 files changed, 592 insertions, 0 deletions
diff --git a/toolkit/components/extensions/parent/ext-browserSettings.js b/toolkit/components/extensions/parent/ext-browserSettings.js
new file mode 100644
index 0000000000..7b292f76b8
--- /dev/null
+++ b/toolkit/components/extensions/parent/ext-browserSettings.js
@@ -0,0 +1,592 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+ChromeUtils.defineESModuleGetters(this, {
+ AboutNewTab: "resource:///modules/AboutNewTab.sys.mjs",
+});
+
+var { ExtensionPreferencesManager } = ChromeUtils.importESModule(
+ "resource://gre/modules/ExtensionPreferencesManager.sys.mjs"
+);
+
+var { ExtensionError } = ExtensionUtils;
+var { getSettingsAPI, getPrimedSettingsListener } = ExtensionPreferencesManager;
+
+const HOMEPAGE_URL_PREF = "browser.startup.homepage";
+
+const PERM_DENY_ACTION = Services.perms.DENY_ACTION;
+
+// Add settings objects for supported APIs to the preferences manager.
+ExtensionPreferencesManager.addSetting("allowPopupsForUserEvents", {
+ permission: "browserSettings",
+ prefNames: ["dom.popup_allowed_events"],
+
+ setCallback(value) {
+ let returnObj = {};
+ // If the value is true, then reset the pref, otherwise set it to "".
+ returnObj[this.prefNames[0]] = value ? undefined : "";
+ return returnObj;
+ },
+
+ getCallback() {
+ return Services.prefs.getCharPref("dom.popup_allowed_events") != "";
+ },
+});
+
+ExtensionPreferencesManager.addSetting("cacheEnabled", {
+ permission: "browserSettings",
+ prefNames: ["browser.cache.disk.enable", "browser.cache.memory.enable"],
+
+ setCallback(value) {
+ let returnObj = {};
+ for (let pref of this.prefNames) {
+ returnObj[pref] = value;
+ }
+ return returnObj;
+ },
+
+ getCallback() {
+ return (
+ Services.prefs.getBoolPref("browser.cache.disk.enable") &&
+ Services.prefs.getBoolPref("browser.cache.memory.enable")
+ );
+ },
+});
+
+ExtensionPreferencesManager.addSetting("closeTabsByDoubleClick", {
+ permission: "browserSettings",
+ prefNames: ["browser.tabs.closeTabByDblclick"],
+
+ setCallback(value) {
+ return { [this.prefNames[0]]: value };
+ },
+
+ getCallback() {
+ return Services.prefs.getBoolPref("browser.tabs.closeTabByDblclick");
+ },
+
+ validate() {
+ if (AppConstants.platform == "android") {
+ throw new ExtensionError(
+ `android is not a supported platform for the closeTabsByDoubleClick setting.`
+ );
+ }
+ },
+});
+
+ExtensionPreferencesManager.addSetting("colorManagement.mode", {
+ permission: "browserSettings",
+ prefNames: ["gfx.color_management.mode"],
+
+ setCallback(value) {
+ switch (value) {
+ case "off":
+ return { [this.prefNames[0]]: 0 };
+ case "full":
+ return { [this.prefNames[0]]: 1 };
+ case "tagged_only":
+ return { [this.prefNames[0]]: 2 };
+ }
+ },
+
+ getCallback() {
+ switch (Services.prefs.getIntPref("gfx.color_management.mode")) {
+ case 0:
+ return "off";
+ case 1:
+ return "full";
+ case 2:
+ return "tagged_only";
+ }
+ },
+});
+
+ExtensionPreferencesManager.addSetting("colorManagement.useNativeSRGB", {
+ permission: "browserSettings",
+ prefNames: ["gfx.color_management.native_srgb"],
+
+ setCallback(value) {
+ return { [this.prefNames[0]]: value };
+ },
+
+ getCallback() {
+ return Services.prefs.getBoolPref("gfx.color_management.native_srgb");
+ },
+});
+
+ExtensionPreferencesManager.addSetting(
+ "colorManagement.useWebRenderCompositor",
+ {
+ permission: "browserSettings",
+ prefNames: ["gfx.webrender.compositor"],
+
+ setCallback(value) {
+ return { [this.prefNames[0]]: value };
+ },
+
+ getCallback() {
+ return Services.prefs.getBoolPref("gfx.webrender.compositor");
+ },
+ }
+);
+
+ExtensionPreferencesManager.addSetting("contextMenuShowEvent", {
+ permission: "browserSettings",
+ prefNames: ["ui.context_menus.after_mouseup"],
+
+ setCallback(value) {
+ return { [this.prefNames[0]]: value === "mouseup" };
+ },
+
+ getCallback() {
+ if (AppConstants.platform === "win") {
+ return "mouseup";
+ }
+ let prefValue = Services.prefs.getBoolPref(
+ "ui.context_menus.after_mouseup",
+ null
+ );
+ return prefValue ? "mouseup" : "mousedown";
+ },
+});
+
+ExtensionPreferencesManager.addSetting("imageAnimationBehavior", {
+ permission: "browserSettings",
+ prefNames: ["image.animation_mode"],
+
+ setCallback(value) {
+ return { [this.prefNames[0]]: value };
+ },
+
+ getCallback() {
+ return Services.prefs.getCharPref("image.animation_mode");
+ },
+});
+
+ExtensionPreferencesManager.addSetting("newTabPosition", {
+ permission: "browserSettings",
+ prefNames: [
+ "browser.tabs.insertRelatedAfterCurrent",
+ "browser.tabs.insertAfterCurrent",
+ ],
+
+ setCallback(value) {
+ return {
+ "browser.tabs.insertAfterCurrent": value === "afterCurrent",
+ "browser.tabs.insertRelatedAfterCurrent": value === "relatedAfterCurrent",
+ };
+ },
+
+ getCallback() {
+ if (Services.prefs.getBoolPref("browser.tabs.insertAfterCurrent")) {
+ return "afterCurrent";
+ }
+ if (Services.prefs.getBoolPref("browser.tabs.insertRelatedAfterCurrent")) {
+ return "relatedAfterCurrent";
+ }
+ return "atEnd";
+ },
+});
+
+ExtensionPreferencesManager.addSetting("openBookmarksInNewTabs", {
+ permission: "browserSettings",
+ prefNames: ["browser.tabs.loadBookmarksInTabs"],
+
+ setCallback(value) {
+ return { [this.prefNames[0]]: value };
+ },
+
+ getCallback() {
+ return Services.prefs.getBoolPref("browser.tabs.loadBookmarksInTabs");
+ },
+});
+
+ExtensionPreferencesManager.addSetting("openSearchResultsInNewTabs", {
+ permission: "browserSettings",
+ prefNames: ["browser.search.openintab"],
+
+ setCallback(value) {
+ return { [this.prefNames[0]]: value };
+ },
+
+ getCallback() {
+ return Services.prefs.getBoolPref("browser.search.openintab");
+ },
+});
+
+ExtensionPreferencesManager.addSetting("openUrlbarResultsInNewTabs", {
+ permission: "browserSettings",
+ prefNames: ["browser.urlbar.openintab"],
+
+ setCallback(value) {
+ return { [this.prefNames[0]]: value };
+ },
+
+ getCallback() {
+ return Services.prefs.getBoolPref("browser.urlbar.openintab");
+ },
+});
+
+ExtensionPreferencesManager.addSetting("webNotificationsDisabled", {
+ permission: "browserSettings",
+ prefNames: ["permissions.default.desktop-notification"],
+
+ setCallback(value) {
+ return { [this.prefNames[0]]: value ? PERM_DENY_ACTION : undefined };
+ },
+
+ getCallback() {
+ let prefValue = Services.prefs.getIntPref(
+ "permissions.default.desktop-notification",
+ null
+ );
+ return prefValue === PERM_DENY_ACTION;
+ },
+});
+
+ExtensionPreferencesManager.addSetting("overrideDocumentColors", {
+ permission: "browserSettings",
+ prefNames: ["browser.display.document_color_use"],
+
+ setCallback(value) {
+ return { [this.prefNames[0]]: value };
+ },
+
+ getCallback() {
+ let prefValue = Services.prefs.getIntPref(
+ "browser.display.document_color_use"
+ );
+ if (prefValue === 1) {
+ return "never";
+ } else if (prefValue === 2) {
+ return "always";
+ }
+ return "high-contrast-only";
+ },
+});
+
+ExtensionPreferencesManager.addSetting("overrideContentColorScheme", {
+ permission: "browserSettings",
+ prefNames: ["layout.css.prefers-color-scheme.content-override"],
+
+ setCallback(value) {
+ return { [this.prefNames[0]]: value };
+ },
+
+ getCallback() {
+ let prefValue = Services.prefs.getIntPref(
+ "layout.css.prefers-color-scheme.content-override"
+ );
+ switch (prefValue) {
+ case 0:
+ return "dark";
+ case 1:
+ return "light";
+ default:
+ return "auto";
+ }
+ },
+});
+
+ExtensionPreferencesManager.addSetting("useDocumentFonts", {
+ permission: "browserSettings",
+ prefNames: ["browser.display.use_document_fonts"],
+
+ setCallback(value) {
+ return { [this.prefNames[0]]: value };
+ },
+
+ getCallback() {
+ return (
+ Services.prefs.getIntPref("browser.display.use_document_fonts") !== 0
+ );
+ },
+});
+
+ExtensionPreferencesManager.addSetting("zoomFullPage", {
+ permission: "browserSettings",
+ prefNames: ["browser.zoom.full"],
+
+ setCallback(value) {
+ return { [this.prefNames[0]]: value };
+ },
+
+ getCallback() {
+ return Services.prefs.getBoolPref("browser.zoom.full");
+ },
+});
+
+ExtensionPreferencesManager.addSetting("zoomSiteSpecific", {
+ permission: "browserSettings",
+ prefNames: ["browser.zoom.siteSpecific"],
+
+ setCallback(value) {
+ return { [this.prefNames[0]]: value };
+ },
+
+ getCallback() {
+ return Services.prefs.getBoolPref("browser.zoom.siteSpecific");
+ },
+});
+
+this.browserSettings = class extends ExtensionAPI {
+ homePageOverrideListener(fire) {
+ let listener = () => {
+ fire.async({
+ levelOfControl: "not_controllable",
+ value: Services.prefs.getStringPref(HOMEPAGE_URL_PREF),
+ });
+ };
+ Services.prefs.addObserver(HOMEPAGE_URL_PREF, listener);
+ return {
+ unregister: () => {
+ Services.prefs.removeObserver(HOMEPAGE_URL_PREF, listener);
+ },
+ convert(_fire) {
+ fire = _fire;
+ },
+ };
+ }
+
+ newTabOverrideListener(fire) {
+ let listener = () => {
+ fire.async({
+ levelOfControl: "not_controllable",
+ value: AboutNewTab.newTabURL,
+ });
+ };
+ Services.obs.addObserver(listener, "newtab-url-changed");
+ return {
+ unregister: () => {
+ Services.obs.removeObserver(listener, "newtab-url-changed");
+ },
+ convert(_fire) {
+ fire = _fire;
+ },
+ };
+ }
+
+ primeListener(event, fire) {
+ let { extension } = this;
+ if (event == "homepageOverride") {
+ return this.homePageOverrideListener(fire);
+ }
+ if (event == "newTabPageOverride") {
+ return this.newTabOverrideListener(fire);
+ }
+ let listener = getPrimedSettingsListener({
+ extension,
+ name: event,
+ });
+ return listener(fire);
+ }
+
+ getAPI(context) {
+ let self = this;
+ let { extension } = context;
+
+ function makeSettingsAPI(name) {
+ return getSettingsAPI({
+ context,
+ module: "browserSettings",
+ name,
+ });
+ }
+
+ return {
+ browserSettings: {
+ allowPopupsForUserEvents: makeSettingsAPI("allowPopupsForUserEvents"),
+ cacheEnabled: makeSettingsAPI("cacheEnabled"),
+ closeTabsByDoubleClick: makeSettingsAPI("closeTabsByDoubleClick"),
+ contextMenuShowEvent: Object.assign(
+ makeSettingsAPI("contextMenuShowEvent"),
+ {
+ set: details => {
+ if (!["mouseup", "mousedown"].includes(details.value)) {
+ throw new ExtensionError(
+ `${details.value} is not a valid value for contextMenuShowEvent.`
+ );
+ }
+ if (
+ AppConstants.platform === "android" ||
+ (AppConstants.platform === "win" &&
+ details.value === "mousedown")
+ ) {
+ return false;
+ }
+ return ExtensionPreferencesManager.setSetting(
+ extension.id,
+ "contextMenuShowEvent",
+ details.value
+ );
+ },
+ }
+ ),
+ ftpProtocolEnabled: getSettingsAPI({
+ context,
+ name: "ftpProtocolEnabled",
+ readOnly: true,
+ callback() {
+ return false;
+ },
+ }),
+ homepageOverride: getSettingsAPI({
+ context,
+ // Name differs here to preserve this setting properly
+ name: "homepage_override",
+ callback() {
+ return Services.prefs.getStringPref(HOMEPAGE_URL_PREF);
+ },
+ readOnly: true,
+ onChange: new ExtensionCommon.EventManager({
+ context,
+ module: "browserSettings",
+ event: "homepageOverride",
+ name: "homepageOverride.onChange",
+ register: fire => {
+ return self.homePageOverrideListener(fire).unregister;
+ },
+ }).api(),
+ }),
+ imageAnimationBehavior: makeSettingsAPI("imageAnimationBehavior"),
+ newTabPosition: makeSettingsAPI("newTabPosition"),
+ newTabPageOverride: getSettingsAPI({
+ context,
+ // Name differs here to preserve this setting properly
+ name: "newTabURL",
+ callback() {
+ return AboutNewTab.newTabURL;
+ },
+ storeType: "url_overrides",
+ readOnly: true,
+ onChange: new ExtensionCommon.EventManager({
+ context,
+ module: "browserSettings",
+ event: "newTabPageOverride",
+ name: "newTabPageOverride.onChange",
+ register: fire => {
+ return self.newTabOverrideListener(fire).unregister;
+ },
+ }).api(),
+ }),
+ openBookmarksInNewTabs: makeSettingsAPI("openBookmarksInNewTabs"),
+ openSearchResultsInNewTabs: makeSettingsAPI(
+ "openSearchResultsInNewTabs"
+ ),
+ openUrlbarResultsInNewTabs: makeSettingsAPI(
+ "openUrlbarResultsInNewTabs"
+ ),
+ webNotificationsDisabled: makeSettingsAPI("webNotificationsDisabled"),
+ overrideDocumentColors: Object.assign(
+ makeSettingsAPI("overrideDocumentColors"),
+ {
+ set: details => {
+ if (
+ !["never", "always", "high-contrast-only"].includes(
+ details.value
+ )
+ ) {
+ throw new ExtensionError(
+ `${details.value} is not a valid value for overrideDocumentColors.`
+ );
+ }
+ let prefValue = 0; // initialize to 0 - auto/high-contrast-only
+ if (details.value === "never") {
+ prefValue = 1;
+ } else if (details.value === "always") {
+ prefValue = 2;
+ }
+ return ExtensionPreferencesManager.setSetting(
+ extension.id,
+ "overrideDocumentColors",
+ prefValue
+ );
+ },
+ }
+ ),
+ overrideContentColorScheme: Object.assign(
+ makeSettingsAPI("overrideContentColorScheme"),
+ {
+ set: details => {
+ let value = details.value;
+ if (value == "system" || value == "browser") {
+ // Map previous values that used to be different but were
+ // unified under the "auto" setting. In practice this should
+ // almost always behave like the extension author expects.
+ extension.logger.warn(
+ `The "${value}" value for overrideContentColorScheme has been deprecated. Use "auto" instead`
+ );
+ value = "auto";
+ }
+ let prefValue = ["dark", "light", "auto"].indexOf(value);
+ if (prefValue === -1) {
+ throw new ExtensionError(
+ `${value} is not a valid value for overrideContentColorScheme.`
+ );
+ }
+ return ExtensionPreferencesManager.setSetting(
+ extension.id,
+ "overrideContentColorScheme",
+ prefValue
+ );
+ },
+ }
+ ),
+ useDocumentFonts: Object.assign(makeSettingsAPI("useDocumentFonts"), {
+ set: details => {
+ if (typeof details.value !== "boolean") {
+ throw new ExtensionError(
+ `${details.value} is not a valid value for useDocumentFonts.`
+ );
+ }
+ return ExtensionPreferencesManager.setSetting(
+ extension.id,
+ "useDocumentFonts",
+ Number(details.value)
+ );
+ },
+ }),
+ zoomFullPage: Object.assign(makeSettingsAPI("zoomFullPage"), {
+ set: details => {
+ if (typeof details.value !== "boolean") {
+ throw new ExtensionError(
+ `${details.value} is not a valid value for zoomFullPage.`
+ );
+ }
+ return ExtensionPreferencesManager.setSetting(
+ extension.id,
+ "zoomFullPage",
+ details.value
+ );
+ },
+ }),
+ zoomSiteSpecific: Object.assign(makeSettingsAPI("zoomSiteSpecific"), {
+ set: details => {
+ if (typeof details.value !== "boolean") {
+ throw new ExtensionError(
+ `${details.value} is not a valid value for zoomSiteSpecific.`
+ );
+ }
+ return ExtensionPreferencesManager.setSetting(
+ extension.id,
+ "zoomSiteSpecific",
+ details.value
+ );
+ },
+ }),
+ colorManagement: {
+ mode: makeSettingsAPI("colorManagement.mode"),
+ useNativeSRGB: makeSettingsAPI("colorManagement.useNativeSRGB"),
+ useWebRenderCompositor: makeSettingsAPI(
+ "colorManagement.useWebRenderCompositor"
+ ),
+ },
+ },
+ };
+ }
+};