Backed out changeset b7a347f011cb (bug 1455755) for browser chrome failure on browser/components/preferences/in-content/tests/browser_extension_controlled.js. CLOSED TREE
authorDorel Luca <dluca@mozilla.com>
Wed, 25 Apr 2018 21:43:05 +0300
changeset 469081 1d99f96c0aec2f65e4d17dd3d11a46615f1d690a
parent 469080 801fa27ae7b8b454bd56677c09038e264421c807
child 469082 63ecf1e96a20c56625258dfa5136dc18e016c100
push id9165
push userasasaki@mozilla.com
push dateThu, 26 Apr 2018 21:04:54 +0000
treeherdermozilla-beta@064c3804de2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1455755
milestone61.0a1
backs outb7a347f011cb8c1eb15e8357f2dae0f97eef9bd8
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out changeset b7a347f011cb (bug 1455755) for browser chrome failure on browser/components/preferences/in-content/tests/browser_extension_controlled.js. CLOSED TREE
toolkit/components/extensions/ExtensionPreferencesManager.jsm
toolkit/components/extensions/parent/ext-browserSettings.js
toolkit/components/extensions/parent/ext-proxy.js
toolkit/components/extensions/schemas/browser_settings.json
toolkit/components/extensions/schemas/proxy.json
toolkit/components/extensions/test/xpcshell/test_ext_browserSettings.js
toolkit/components/extensions/test/xpcshell/test_ext_proxy_config.js
toolkit/components/extensions/test/xpcshell/test_ext_proxy_settings.js
toolkit/components/extensions/test/xpcshell/xpcshell-common.ini
--- a/toolkit/components/extensions/ExtensionPreferencesManager.jsm
+++ b/toolkit/components/extensions/ExtensionPreferencesManager.jsm
@@ -344,62 +344,9 @@ 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,27 +11,76 @@ XPCOMUtils.defineLazyServiceGetter(this,
                                    "@mozilla.org/browser/aboutnewtab-service;1",
                                    "nsIAboutNewTabService");
 
 ChromeUtils.import("resource://gre/modules/ExtensionPreferencesManager.jsm");
 
 var {
   ExtensionError,
 } = ExtensionUtils;
-var {
-  getSettingsAPI,
-} = ExtensionPreferencesManager;
+
+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],
+]);
 
 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 = {};
@@ -125,16 +174,62 @@ 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};
   },
@@ -161,39 +256,34 @@ ExtensionPreferencesManager.addSetting("
 });
 
 this.browserSettings = class extends ExtensionAPI {
   getAPI(context) {
     let {extension} = context;
     return {
       browserSettings: {
         allowPopupsForUserEvents: getSettingsAPI(
-          extension.id, "allowPopupsForUserEvents",
+          extension, "allowPopupsForUserEvents",
           () => {
             return Services.prefs.getCharPref("dom.popup_allowed_events") != "";
           }),
         cacheEnabled: getSettingsAPI(
-          extension.id, "cacheEnabled",
+          extension, "cacheEnabled",
           () => {
             return Services.prefs.getBoolPref("browser.cache.disk.enable") &&
               Services.prefs.getBoolPref("browser.cache.memory.enable");
           }),
         closeTabsByDoubleClick: getSettingsAPI(
-          extension.id, "closeTabsByDoubleClick",
+          extension, "closeTabsByDoubleClick",
           () => {
             return Services.prefs.getBoolPref("browser.tabs.closeTabByDblclick");
-          }, undefined, false, () => {
-            if (AppConstants.platform == "android") {
-              throw new ExtensionError(
-                `android is not a supported platform for the closeTabsByDoubleClick setting.`);
-            }
-          }),
+          }, undefined, false, ["android"]),
         contextMenuShowEvent: Object.assign(
           getSettingsAPI(
-            extension.id, "contextMenuShowEvent",
+            extension, "contextMenuShowEvent",
             () => {
               if (AppConstants.platform === "win") {
                 return "mouseup";
               }
               let prefValue = Services.prefs.getBoolPref(
                 "ui.context_menus.after_mouseup", null);
               return prefValue ? "mouseup" : "mousedown";
             }
@@ -210,68 +300,165 @@ this.browserSettings = class extends Ext
                 return false;
               }
               return ExtensionPreferencesManager.setSetting(
                 extension.id, "contextMenuShowEvent", details.value);
             },
           }
         ),
         homepageOverride: getSettingsAPI(
-          extension.id, HOMEPAGE_OVERRIDE_SETTING,
+          extension, HOMEPAGE_OVERRIDE_SETTING,
           () => {
             return Services.prefs.getComplexValue(
               HOMEPAGE_URL_PREF, Ci.nsIPrefLocalizedString).data;
           }, undefined, true),
         imageAnimationBehavior: getSettingsAPI(
-          extension.id, "imageAnimationBehavior",
+          extension, "imageAnimationBehavior",
           () => {
             return Services.prefs.getCharPref("image.animation_mode");
           }),
         newTabPosition: getSettingsAPI(
-          extension.id, "newTabPosition",
+          extension, "newTabPosition",
           () => {
             if (Services.prefs.getBoolPref("browser.tabs.insertAfterCurrent")) {
               return "afterCurrent";
             }
             if (Services.prefs.getBoolPref("browser.tabs.insertRelatedAfterCurrent")) {
               return "relatedAfterCurrent";
             }
             return "atEnd";
           }),
         newTabPageOverride: getSettingsAPI(
-          extension.id, NEW_TAB_OVERRIDE_SETTING,
+          extension, NEW_TAB_OVERRIDE_SETTING,
           () => {
             return aboutNewTabService.newTabURL;
           }, URL_STORE_TYPE, true),
         openBookmarksInNewTabs: getSettingsAPI(
-          extension.id, "openBookmarksInNewTabs",
+          extension, "openBookmarksInNewTabs",
           () => {
             return Services.prefs.getBoolPref("browser.tabs.loadBookmarksInTabs");
           }),
         openSearchResultsInNewTabs: getSettingsAPI(
-          extension.id, "openSearchResultsInNewTabs",
+          extension, "openSearchResultsInNewTabs",
           () => {
             return Services.prefs.getBoolPref("browser.search.openintab");
           }),
         openUrlbarResultsInNewTabs: getSettingsAPI(
-          extension.id, "openUrlbarResultsInNewTabs",
+          extension, "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.id, "webNotificationsDisabled",
+          extension, "webNotificationsDisabled",
           () => {
             let prefValue =
               Services.prefs.getIntPref(
                 "permissions.default.desktop-notification", null);
             return prefValue === PERM_DENY_ACTION;
           }),
         overrideDocumentColors: Object.assign(
           getSettingsAPI(
-            extension.id, "overrideDocumentColors",
+            extension, "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";
@@ -291,17 +478,17 @@ this.browserSettings = class extends Ext
               }
               return ExtensionPreferencesManager.setSetting(
                 extension.id, "overrideDocumentColors", prefValue);
             },
           }
         ),
         useDocumentFonts: Object.assign(
           getSettingsAPI(
-            extension.id, "useDocumentFonts",
+            extension, "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,84 +5,20 @@
  * 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) => {
@@ -163,115 +99,12 @@ 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,16 +30,87 @@
         "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": {
@@ -77,16 +148,20 @@
       "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,95 +12,16 @@
         }]
       }
     ]
   },
   {
     "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,30 +13,46 @@ 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) => {
@@ -214,16 +230,185 @@ 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"}),
@@ -285,8 +470,84 @@ 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();
+});
deleted file mode 100644
--- a/toolkit/components/extensions/test/xpcshell/test_ext_proxy_config.js
+++ /dev/null
@@ -1,336 +0,0 @@
-"use strict";
-
-ChromeUtils.defineModuleGetter(this, "ExtensionPreferencesManager",
-                               "resource://gre/modules/ExtensionPreferencesManager.jsm");
-ChromeUtils.defineModuleGetter(this, "Preferences",
-                               "resource://gre/modules/Preferences.jsm");
-
-const {
-  createAppInfo,
-  promiseShutdownManager,
-  promiseStartupManager,
-} = AddonTestUtils;
-
-AddonTestUtils.init(this);
-
-createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "42");
-
-add_task(async function test_browser_settings() {
-  const proxySvc = Ci.nsIProtocolProxyService;
-
-  // Create an object to hold the values to which we will initialize the prefs.
-  const PREFS = {
-    "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,
-  };
-
-  async function background() {
-    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");
-      }
-    });
-  }
-
-  // Set prefs to our initial values.
-  for (let pref in PREFS) {
-    Preferences.set(pref, PREFS[pref]);
-  }
-
-  registerCleanupFunction(() => {
-    // Reset the prefs.
-    for (let pref in PREFS) {
-      Preferences.reset(pref);
-    }
-  });
-
-  let extension = ExtensionTestUtils.loadExtension({
-    background,
-    manifest: {
-      permissions: ["proxy"],
-    },
-    useAddonManager: "temporary",
-  });
-
-  await promiseStartupManager();
-  await extension.startup();
-
-  async function testSetting(value, expected, expectedValue = value) {
-    extension.sendMessage("set", value);
-    let data = await extension.awaitMessage("settingData");
-    deepEqual(data.value, expectedValue,
-              `The setting has the expected value.`);
-    equal(data.levelOfControl, "controlled_by_this_extension",
-          `The setting has the expected levelOfControl.`);
-    for (let pref in expected) {
-      equal(Preferences.get(pref), expected[pref], `${pref} set correctly for ${value}`);
-    }
-  }
-
-  async function testProxy(config, expectedPrefs, expectedConfig = config) {
-    // proxy.settings 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(
-      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_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.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.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.");
-
-      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: ["proxy"],
-    },
-  });
-
-  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,28 +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.proxy.settings.set({value: {
+    await browser.browserSettings.proxyConfig.set({value: {
       proxyType: "manual",
       http: `${host}:${port}`,
     }});
     browser.test.sendMessage("ready");
   }
 
   let extension = ExtensionTestUtils.loadExtension({
     manifest: {
       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,17 +61,16 @@ 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]