summaryrefslogtreecommitdiffstats
path: root/browser/components/urlbar/tests/ext/api.js
diff options
context:
space:
mode:
Diffstat (limited to 'browser/components/urlbar/tests/ext/api.js')
-rw-r--r--browser/components/urlbar/tests/ext/api.js260
1 files changed, 260 insertions, 0 deletions
diff --git a/browser/components/urlbar/tests/ext/api.js b/browser/components/urlbar/tests/ext/api.js
new file mode 100644
index 0000000000..77da790190
--- /dev/null
+++ b/browser/components/urlbar/tests/ext/api.js
@@ -0,0 +1,260 @@
+/* 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/. */
+
+/* global ExtensionAPI, ExtensionCommon */
+
+"use strict";
+
+const { XPCOMUtils } = ChromeUtils.importESModule(
+ "resource://gre/modules/XPCOMUtils.sys.mjs"
+);
+
+ChromeUtils.defineESModuleGetters(this, {
+ Preferences: "resource://gre/modules/Preferences.sys.mjs",
+ UrlbarProviderExtension:
+ "resource:///modules/UrlbarProviderExtension.sys.mjs",
+ UrlbarResult: "resource:///modules/UrlbarResult.sys.mjs",
+ UrlbarView: "resource:///modules/UrlbarView.sys.mjs",
+});
+
+XPCOMUtils.defineLazyModuleGetters(this, {
+ BrowserWindowTracker: "resource:///modules/BrowserWindowTracker.jsm",
+});
+
+XPCOMUtils.defineLazyGetter(
+ this,
+ "defaultPreferences",
+ () => new Preferences({ defaultBranch: true })
+);
+
+let { EventManager } = ExtensionCommon;
+
+this.experiments_urlbar = class extends ExtensionAPI {
+ getAPI(context) {
+ return {
+ experiments: {
+ urlbar: {
+ addDynamicResultType: (name, type) => {
+ this._addDynamicResultType(name, type);
+ },
+
+ addDynamicViewTemplate: (name, viewTemplate) => {
+ this._addDynamicViewTemplate(name, viewTemplate);
+ },
+
+ attributionURL: this._getDefaultSettingsAPI(
+ "browser.partnerlink.attributionURL"
+ ),
+
+ clearInput() {
+ let window = BrowserWindowTracker.getTopWindow();
+ window.gURLBar.value = "";
+ window.gURLBar.setPageProxyState("invalid");
+ },
+
+ engagementTelemetry: this._getDefaultSettingsAPI(
+ "browser.urlbar.eventTelemetry.enabled"
+ ),
+
+ extensionTimeout: this._getDefaultSettingsAPI(
+ "browser.urlbar.extension.timeout"
+ ),
+
+ onViewUpdateRequested: new EventManager({
+ context,
+ name: "experiments.urlbar.onViewUpdateRequested",
+ register: (fire, providerName) => {
+ let provider = UrlbarProviderExtension.getOrCreate(providerName);
+ provider.setEventListener(
+ "getViewUpdate",
+ (result, idsByName) => {
+ return fire.async(result.payload, idsByName).catch(error => {
+ throw context.normalizeError(error);
+ });
+ }
+ );
+ return () => provider.setEventListener("getViewUpdate", null);
+ },
+ }).api(),
+ },
+ },
+ };
+ }
+
+ onShutdown() {
+ // Reset the default prefs. This is necessary because
+ // ExtensionPreferencesManager doesn't properly reset prefs set on the
+ // default branch. See bug 1586543, bug 1578513, bug 1578508.
+ if (this._initialDefaultPrefs) {
+ for (let [pref, value] of this._initialDefaultPrefs.entries()) {
+ defaultPreferences.set(pref, value);
+ }
+ }
+
+ this._removeDynamicViewTemplates();
+ this._removeDynamicResultTypes();
+ }
+
+ _getDefaultSettingsAPI(pref) {
+ return {
+ get: details => {
+ return {
+ value: Preferences.get(pref),
+
+ // Nothing actually uses this, but on debug builds there are extra
+ // checks enabled in Schema.sys.mjs that fail if it's not present. The
+ // value doesn't matter.
+ levelOfControl: "controllable_by_this_extension",
+ };
+ },
+ set: details => {
+ if (!this._initialDefaultPrefs) {
+ this._initialDefaultPrefs = new Map();
+ }
+ if (!this._initialDefaultPrefs.has(pref)) {
+ this._initialDefaultPrefs.set(pref, defaultPreferences.get(pref));
+ }
+ defaultPreferences.set(pref, details.value);
+ return true;
+ },
+ clear: details => {
+ if (this._initialDefaultPrefs && this._initialDefaultPrefs.has(pref)) {
+ defaultPreferences.set(pref, this._initialDefaultPrefs.get(pref));
+ return true;
+ }
+ return false;
+ },
+ };
+ }
+
+ // We use the following four properties as bookkeeping to keep track of
+ // dynamic result types and view templates registered by extensions so that
+ // they can be properly removed on extension shutdown.
+
+ // Names of dynamic result types added by this extension.
+ _dynamicResultTypeNames = new Set();
+
+ // Names of dynamic result type view templates added by this extension.
+ _dynamicViewTemplateNames = new Set();
+
+ // Maps dynamic result type names to Sets of IDs of extensions that have
+ // registered those types.
+ static extIDsByDynamicResultTypeName = new Map();
+
+ // Maps dynamic result type view template names to Sets of IDs of extensions
+ // that have registered those view templates.
+ static extIDsByDynamicViewTemplateName = new Map();
+
+ /**
+ * Adds a dynamic result type and includes it in our bookkeeping. See
+ * UrlbarResult.addDynamicResultType().
+ *
+ * @param {string} name
+ * The name of the dynamic result type.
+ * @param {object} type
+ * The type.
+ */
+ _addDynamicResultType(name, type) {
+ this._dynamicResultTypeNames.add(name);
+ this._addExtIDToDynamicResultTypeMap(
+ experiments_urlbar.extIDsByDynamicResultTypeName,
+ name
+ );
+ UrlbarResult.addDynamicResultType(name, type);
+ }
+
+ /**
+ * Removes all dynamic result types added by the extension.
+ */
+ _removeDynamicResultTypes() {
+ for (let name of this._dynamicResultTypeNames) {
+ let allRemoved = this._removeExtIDFromDynamicResultTypeMap(
+ experiments_urlbar.extIDsByDynamicResultTypeName,
+ name
+ );
+ if (allRemoved) {
+ UrlbarResult.removeDynamicResultType(name);
+ }
+ }
+ }
+
+ /**
+ * Adds a dynamic result type view template and includes it in our
+ * bookkeeping. See UrlbarView.addDynamicViewTemplate().
+ *
+ * @param {string} name
+ * The view template will be registered for the dynamic result type with
+ * this name.
+ * @param {object} viewTemplate
+ * The view template.
+ */
+ _addDynamicViewTemplate(name, viewTemplate) {
+ this._dynamicViewTemplateNames.add(name);
+ this._addExtIDToDynamicResultTypeMap(
+ experiments_urlbar.extIDsByDynamicViewTemplateName,
+ name
+ );
+ if (viewTemplate.stylesheet) {
+ viewTemplate.stylesheet = this.extension.baseURI.resolve(
+ viewTemplate.stylesheet
+ );
+ }
+ UrlbarView.addDynamicViewTemplate(name, viewTemplate);
+ }
+
+ /**
+ * Removes all dynamic result type view templates added by the extension.
+ */
+ _removeDynamicViewTemplates() {
+ for (let name of this._dynamicViewTemplateNames) {
+ let allRemoved = this._removeExtIDFromDynamicResultTypeMap(
+ experiments_urlbar.extIDsByDynamicViewTemplateName,
+ name
+ );
+ if (allRemoved) {
+ UrlbarView.removeDynamicViewTemplate(name);
+ }
+ }
+ }
+
+ /**
+ * Adds a dynamic result type name and this extension's ID to a bookkeeping
+ * map.
+ *
+ * @param {Map} map
+ * Either extIDsByDynamicResultTypeName or extIDsByDynamicViewTemplateName.
+ * @param {string} dynamicTypeName
+ * The dynamic result type name.
+ */
+ _addExtIDToDynamicResultTypeMap(map, dynamicTypeName) {
+ let extIDs = map.get(dynamicTypeName);
+ if (!extIDs) {
+ extIDs = new Set();
+ map.set(dynamicTypeName, extIDs);
+ }
+ extIDs.add(this.extension.id);
+ }
+
+ /**
+ * Removes a dynamic result type name and this extension's ID from a
+ * bookkeeping map.
+ *
+ * @param {Map} map
+ * Either extIDsByDynamicResultTypeName or extIDsByDynamicViewTemplateName.
+ * @param {string} dynamicTypeName
+ * The dynamic result type name.
+ * @returns {boolean}
+ * True if no other extension IDs are in the map under the same
+ * dynamicTypeName, and false otherwise.
+ */
+ _removeExtIDFromDynamicResultTypeMap(map, dynamicTypeName) {
+ let extIDs = map.get(dynamicTypeName);
+ extIDs.delete(this.extension.id);
+ if (!extIDs.size) {
+ map.delete(dynamicTypeName);
+ return true;
+ }
+ return false;
+ }
+};