mirror of
				https://github.com/mozilla/gecko-dev.git
				synced 2025-11-04 10:18:41 +02:00 
			
		
		
		
	
		
			
				
	
	
		
			152 lines
		
	
	
	
		
			4.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			152 lines
		
	
	
	
		
			4.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
/* 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 {
 | 
						|
  ActionsProvider,
 | 
						|
  ActionsResult,
 | 
						|
} from "resource:///modules/ActionsProvider.sys.mjs";
 | 
						|
 | 
						|
const lazy = {};
 | 
						|
ChromeUtils.defineESModuleGetters(lazy, {
 | 
						|
  QuickActionsLoaderDefault:
 | 
						|
    "resource:///modules/QuickActionsLoaderDefault.sys.mjs",
 | 
						|
  UrlbarPrefs: "resource:///modules/UrlbarPrefs.sys.mjs",
 | 
						|
});
 | 
						|
 | 
						|
// These prefs are relative to the `browser.urlbar` branch.
 | 
						|
const ENABLED_PREF = "quickactions.enabled";
 | 
						|
const MATCH_IN_PHRASE_PREF = "quickactions.matchInPhrase";
 | 
						|
const MIN_SEARCH_PREF = "quickactions.minimumSearchString";
 | 
						|
 | 
						|
/**
 | 
						|
 * A provider that matches the urlbar input to built in actions.
 | 
						|
 */
 | 
						|
class ProviderQuickActions extends ActionsProvider {
 | 
						|
  get name() {
 | 
						|
    return "ActionsProviderQuickActions";
 | 
						|
  }
 | 
						|
 | 
						|
  isActive(queryContext) {
 | 
						|
    return (
 | 
						|
      lazy.UrlbarPrefs.getScotchBonnetPref(ENABLED_PREF) &&
 | 
						|
      !queryContext.searchMode &&
 | 
						|
      queryContext.trimmedSearchString.length < 50 &&
 | 
						|
      queryContext.trimmedSearchString.length >=
 | 
						|
        lazy.UrlbarPrefs.get(MIN_SEARCH_PREF)
 | 
						|
    );
 | 
						|
  }
 | 
						|
 | 
						|
  async queryAction(queryContext) {
 | 
						|
    await lazy.QuickActionsLoaderDefault.ensureLoaded();
 | 
						|
    let input = queryContext.trimmedLowerCaseSearchString;
 | 
						|
    let results = [...(this.#prefixes.get(input) ?? [])];
 | 
						|
 | 
						|
    if (lazy.UrlbarPrefs.get(MATCH_IN_PHRASE_PREF)) {
 | 
						|
      for (let [keyword, key] of this.#keywords) {
 | 
						|
        if (input.includes(keyword)) {
 | 
						|
          results.push(key);
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    // Remove invisible actions.
 | 
						|
    results = results.filter(key => {
 | 
						|
      const action = this.#actions.get(key);
 | 
						|
      return action.isVisible?.() ?? true;
 | 
						|
    });
 | 
						|
 | 
						|
    if (!results.length) {
 | 
						|
      return null;
 | 
						|
    }
 | 
						|
 | 
						|
    let action = this.#actions.get(results[0]);
 | 
						|
    return new ActionsResult({
 | 
						|
      key: results[0],
 | 
						|
      l10nId: action.label,
 | 
						|
      icon: action.icon,
 | 
						|
      dataset: {
 | 
						|
        action: results[0],
 | 
						|
        inputLength: queryContext.trimmedSearchString.length,
 | 
						|
      },
 | 
						|
    });
 | 
						|
  }
 | 
						|
 | 
						|
  pickAction(_queryContext, _controller, element) {
 | 
						|
    let action = element.dataset.action;
 | 
						|
    let inputLength = Math.min(element.dataset.inputLength, 10);
 | 
						|
    Services.telemetry.keyedScalarAdd(
 | 
						|
      `quickaction.picked`,
 | 
						|
      `${action}-${inputLength}`,
 | 
						|
      1
 | 
						|
    );
 | 
						|
    let options = this.#actions.get(action).onPick();
 | 
						|
    if (options?.focusContent) {
 | 
						|
      element.ownerGlobal.gBrowser.selectedBrowser.focus();
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Adds a new QuickAction.
 | 
						|
   *
 | 
						|
   * @param {string} key A key to identify this action.
 | 
						|
   * @param {string} definition An object that describes the action.
 | 
						|
   */
 | 
						|
  addAction(key, definition) {
 | 
						|
    this.#actions.set(key, definition);
 | 
						|
    definition.commands.forEach(cmd => this.#keywords.set(cmd, key));
 | 
						|
    this.#loopOverPrefixes(definition.commands, prefix => {
 | 
						|
      let result = this.#prefixes.get(prefix);
 | 
						|
      if (result) {
 | 
						|
        if (!result.includes(key)) {
 | 
						|
          result.push(key);
 | 
						|
        }
 | 
						|
      } else {
 | 
						|
        result = [key];
 | 
						|
      }
 | 
						|
      this.#prefixes.set(prefix, result);
 | 
						|
    });
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Removes an action.
 | 
						|
   *
 | 
						|
   * @param {string} key A key to identify this action.
 | 
						|
   */
 | 
						|
  removeAction(key) {
 | 
						|
    let definition = this.#actions.get(key);
 | 
						|
    this.#actions.delete(key);
 | 
						|
    definition.commands.forEach(cmd => this.#keywords.delete(cmd));
 | 
						|
    this.#loopOverPrefixes(definition.commands, prefix => {
 | 
						|
      let result = this.#prefixes.get(prefix);
 | 
						|
      if (result) {
 | 
						|
        result = result.filter(val => val != key);
 | 
						|
      }
 | 
						|
      this.#prefixes.set(prefix, result);
 | 
						|
    });
 | 
						|
  }
 | 
						|
 | 
						|
  // A map from keywords to an action.
 | 
						|
  #keywords = new Map();
 | 
						|
 | 
						|
  // A map of all prefixes to an array of actions.
 | 
						|
  #prefixes = new Map();
 | 
						|
 | 
						|
  // The actions that have been added.
 | 
						|
  #actions = new Map();
 | 
						|
 | 
						|
  #loopOverPrefixes(commands, fun) {
 | 
						|
    for (const command of commands) {
 | 
						|
      // Loop over all the prefixes of the word, ie
 | 
						|
      // "", "w", "wo", "wor", stopping just before the full
 | 
						|
      // word itself which will be matched by the whole
 | 
						|
      // phrase matching.
 | 
						|
      for (let i = 1; i <= command.length; i++) {
 | 
						|
        let prefix = command.substring(0, command.length - i);
 | 
						|
        fun(prefix);
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
export var ActionsProviderQuickActions = new ProviderQuickActions();
 |