diff options
Diffstat (limited to '')
-rw-r--r-- | comm/mail/base/content/aboutAddonsExtra.js | 211 |
1 files changed, 211 insertions, 0 deletions
diff --git a/comm/mail/base/content/aboutAddonsExtra.js b/comm/mail/base/content/aboutAddonsExtra.js new file mode 100644 index 0000000000..1499d3927b --- /dev/null +++ b/comm/mail/base/content/aboutAddonsExtra.js @@ -0,0 +1,211 @@ +/* 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( + {} + ), + }); + }; +})(); |