tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

UrlbarProviderRecentSearches.sys.mjs (4825B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 /**
      6 * This module exports a provider returning the user's recent searches.
      7 */
      8 
      9 import {
     10  UrlbarProvider,
     11  UrlbarUtils,
     12 } from "moz-src:///browser/components/urlbar/UrlbarUtils.sys.mjs";
     13 
     14 const lazy = {};
     15 ChromeUtils.defineESModuleGetters(lazy, {
     16  DEFAULT_FORM_HISTORY_PARAM:
     17    "moz-src:///toolkit/components/search/SearchSuggestionController.sys.mjs",
     18  FormHistory: "resource://gre/modules/FormHistory.sys.mjs",
     19  SearchUtils: "moz-src:///toolkit/components/search/SearchUtils.sys.mjs",
     20  UrlbarPrefs: "moz-src:///browser/components/urlbar/UrlbarPrefs.sys.mjs",
     21  UrlbarResult: "moz-src:///browser/components/urlbar/UrlbarResult.sys.mjs",
     22  UrlbarSearchUtils:
     23    "moz-src:///browser/components/urlbar/UrlbarSearchUtils.sys.mjs",
     24 });
     25 
     26 // These prefs are relative to the `browser.urlbar` branch.
     27 const ENABLED_PREF = "recentsearches.featureGate";
     28 const SUGGEST_PREF = "suggest.recentsearches";
     29 const EXPIRATION_PREF = "recentsearches.expirationMs";
     30 const LASTDEFAULTCHANGED_PREF = "recentsearches.lastDefaultChanged";
     31 
     32 /**
     33 * A provider that returns the Recent Searches performed by the user.
     34 */
     35 export class UrlbarProviderRecentSearches extends UrlbarProvider {
     36  constructor() {
     37    super();
     38    Services.obs.addObserver(this, lazy.SearchUtils.TOPIC_ENGINE_MODIFIED);
     39  }
     40 
     41  /**
     42   * @returns {Values<typeof UrlbarUtils.PROVIDER_TYPE>}
     43   */
     44  get type() {
     45    return UrlbarUtils.PROVIDER_TYPE.PROFILE;
     46  }
     47 
     48  async isActive(queryContext) {
     49    return (
     50      lazy.UrlbarPrefs.get(ENABLED_PREF) &&
     51      lazy.UrlbarPrefs.get(SUGGEST_PREF) &&
     52      !queryContext.restrictSource &&
     53      !queryContext.searchString &&
     54      !queryContext.searchMode
     55    );
     56  }
     57 
     58  /**
     59   * We use the same priority as `UrlbarProviderTopSites` as these are both
     60   * shown on an empty urlbar query.
     61   *
     62   * @returns {number} The provider's priority for the given query.
     63   */
     64  getPriority() {
     65    return 1;
     66  }
     67 
     68  onEngagement(queryContext, controller, details) {
     69    let { result } = details;
     70    let engine = lazy.UrlbarSearchUtils.getDefaultEngine(
     71      queryContext.isPrivate
     72    );
     73 
     74    if (details.selType == "dismiss") {
     75      lazy.FormHistory.update({
     76        op: "remove",
     77        fieldname: lazy.DEFAULT_FORM_HISTORY_PARAM,
     78        value: result.payload.suggestion,
     79        source: engine.name,
     80      }).catch(error =>
     81        console.error(`Removing form history failed: ${error}`)
     82      );
     83      controller.removeResult(result);
     84    }
     85  }
     86 
     87  /**
     88   * Starts querying.
     89   *
     90   * @param {UrlbarQueryContext} queryContext
     91   * @param {(provider: UrlbarProvider, result: UrlbarResult) => void} addCallback
     92   *   Callback invoked by the provider to add a new result.
     93   */
     94  async startQuery(queryContext, addCallback) {
     95    let engine = lazy.UrlbarSearchUtils.getDefaultEngine(
     96      queryContext.isPrivate
     97    );
     98    if (!engine) {
     99      return;
    100    }
    101    let results = await lazy.FormHistory.search(["value", "lastUsed"], {
    102      fieldname: lazy.DEFAULT_FORM_HISTORY_PARAM,
    103      source: engine.name,
    104    });
    105 
    106    let expiration = parseInt(lazy.UrlbarPrefs.get(EXPIRATION_PREF), 10);
    107    let lastDefaultChanged = parseInt(
    108      lazy.UrlbarPrefs.get(LASTDEFAULTCHANGED_PREF),
    109      10
    110    );
    111    let now = Date.now();
    112 
    113    // We only want to show searches since the last engine change, if we
    114    // havent changed the engine we expire the display of the searches
    115    // after a period of time.
    116    if (lastDefaultChanged != -1) {
    117      expiration = Math.min(expiration, now - lastDefaultChanged);
    118    }
    119 
    120    results = results.filter(
    121      result => now - Math.floor(result.lastUsed / 1000) < expiration
    122    );
    123    results.sort((a, b) => b.lastUsed - a.lastUsed);
    124 
    125    if (results.length > lazy.UrlbarPrefs.get("recentsearches.maxResults")) {
    126      results.length = lazy.UrlbarPrefs.get("recentsearches.maxResults");
    127    }
    128 
    129    for (let result of results) {
    130      let res = new lazy.UrlbarResult({
    131        type: UrlbarUtils.RESULT_TYPE.SEARCH,
    132        source: UrlbarUtils.RESULT_SOURCE.HISTORY,
    133        payload: {
    134          engine: engine.name,
    135          suggestion: result.value,
    136          title: result.value,
    137          isBlockable: true,
    138          blockL10n: { id: "urlbar-result-menu-remove-from-history" },
    139          helpUrl:
    140            Services.urlFormatter.formatURLPref("app.support.baseURL") +
    141            "awesome-bar-result-menu",
    142        },
    143      });
    144      addCallback(this, res);
    145    }
    146  }
    147 
    148  observe(subject, topic, data) {
    149    switch (data) {
    150      case lazy.SearchUtils.MODIFIED_TYPE.DEFAULT:
    151        lazy.UrlbarPrefs.set(LASTDEFAULTCHANGED_PREF, Date.now().toString());
    152        break;
    153    }
    154  }
    155 }