/* 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/. */ const lazy = {}; ChromeUtils.defineESModuleGetters(lazy, { Extension: "resource://gre/modules/Extension.sys.mjs", ExtensionPermissions: "resource://gre/modules/ExtensionPermissions.sys.mjs", }); import { AboutAddonsHTMLElement } from "../aboutaddons-utils.mjs"; import { AddonCard } from "./addon-card.mjs"; class AddonPermissionsList extends AboutAddonsHTMLElement { static get markup() { return ` `; } setAddon(addon) { this.addon = addon; this.render(); } async render() { let empty = { origins: [], permissions: [], data_collection: [] }; let requiredPerms = { ...(this.addon.userPermissions ?? empty) }; let optionalPerms = { ...(this.addon.optionalPermissions ?? empty) }; let grantedPerms = await lazy.ExtensionPermissions.get(this.addon.id); // If optional permissions include , extension can request and // be granted permission for individual sites not listed in the manifest. // Include them as well in the optional origins list. let origins = [ ...(this.addon.optionalOriginsNormalized ?? []), ...grantedPerms.origins.filter(o => !requiredPerms.origins.includes(o)), ]; optionalPerms.origins = [...new Set(origins)]; let permissions = lazy.Extension.formatPermissionStrings( { permissions: requiredPerms, optionalPermissions: optionalPerms, }, { buildOptionalOrigins: true } ); let optionalEntries = [ ...Object.entries(permissions.optionalPermissions), ...Object.entries(permissions.optionalOrigins), ...Object.entries(permissions.optionalDataCollectionPermissions), ]; this.textContent = ""; let permissionsFrag = AddonPermissionsList.fragment; let dataCollectionFrag = AddonPermissionsList.fragment; if (permissions.msgs.length) { let section = permissionsFrag.querySelector( ".addon-permissions-required" ); section.hidden = false; let list = section.querySelector(".addon-permissions-list"); for (const msg of permissions.msgs) { let item = document.createElement("li"); item.classList.add("permission-info", "permission-checked"); item.appendChild(document.createTextNode(msg)); list.appendChild(item); } } if ( permissions.dataCollectionPermissions?.msg && !permissions.dataCollectionPermissions.hasNone ) { let section = dataCollectionFrag.querySelector( ".addon-permissions-required" ); section.hidden = false; let list = section.querySelector(".addon-permissions-list"); let item = document.createElement("li"); item.classList.add("permission-info", "permission-checked"); item.appendChild( document.createTextNode(permissions.dataCollectionPermissions.msg) ); list.appendChild(item); } if (optionalEntries.length) { let section = permissionsFrag.querySelector( ".addon-permissions-optional" ); let dataCollectionSection = dataCollectionFrag.querySelector( ".addon-permissions-optional" ); let list = section.querySelector(".addon-permissions-list"); let dataCollectionList = dataCollectionSection.querySelector( ".addon-permissions-list" ); for (let id = 0; id < optionalEntries.length; id++) { let [perm, msg] = optionalEntries[id]; let type = "permission"; if (permissions.optionalOrigins[perm]) { type = "origin"; } else if (permissions.optionalDataCollectionPermissions[perm]) { type = "data_collection"; } let item = document.createElement("li"); item.classList.add("permission-info"); let toggle = document.createElement("moz-toggle"); toggle.setAttribute("label", msg); toggle.id = `permission-${id}`; toggle.setAttribute("permission-type", type); let checked = grantedPerms.permissions.includes(perm) || grantedPerms.origins.includes(perm) || grantedPerms.data_collection.includes(perm); // If this is one of the "all sites" permissions if (lazy.Extension.isAllSitesPermission(perm)) { // mark it as checked if ANY of the "all sites" permission is granted. checked = await AddonCard.optionalAllSitesGranted(this.addon.id); toggle.toggleAttribute("permission-all-sites", true); } toggle.pressed = checked; toggle.setAttribute("permission-key", perm); toggle.setAttribute("action", "toggle-permission"); if (perm === "userScripts") { let mb = document.createElement("moz-message-bar"); mb.setAttribute("type", "warning"); mb.messageL10nId = "webext-perms-extra-warning-userScripts-long"; mb.slot = "nested"; toggle.append(mb); } item.appendChild(toggle); if (type === "data_collection") { dataCollectionSection.hidden = false; dataCollectionList.appendChild(item); } else { section.hidden = false; list.appendChild(item); } } } let configureSection = ({ fragment, headerL10n, subheaderL10n, emptyL10n, supportPage, supportL10n, }) => { let header = fragment.querySelector(".permission-header"); let subheader = fragment.querySelector(".permission-subheader"); let footer = fragment.querySelector(".addon-permissions-footer"); let requiredSection = fragment.querySelector( ".addon-permissions-required" ); let optionalSection = fragment.querySelector( ".addon-permissions-optional" ); let emptySection = fragment.querySelector(".addon-permissions-empty"); let isPopulated = !(requiredSection.hidden && optionalSection.hidden); header.setAttribute("data-l10n-id", headerL10n); let supportUrl = document.createElement("a", { is: "moz-support-link", }); supportUrl.setAttribute("support-page", supportPage); supportUrl.setAttribute("data-l10n-id", supportL10n); footer.append(supportUrl); if (subheaderL10n) { subheader.setAttribute("data-l10n-id", subheaderL10n); subheader.hidden = !isPopulated; } if (isPopulated) { emptySection.hidden = true; emptySection.removeAttribute("data-l10n-id"); } else { emptySection.setAttribute("data-l10n-id", emptyL10n); emptySection.hidden = false; } }; configureSection({ fragment: permissionsFrag, headerL10n: "addon-permissions-heading", emptyL10n: "addon-permissions-empty2", supportPage: "extension-permissions", supportL10n: "addon-permissions-learnmore", }); configureSection({ fragment: dataCollectionFrag, headerL10n: "addon-permissions-data-collection-heading", subheaderL10n: "addon-data-collection-provided", emptyL10n: "addon-permissions-data-collection-empty", supportPage: "extension-data-collection", supportL10n: "addon-data-collection-learnmore", }); this.appendChild(permissionsFrag); if (this.addon.hasDataCollectionPermissions) { this.appendChild(dataCollectionFrag); } } } customElements.define("addon-permissions-list", AddonPermissionsList);