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 }