/* - 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 preferences.js */
"use strict";
var { XPCOMUtils } = ChromeUtils.importESModule( "resource://gre/modules/XPCOMUtils.sys.mjs"
);
// Note: we get loaded in dialogs so we need to define our // own getters, separate from preferences.js .
ChromeUtils.defineESModuleGetters(this, {
AddonManager: "resource://gre/modules/AddonManager.sys.mjs",
BrowserUtils: "resource://gre/modules/BrowserUtils.sys.mjs",
DeferredTask: "resource://gre/modules/DeferredTask.sys.mjs",
/** * Check if a pref is being managed by an extension.
*/
async function getControllingExtensionInfo(type, settingName) {
await ExtensionSettingsStore.initialize(); return ExtensionSettingsStore.getSetting(type, settingName);
}
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. if (addon) {
extensionControlledIds[settingName] = addon.id;
showControllingExtension(settingName, addon);
} else {
let elements = getControllingExtensionEls(settingName); if (
extensionControlledIds[settingName] &&
!document.hidden &&
elements.button
) {
showEnableExtensionMessage(settingName);
} else {
hideControllingExtension(settingName);
} delete extensionControlledIds[settingName];
}
return !!addon;
}
function settingNameToL10nID(settingName) { if (!extensionControlledL10nKeys.hasOwnProperty(settingName)) { thrownew Error(
`Unknown extension controlled setting name: ${settingName}`
);
} return `extension-controlling-${extensionControlledL10nKeys[settingName]}`;
}
/** * 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.
*/ 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;
}
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.setAttribute("role", "presentation");
image.classList.add("extension-controlled-icon");
elem.appendChild(image);
} elseif (existingImg.getAttribute("src") !== src) {
existingImg.setAttribute("src", src);
}
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;
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);
// 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.setAttribute("role", "presentation");
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 disableExtension() {
let { id } = await getControllingExtensionInfo(type, settingName);
let addon = await AddonManager.getAddonByID(id);
await addon.disable();
};
}
/** * 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
*/
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);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.