/* 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 ../../../../toolkit/mozapps/extensions/content/aboutaddons.js */ const THUNDERBIRD_THEME_PREVIEWS = new Map([ [ "thunderbird-compact-light@mozilla.org", "resource://builtin-themes/light/preview.svg", ], [ "thunderbird-compact-dark@mozilla.org", "resource://builtin-themes/dark/preview.svg", ], ]); var { UIFontSize } = ChromeUtils.import("resource:///modules/UIFontSize.jsm"); ChromeUtils.defineESModuleGetters(this, { ExtensionData: "resource://gre/modules/Extension.sys.mjs", }); XPCOMUtils.defineLazyPreferenceGetter( this, "alternativeAddonSearchUrl", "extensions.alternativeAddonSearch.url" ); (async function () { window.MozXULElement.insertFTLIfNeeded("messenger/aboutAddonsExtra.ftl"); // Needed for webext-perms-description-experiment. window.MozXULElement.insertFTLIfNeeded("messenger/extensionPermissions.ftl"); UIFontSize.registerWindow(window); // Consume clicks on a-tags and let openTrustedLinkIn() decide how to open them. window.addEventListener("click", event => { if (event.target.matches("a[href]") && event.target.href) { let uri = Services.io.newURI(event.target.href); if (uri.scheme == "http" || uri.scheme == "https") { event.preventDefault(); event.stopPropagation(); windowRoot.ownerGlobal.openTrustedLinkIn(event.target.href, "tab"); } } }); // Fix the "Search on addons.mozilla.org" placeholder text in the searchbox. let textbox = document.querySelector("search-addons > search-textbox"); document.l10n.setAttributes(textbox, "atn-addons-heading-search-input"); // Add our stylesheet. let contentStylesheet = document.createElement("link"); contentStylesheet.rel = "stylesheet"; contentStylesheet.href = "chrome://messenger/skin/aboutAddonsExtra.css"; document.head.appendChild(contentStylesheet); // Override logic for detecting unsigned add-ons. window.isCorrectlySigned = function () { return true; }; // Load our theme screenshots. let _getScreenshotUrlForAddon = getScreenshotUrlForAddon; getScreenshotUrlForAddon = function (addon) { if (THUNDERBIRD_THEME_PREVIEWS.has(addon.id)) { return THUNDERBIRD_THEME_PREVIEWS.get(addon.id); } return _getScreenshotUrlForAddon(addon); }; // Add logic to detect add-ons using the unsupported legacy API. let getMozillaAddonMessageInfo = window.getAddonMessageInfo; window.getAddonMessageInfo = async function (addon) { const { name } = addon; const { STATE_SOFTBLOCKED } = Ci.nsIBlocklistService; let data = new ExtensionData(addon.getResourceURI()); await data.loadManifest(); if ( addon.type == "extension" && (data.manifest.legacy || (!addon.isCompatible && (AddonManager.checkCompatibility || addon.blocklistState !== STATE_SOFTBLOCKED))) ) { return { linkText: await document.l10n.formatValue( "add-on-search-alternative-button-label" ), linkUrl: `${alternativeAddonSearchUrl}?id=${encodeURIComponent( addon.id )}&q=${encodeURIComponent(name)}`, messageId: "details-notification-incompatible", messageArgs: { name, version: Services.appinfo.version }, type: "warning", }; } return getMozillaAddonMessageInfo(addon); }; document.querySelectorAll("addon-card").forEach(card => card.updateMessage()); // Override parts of the addon-card customElement to be able // to add a dedicated button for extension preferences. await customElements.whenDefined("addon-card"); AddonCard.prototype.addOptionsButton = async function () { let { addon, optionsButton } = this; if (addon.type != "extension") { return; } let addonOptionsButton = this.querySelector(".extension-options-button"); if (!addonOptionsButton) { addonOptionsButton = document.createElement("button"); addonOptionsButton.classList.add("extension-options-button"); addonOptionsButton.setAttribute("action", "preferences"); document.l10n.setAttributes(addonOptionsButton, "add-on-options-button"); addonOptionsButton.disabled = true; optionsButton.parentNode.insertBefore(addonOptionsButton, optionsButton); } // Upon fresh install the manifest has not been parsed and optionsType // is not known, manually trigger parsing. if (addon.isActive && !addon.optionsType) { let data = new ExtensionData(addon.getResourceURI()); await data.loadManifest(); } addonOptionsButton.disabled = !(addon.isActive && addon.optionsType); }; AddonCard.prototype._update = AddonCard.prototype.update; AddonCard.prototype.update = function () { this._update(); this.addOptionsButton(); }; // Override parts of the addon-permission-list customElement to be able // to show the usage of Experiments in the permission list. await customElements.whenDefined("addon-permissions-list"); AddonPermissionsList.prototype.renderExperimentOnly = function () { this.textContent = ""; let frag = importTemplate("addon-permissions-list"); let section = frag.querySelector(".addon-permissions-required"); section.hidden = false; let list = section.querySelector(".addon-permissions-list"); let item = document.createElement("li"); document.l10n.setAttributes(item, "webext-perms-description-experiment"); item.classList.add("permission-info", "permission-checked"); list.appendChild(item); this.appendChild(frag); }; // We change this function from sync to async, which does not matter. // It calls this.render() which is async without awaiting it anyway. AddonPermissionsList.prototype.setAddon = async function (addon) { this.addon = addon; let data = new ExtensionData(addon.getResourceURI()); await data.loadManifest(); if (data.manifest.experiment_apis) { this.renderExperimentOnly(); } else { this.render(); } }; await customElements.whenDefined("recommended-addon-card"); RecommendedAddonCard.prototype._setCardContent = RecommendedAddonCard.prototype.setCardContent; RecommendedAddonCard.prototype.setCardContent = function (card, addon) { this._setCardContent(card, addon); card.addEventListener("click", event => { if (event.target.matches("a[href]") || event.target.matches("button")) { return; } windowRoot.ownerGlobal.openTrustedLinkIn( card.querySelector(".disco-addon-author a").href, "tab" ); }); }; await customElements.whenDefined("search-addons"); SearchAddons.prototype.searchAddons = function (query) { if (query.length === 0) { return; } let url = new URL( formatUTMParams( "addons-manager-search", AddonRepository.getSearchURL(query) ) ); // Limit search to themes, if the themes section is currently active. if ( document.getElementById("page-header").getAttribute("type") == "theme" ) { url.searchParams.set("cat", "themes"); } let browser = getBrowserElement(); let chromewin = browser.ownerGlobal; chromewin.openLinkIn(url.href, "tab", { fromChrome: true, triggeringPrincipal: Services.scriptSecurityManager.createNullPrincipal( {} ), }); }; })();