--- a/browser/components/preferences/connection.js
+++ b/browser/components/preferences/connection.js
@@ -269,13 +269,13 @@ var gConnectionsDialog = {
}
}
if (isLocked) {
// An extension can't control this setting if any pref is locked.
hideControllingExtension(PROXY_KEY);
setInputsDisabledState(false);
} else {
- handleControllingExtension(PREF_SETTING_TYPE, PROXY_KEY)
+ handleControllingExtension(PREF_SETTING_TYPE, PROXY_KEY, "extensionControlled.proxyConfig")
.then(setInputsDisabledState);
}
}
};
--- a/browser/components/preferences/in-content/extensionControlled.js
+++ b/browser/components/preferences/in-content/extensionControlled.js
@@ -16,17 +16,17 @@ ChromeUtils.defineModuleGetter(this, "De
"resource://gre/modules/DeferredTask.jsm");
ChromeUtils.defineModuleGetter(this, "ExtensionSettingsStore",
"resource://gre/modules/ExtensionSettingsStore.jsm");
XPCOMUtils.defineLazyPreferenceGetter(this, "trackingprotectionUiEnabled",
"privacy.trackingprotection.ui.enabled");
const PREF_SETTING_TYPE = "prefs";
-const PROXY_KEY = "proxyConfig";
+const PROXY_KEY = "proxy.settings";
const API_PROXY_PREFS = [
"network.proxy.type",
"network.proxy.http",
"network.proxy.http_port",
"network.proxy.share_proxy_settings",
"network.proxy.ftp",
"network.proxy.ftp_port",
"network.proxy.ssl",
@@ -40,31 +40,31 @@ const API_PROXY_PREFS = [
"signon.autologin.proxy",
];
let extensionControlledContentIds = {
"privacy.containers": "browserContainersExtensionContent",
"homepage_override": "browserHomePageExtensionContent",
"newTabURL": "browserNewTabExtensionContent",
"defaultSearch": "browserDefaultSearchExtensionContent",
- "proxyConfig": "proxyExtensionContent",
+ "proxy.settings": "proxyExtensionContent",
get "websites.trackingProtectionMode"() {
return {
button: "trackingProtectionExtensionContentButton",
section:
trackingprotectionUiEnabled ?
"trackingProtectionExtensionContentLabel" :
"trackingProtectionPBMExtensionContentLabel",
};
}
};
function getExtensionControlledArgs(settingName) {
switch (settingName) {
- case "proxyConfig":
+ case "proxy.settings":
return [document.getElementById("bundleBrand").getString("brandShortName")];
default:
return [];
}
}
let extensionControlledIds = {};
--- a/browser/components/preferences/in-content/tests/browser_extension_controlled.js
+++ b/browser/components/preferences/in-content/tests/browser_extension_controlled.js
@@ -641,17 +641,17 @@ add_task(async function testExtensionCon
const CONTROLLED_SECTION_ID = "proxyExtensionContent";
const CONTROLLED_BUTTON_ID = "disableProxyExtension";
const CONNECTION_SETTINGS_DESC_ID = "connectionSettingsDescription";
const PANEL_URL = "chrome://browser/content/preferences/connection.xul";
await SpecialPowers.pushPrefEnv({"set": [[PROXY_PREF, PROXY_DEFAULT]]});
function background() {
- browser.browserSettings.proxyConfig.set({value: {proxyType: "none"}});
+ browser.proxy.settings.set({value: {proxyType: "none"}});
}
function expectedConnectionSettingsMessage(doc, isControlled) {
let brandShortName = doc.getElementById("bundleBrand").getString("brandShortName");
return isControlled ?
`An extension, set_proxy, is controlling how ${brandShortName} connects to the internet.` :
`Configure how ${brandShortName} connects to the internet.`;
}
@@ -775,17 +775,17 @@ add_task(async function testExtensionCon
verifyState(mainDoc, false);
// Install an extension that controls proxy settings.
let extension = ExtensionTestUtils.loadExtension({
useAddonManager: "permanent",
manifest: {
name: "set_proxy",
applications: {gecko: {id: EXTENSION_ID}},
- permissions: ["browserSettings"],
+ permissions: ["proxy"],
},
background,
});
let messageChanged = connectionSettingsMessagePromise(mainDoc, true);
await extension.startup();
await messageChanged;
let addon = await AddonManager.getAddonByID(EXTENSION_ID);
--- a/toolkit/components/extensions/ExtensionPreferencesManager.jsm
+++ b/toolkit/components/extensions/ExtensionPreferencesManager.jsm
@@ -344,9 +344,62 @@ this.ExtensionPreferencesManager = {
if (Preferences.locked(prefName)) {
return "not_controllable";
}
}
}
await ExtensionSettingsStore.initialize();
return ExtensionSettingsStore.getLevelOfControl(id, storeType, name);
},
+
+ /**
+ * Returns an API object with get/set/clear used for a setting.
+ *
+ * @param {string} extensionId
+ * @param {string} name
+ * The unique id of the setting.
+ * @param {Function} callback
+ * The function that retreives the current setting from prefs.
+ * @param {string} storeType
+ * The name of the store in ExtensionSettingsStore.
+ * Defaults to STORE_TYPE.
+ * @param {boolean} readOnly
+ * @param {Function} validate
+ * Utility function for any specific validation, such as checking
+ * for supported platform. Function should throw an error if necessary.
+ *
+ * @returns {object} API object with get/set/clear methods
+ */
+ getSettingsAPI(extensionId, name, callback, storeType, readOnly = false, validate = () => {}) {
+ return {
+ async get(details) {
+ validate();
+ let levelOfControl = details.incognito ?
+ "not_controllable" :
+ await ExtensionPreferencesManager.getLevelOfControl(
+ extensionId, name, storeType);
+ levelOfControl =
+ (readOnly && levelOfControl === "controllable_by_this_extension") ?
+ "not_controllable" :
+ levelOfControl;
+ return {
+ levelOfControl,
+ value: await callback(),
+ };
+ },
+ set(details) {
+ validate();
+ if (!readOnly) {
+ return ExtensionPreferencesManager.setSetting(
+ extensionId, name, details.value);
+ }
+ return false;
+ },
+ clear(details) {
+ validate();
+ if (!readOnly) {
+ return ExtensionPreferencesManager.removeSetting(extensionId, name);
+ }
+ return false;
+ },
+ };
+ },
};
--- a/toolkit/components/extensions/parent/ext-browserSettings.js
+++ b/toolkit/components/extensions/parent/ext-browserSettings.js
@@ -11,76 +11,27 @@ XPCOMUtils.defineLazyServiceGetter(this,
"@mozilla.org/browser/aboutnewtab-service;1",
"nsIAboutNewTabService");
ChromeUtils.import("resource://gre/modules/ExtensionPreferencesManager.jsm");
var {
ExtensionError,
} = ExtensionUtils;
-
-const proxySvc = Ci.nsIProtocolProxyService;
-
-const PROXY_TYPES_MAP = new Map([
- ["none", proxySvc.PROXYCONFIG_DIRECT],
- ["autoDetect", proxySvc.PROXYCONFIG_WPAD],
- ["system", proxySvc.PROXYCONFIG_SYSTEM],
- ["manual", proxySvc.PROXYCONFIG_MANUAL],
- ["autoConfig", proxySvc.PROXYCONFIG_PAC],
-]);
+var {
+ getSettingsAPI,
+} = ExtensionPreferencesManager;
const HOMEPAGE_OVERRIDE_SETTING = "homepage_override";
const HOMEPAGE_URL_PREF = "browser.startup.homepage";
const URL_STORE_TYPE = "url_overrides";
const NEW_TAB_OVERRIDE_SETTING = "newTabURL";
const PERM_DENY_ACTION = Services.perms.DENY_ACTION;
-const checkUnsupported = (name, unsupportedPlatforms) => {
- if (unsupportedPlatforms.includes(AppConstants.platform)) {
- throw new ExtensionError(
- `${AppConstants.platform} is not a supported platform for the ${name} setting.`);
- }
-};
-
-const getSettingsAPI = (extension, name, callback, storeType, readOnly = false, unsupportedPlatforms = []) => {
- return {
- async get(details) {
- checkUnsupported(name, unsupportedPlatforms);
- let levelOfControl = details.incognito ?
- "not_controllable" :
- await ExtensionPreferencesManager.getLevelOfControl(
- extension.id, name, storeType);
- levelOfControl =
- (readOnly && levelOfControl === "controllable_by_this_extension") ?
- "not_controllable" :
- levelOfControl;
- return {
- levelOfControl,
- value: await callback(),
- };
- },
- set(details) {
- checkUnsupported(name, unsupportedPlatforms);
- if (!readOnly) {
- return ExtensionPreferencesManager.setSetting(
- extension.id, name, details.value);
- }
- return false;
- },
- clear(details) {
- checkUnsupported(name, unsupportedPlatforms);
- if (!readOnly) {
- return ExtensionPreferencesManager.removeSetting(extension.id, name);
- }
- return false;
- },
- };
-};
-
// Add settings objects for supported APIs to the preferences manager.
ExtensionPreferencesManager.addSetting("allowPopupsForUserEvents", {
prefNames: [
"dom.popup_allowed_events",
],
setCallback(value) {
let returnObj = {};
@@ -174,62 +125,16 @@ ExtensionPreferencesManager.addSetting("
"browser.urlbar.openintab",
],
setCallback(value) {
return {[this.prefNames[0]]: value};
},
});
-ExtensionPreferencesManager.addSetting("proxyConfig", {
- prefNames: [
- "network.proxy.type",
- "network.proxy.http",
- "network.proxy.http_port",
- "network.proxy.share_proxy_settings",
- "network.proxy.ftp",
- "network.proxy.ftp_port",
- "network.proxy.ssl",
- "network.proxy.ssl_port",
- "network.proxy.socks",
- "network.proxy.socks_port",
- "network.proxy.socks_version",
- "network.proxy.socks_remote_dns",
- "network.proxy.no_proxies_on",
- "network.proxy.autoconfig_url",
- "signon.autologin.proxy",
- ],
-
- setCallback(value) {
- let prefs = {
- "network.proxy.type": PROXY_TYPES_MAP.get(value.proxyType),
- "signon.autologin.proxy": value.autoLogin,
- "network.proxy.socks_remote_dns": value.proxyDNS,
- "network.proxy.autoconfig_url": value.autoConfigUrl,
- "network.proxy.share_proxy_settings": value.httpProxyAll,
- "network.proxy.socks_version": value.socksVersion,
- "network.proxy.no_proxies_on": value.passthrough,
- };
-
- for (let prop of ["http", "ftp", "ssl", "socks"]) {
- if (value[prop]) {
- let url = new URL(`http://${value[prop]}`);
- prefs[`network.proxy.${prop}`] = url.hostname;
- let port = parseInt(url.port, 10);
- prefs[`network.proxy.${prop}_port`] = isNaN(port) ? 0 : port;
- } else {
- prefs[`network.proxy.${prop}`] = undefined;
- prefs[`network.proxy.${prop}_port`] = undefined;
- }
- }
-
- return prefs;
- },
-});
-
ExtensionPreferencesManager.addSetting("webNotificationsDisabled", {
prefNames: [
"permissions.default.desktop-notification",
],
setCallback(value) {
return {[this.prefNames[0]]: value ? PERM_DENY_ACTION : undefined};
},
@@ -256,34 +161,39 @@ ExtensionPreferencesManager.addSetting("
});
this.browserSettings = class extends ExtensionAPI {
getAPI(context) {
let {extension} = context;
return {
browserSettings: {
allowPopupsForUserEvents: getSettingsAPI(
- extension, "allowPopupsForUserEvents",
+ extension.id, "allowPopupsForUserEvents",
() => {
return Services.prefs.getCharPref("dom.popup_allowed_events") != "";
}),
cacheEnabled: getSettingsAPI(
- extension, "cacheEnabled",
+ extension.id, "cacheEnabled",
() => {
return Services.prefs.getBoolPref("browser.cache.disk.enable") &&
Services.prefs.getBoolPref("browser.cache.memory.enable");
}),
closeTabsByDoubleClick: getSettingsAPI(
- extension, "closeTabsByDoubleClick",
+ extension.id, "closeTabsByDoubleClick",
() => {
return Services.prefs.getBoolPref("browser.tabs.closeTabByDblclick");
- }, undefined, false, ["android"]),
+ }, undefined, false, () => {
+ if (AppConstants.platform == "android") {
+ throw new ExtensionError(
+ `android is not a supported platform for the closeTabsByDoubleClick setting.`);
+ }
+ }),
contextMenuShowEvent: Object.assign(
getSettingsAPI(
- extension, "contextMenuShowEvent",
+ extension.id, "contextMenuShowEvent",
() => {
if (AppConstants.platform === "win") {
return "mouseup";
}
let prefValue = Services.prefs.getBoolPref(
"ui.context_menus.after_mouseup", null);
return prefValue ? "mouseup" : "mousedown";
}
@@ -300,165 +210,68 @@ this.browserSettings = class extends Ext
return false;
}
return ExtensionPreferencesManager.setSetting(
extension.id, "contextMenuShowEvent", details.value);
},
}
),
homepageOverride: getSettingsAPI(
- extension, HOMEPAGE_OVERRIDE_SETTING,
+ extension.id, HOMEPAGE_OVERRIDE_SETTING,
() => {
return Services.prefs.getComplexValue(
HOMEPAGE_URL_PREF, Ci.nsIPrefLocalizedString).data;
}, undefined, true),
imageAnimationBehavior: getSettingsAPI(
- extension, "imageAnimationBehavior",
+ extension.id, "imageAnimationBehavior",
() => {
return Services.prefs.getCharPref("image.animation_mode");
}),
newTabPosition: getSettingsAPI(
- extension, "newTabPosition",
+ extension.id, "newTabPosition",
() => {
if (Services.prefs.getBoolPref("browser.tabs.insertAfterCurrent")) {
return "afterCurrent";
}
if (Services.prefs.getBoolPref("browser.tabs.insertRelatedAfterCurrent")) {
return "relatedAfterCurrent";
}
return "atEnd";
}),
newTabPageOverride: getSettingsAPI(
- extension, NEW_TAB_OVERRIDE_SETTING,
+ extension.id, NEW_TAB_OVERRIDE_SETTING,
() => {
return aboutNewTabService.newTabURL;
}, URL_STORE_TYPE, true),
openBookmarksInNewTabs: getSettingsAPI(
- extension, "openBookmarksInNewTabs",
+ extension.id, "openBookmarksInNewTabs",
() => {
return Services.prefs.getBoolPref("browser.tabs.loadBookmarksInTabs");
}),
openSearchResultsInNewTabs: getSettingsAPI(
- extension, "openSearchResultsInNewTabs",
+ extension.id, "openSearchResultsInNewTabs",
() => {
return Services.prefs.getBoolPref("browser.search.openintab");
}),
openUrlbarResultsInNewTabs: getSettingsAPI(
- extension, "openUrlbarResultsInNewTabs",
+ extension.id, "openUrlbarResultsInNewTabs",
() => {
return Services.prefs.getBoolPref("browser.urlbar.openintab");
}),
- proxyConfig: Object.assign(
- getSettingsAPI(
- extension, "proxyConfig",
- () => {
- let prefValue = Services.prefs.getIntPref("network.proxy.type");
- let proxyConfig = {
- proxyType:
- Array.from(
- PROXY_TYPES_MAP.entries()).find(entry => entry[1] === prefValue)[0],
- autoConfigUrl: Services.prefs.getCharPref("network.proxy.autoconfig_url"),
- autoLogin: Services.prefs.getBoolPref("signon.autologin.proxy"),
- proxyDNS: Services.prefs.getBoolPref("network.proxy.socks_remote_dns"),
- httpProxyAll: Services.prefs.getBoolPref("network.proxy.share_proxy_settings"),
- socksVersion: Services.prefs.getIntPref("network.proxy.socks_version"),
- passthrough: Services.prefs.getCharPref("network.proxy.no_proxies_on"),
- };
-
- for (let prop of ["http", "ftp", "ssl", "socks"]) {
- let host = Services.prefs.getCharPref(`network.proxy.${prop}`);
- let port = Services.prefs.getIntPref(`network.proxy.${prop}_port`);
- proxyConfig[prop] = port ? `${host}:${port}` : host;
- }
-
- return proxyConfig;
- },
- // proxyConfig is unsupported on android.
- undefined, false, ["android"]
- ),
- {
- set: details => {
- if (AppConstants.platform === "android") {
- throw new ExtensionError(
- "proxyConfig is not supported on android.");
- }
-
- if (!Services.policies.isAllowed("changeProxySettings")) {
- throw new ExtensionError(
- "Proxy settings are being managed by the Policies manager.");
- }
-
- let value = details.value;
-
- if (!PROXY_TYPES_MAP.has(value.proxyType)) {
- throw new ExtensionError(
- `${value.proxyType} is not a valid value for proxyType.`);
- }
-
- if (value.httpProxyAll) {
- // Match what about:preferences does with proxy settings
- // since the proxy service does not check the value
- // of share_proxy_settings.
- for (let prop of ["ftp", "ssl", "socks"]) {
- value[prop] = value.http;
- }
- }
-
- for (let prop of ["http", "ftp", "ssl", "socks"]) {
- let host = value[prop];
- if (host) {
- try {
- // Fixup in case a full url is passed.
- if (host.includes("://")) {
- value[prop] = new URL(host).host;
- } else {
- // Validate the host value.
- new URL(`http://${host}`);
- }
- } catch (e) {
- throw new ExtensionError(
- `${value[prop]} is not a valid value for ${prop}.`);
- }
- }
- }
-
- if (value.proxyType === "autoConfig" || value.autoConfigUrl) {
- try {
- new URL(value.autoConfigUrl);
- } catch (e) {
- throw new ExtensionError(
- `${value.autoConfigUrl} is not a valid value for autoConfigUrl.`);
- }
- }
-
- if (value.socksVersion !== undefined) {
- if (!Number.isInteger(value.socksVersion) ||
- value.socksVersion < 4 ||
- value.socksVersion > 5) {
- throw new ExtensionError(
- `${value.socksVersion} is not a valid value for socksVersion.`);
- }
- }
-
- return ExtensionPreferencesManager.setSetting(
- extension.id, "proxyConfig", value);
- },
- }
- ),
webNotificationsDisabled: getSettingsAPI(
- extension, "webNotificationsDisabled",
+ extension.id, "webNotificationsDisabled",
() => {
let prefValue =
Services.prefs.getIntPref(
"permissions.default.desktop-notification", null);
return prefValue === PERM_DENY_ACTION;
}),
overrideDocumentColors: Object.assign(
getSettingsAPI(
- extension, "overrideDocumentColors",
+ extension.id, "overrideDocumentColors",
() => {
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";
@@ -478,17 +291,17 @@ this.browserSettings = class extends Ext
}
return ExtensionPreferencesManager.setSetting(
extension.id, "overrideDocumentColors", prefValue);
},
}
),
useDocumentFonts: Object.assign(
getSettingsAPI(
- extension, "useDocumentFonts",
+ extension.id, "useDocumentFonts",
() => {
return Services.prefs.getIntPref("browser.display.use_document_fonts") !== 0;
}
),
{
set: details => {
if (typeof details.value !== "boolean") {
throw new ExtensionError(
--- a/toolkit/components/extensions/parent/ext-proxy.js
+++ b/toolkit/components/extensions/parent/ext-proxy.js
@@ -5,20 +5,84 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
ChromeUtils.defineModuleGetter(this, "ProxyScriptContext",
"resource://gre/modules/ProxyScriptContext.jsm");
ChromeUtils.defineModuleGetter(this, "ProxyChannelFilter",
"resource://gre/modules/ProxyScriptContext.jsm");
+ChromeUtils.import("resource://gre/modules/ExtensionPreferencesManager.jsm");
+
+var {
+ ExtensionError,
+} = ExtensionUtils;
+var {
+ getSettingsAPI,
+} = ExtensionPreferencesManager;
// WeakMap[Extension -> ProxyScriptContext]
const proxyScriptContextMap = new WeakMap();
+const proxySvc = Ci.nsIProtocolProxyService;
+
+const PROXY_TYPES_MAP = new Map([
+ ["none", proxySvc.PROXYCONFIG_DIRECT],
+ ["autoDetect", proxySvc.PROXYCONFIG_WPAD],
+ ["system", proxySvc.PROXYCONFIG_SYSTEM],
+ ["manual", proxySvc.PROXYCONFIG_MANUAL],
+ ["autoConfig", proxySvc.PROXYCONFIG_PAC],
+]);
+
+ExtensionPreferencesManager.addSetting("proxy.settings", {
+ prefNames: [
+ "network.proxy.type",
+ "network.proxy.http",
+ "network.proxy.http_port",
+ "network.proxy.share_proxy_settings",
+ "network.proxy.ftp",
+ "network.proxy.ftp_port",
+ "network.proxy.ssl",
+ "network.proxy.ssl_port",
+ "network.proxy.socks",
+ "network.proxy.socks_port",
+ "network.proxy.socks_version",
+ "network.proxy.socks_remote_dns",
+ "network.proxy.no_proxies_on",
+ "network.proxy.autoconfig_url",
+ "signon.autologin.proxy",
+ ],
+
+ setCallback(value) {
+ let prefs = {
+ "network.proxy.type": PROXY_TYPES_MAP.get(value.proxyType),
+ "signon.autologin.proxy": value.autoLogin,
+ "network.proxy.socks_remote_dns": value.proxyDNS,
+ "network.proxy.autoconfig_url": value.autoConfigUrl,
+ "network.proxy.share_proxy_settings": value.httpProxyAll,
+ "network.proxy.socks_version": value.socksVersion,
+ "network.proxy.no_proxies_on": value.passthrough,
+ };
+
+ for (let prop of ["http", "ftp", "ssl", "socks"]) {
+ if (value[prop]) {
+ let url = new URL(`http://${value[prop]}`);
+ prefs[`network.proxy.${prop}`] = url.hostname;
+ let port = parseInt(url.port, 10);
+ prefs[`network.proxy.${prop}_port`] = isNaN(port) ? 0 : port;
+ } else {
+ prefs[`network.proxy.${prop}`] = undefined;
+ prefs[`network.proxy.${prop}_port`] = undefined;
+ }
+ }
+
+ return prefs;
+ },
+});
+
// EventManager-like class specifically for Proxy filters. Inherits from
// EventManager. Takes care of converting |details| parameter
// when invoking listeners.
class ProxyFilterEventManager extends EventManager {
constructor(context, eventName) {
let name = `proxy.${eventName}`;
let register = (fire, filterProps, extraInfoSpec = []) => {
let listener = (data) => {
@@ -99,12 +163,115 @@ this.proxy = class extends ExtensionAPI
},
onRequest: new ProxyFilterEventManager(context, "onRequest").api(),
onError,
// TODO Bug 1388619 deprecate onProxyError.
onProxyError: onError,
+
+ settings: Object.assign(
+ getSettingsAPI(
+ extension.id, "proxy.settings",
+ () => {
+ let prefValue = Services.prefs.getIntPref("network.proxy.type");
+ let proxyConfig = {
+ proxyType:
+ Array.from(
+ PROXY_TYPES_MAP.entries()).find(entry => entry[1] === prefValue)[0],
+ autoConfigUrl: Services.prefs.getCharPref("network.proxy.autoconfig_url"),
+ autoLogin: Services.prefs.getBoolPref("signon.autologin.proxy"),
+ proxyDNS: Services.prefs.getBoolPref("network.proxy.socks_remote_dns"),
+ httpProxyAll: Services.prefs.getBoolPref("network.proxy.share_proxy_settings"),
+ socksVersion: Services.prefs.getIntPref("network.proxy.socks_version"),
+ passthrough: Services.prefs.getCharPref("network.proxy.no_proxies_on"),
+ };
+
+ for (let prop of ["http", "ftp", "ssl", "socks"]) {
+ let host = Services.prefs.getCharPref(`network.proxy.${prop}`);
+ let port = Services.prefs.getIntPref(`network.proxy.${prop}_port`);
+ proxyConfig[prop] = port ? `${host}:${port}` : host;
+ }
+
+ return proxyConfig;
+ },
+ // proxy.settings is unsupported on android.
+ undefined, false, () => {
+ if (AppConstants.platform == "android") {
+ throw new ExtensionError(
+ `proxy.settings is not supported on android.`);
+ }
+ },
+ ),
+ {
+ set: details => {
+ if (AppConstants.platform === "android") {
+ throw new ExtensionError(
+ "proxy.settings is not supported on android.");
+ }
+
+ if (!Services.policies.isAllowed("changeProxySettings")) {
+ throw new ExtensionError(
+ "Proxy settings are being managed by the Policies manager.");
+ }
+
+ let value = details.value;
+
+ if (!PROXY_TYPES_MAP.has(value.proxyType)) {
+ throw new ExtensionError(
+ `${value.proxyType} is not a valid value for proxyType.`);
+ }
+
+ if (value.httpProxyAll) {
+ // Match what about:preferences does with proxy settings
+ // since the proxy service does not check the value
+ // of share_proxy_settings.
+ for (let prop of ["ftp", "ssl", "socks"]) {
+ value[prop] = value.http;
+ }
+ }
+
+ for (let prop of ["http", "ftp", "ssl", "socks"]) {
+ let host = value[prop];
+ if (host) {
+ try {
+ // Fixup in case a full url is passed.
+ if (host.includes("://")) {
+ value[prop] = new URL(host).host;
+ } else {
+ // Validate the host value.
+ new URL(`http://${host}`);
+ }
+ } catch (e) {
+ throw new ExtensionError(
+ `${value[prop]} is not a valid value for ${prop}.`);
+ }
+ }
+ }
+
+ if (value.proxyType === "autoConfig" || value.autoConfigUrl) {
+ try {
+ new URL(value.autoConfigUrl);
+ } catch (e) {
+ throw new ExtensionError(
+ `${value.autoConfigUrl} is not a valid value for autoConfigUrl.`);
+ }
+ }
+
+ if (value.socksVersion !== undefined) {
+ if (!Number.isInteger(value.socksVersion) ||
+ value.socksVersion < 4 ||
+ value.socksVersion > 5) {
+ throw new ExtensionError(
+ `${value.socksVersion} is not a valid value for socksVersion.`);
+ }
+ }
+
+ return ExtensionPreferencesManager.setSetting(
+ extension.id, "proxy.settings", value);
+ },
+ }
+ ),
},
};
}
};
--- a/toolkit/components/extensions/schemas/browser_settings.json
+++ b/toolkit/components/extensions/schemas/browser_settings.json
@@ -30,87 +30,16 @@
"enum": ["normal", "none", "once"],
"description": "How images should be animated in the browser."
},
{
"id": "ContextMenuMouseEvent",
"type": "string",
"enum": ["mouseup", "mousedown"],
"description": "After which mouse event context menus should popup."
- },
- {
- "id": "ProxyConfig",
- "type": "object",
- "description": "An object which describes proxy settings.",
- "properties": {
- "proxyType": {
- "type": "string",
- "optional": true,
- "enum": [
- "none",
- "autoDetect",
- "system",
- "manual",
- "autoConfig"
- ],
- "description": "The type of proxy to use."
- },
- "http": {
- "type": "string",
- "optional": true,
- "description": "The address of the http proxy, can include a port."
- },
- "httpProxyAll":{
- "type": "boolean",
- "optional": true,
- "description": "Use the http proxy server for all protocols."
- },
- "ftp": {
- "type": "string",
- "optional": true,
- "description": "The address of the ftp proxy, can include a port."
- },
- "ssl": {
- "type": "string",
- "optional": true,
- "description": "The address of the ssl proxy, can include a port."
- },
- "socks": {
- "type": "string",
- "optional": true,
- "description": "The address of the socks proxy, can include a port."
- },
- "socksVersion": {
- "type": "integer",
- "optional": true,
- "description": "The version of the socks proxy.",
- "minimum": 4,
- "maximum": 5
- },
- "passthrough": {
- "type": "string",
- "optional": true,
- "description": "A list of hosts which should not be proxied."
- },
- "autoConfigUrl": {
- "type": "string",
- "optional": true,
- "description": "A URL to use to configure the proxy."
- },
- "autoLogin": {
- "type": "boolean",
- "optional": true,
- "description": "Do not prompt for authentication if password is saved."
- },
- "proxyDNS": {
- "type": "boolean",
- "optional": true,
- "description": "Proxy DNS when using SOCKS v5."
- }
- }
}
],
"properties": {
"allowPopupsForUserEvents": {
"$ref": "types.Setting",
"description": "Allows or disallows pop-up windows from opening in response to user events."
},
"cacheEnabled": {
@@ -148,20 +77,16 @@
"openSearchResultsInNewTabs": {
"$ref": "types.Setting",
"description": "This boolean setting controls whether search results are opened in the current tab or in a new tab."
},
"openUrlbarResultsInNewTabs": {
"$ref": "types.Setting",
"description": "This boolean setting controls whether urlbar results are opened in the current tab or in a new tab."
},
- "proxyConfig": {
- "$ref": "types.Setting",
- "description": "Configures proxy settings. This setting's value is an object of type ProxyConfig."
- },
"webNotificationsDisabled": {
"$ref": "types.Setting",
"description": "Disables webAPI notifications."
},
"overrideDocumentColors": {
"$ref": "types.Setting",
"description": "This setting controls whether the user-chosen colors override the page's colors."
},
--- a/toolkit/components/extensions/schemas/proxy.json
+++ b/toolkit/components/extensions/schemas/proxy.json
@@ -12,16 +12,95 @@
}]
}
]
},
{
"namespace": "proxy",
"description": "Use the browser.proxy API to register proxy scripts in Firefox. Proxy scripts in Firefox are proxy auto-config files with extra contextual information and support for additional return types.",
"permissions": ["proxy"],
+ "types": [
+ {
+ "id": "ProxyConfig",
+ "type": "object",
+ "description": "An object which describes proxy settings.",
+ "properties": {
+ "proxyType": {
+ "type": "string",
+ "optional": true,
+ "enum": [
+ "none",
+ "autoDetect",
+ "system",
+ "manual",
+ "autoConfig"
+ ],
+ "description": "The type of proxy to use."
+ },
+ "http": {
+ "type": "string",
+ "optional": true,
+ "description": "The address of the http proxy, can include a port."
+ },
+ "httpProxyAll":{
+ "type": "boolean",
+ "optional": true,
+ "description": "Use the http proxy server for all protocols."
+ },
+ "ftp": {
+ "type": "string",
+ "optional": true,
+ "description": "The address of the ftp proxy, can include a port."
+ },
+ "ssl": {
+ "type": "string",
+ "optional": true,
+ "description": "The address of the ssl proxy, can include a port."
+ },
+ "socks": {
+ "type": "string",
+ "optional": true,
+ "description": "The address of the socks proxy, can include a port."
+ },
+ "socksVersion": {
+ "type": "integer",
+ "optional": true,
+ "description": "The version of the socks proxy.",
+ "minimum": 4,
+ "maximum": 5
+ },
+ "passthrough": {
+ "type": "string",
+ "optional": true,
+ "description": "A list of hosts which should not be proxied."
+ },
+ "autoConfigUrl": {
+ "type": "string",
+ "optional": true,
+ "description": "A URL to use to configure the proxy."
+ },
+ "autoLogin": {
+ "type": "boolean",
+ "optional": true,
+ "description": "Do not prompt for authentication if password is saved."
+ },
+ "proxyDNS": {
+ "type": "boolean",
+ "optional": true,
+ "description": "Proxy DNS when using SOCKS v5."
+ }
+ }
+ }
+ ],
+ "properties": {
+ "settings": {
+ "$ref": "types.Setting",
+ "description": "Configures proxy settings. This setting's value is an object of type ProxyConfig."
+ }
+ },
"functions": [
{
"name": "register",
"type": "function",
"description": "Registers the proxy script for the extension.",
"async": true,
"parameters": [
{
--- a/toolkit/components/extensions/test/xpcshell/test_ext_browserSettings.js
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_browserSettings.js
@@ -13,46 +13,30 @@ const {
promiseStartupManager,
} = AddonTestUtils;
AddonTestUtils.init(this);
createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "42");
add_task(async function test_browser_settings() {
- const proxySvc = Ci.nsIProtocolProxyService;
const PERM_DENY_ACTION = Services.perms.DENY_ACTION;
const PERM_UNKNOWN_ACTION = Services.perms.UNKNOWN_ACTION;
// Create an object to hold the values to which we will initialize the prefs.
const PREFS = {
"browser.cache.disk.enable": true,
"browser.cache.memory.enable": true,
"dom.popup_allowed_events": Preferences.get("dom.popup_allowed_events"),
"image.animation_mode": "none",
"permissions.default.desktop-notification": PERM_UNKNOWN_ACTION,
"ui.context_menus.after_mouseup": false,
"browser.tabs.closeTabByDblclick": false,
"browser.tabs.loadBookmarksInTabs": false,
"browser.search.openintab": false,
- "network.proxy.type": proxySvc.PROXYCONFIG_SYSTEM,
- "network.proxy.http": "",
- "network.proxy.http_port": 0,
- "network.proxy.share_proxy_settings": false,
- "network.proxy.ftp": "",
- "network.proxy.ftp_port": 0,
- "network.proxy.ssl": "",
- "network.proxy.ssl_port": 0,
- "network.proxy.socks": "",
- "network.proxy.socks_port": 0,
- "network.proxy.socks_version": 5,
- "network.proxy.socks_remote_dns": false,
- "network.proxy.no_proxies_on": "localhost, 127.0.0.1",
- "network.proxy.autoconfig_url": "",
- "signon.autologin.proxy": false,
"browser.tabs.insertRelatedAfterCurrent": true,
"browser.tabs.insertAfterCurrent": false,
"browser.display.document_color_use": 1,
"browser.display.use_document_fonts": 1,
};
async function background() {
browser.test.onMessage.addListener(async (msg, apiName, value) => {
@@ -230,185 +214,16 @@ add_task(async function test_browser_set
await testSetting(
"useDocumentFonts", false,
{"browser.display.use_document_fonts": 0});
await testSetting(
"useDocumentFonts", true,
{"browser.display.use_document_fonts": 1});
- async function testProxy(config, expectedPrefs, expectedConfig = config) {
- // proxyConfig is not supported on Android.
- if (AppConstants.platform === "android") {
- return Promise.resolve();
- }
-
- let proxyConfig = {
- proxyType: "none",
- autoConfigUrl: "",
- autoLogin: false,
- proxyDNS: false,
- httpProxyAll: false,
- socksVersion: 5,
- passthrough: "localhost, 127.0.0.1",
- http: "",
- ftp: "",
- ssl: "",
- socks: "",
- };
- return testSetting(
- "proxyConfig", config, expectedPrefs, Object.assign(proxyConfig, expectedConfig)
- );
- }
-
- await testProxy(
- {proxyType: "none"},
- {"network.proxy.type": proxySvc.PROXYCONFIG_DIRECT},
- );
-
- await testProxy(
- {
- proxyType: "autoDetect",
- autoLogin: true,
- proxyDNS: true,
- },
- {
- "network.proxy.type": proxySvc.PROXYCONFIG_WPAD,
- "signon.autologin.proxy": true,
- "network.proxy.socks_remote_dns": true,
- },
- );
-
- await testProxy(
- {
- proxyType: "system",
- autoLogin: false,
- proxyDNS: false,
- },
- {
- "network.proxy.type": proxySvc.PROXYCONFIG_SYSTEM,
- "signon.autologin.proxy": false,
- "network.proxy.socks_remote_dns": false,
- },
- );
-
- await testProxy(
- {
- proxyType: "autoConfig",
- autoConfigUrl: "http://mozilla.org",
- },
- {
- "network.proxy.type": proxySvc.PROXYCONFIG_PAC,
- "network.proxy.autoconfig_url": "http://mozilla.org",
- },
- );
-
- await testProxy(
- {
- proxyType: "manual",
- http: "http://www.mozilla.org",
- autoConfigUrl: "",
- },
- {
- "network.proxy.type": proxySvc.PROXYCONFIG_MANUAL,
- "network.proxy.http": "www.mozilla.org",
- "network.proxy.http_port": 0,
- "network.proxy.autoconfig_url": "",
- },
- {
- proxyType: "manual",
- http: "www.mozilla.org",
- autoConfigUrl: "",
- }
- );
-
- // When using proxyAll, we expect all proxies to be set to
- // be the same as http.
- await testProxy(
- {
- proxyType: "manual",
- http: "http://www.mozilla.org:8080",
- ftp: "http://www.mozilla.org:1234",
- httpProxyAll: true,
- },
- {
- "network.proxy.type": proxySvc.PROXYCONFIG_MANUAL,
- "network.proxy.http": "www.mozilla.org",
- "network.proxy.http_port": 8080,
- "network.proxy.ftp": "www.mozilla.org",
- "network.proxy.ftp_port": 8080,
- "network.proxy.ssl": "www.mozilla.org",
- "network.proxy.ssl_port": 8080,
- "network.proxy.socks": "www.mozilla.org",
- "network.proxy.socks_port": 8080,
- "network.proxy.share_proxy_settings": true,
- },
- {
- proxyType: "manual",
- http: "www.mozilla.org:8080",
- ftp: "www.mozilla.org:8080",
- ssl: "www.mozilla.org:8080",
- socks: "www.mozilla.org:8080",
- httpProxyAll: true,
- }
- );
-
- await testProxy(
- {
- proxyType: "manual",
- http: "www.mozilla.org:8080",
- httpProxyAll: false,
- ftp: "www.mozilla.org:8081",
- ssl: "www.mozilla.org:8082",
- socks: "mozilla.org:8083",
- socksVersion: 4,
- passthrough: ".mozilla.org",
- },
- {
- "network.proxy.type": proxySvc.PROXYCONFIG_MANUAL,
- "network.proxy.http": "www.mozilla.org",
- "network.proxy.http_port": 8080,
- "network.proxy.share_proxy_settings": false,
- "network.proxy.ftp": "www.mozilla.org",
- "network.proxy.ftp_port": 8081,
- "network.proxy.ssl": "www.mozilla.org",
- "network.proxy.ssl_port": 8082,
- "network.proxy.socks": "mozilla.org",
- "network.proxy.socks_port": 8083,
- "network.proxy.socks_version": 4,
- "network.proxy.no_proxies_on": ".mozilla.org",
- }
- );
-
- // Test resetting values.
- await testProxy(
- {
- proxyType: "none",
- http: "",
- ftp: "",
- ssl: "",
- socks: "",
- socksVersion: 5,
- passthrough: "",
- },
- {
- "network.proxy.type": proxySvc.PROXYCONFIG_DIRECT,
- "network.proxy.http": "",
- "network.proxy.http_port": 0,
- "network.proxy.ftp": "",
- "network.proxy.ftp_port": 0,
- "network.proxy.ssl": "",
- "network.proxy.ssl_port": 0,
- "network.proxy.socks": "",
- "network.proxy.socks_port": 0,
- "network.proxy.socks_version": 5,
- "network.proxy.no_proxies_on": "",
- }
- );
-
await extension.unload();
await promiseShutdownManager();
});
add_task(async function test_bad_value() {
async function background() {
await browser.test.assertRejects(
browser.browserSettings.contextMenuShowEvent.set({value: "bad"}),
@@ -470,84 +285,8 @@ add_task(async function test_bad_value_a
permissions: ["browserSettings"],
},
});
await extension.startup();
await extension.awaitMessage("done");
await extension.unload();
});
-
-add_task(async function test_bad_value_proxy_config() {
- let background = AppConstants.platform === "android" ?
- async () => {
- await browser.test.assertRejects(
- browser.browserSettings.proxyConfig.set({value: {
- proxyType: "none",
- }}),
- /proxyConfig is not supported on android/,
- "proxyConfig.set rejects on Android.");
-
- await browser.test.assertRejects(
- browser.browserSettings.proxyConfig.get({}),
- /android is not a supported platform for the proxyConfig setting/,
- "proxyConfig.get rejects on Android.");
-
- await browser.test.assertRejects(
- browser.browserSettings.proxyConfig.clear({}),
- /android is not a supported platform for the proxyConfig setting/,
- "proxyConfig.clear rejects on Android.");
-
- browser.test.sendMessage("done");
- } :
- async () => {
- await browser.test.assertRejects(
- browser.browserSettings.proxyConfig.set({value: {
- proxyType: "abc",
- }}),
- /abc is not a valid value for proxyType/,
- "proxyConfig.set rejects with an invalid proxyType value.");
-
- await browser.test.assertRejects(
- browser.browserSettings.proxyConfig.set({value: {
- proxyType: "autoConfig",
- }}),
- /undefined is not a valid value for autoConfigUrl/,
- "proxyConfig.set for type autoConfig rejects with an empty autoConfigUrl value.");
-
- await browser.test.assertRejects(
- browser.browserSettings.proxyConfig.set({value: {
- proxyType: "autoConfig",
- autoConfigUrl: "abc",
- }}),
- /abc is not a valid value for autoConfigUrl/,
- "proxyConfig.set rejects with an invalid autoConfigUrl value.");
-
- await browser.test.assertRejects(
- browser.browserSettings.proxyConfig.set({value: {
- proxyType: "manual",
- socksVersion: "abc",
- }}),
- /abc is not a valid value for socksVersion/,
- "proxyConfig.set rejects with an invalid socksVersion value.");
-
- await browser.test.assertRejects(
- browser.browserSettings.proxyConfig.set({value: {
- proxyType: "manual",
- socksVersion: 3,
- }}),
- /3 is not a valid value for socksVersion/,
- "proxyConfig.set rejects with an invalid socksVersion value.");
-
- browser.test.sendMessage("done");
- };
-
- let extension = ExtensionTestUtils.loadExtension({
- background,
- manifest: {
- permissions: ["browserSettings"],
- },
- });
-
- await extension.startup();
- await extension.awaitMessage("done");
- await extension.unload();
-});
copy from toolkit/components/extensions/test/xpcshell/test_ext_browserSettings.js
copy to toolkit/components/extensions/test/xpcshell/test_ext_proxy_config.js
--- a/toolkit/components/extensions/test/xpcshell/test_ext_browserSettings.js
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_proxy_config.js
@@ -1,10 +1,8 @@
-/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
-/* vim: set sts=2 sw=2 et tw=80: */
"use strict";
ChromeUtils.defineModuleGetter(this, "ExtensionPreferencesManager",
"resource://gre/modules/ExtensionPreferencesManager.jsm");
ChromeUtils.defineModuleGetter(this, "Preferences",
"resource://gre/modules/Preferences.jsm");
const {
@@ -14,54 +12,39 @@ const {
} = AddonTestUtils;
AddonTestUtils.init(this);
createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "42");
add_task(async function test_browser_settings() {
const proxySvc = Ci.nsIProtocolProxyService;
- const PERM_DENY_ACTION = Services.perms.DENY_ACTION;
- const PERM_UNKNOWN_ACTION = Services.perms.UNKNOWN_ACTION;
// Create an object to hold the values to which we will initialize the prefs.
const PREFS = {
- "browser.cache.disk.enable": true,
- "browser.cache.memory.enable": true,
- "dom.popup_allowed_events": Preferences.get("dom.popup_allowed_events"),
- "image.animation_mode": "none",
- "permissions.default.desktop-notification": PERM_UNKNOWN_ACTION,
- "ui.context_menus.after_mouseup": false,
- "browser.tabs.closeTabByDblclick": false,
- "browser.tabs.loadBookmarksInTabs": false,
- "browser.search.openintab": false,
"network.proxy.type": proxySvc.PROXYCONFIG_SYSTEM,
"network.proxy.http": "",
"network.proxy.http_port": 0,
"network.proxy.share_proxy_settings": false,
"network.proxy.ftp": "",
"network.proxy.ftp_port": 0,
"network.proxy.ssl": "",
"network.proxy.ssl_port": 0,
"network.proxy.socks": "",
"network.proxy.socks_port": 0,
"network.proxy.socks_version": 5,
"network.proxy.socks_remote_dns": false,
"network.proxy.no_proxies_on": "localhost, 127.0.0.1",
"network.proxy.autoconfig_url": "",
"signon.autologin.proxy": false,
- "browser.tabs.insertRelatedAfterCurrent": true,
- "browser.tabs.insertAfterCurrent": false,
- "browser.display.document_color_use": 1,
- "browser.display.use_document_fonts": 1,
};
async function background() {
- browser.test.onMessage.addListener(async (msg, apiName, value) => {
- let apiObj = browser.browserSettings[apiName];
+ browser.test.onMessage.addListener(async (msg, value) => {
+ let apiObj = browser.proxy.settings;
let result = await apiObj.set({value});
if (msg === "set") {
browser.test.assertTrue(result, "set returns true.");
browser.test.sendMessage("settingData", await apiObj.get({}));
} else {
browser.test.assertFalse(result, "set returns false for a no-op.");
browser.test.sendMessage("no-op set");
}
@@ -78,170 +61,38 @@ add_task(async function test_browser_set
for (let pref in PREFS) {
Preferences.reset(pref);
}
});
let extension = ExtensionTestUtils.loadExtension({
background,
manifest: {
- permissions: ["browserSettings"],
+ permissions: ["proxy"],
},
useAddonManager: "temporary",
});
await promiseStartupManager();
await extension.startup();
- async function testSetting(setting, value, expected, expectedValue = value) {
- extension.sendMessage("set", setting, value);
+ async function testSetting(value, expected, expectedValue = value) {
+ extension.sendMessage("set", value);
let data = await extension.awaitMessage("settingData");
deepEqual(data.value, expectedValue,
- `The ${setting} setting has the expected value.`);
+ `The setting has the expected value.`);
equal(data.levelOfControl, "controlled_by_this_extension",
- `The ${setting} setting has the expected levelOfControl.`);
- for (let pref in expected) {
- equal(Preferences.get(pref), expected[pref], `${pref} set correctly for ${value}`);
- }
- }
-
- async function testNoOpSetting(setting, value, expected) {
- extension.sendMessage("setNoOp", setting, value);
- await extension.awaitMessage("no-op set");
+ `The setting has the expected levelOfControl.`);
for (let pref in expected) {
equal(Preferences.get(pref), expected[pref], `${pref} set correctly for ${value}`);
}
}
- await testSetting(
- "cacheEnabled", false,
- {
- "browser.cache.disk.enable": false,
- "browser.cache.memory.enable": false,
- });
- await testSetting(
- "cacheEnabled", true,
- {
- "browser.cache.disk.enable": true,
- "browser.cache.memory.enable": true,
- });
-
- await testSetting(
- "allowPopupsForUserEvents", false,
- {"dom.popup_allowed_events": ""});
- await testSetting(
- "allowPopupsForUserEvents", true,
- {"dom.popup_allowed_events": PREFS["dom.popup_allowed_events"]});
-
- for (let value of ["normal", "none", "once"]) {
- await testSetting(
- "imageAnimationBehavior", value,
- {"image.animation_mode": value});
- }
-
- await testSetting(
- "webNotificationsDisabled", true,
- {"permissions.default.desktop-notification": PERM_DENY_ACTION});
- await testSetting(
- "webNotificationsDisabled", false,
- {
- // This pref is not defaulted on Android.
- "permissions.default.desktop-notification":
- AppConstants.MOZ_BUILD_APP !== "browser" ? undefined : PERM_UNKNOWN_ACTION,
- });
-
- // This setting is a no-op on Android.
- if (AppConstants.platform === "android") {
- await testNoOpSetting("contextMenuShowEvent", "mouseup",
- {"ui.context_menus.after_mouseup": false});
- } else {
- await testSetting(
- "contextMenuShowEvent", "mouseup",
- {"ui.context_menus.after_mouseup": true});
- }
-
- // "mousedown" is also a no-op on Windows.
- if (["android", "win"].includes(AppConstants.platform)) {
- await testNoOpSetting(
- "contextMenuShowEvent", "mousedown",
- {"ui.context_menus.after_mouseup": AppConstants.platform === "win"});
- } else {
- await testSetting(
- "contextMenuShowEvent", "mousedown",
- {"ui.context_menus.after_mouseup": false});
- }
-
- if (AppConstants.platform !== "android") {
- await testSetting(
- "closeTabsByDoubleClick", true,
- {"browser.tabs.closeTabByDblclick": true});
- await testSetting(
- "closeTabsByDoubleClick", false,
- {"browser.tabs.closeTabByDblclick": false});
- }
-
- await testSetting(
- "newTabPosition", "afterCurrent",
- {
- "browser.tabs.insertRelatedAfterCurrent": false,
- "browser.tabs.insertAfterCurrent": true,
- });
- await testSetting(
- "newTabPosition", "atEnd",
- {
- "browser.tabs.insertRelatedAfterCurrent": false,
- "browser.tabs.insertAfterCurrent": false,
- });
- await testSetting(
- "newTabPosition", "relatedAfterCurrent",
- {
- "browser.tabs.insertRelatedAfterCurrent": true,
- "browser.tabs.insertAfterCurrent": false,
- });
-
- await testSetting(
- "openBookmarksInNewTabs", true,
- {"browser.tabs.loadBookmarksInTabs": true});
- await testSetting(
- "openBookmarksInNewTabs", false,
- {"browser.tabs.loadBookmarksInTabs": false});
-
- await testSetting(
- "openSearchResultsInNewTabs", true,
- {"browser.search.openintab": true});
- await testSetting(
- "openSearchResultsInNewTabs", false,
- {"browser.search.openintab": false});
-
- await testSetting(
- "openUrlbarResultsInNewTabs", true,
- {"browser.urlbar.openintab": true});
- await testSetting(
- "openUrlbarResultsInNewTabs", false,
- {"browser.urlbar.openintab": false});
-
- await testSetting(
- "overrideDocumentColors", "high-contrast-only",
- {"browser.display.document_color_use": 0});
- await testSetting(
- "overrideDocumentColors", "never",
- {"browser.display.document_color_use": 1});
- await testSetting(
- "overrideDocumentColors", "always",
- {"browser.display.document_color_use": 2});
-
- await testSetting(
- "useDocumentFonts", false,
- {"browser.display.use_document_fonts": 0});
- await testSetting(
- "useDocumentFonts", true,
- {"browser.display.use_document_fonts": 1});
-
async function testProxy(config, expectedPrefs, expectedConfig = config) {
- // proxyConfig is not supported on Android.
+ // proxy.settings is not supported on Android.
if (AppConstants.platform === "android") {
return Promise.resolve();
}
let proxyConfig = {
proxyType: "none",
autoConfigUrl: "",
autoLogin: false,
@@ -250,17 +101,17 @@ add_task(async function test_browser_set
socksVersion: 5,
passthrough: "localhost, 127.0.0.1",
http: "",
ftp: "",
ssl: "",
socks: "",
};
return testSetting(
- "proxyConfig", config, expectedPrefs, Object.assign(proxyConfig, expectedConfig)
+ config, expectedPrefs, Object.assign(proxyConfig, expectedConfig)
);
}
await testProxy(
{proxyType: "none"},
{"network.proxy.type": proxySvc.PROXYCONFIG_DIRECT},
);
@@ -403,151 +254,83 @@ add_task(async function test_browser_set
"network.proxy.no_proxies_on": "",
}
);
await extension.unload();
await promiseShutdownManager();
});
-add_task(async function test_bad_value() {
- async function background() {
- await browser.test.assertRejects(
- browser.browserSettings.contextMenuShowEvent.set({value: "bad"}),
- /bad is not a valid value for contextMenuShowEvent/,
- "contextMenuShowEvent.set rejects with an invalid value.");
+add_task(async function test_bad_value_proxy_config() {
+ let background = AppConstants.platform === "android" ?
+ async () => {
+ await browser.test.assertRejects(
+ browser.proxy.settings.set({value: {
+ proxyType: "none",
+ }}),
+ /proxy.settings is not supported on android/,
+ "proxy.settings.set rejects on Android.");
+
+ await browser.test.assertRejects(
+ browser.proxy.settings.get({}),
+ /proxy.settings is not supported on android/,
+ "proxy.settings.get rejects on Android.");
+
+ await browser.test.assertRejects(
+ browser.proxy.settings.clear({}),
+ /proxy.settings is not supported on android/,
+ "proxy.settings.clear rejects on Android.");
+
+ browser.test.sendMessage("done");
+ } :
+ async () => {
+ await browser.test.assertRejects(
+ browser.proxy.settings.set({value: {
+ proxyType: "abc",
+ }}),
+ /abc is not a valid value for proxyType/,
+ "proxy.settings.set rejects with an invalid proxyType value.");
- await browser.test.assertRejects(
- browser.browserSettings.overrideDocumentColors.set({value: 2}),
- /2 is not a valid value for overrideDocumentColors/,
- "overrideDocumentColors.set rejects with an invalid value.");
+ await browser.test.assertRejects(
+ browser.proxy.settings.set({value: {
+ proxyType: "autoConfig",
+ }}),
+ /undefined is not a valid value for autoConfigUrl/,
+ "proxy.settings.set for type autoConfig rejects with an empty autoConfigUrl value.");
+
+ await browser.test.assertRejects(
+ browser.proxy.settings.set({value: {
+ proxyType: "autoConfig",
+ autoConfigUrl: "abc",
+ }}),
+ /abc is not a valid value for autoConfigUrl/,
+ "proxy.settings.set rejects with an invalid autoConfigUrl value.");
- await browser.test.assertRejects(
- browser.browserSettings.overrideDocumentColors.set({value: "bad"}),
- /bad is not a valid value for overrideDocumentColors/,
- "overrideDocumentColors.set rejects with an invalid value.");
+ await browser.test.assertRejects(
+ browser.proxy.settings.set({value: {
+ proxyType: "manual",
+ socksVersion: "abc",
+ }}),
+ /abc is not a valid value for socksVersion/,
+ "proxy.settings.set rejects with an invalid socksVersion value.");
- browser.test.sendMessage("done");
- }
+ await browser.test.assertRejects(
+ browser.proxy.settings.set({value: {
+ proxyType: "manual",
+ socksVersion: 3,
+ }}),
+ /3 is not a valid value for socksVersion/,
+ "proxy.settings.set rejects with an invalid socksVersion value.");
+
+ browser.test.sendMessage("done");
+ };
let extension = ExtensionTestUtils.loadExtension({
background,
manifest: {
- permissions: ["browserSettings"],
- },
- });
-
- await extension.startup();
- await extension.awaitMessage("done");
- await extension.unload();
-});
-
-add_task(async function test_bad_value_android() {
- if (AppConstants.platform !== "android") {
- return;
- }
-
- async function background() {
- await browser.test.assertRejects(
- browser.browserSettings.closeTabsByDoubleClick.set({value: true}),
- /android is not a supported platform for the closeTabsByDoubleClick setting/,
- "closeTabsByDoubleClick.set rejects on Android.");
-
- await browser.test.assertRejects(
- browser.browserSettings.closeTabsByDoubleClick.get({}),
- /android is not a supported platform for the closeTabsByDoubleClick setting/,
- "closeTabsByDoubleClick.get rejects on Android.");
-
- await browser.test.assertRejects(
- browser.browserSettings.closeTabsByDoubleClick.clear({}),
- /android is not a supported platform for the closeTabsByDoubleClick setting/,
- "closeTabsByDoubleClick.clear rejects on Android.");
-
- browser.test.sendMessage("done");
- }
-
- let extension = ExtensionTestUtils.loadExtension({
- background,
- manifest: {
- permissions: ["browserSettings"],
+ permissions: ["proxy"],
},
});
await extension.startup();
await extension.awaitMessage("done");
await extension.unload();
});
-
-add_task(async function test_bad_value_proxy_config() {
- let background = AppConstants.platform === "android" ?
- async () => {
- await browser.test.assertRejects(
- browser.browserSettings.proxyConfig.set({value: {
- proxyType: "none",
- }}),
- /proxyConfig is not supported on android/,
- "proxyConfig.set rejects on Android.");
-
- await browser.test.assertRejects(
- browser.browserSettings.proxyConfig.get({}),
- /android is not a supported platform for the proxyConfig setting/,
- "proxyConfig.get rejects on Android.");
-
- await browser.test.assertRejects(
- browser.browserSettings.proxyConfig.clear({}),
- /android is not a supported platform for the proxyConfig setting/,
- "proxyConfig.clear rejects on Android.");
-
- browser.test.sendMessage("done");
- } :
- async () => {
- await browser.test.assertRejects(
- browser.browserSettings.proxyConfig.set({value: {
- proxyType: "abc",
- }}),
- /abc is not a valid value for proxyType/,
- "proxyConfig.set rejects with an invalid proxyType value.");
-
- await browser.test.assertRejects(
- browser.browserSettings.proxyConfig.set({value: {
- proxyType: "autoConfig",
- }}),
- /undefined is not a valid value for autoConfigUrl/,
- "proxyConfig.set for type autoConfig rejects with an empty autoConfigUrl value.");
-
- await browser.test.assertRejects(
- browser.browserSettings.proxyConfig.set({value: {
- proxyType: "autoConfig",
- autoConfigUrl: "abc",
- }}),
- /abc is not a valid value for autoConfigUrl/,
- "proxyConfig.set rejects with an invalid autoConfigUrl value.");
-
- await browser.test.assertRejects(
- browser.browserSettings.proxyConfig.set({value: {
- proxyType: "manual",
- socksVersion: "abc",
- }}),
- /abc is not a valid value for socksVersion/,
- "proxyConfig.set rejects with an invalid socksVersion value.");
-
- await browser.test.assertRejects(
- browser.browserSettings.proxyConfig.set({value: {
- proxyType: "manual",
- socksVersion: 3,
- }}),
- /3 is not a valid value for socksVersion/,
- "proxyConfig.set rejects with an invalid socksVersion value.");
-
- browser.test.sendMessage("done");
- };
-
- let extension = ExtensionTestUtils.loadExtension({
- background,
- manifest: {
- permissions: ["browserSettings"],
- },
- });
-
- await extension.startup();
- await extension.awaitMessage("done");
- await extension.unload();
-});
--- a/toolkit/components/extensions/test/xpcshell/test_ext_proxy_settings.js
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_proxy_settings.js
@@ -39,29 +39,29 @@ add_task(async function test_proxy_setti
browser.webRequest.onCompleted.addListener(details => {
browser.test.notifyPass("proxytest");
}, {urls: ["http://example.com/*"]});
browser.webRequest.onErrorOccurred.addListener(details => {
browser.test.notifyFail("proxytest");
}, {urls: ["http://example.com/*"]});
// Wait for the settings before testing a request.
- await browser.browserSettings.proxyConfig.set({value: {
+ await browser.proxy.settings.set({value: {
proxyType: "manual",
http: `${host}:${port}`,
}});
browser.test.sendMessage("ready");
}
let extension = ExtensionTestUtils.loadExtension({
manifest: {
+ applications: {gecko: {id: "proxy.settings@mochi.test"}},
permissions: [
"proxy",
"webRequest",
- "browserSettings",
"<all_urls>",
],
},
useAddonManager: "temporary",
background: `(${background})("${proxy.identity.primaryHost}", ${proxy.identity.primaryPort})`,
});
await promiseStartupManager();
--- a/toolkit/components/extensions/test/xpcshell/xpcshell-common.ini
+++ b/toolkit/components/extensions/test/xpcshell/xpcshell-common.ini
@@ -61,16 +61,17 @@ skip-if = (os == "win" && !debug) #Bug 1
[test_ext_onmessage_removelistener.js]
skip-if = true # This test no longer tests what it is meant to test.
[test_ext_permission_xhr.js]
[test_ext_persistent_events.js]
[test_ext_privacy.js]
[test_ext_privacy_disable.js]
[test_ext_privacy_update.js]
[test_ext_proxy_auth.js]
+[test_ext_proxy_config.js]
[test_ext_proxy_onauthrequired.js]
[test_ext_proxy_settings.js]
skip-if = os == "android" # proxy settings are not supported on android
[test_ext_proxy_socks.js]
[test_ext_proxy_speculative.js]
[test_ext_redirects.js]
[test_ext_runtime_connect_no_receiver.js]
[test_ext_runtime_getBrowserInfo.js]