summaryrefslogtreecommitdiffstats
path: root/browser/components/preferences/dialogs/connection.js
diff options
context:
space:
mode:
Diffstat (limited to 'browser/components/preferences/dialogs/connection.js')
-rw-r--r--browser/components/preferences/dialogs/connection.js653
1 files changed, 653 insertions, 0 deletions
diff --git a/browser/components/preferences/dialogs/connection.js b/browser/components/preferences/dialogs/connection.js
new file mode 100644
index 0000000000..06c070dc54
--- /dev/null
+++ b/browser/components/preferences/dialogs/connection.js
@@ -0,0 +1,653 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* import-globals-from /browser/base/content/utilityOverlay.js */
+/* import-globals-from /toolkit/content/preferencesBindings.js */
+/* import-globals-from ../extensionControlled.js */
+
+ChromeUtils.defineModuleGetter(
+ this,
+ "DoHConfigController",
+ "resource:///modules/DoHConfig.jsm"
+);
+
+document
+ .getElementById("ConnectionsDialog")
+ .addEventListener("dialoghelp", window.top.openPrefsHelp);
+
+Preferences.addAll([
+ // Add network.proxy.autoconfig_url before network.proxy.type so they're
+ // both initialized when network.proxy.type initialization triggers a call to
+ // gConnectionsDialog.updateReloadButton().
+ { id: "network.proxy.autoconfig_url", type: "string" },
+ { id: "network.proxy.type", type: "int" },
+ { id: "network.proxy.http", type: "string" },
+ { id: "network.proxy.http_port", type: "int" },
+ { id: "network.proxy.ssl", type: "string" },
+ { id: "network.proxy.ssl_port", type: "int" },
+ { id: "network.proxy.socks", type: "string" },
+ { id: "network.proxy.socks_port", type: "int" },
+ { id: "network.proxy.socks_version", type: "int" },
+ { id: "network.proxy.socks_remote_dns", type: "bool" },
+ { id: "network.proxy.no_proxies_on", type: "string" },
+ { id: "network.proxy.share_proxy_settings", type: "bool" },
+ { id: "signon.autologin.proxy", type: "bool" },
+ { id: "pref.advanced.proxies.disable_button.reload", type: "bool" },
+ { id: "network.proxy.backup.ssl", type: "string" },
+ { id: "network.proxy.backup.ssl_port", type: "int" },
+ { id: "network.trr.mode", type: "int" },
+ { id: "network.trr.uri", type: "string" },
+ { id: "network.trr.custom_uri", type: "string" },
+ { id: "doh-rollout.disable-heuristics", type: "bool" },
+ { id: "doh-rollout.skipHeuristicsCheck", type: "bool" },
+]);
+
+const DoHConfigObserver = () => {
+ gConnectionsDialog.initDnsOverHttpsUI();
+};
+
+window.addEventListener(
+ "DOMContentLoaded",
+ () => {
+ Preferences.get("network.proxy.type").on(
+ "change",
+ gConnectionsDialog.proxyTypeChanged.bind(gConnectionsDialog)
+ );
+ Preferences.get("network.proxy.socks_version").on(
+ "change",
+ gConnectionsDialog.updateDNSPref.bind(gConnectionsDialog)
+ );
+
+ Preferences.get("network.trr.uri").on("change", () => {
+ gConnectionsDialog.updateDnsOverHttpsUI();
+ });
+
+ Services.obs.addObserver(
+ DoHConfigObserver,
+ DoHConfigController.kConfigUpdateTopic
+ );
+ window.addEventListener(
+ "unload",
+ e => {
+ Services.obs.removeObserver(
+ DoHConfigObserver,
+ DoHConfigController.kConfigUpdateTopic
+ );
+ },
+ { once: true }
+ );
+
+ // XXX: We can't init the DNS-over-HTTPs UI until the onsyncfrompreference for network.trr.mode
+ // has been called. The uiReady promise will be resolved after the first call to
+ // readDnsOverHttpsMode and the subsequent call to initDnsOverHttpsUI has happened.
+ gConnectionsDialog.uiReady = new Promise(resolve => {
+ gConnectionsDialog._areTrrPrefsReady = false;
+ gConnectionsDialog._handleTrrPrefsReady = resolve;
+ }).then(async () => {
+ // awaiting this ensures that initDnsOverHttpsUI() is called after
+ // execution has been returned to the caller of _handleTrrPrefsReady,
+ // which is the checkbox value reading path. This ensures the checkbox
+ // gets checked, then initDnsOverHttpsUI() is called, then the uiReady
+ // promise resolves, preventing intermittent failures in tests.
+ await gConnectionsDialog.initDnsOverHttpsUI();
+ });
+
+ document
+ .getElementById("disableProxyExtension")
+ .addEventListener(
+ "command",
+ makeDisableControllingExtension(PREF_SETTING_TYPE, PROXY_KEY).bind(
+ gConnectionsDialog
+ )
+ );
+ gConnectionsDialog.updateProxySettingsUI();
+ initializeProxyUI(gConnectionsDialog);
+ gConnectionsDialog.registerSyncPrefListeners();
+ document
+ .getElementById("ConnectionsDialog")
+ .addEventListener("beforeaccept", e =>
+ gConnectionsDialog.beforeAccept(e)
+ );
+ },
+ { once: true, capture: true }
+);
+
+var gConnectionsDialog = {
+ beforeAccept(event) {
+ let dnsOverHttpsResolverChoice = document.getElementById(
+ "networkDnsOverHttpsResolverChoices"
+ ).value;
+ let writeURIandMode = uri => {
+ Services.prefs.setStringPref("network.trr.uri", uri);
+ // When writing the URI, also write the mode. This is needed in addition
+ // to the mode reacting in realtime to the checkbox state because of the
+ // case when the checkbox was ticked due to the rollout being enabled at
+ // the time of clicking "Accept".
+ Services.prefs.setIntPref(
+ "network.trr.mode",
+ this.writeDnsOverHttpsMode()
+ );
+ };
+ // We treat clicking "Accept" as a user choice, and set both the TRR
+ // URI and mode here. This will cause DoHController to permanently
+ // disable heuristics and the values at the time of accept will persist.
+ // This includes the case when no changes were made.
+ if (dnsOverHttpsResolverChoice == "custom") {
+ let customValue = document
+ .getElementById("networkCustomDnsOverHttpsInput")
+ .value.trim();
+ if (customValue) {
+ writeURIandMode(customValue);
+ } else {
+ writeURIandMode(DoHConfigController.currentConfig.fallbackProviderURI);
+ }
+ } else {
+ writeURIandMode(dnsOverHttpsResolverChoice);
+ }
+
+ var proxyTypePref = Preferences.get("network.proxy.type");
+ if (proxyTypePref.value == 2) {
+ this.doAutoconfigURLFixup();
+ return;
+ }
+
+ if (proxyTypePref.value != 1) {
+ return;
+ }
+
+ var httpProxyURLPref = Preferences.get("network.proxy.http");
+ var httpProxyPortPref = Preferences.get("network.proxy.http_port");
+ var shareProxiesPref = Preferences.get(
+ "network.proxy.share_proxy_settings"
+ );
+
+ // If the port is 0 and the proxy server is specified, focus on the port and cancel submission.
+ for (let prefName of ["http", "ssl", "socks"]) {
+ let proxyPortPref = Preferences.get(
+ "network.proxy." + prefName + "_port"
+ );
+ let proxyPref = Preferences.get("network.proxy." + prefName);
+ // Only worry about ports which are currently active. If the share option is on, then ignore
+ // all ports except the HTTP and SOCKS port
+ if (
+ proxyPref.value != "" &&
+ proxyPortPref.value == 0 &&
+ (prefName == "http" || prefName == "socks" || !shareProxiesPref.value)
+ ) {
+ document
+ .getElementById("networkProxy" + prefName.toUpperCase() + "_Port")
+ .focus();
+ event.preventDefault();
+ return;
+ }
+ }
+
+ // In the case of a shared proxy preference, backup the current values and update with the HTTP value
+ if (shareProxiesPref.value) {
+ var proxyServerURLPref = Preferences.get("network.proxy.ssl");
+ var proxyPortPref = Preferences.get("network.proxy.ssl_port");
+ var backupServerURLPref = Preferences.get("network.proxy.backup.ssl");
+ var backupPortPref = Preferences.get("network.proxy.backup.ssl_port");
+ backupServerURLPref.value =
+ backupServerURLPref.value || proxyServerURLPref.value;
+ backupPortPref.value = backupPortPref.value || proxyPortPref.value;
+ proxyServerURLPref.value = httpProxyURLPref.value;
+ proxyPortPref.value = httpProxyPortPref.value;
+ }
+
+ this.sanitizeNoProxiesPref();
+ },
+
+ checkForSystemProxy() {
+ if ("@mozilla.org/system-proxy-settings;1" in Cc) {
+ document.getElementById("systemPref").removeAttribute("hidden");
+ }
+ },
+
+ proxyTypeChanged() {
+ var proxyTypePref = Preferences.get("network.proxy.type");
+
+ // Update http
+ var httpProxyURLPref = Preferences.get("network.proxy.http");
+ httpProxyURLPref.updateControlDisabledState(proxyTypePref.value != 1);
+ var httpProxyPortPref = Preferences.get("network.proxy.http_port");
+ httpProxyPortPref.updateControlDisabledState(proxyTypePref.value != 1);
+
+ // Now update the other protocols
+ this.updateProtocolPrefs();
+
+ var shareProxiesPref = Preferences.get(
+ "network.proxy.share_proxy_settings"
+ );
+ shareProxiesPref.updateControlDisabledState(proxyTypePref.value != 1);
+ var autologinProxyPref = Preferences.get("signon.autologin.proxy");
+ autologinProxyPref.updateControlDisabledState(proxyTypePref.value == 0);
+ var noProxiesPref = Preferences.get("network.proxy.no_proxies_on");
+ noProxiesPref.updateControlDisabledState(proxyTypePref.value == 0);
+
+ var autoconfigURLPref = Preferences.get("network.proxy.autoconfig_url");
+ autoconfigURLPref.updateControlDisabledState(proxyTypePref.value != 2);
+
+ this.updateReloadButton();
+
+ document.getElementById(
+ "networkProxyNoneLocalhost"
+ ).hidden = Services.prefs.getBoolPref(
+ "network.proxy.allow_hijacking_localhost",
+ false
+ );
+ },
+
+ updateDNSPref() {
+ var socksVersionPref = Preferences.get("network.proxy.socks_version");
+ var socksDNSPref = Preferences.get("network.proxy.socks_remote_dns");
+ var proxyTypePref = Preferences.get("network.proxy.type");
+ var isDefinitelySocks4 =
+ proxyTypePref.value == 1 && socksVersionPref.value == 4;
+ socksDNSPref.updateControlDisabledState(
+ isDefinitelySocks4 || proxyTypePref.value == 0
+ );
+ return undefined;
+ },
+
+ updateReloadButton() {
+ // Disable the "Reload PAC" button if the selected proxy type is not PAC or
+ // if the current value of the PAC input does not match the value stored
+ // in prefs. Likewise, disable the reload button if PAC is not configured
+ // in prefs.
+
+ var typedURL = document.getElementById("networkProxyAutoconfigURL").value;
+ var proxyTypeCur = Preferences.get("network.proxy.type").value;
+
+ var pacURL = Services.prefs.getCharPref("network.proxy.autoconfig_url");
+ var proxyType = Services.prefs.getIntPref("network.proxy.type");
+
+ var disableReloadPref = Preferences.get(
+ "pref.advanced.proxies.disable_button.reload"
+ );
+ disableReloadPref.updateControlDisabledState(
+ proxyTypeCur != 2 || proxyType != 2 || typedURL != pacURL
+ );
+ },
+
+ readProxyType() {
+ this.proxyTypeChanged();
+ return undefined;
+ },
+
+ updateProtocolPrefs() {
+ var proxyTypePref = Preferences.get("network.proxy.type");
+ var shareProxiesPref = Preferences.get(
+ "network.proxy.share_proxy_settings"
+ );
+ var proxyPrefs = ["ssl", "socks"];
+ for (var i = 0; i < proxyPrefs.length; ++i) {
+ var proxyServerURLPref = Preferences.get(
+ "network.proxy." + proxyPrefs[i]
+ );
+ var proxyPortPref = Preferences.get(
+ "network.proxy." + proxyPrefs[i] + "_port"
+ );
+
+ // Restore previous per-proxy custom settings, if present.
+ if (proxyPrefs[i] != "socks" && !shareProxiesPref.value) {
+ var backupServerURLPref = Preferences.get(
+ "network.proxy.backup." + proxyPrefs[i]
+ );
+ var backupPortPref = Preferences.get(
+ "network.proxy.backup." + proxyPrefs[i] + "_port"
+ );
+ if (backupServerURLPref.hasUserValue) {
+ proxyServerURLPref.value = backupServerURLPref.value;
+ backupServerURLPref.reset();
+ }
+ if (backupPortPref.hasUserValue) {
+ proxyPortPref.value = backupPortPref.value;
+ backupPortPref.reset();
+ }
+ }
+
+ proxyServerURLPref.updateElements();
+ proxyPortPref.updateElements();
+ let prefIsShared = proxyPrefs[i] != "socks" && shareProxiesPref.value;
+ proxyServerURLPref.updateControlDisabledState(
+ proxyTypePref.value != 1 || prefIsShared
+ );
+ proxyPortPref.updateControlDisabledState(
+ proxyTypePref.value != 1 || prefIsShared
+ );
+ }
+ var socksVersionPref = Preferences.get("network.proxy.socks_version");
+ socksVersionPref.updateControlDisabledState(proxyTypePref.value != 1);
+ this.updateDNSPref();
+ return undefined;
+ },
+
+ readProxyProtocolPref(aProtocol, aIsPort) {
+ if (aProtocol != "socks") {
+ var shareProxiesPref = Preferences.get(
+ "network.proxy.share_proxy_settings"
+ );
+ if (shareProxiesPref.value) {
+ var pref = Preferences.get(
+ "network.proxy.http" + (aIsPort ? "_port" : "")
+ );
+ return pref.value;
+ }
+
+ var backupPref = Preferences.get(
+ "network.proxy.backup." + aProtocol + (aIsPort ? "_port" : "")
+ );
+ return backupPref.hasUserValue ? backupPref.value : undefined;
+ }
+ return undefined;
+ },
+
+ reloadPAC() {
+ Cc["@mozilla.org/network/protocol-proxy-service;1"]
+ .getService()
+ .reloadPAC();
+ },
+
+ doAutoconfigURLFixup() {
+ var autoURL = document.getElementById("networkProxyAutoconfigURL");
+ var autoURLPref = Preferences.get("network.proxy.autoconfig_url");
+ try {
+ autoURLPref.value = autoURL.value = Services.uriFixup.getFixupURIInfo(
+ autoURL.value
+ ).preferredURI.spec;
+ } catch (ex) {}
+ },
+
+ sanitizeNoProxiesPref() {
+ var noProxiesPref = Preferences.get("network.proxy.no_proxies_on");
+ // replace substrings of ; and \n with commas if they're neither immediately
+ // preceded nor followed by a valid separator character
+ noProxiesPref.value = noProxiesPref.value.replace(
+ /([^, \n;])[;\n]+(?![,\n;])/g,
+ "$1,"
+ );
+ // replace any remaining ; and \n since some may follow commas, etc.
+ noProxiesPref.value = noProxiesPref.value.replace(/[;\n]/g, "");
+ },
+
+ readHTTPProxyServer() {
+ var shareProxiesPref = Preferences.get(
+ "network.proxy.share_proxy_settings"
+ );
+ if (shareProxiesPref.value) {
+ this.updateProtocolPrefs();
+ }
+ return undefined;
+ },
+
+ readHTTPProxyPort() {
+ var shareProxiesPref = Preferences.get(
+ "network.proxy.share_proxy_settings"
+ );
+ if (shareProxiesPref.value) {
+ this.updateProtocolPrefs();
+ }
+ return undefined;
+ },
+
+ getProxyControls() {
+ let controlGroup = document.getElementById("networkProxyType");
+ return [
+ ...controlGroup.querySelectorAll(":scope > radio"),
+ ...controlGroup.querySelectorAll("label"),
+ ...controlGroup.querySelectorAll("input"),
+ ...controlGroup.querySelectorAll("checkbox"),
+ ...document.querySelectorAll("#networkProxySOCKSVersion > radio"),
+ ...document.querySelectorAll("#ConnectionsDialogPane > checkbox"),
+ ];
+ },
+
+ // Update the UI to show/hide the extension controlled message for
+ // proxy settings.
+ async updateProxySettingsUI() {
+ let isLocked = API_PROXY_PREFS.some(pref =>
+ Services.prefs.prefIsLocked(pref)
+ );
+
+ function setInputsDisabledState(isControlled) {
+ for (let element of gConnectionsDialog.getProxyControls()) {
+ element.disabled = isControlled;
+ }
+ gConnectionsDialog.proxyTypeChanged();
+ }
+
+ if (isLocked) {
+ // An extension can't control this setting if any pref is locked.
+ hideControllingExtension(PROXY_KEY);
+ } else {
+ handleControllingExtension(PREF_SETTING_TYPE, PROXY_KEY).then(
+ setInputsDisabledState
+ );
+ }
+ },
+
+ get dnsOverHttpsResolvers() {
+ let providers = DoHConfigController.currentConfig.providerList;
+ // if there's no default, we'll hold its position with an empty string
+ let defaultURI = DoHConfigController.currentConfig.fallbackProviderURI;
+ let defaultIndex = providers.findIndex(p => p.uri == defaultURI);
+ if (defaultIndex == -1 && defaultURI) {
+ // the default value for the pref isn't included in the resolvers list
+ // so we'll make a stub for it. Without an id, we'll have to use the url as the label
+ providers.unshift({ uri: defaultURI });
+ }
+ return providers;
+ },
+
+ isDnsOverHttpsLocked() {
+ return Services.prefs.prefIsLocked("network.trr.mode");
+ },
+
+ isDnsOverHttpsEnabled() {
+ // We consider DoH enabled if:
+ // 1. network.trr.mode has a user-set value equal to 2 or 3.
+ // 2. network.trr.mode is 0, and DoH heuristics are enabled
+ let trrPref = Preferences.get("network.trr.mode");
+ if (trrPref.value > 0) {
+ return trrPref.value == 2 || trrPref.value == 3;
+ }
+
+ let rolloutEnabled = DoHConfigController.currentConfig.enabled;
+ let heuristicsDisabled =
+ Preferences.get("doh-rollout.disable-heuristics").value ||
+ Preferences.get("doh-rollout.skipHeuristicsCheck").value;
+ return rolloutEnabled && !heuristicsDisabled;
+ },
+
+ readDnsOverHttpsMode() {
+ // called to update checked element property to reflect current pref value
+ let enabled = this.isDnsOverHttpsEnabled();
+ let uriPref = Preferences.get("network.trr.uri");
+ uriPref.updateControlDisabledState(!enabled || this.isDnsOverHttpsLocked());
+ // this is the first signal we get when the prefs are available, so
+ // lazy-init if appropriate
+ if (!this._areTrrPrefsReady) {
+ this._areTrrPrefsReady = true;
+ this._handleTrrPrefsReady();
+ } else {
+ this.updateDnsOverHttpsUI();
+ }
+ return enabled;
+ },
+
+ writeDnsOverHttpsMode() {
+ // called to update pref with user change
+ let trrModeCheckbox = document.getElementById("networkDnsOverHttps");
+
+ let trrModeCurrent = Preferences.get("network.trr.mode").value;
+ if (trrModeCheckbox.checked) {
+ //Check if the user has set the value themself through about:config.
+ if (trrModeCurrent == Ci.nsIDNSService.MODE_TRRONLY) {
+ return Ci.nsIDNSService.MODE_TRRONLY;
+ }
+ // we treat checked/enabled as mode 2
+ return Ci.nsIDNSService.MODE_TRRFIRST;
+ }
+
+ return Ci.nsIDNSService.MODE_TRROFF;
+ },
+
+ updateDnsOverHttpsUI() {
+ // init and update of the UI must wait until the pref values are ready
+ if (!this._areTrrPrefsReady) {
+ return;
+ }
+ let [menu, customInput] = this.getDnsOverHttpsControls();
+ let customDohContainer = document.getElementById(
+ "customDnsOverHttpsContainer"
+ );
+ let customURI = Preferences.get("network.trr.custom_uri").value;
+ let currentURI = Preferences.get("network.trr.uri").value;
+ let resolvers = this.dnsOverHttpsResolvers;
+ let isCustom = menu.value == "custom";
+
+ if (this.isDnsOverHttpsEnabled()) {
+ this.toggleDnsOverHttpsUI(false);
+ if (isCustom) {
+ // if the current and custom_uri values mismatch, update the uri pref
+ if (
+ currentURI &&
+ !customURI &&
+ !resolvers.find(r => r.uri == currentURI)
+ ) {
+ Services.prefs.setStringPref("network.trr.custom_uri", currentURI);
+ }
+ }
+ } else {
+ this.toggleDnsOverHttpsUI(true);
+ }
+
+ if (!menu.disabled && isCustom) {
+ customDohContainer.hidden = false;
+ customInput.disabled = false;
+ customInput.scrollIntoView();
+ } else {
+ customDohContainer.hidden = true;
+ customInput.disabled = true;
+ }
+
+ // The height has likely changed, find our SubDialog and tell it to resize.
+ requestAnimationFrame(() => {
+ let dialogs = window.opener.gSubDialog._dialogs;
+ let dialog = dialogs.find(d => d._frame.contentDocument == document);
+ if (dialog) {
+ dialog.resizeVertically();
+ }
+ });
+ },
+
+ getDnsOverHttpsControls() {
+ return [
+ document.getElementById("networkDnsOverHttpsResolverChoices"),
+ document.getElementById("networkCustomDnsOverHttpsInput"),
+ document.getElementById("networkDnsOverHttpsResolverChoicesLabel"),
+ document.getElementById("networkCustomDnsOverHttpsInputLabel"),
+ ];
+ },
+
+ toggleDnsOverHttpsUI(disabled) {
+ for (let element of this.getDnsOverHttpsControls()) {
+ element.disabled = disabled;
+ }
+ },
+
+ initDnsOverHttpsUI() {
+ let resolvers = this.dnsOverHttpsResolvers;
+ let defaultURI = DoHConfigController.currentConfig.fallbackProviderURI;
+ let currentURI = Preferences.get("network.trr.uri").value;
+ let menu = document.getElementById("networkDnsOverHttpsResolverChoices");
+
+ // populate the DNS-Over-HTTPs resolver list
+ menu.removeAllItems();
+ for (let resolver of resolvers) {
+ let item = menu.appendItem(undefined, resolver.uri);
+ if (resolver.uri == defaultURI) {
+ document.l10n.setAttributes(
+ item,
+ "connection-dns-over-https-url-item-default",
+ {
+ name: resolver.UIName || resolver.uri,
+ }
+ );
+ } else {
+ item.label = resolver.UIName || resolver.uri;
+ }
+ }
+ let lastItem = menu.appendItem(undefined, "custom");
+ document.l10n.setAttributes(
+ lastItem,
+ "connection-dns-over-https-url-custom"
+ );
+
+ // set initial selection in the resolver provider picker
+ let selectedIndex = currentURI
+ ? resolvers.findIndex(r => r.uri == currentURI)
+ : 0;
+ if (selectedIndex == -1) {
+ // select the last "Custom" item
+ selectedIndex = menu.itemCount - 1;
+ }
+ menu.selectedIndex = selectedIndex;
+
+ if (this.isDnsOverHttpsLocked()) {
+ // disable all the options and the checkbox itself to disallow enabling them
+ this.toggleDnsOverHttpsUI(true);
+ document.getElementById("networkDnsOverHttps").disabled = true;
+ } else {
+ this.toggleDnsOverHttpsUI(false);
+ this.updateDnsOverHttpsUI();
+ document.getElementById("networkDnsOverHttps").disabled = false;
+ }
+ },
+
+ registerSyncPrefListeners() {
+ function setSyncFromPrefListener(element_id, callback) {
+ Preferences.addSyncFromPrefListener(
+ document.getElementById(element_id),
+ callback
+ );
+ }
+ function setSyncToPrefListener(element_id, callback) {
+ Preferences.addSyncToPrefListener(
+ document.getElementById(element_id),
+ callback
+ );
+ }
+ setSyncFromPrefListener("networkProxyType", () => this.readProxyType());
+ setSyncFromPrefListener("networkProxyHTTP", () =>
+ this.readHTTPProxyServer()
+ );
+ setSyncFromPrefListener("networkProxyHTTP_Port", () =>
+ this.readHTTPProxyPort()
+ );
+ setSyncFromPrefListener("shareAllProxies", () =>
+ this.updateProtocolPrefs()
+ );
+ setSyncFromPrefListener("networkProxySSL", () =>
+ this.readProxyProtocolPref("ssl", false)
+ );
+ setSyncFromPrefListener("networkProxySSL_Port", () =>
+ this.readProxyProtocolPref("ssl", true)
+ );
+ setSyncFromPrefListener("networkProxySOCKS", () =>
+ this.readProxyProtocolPref("socks", false)
+ );
+ setSyncFromPrefListener("networkProxySOCKS_Port", () =>
+ this.readProxyProtocolPref("socks", true)
+ );
+ setSyncFromPrefListener("networkDnsOverHttps", () =>
+ this.readDnsOverHttpsMode()
+ );
+ setSyncToPrefListener("networkDnsOverHttps", () =>
+ this.writeDnsOverHttpsMode()
+ );
+ },
+};