Bug 1728323 - Simplify extensionControlled and add missing fluent translation. r=mkmelin
We were missing lots of fluent ids that the previous code would have needed. We only have extension control for proxy.settings, so this was simplified. Differential Revision: https://phabricator.services.mozilla.com/D126094 --HG-- extra : amend_source : 07c340aa7c884f934792f008f5febeb6a37749b7
This commit is contained in:
Родитель
339a2b6136
Коммит
c97e8fad0c
|
@ -113,13 +113,8 @@ window.addEventListener(
|
|||
);
|
||||
|
||||
document
|
||||
.getElementById("disableProxyExtension")
|
||||
.addEventListener(
|
||||
"command",
|
||||
makeDisableControllingExtension(PREF_SETTING_TYPE, PROXY_KEY).bind(
|
||||
gConnectionsDialog
|
||||
)
|
||||
);
|
||||
.getElementById("proxyExtensionDisable")
|
||||
.addEventListener("click", disableControllingProxyExtension);
|
||||
gConnectionsDialog.updateProxySettingsUI();
|
||||
initializeProxyUI(gConnectionsDialog);
|
||||
},
|
||||
|
@ -433,11 +428,9 @@ var gConnectionsDialog = {
|
|||
|
||||
if (isLocked) {
|
||||
// An extension can't control this setting if any pref is locked.
|
||||
hideControllingExtension(PROXY_KEY);
|
||||
hideControllingProxyExtension();
|
||||
} else {
|
||||
handleControllingExtension(PREF_SETTING_TYPE, PROXY_KEY).then(
|
||||
setInputsDisabledState
|
||||
);
|
||||
handleControllingProxyExtension().then(setInputsDisabledState);
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -31,13 +31,19 @@
|
|||
<script src="chrome://messenger/content/preferences/extensionControlled.js"/>
|
||||
<script src="chrome://messenger/content/preferences/connection.js"/>
|
||||
|
||||
<hbox id="proxyExtensionContent"
|
||||
align="start" hidden="true" class="extension-controlled">
|
||||
<description control="disableProxyExtension" flex="1" />
|
||||
<button id="disableProxyExtension"
|
||||
class="extension-controlled-button accessory-button"
|
||||
data-l10n-id="connection-disable-extension" />
|
||||
</hbox>
|
||||
<!-- Need a wrapper div within the xul:dialog, which otherwise does not give
|
||||
- enough height for the flex display.
|
||||
- REMOVE when we use HTML only. -->
|
||||
<html:div>
|
||||
<html:div id="proxyExtensionContent" hidden="hidden">
|
||||
<html:p id="proxyExtensionDescription">
|
||||
<html:img data-l10n-name="extension-icon" />
|
||||
</html:p>
|
||||
<html:button id="proxyExtensionDisable"
|
||||
data-l10n-id="disable-extension-button">
|
||||
</html:button>
|
||||
</html:div>
|
||||
</html:div>
|
||||
|
||||
<html:div>
|
||||
<html:fieldset>
|
||||
|
|
|
@ -11,11 +11,6 @@ ChromeUtils.defineModuleGetter(
|
|||
"AddonManager",
|
||||
"resource://gre/modules/AddonManager.jsm"
|
||||
);
|
||||
ChromeUtils.defineModuleGetter(
|
||||
this,
|
||||
"BrowserUtils",
|
||||
"resource://gre/modules/BrowserUtils.jsm"
|
||||
);
|
||||
ChromeUtils.defineModuleGetter(
|
||||
this,
|
||||
"DeferredTask",
|
||||
|
@ -26,19 +21,7 @@ ChromeUtils.defineModuleGetter(
|
|||
"ExtensionSettingsStore",
|
||||
"resource://gre/modules/ExtensionSettingsStore.jsm"
|
||||
);
|
||||
ChromeUtils.defineModuleGetter(
|
||||
this,
|
||||
"ExtensionPreferencesManager",
|
||||
"resource://gre/modules/ExtensionPreferencesManager.jsm"
|
||||
);
|
||||
ChromeUtils.defineModuleGetter(
|
||||
this,
|
||||
"Management",
|
||||
"resource://gre/modules/Extension.jsm"
|
||||
);
|
||||
|
||||
const PREF_SETTING_TYPE = "prefs";
|
||||
const PROXY_KEY = "proxy.settings";
|
||||
const API_PROXY_PREFS = [
|
||||
"network.proxy.type",
|
||||
"network.proxy.http",
|
||||
|
@ -55,251 +38,88 @@ const API_PROXY_PREFS = [
|
|||
"signon.autologin.proxy",
|
||||
];
|
||||
|
||||
let extensionControlledContentIds = {
|
||||
"privacy.containers": "browserContainersExtensionContent",
|
||||
webNotificationsDisabled: "browserNotificationsPermissionExtensionContent",
|
||||
"services.passwordSavingEnabled": "passwordManagerExtensionContent",
|
||||
"proxy.settings": "proxyExtensionContent",
|
||||
get "websites.trackingProtectionMode"() {
|
||||
return {
|
||||
button: "contentBlockingDisableTrackingProtectionExtension",
|
||||
section: "contentBlockingTrackingProtectionExtensionContentLabel",
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
const extensionControlledL10nKeys = {
|
||||
webNotificationsDisabled: "web-notifications",
|
||||
"services.passwordSavingEnabled": "password-saving",
|
||||
"privacy.containers": "privacy-containers",
|
||||
"websites.trackingProtectionMode": "websites-content-blocking-all-trackers",
|
||||
"proxy.settings": "proxy-config",
|
||||
};
|
||||
|
||||
let extensionControlledIds = {};
|
||||
|
||||
/**
|
||||
* Check if a pref is being managed by an extension.
|
||||
*
|
||||
* NOTE: We only currently handle proxy.settings.
|
||||
*/
|
||||
async function getControllingExtensionInfo(type, settingName) {
|
||||
/**
|
||||
* Get the addon extension that is controlling the proxy settings.
|
||||
*
|
||||
* @return - The found addon, or undefined if none was found.
|
||||
*/
|
||||
async function getControllingProxyExtensionAddon() {
|
||||
await ExtensionSettingsStore.initialize();
|
||||
return ExtensionSettingsStore.getSetting(type, settingName);
|
||||
let id = ExtensionSettingsStore.getSetting("prefs", "proxy.settings")?.id;
|
||||
if (id) {
|
||||
return AddonManager.getAddonByID(id);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function getControllingExtensionEls(settingName) {
|
||||
let idInfo = extensionControlledContentIds[settingName];
|
||||
let section = document.getElementById(idInfo.section || idInfo);
|
||||
let button = idInfo.button
|
||||
? document.getElementById(idInfo.button)
|
||||
: section.querySelector("button");
|
||||
return {
|
||||
section,
|
||||
button,
|
||||
description: section.querySelector("description"),
|
||||
};
|
||||
}
|
||||
|
||||
async function getControllingExtension(type, settingName) {
|
||||
let info = await getControllingExtensionInfo(type, settingName);
|
||||
let addon = info && info.id && (await AddonManager.getAddonByID(info.id));
|
||||
return addon;
|
||||
}
|
||||
|
||||
async function handleControllingExtension(type, settingName) {
|
||||
let addon = await getControllingExtension(type, settingName);
|
||||
|
||||
// Sometimes the ExtensionSettingsStore gets in a bad state where it thinks
|
||||
// an extension is controlling a setting but the extension has been uninstalled
|
||||
// outside of the regular lifecycle. If the extension isn't currently installed
|
||||
// then we should treat the setting as not being controlled.
|
||||
// See https://bugzilla.mozilla.org/show_bug.cgi?id=1411046 for an example.
|
||||
/**
|
||||
* Show or hide the proxy extension message depending on whether or not the
|
||||
* proxy settings are controlled by an extension.
|
||||
*
|
||||
* @return {boolean} - Whether the proxy settings are controlled by an
|
||||
* extension.
|
||||
*/
|
||||
async function handleControllingProxyExtension() {
|
||||
let addon = await getControllingProxyExtensionAddon();
|
||||
if (addon) {
|
||||
extensionControlledIds[settingName] = addon.id;
|
||||
showControllingExtension(settingName, addon);
|
||||
showControllingProxyExtension(addon);
|
||||
} else {
|
||||
let elements = getControllingExtensionEls(settingName);
|
||||
if (
|
||||
extensionControlledIds[settingName] &&
|
||||
!document.hidden &&
|
||||
elements.button
|
||||
) {
|
||||
showEnableExtensionMessage(settingName);
|
||||
} else {
|
||||
hideControllingExtension(settingName);
|
||||
hideControllingProxyExtension();
|
||||
}
|
||||
delete extensionControlledIds[settingName];
|
||||
}
|
||||
|
||||
return !!addon;
|
||||
}
|
||||
|
||||
function settingNameToL10nID(settingName) {
|
||||
if (!extensionControlledL10nKeys.hasOwnProperty(settingName)) {
|
||||
throw new Error(
|
||||
`Unknown extension controlled setting name: ${settingName}`
|
||||
/**
|
||||
* Show the proxy extension message.
|
||||
*
|
||||
* @param {Object} addon - The addon extension that is currently controlling the
|
||||
* proxy settings.
|
||||
* @param {string} addon.name - The addon name.
|
||||
* @param {string} [addon.iconUrl] - The addon icon source.
|
||||
*/
|
||||
function showControllingProxyExtension(addon) {
|
||||
let description = document.getElementById("proxyExtensionDescription");
|
||||
description
|
||||
.querySelector("img")
|
||||
.setAttribute(
|
||||
"src",
|
||||
addon.iconUrl || "chrome://mozapps/skin/extensions/extensionGeneric.svg"
|
||||
);
|
||||
}
|
||||
return `extension-controlled-${extensionControlledL10nKeys[settingName]}`;
|
||||
document.l10n.setAttributes(
|
||||
description,
|
||||
"proxy-settings-controlled-by-extension",
|
||||
{ name: addon.name }
|
||||
);
|
||||
|
||||
document.getElementById("proxyExtensionContent").hidden = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the localization data for the description of the controlling extension.
|
||||
*
|
||||
* The function alters the inner DOM structure of the fragment to, depending
|
||||
* on the `addon` argument, remove the `<img/>` element or ensure it's
|
||||
* set to the correct src.
|
||||
* This allows Fluent DOM Overlays to localize the fragment.
|
||||
*
|
||||
* @param elem {Element}
|
||||
* <description> element to be annotated
|
||||
* @param addon {Object?}
|
||||
* Addon object with meta information about the addon (or null)
|
||||
* @param settingName {String}
|
||||
* If `addon` is set this handled the name of the setting that will be used
|
||||
* to fetch the l10n id for the given message.
|
||||
* If `addon` is set to null, this will be the full l10n-id assigned to the
|
||||
* element.
|
||||
* Hide the proxy extension message.
|
||||
*/
|
||||
function setControllingExtensionDescription(elem, addon, settingName) {
|
||||
const existingImg = elem.querySelector("img");
|
||||
if (addon === null) {
|
||||
// If the element has an image child element,
|
||||
// remove it.
|
||||
if (existingImg) {
|
||||
existingImg.remove();
|
||||
}
|
||||
document.l10n.setAttributes(elem, settingName);
|
||||
return;
|
||||
}
|
||||
|
||||
const defaultIcon = "chrome://mozapps/skin/extensions/extensionGeneric.svg";
|
||||
const src = addon.iconURL || defaultIcon;
|
||||
|
||||
if (!existingImg) {
|
||||
// If an element doesn't have an image child
|
||||
// node, add it.
|
||||
let image = document.createElementNS("http://www.w3.org/1999/xhtml", "img");
|
||||
image.setAttribute("src", src);
|
||||
image.setAttribute("data-l10n-name", "icon");
|
||||
image.classList.add("extension-controlled-icon");
|
||||
elem.appendChild(image);
|
||||
} else if (existingImg.getAttribute("src") !== src) {
|
||||
existingImg.setAttribute("src", src);
|
||||
}
|
||||
|
||||
const l10nId = settingNameToL10nID(settingName);
|
||||
document.l10n.setAttributes(elem, l10nId, {
|
||||
name: addon.name,
|
||||
});
|
||||
}
|
||||
|
||||
async function showControllingExtension(settingName, addon) {
|
||||
// Tell the user what extension is controlling the setting.
|
||||
let elements = getControllingExtensionEls(settingName);
|
||||
|
||||
elements.section.classList.remove("extension-controlled-disabled");
|
||||
let description = elements.description;
|
||||
|
||||
setControllingExtensionDescription(description, addon, settingName);
|
||||
|
||||
if (elements.button) {
|
||||
elements.button.hidden = false;
|
||||
}
|
||||
|
||||
// Show the controlling extension row and hide the old label.
|
||||
elements.section.hidden = false;
|
||||
}
|
||||
|
||||
function hideControllingExtension(settingName) {
|
||||
let elements = getControllingExtensionEls(settingName);
|
||||
elements.section.hidden = true;
|
||||
if (elements.button) {
|
||||
elements.button.hidden = true;
|
||||
}
|
||||
}
|
||||
|
||||
function showEnableExtensionMessage(settingName) {
|
||||
let elements = getControllingExtensionEls(settingName);
|
||||
|
||||
elements.button.hidden = true;
|
||||
elements.section.classList.add("extension-controlled-disabled");
|
||||
|
||||
elements.description.textContent = "";
|
||||
|
||||
// We replace localization of the <description> with a DOM Fragment containing
|
||||
// the enable-extension-enable message. That means a change from:
|
||||
//
|
||||
// <description data-l10n-id="..."/>
|
||||
//
|
||||
// to:
|
||||
//
|
||||
// <description>
|
||||
// <img/>
|
||||
// <label data-l10n-id="..."/>
|
||||
// </description>
|
||||
//
|
||||
// We need to remove the l10n-id annotation from the <description> to prevent
|
||||
// Fluent from overwriting the element in case of any retranslation.
|
||||
elements.description.removeAttribute("data-l10n-id");
|
||||
|
||||
let icon = (url, name) => {
|
||||
let img = document.createElementNS("http://www.w3.org/1999/xhtml", "img");
|
||||
img.src = url;
|
||||
img.setAttribute("data-l10n-name", name);
|
||||
img.className = "extension-controlled-icon";
|
||||
return img;
|
||||
};
|
||||
let label = document.createXULElement("label");
|
||||
let addonIcon = icon(
|
||||
"chrome://mozapps/skin/extensions/extensionGeneric.svg",
|
||||
"addons-icon"
|
||||
);
|
||||
let toolbarIcon = icon("chrome://browser/skin/menu.svg", "menu-icon");
|
||||
label.appendChild(addonIcon);
|
||||
label.appendChild(toolbarIcon);
|
||||
document.l10n.setAttributes(label, "extension-controlled-enable");
|
||||
elements.description.appendChild(label);
|
||||
let dismissButton = document.createXULElement("image");
|
||||
dismissButton.setAttribute("class", "extension-controlled-icon close-icon");
|
||||
dismissButton.addEventListener("click", function dismissHandler() {
|
||||
hideControllingExtension(settingName);
|
||||
dismissButton.removeEventListener("click", dismissHandler);
|
||||
});
|
||||
elements.description.appendChild(dismissButton);
|
||||
}
|
||||
|
||||
function makeDisableControllingExtension(type, settingName) {
|
||||
return async function() {
|
||||
let { id } = await getControllingExtensionInfo(type, settingName);
|
||||
let addon = await AddonManager.getAddonByID(id);
|
||||
await addon.disable();
|
||||
};
|
||||
function hideControllingProxyExtension() {
|
||||
document.getElementById("proxyExtensionContent").hidden = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize listeners though the Management API to update the UI
|
||||
* when an extension is controlling a pref.
|
||||
* @param {string} type
|
||||
* @param {string} prefId The unique id of the setting
|
||||
* @param {HTMLElement} controlledElement
|
||||
* Disable the addon extension that is currently controlling the proxy settings.
|
||||
*/
|
||||
async function initListenersForPrefChange(type, prefId, controlledElement) {
|
||||
await Management.asyncLoadSettingsModules();
|
||||
|
||||
let managementObserver = async () => {
|
||||
let managementControlled = await handleControllingExtension(type, prefId);
|
||||
// Enterprise policy may have locked the pref, so we need to preserve that
|
||||
controlledElement.disabled =
|
||||
managementControlled || Services.prefs.prefIsLocked(prefId);
|
||||
};
|
||||
managementObserver();
|
||||
Management.on(`extension-setting-changed:${prefId}`, managementObserver);
|
||||
|
||||
window.addEventListener("unload", () => {
|
||||
Management.off(`extension-setting-changed:${prefId}`, managementObserver);
|
||||
});
|
||||
function disableControllingProxyExtension() {
|
||||
getControllingProxyExtensionAddon().then(addon => addon?.disable());
|
||||
}
|
||||
|
||||
/**
|
||||
* Start listening to the proxy settings, and update the UI accordingly.
|
||||
*
|
||||
* @param {Object} container - The proxy container.
|
||||
* @param {Function} container.updateProxySettingsUI - A callback to call
|
||||
* whenever the proxy settings change.
|
||||
*/
|
||||
function initializeProxyUI(container) {
|
||||
let deferredUpdate = new DeferredTask(() => {
|
||||
container.updateProxySettingsUI();
|
||||
|
|
|
@ -25,8 +25,14 @@ connection-dialog-window =
|
|||
*[other] width: 49em !important
|
||||
}
|
||||
|
||||
connection-disable-extension =
|
||||
.label = Disable Extension
|
||||
disable-extension-button = Disable Extension
|
||||
|
||||
# Variables:
|
||||
# $name (String) - The extension that is controlling the proxy settings.
|
||||
#
|
||||
# The extension-icon is the extension's icon, or a fallback image. It should be
|
||||
# purely decoration for the actual extension name, with alt="".
|
||||
proxy-settings-controlled-by-extension = An extension, <img data-l10n-name="extension-icon" alt="" /> { $name }, is controlling how { -brand-short-name } connects to the Internet.
|
||||
|
||||
connection-proxy-legend = Configure Proxies to Access the Internet
|
||||
|
||||
|
|
|
@ -602,6 +602,28 @@ checkbox {
|
|||
* Connection dialog
|
||||
*/
|
||||
|
||||
#proxyExtensionContent:not([hidden]) {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#proxyExtensionDescription {
|
||||
margin-block: 0;
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
#proxyExtensionDescription > img {
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
vertical-align: text-bottom;
|
||||
-moz-context-properties: fill;
|
||||
fill: currentColor;
|
||||
}
|
||||
|
||||
#proxyExtensionDisable {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
#proxy-grid,
|
||||
#dnsOverHttps-grid {
|
||||
display: grid;
|
||||
|
|
Загрузка…
Ссылка в новой задаче