.set( 1 ); } else if (!addon.isActive) { lazy.logConsole.debug( `Add-on ${this._extensionID} for search engine ${this.name} is not active!` ); Glean.browserSearchinit.engineInvalidWebextension[this._extensionID].set( 2 ); } else { let policy = await AddonSearchEngine.getWebExtensionPolicy( this._extensionID ); let providerSettings = policy.extension.manifest?.chrome_settings_overrides?.search_provider; if (!providerSettings) { lazy.logConsole.debug( `Add-on ${this._extensionID} for search engine ${this.name} no longer has an engine defined` ); Glean.browserSearchinit.engineInvalidWebextension[ this._extensionID ].set(4); } else if (this.name != providerSettings.name) { lazy.logConsole.debug( `Add-on ${this._extensionID} for search engine ${this.name} has a different name!` ); Glean.browserSearchinit.engineInvalidWebextension[ this._extensionID ].set(5); } else if (!this.checkSearchUrlMatchesManifest(providerSettings)) { lazy.logConsole.debug( `Add-on ${this._extensionID} for search engine ${this.name} has out-of-date manifest!` ); Glean.browserSearchinit.engineInvalidWebextension[ this._extensionID ].set(6); } } } /** * Initializes the engine based on the manifest and other values. * * @param {nsIURI} extensionBaseURI * The Base URI of the WebExtension. * @param {object} manifest * An object representing the WebExtensions' manifest. */ #initFromManifest(extensionBaseURI, manifest) { let searchProvider = manifest.chrome_settings_overrides.search_provider; // Set the main icon URL for the engine. let iconURL = searchProvider.favicon_url; if (!iconURL) { iconURL = manifest.icons && extensionBaseURI.resolve( lazy.ExtensionParent.IconDetails.getPreferredIcon(manifest.icons).icon ); } // Record other icons that the WebExtension has. if (manifest.icons) { for (let [size, icon] of Object.entries(manifest.icons)) { this._addIconToMap( extensionBaseURI.resolve(icon), parseInt(size), false ); } } this._initWithDetails({ ...searchProvider, iconURL, }); } /** * Update this engine based on new manifest, used during * webextension upgrades. * * @param {nsIURI} extensionBaseURI * The Base URI of the WebExtension. * @param {object} manifest * An object representing the WebExtensions' manifest. */ #updateFromManifest(extensionBaseURI, manifest) { this._urls = []; this._iconMapObj = null; this.#initFromManifest(extensionBaseURI, manifest); lazy.SearchUtils.notifyAction(this, lazy.SearchUtils.MODIFIED_TYPE.CHANGED); } /** * Get the localized manifest from the WebExtension for the given locale or * manifest default locale. * * @param {object} [extension] * The extension to get the manifest from. * @returns {Promise} * The loaded manifest. */ async #getExtensionDetailsForLocale(extension) { // If we haven't been passed an extension object, then go and find it. if (!extension) { extension = ( await AddonSearchEngine.getWebExtensionPolicy(this._extensionID) ).extension; } let manifest = extension.manifest; // For user installed add-ons, we have to simulate the add-on manager // code for loading the correct locale. // We do this, as in the case of a live language switch, the add-on manager // may not have yet reloaded the extension, and there's no way for us to // listen for that reload to complete. // See also https://bugzilla.mozilla.org/show_bug.cgi?id=1781768#c3 for // more background. let localeToLoad = Services.locale.negotiateLanguages( Services.locale.appLocalesAsBCP47, [...extension.localeData.locales.keys()], manifest.default_locale )[0]; if (localeToLoad) { manifest = await extension.getLocalizedManifest(localeToLoad); } return { baseURI: extension.baseURI, manifest }; } /** * Gets the WebExtensionPolicy for an add-on. * * @param {string} id * The WebExtension id. * @returns {Promise} */ static async getWebExtensionPolicy(id) { let policy = WebExtensionPolicy.getByID(id); if (!policy) { let idPrefix = id.split("@")[0]; let path = `resource://search-extensions/${idPrefix}/`; await lazy.AddonManager.installBuiltinAddon(path); policy = WebExtensionPolicy.getByID(id); } // On startup the extension may have not finished parsing the // manifest, wait for that here. await policy.readyPromise; return policy; } } PK