Bug 1926241 - Provide tab-to-search results via actions. r=urlbar-reviewers,mak
Differential Revision: https://phabricator.services.mozilla.com/D227236
This commit is contained in:
@@ -32,11 +32,10 @@ export class ActionsProvider {
|
||||
* Query for actions based on the current users input.
|
||||
*
|
||||
* @param {UrlbarQueryContext} _queryContext The query context object.
|
||||
* @param {UrlbarController} _controller The urlbar controller.
|
||||
* @returns {Array} An array of ActionResult's
|
||||
* @abstract
|
||||
*/
|
||||
async queryActions(_queryContext, _controller) {
|
||||
async queryActions(_queryContext) {
|
||||
throw new Error("Not implemented.");
|
||||
}
|
||||
|
||||
@@ -65,6 +64,7 @@ export class ActionsResult {
|
||||
#icon;
|
||||
#dataset;
|
||||
#onPick;
|
||||
#onSelection;
|
||||
|
||||
/**
|
||||
* @param {object} options
|
||||
@@ -82,14 +82,17 @@ export class ActionsResult {
|
||||
* can be used to pass data when it is selected.
|
||||
* @param { Function} options.onPick
|
||||
* A callback function called when the result has been picked.
|
||||
* @param { Function} options.onSelection
|
||||
* A callback function called when the result has been selected.
|
||||
*/
|
||||
constructor({ key, l10nId, l10nArgs, icon, dataset, onPick }) {
|
||||
constructor({ key, l10nId, l10nArgs, icon, dataset, onPick, onSelection }) {
|
||||
this.#key = key;
|
||||
this.#l10nId = l10nId;
|
||||
this.#l10nArgs = l10nArgs;
|
||||
this.#icon = icon;
|
||||
this.#dataset = dataset;
|
||||
this.#onPick = onPick;
|
||||
this.#onSelection = onSelection;
|
||||
}
|
||||
|
||||
get key() {
|
||||
@@ -115,4 +118,8 @@ export class ActionsResult {
|
||||
get onPick() {
|
||||
return this.#onPick;
|
||||
}
|
||||
|
||||
get onSelection() {
|
||||
return this.#onSelection;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,9 @@ ChromeUtils.defineESModuleGetters(lazy, {
|
||||
loadAndParseOpenSearchEngine:
|
||||
"resource://gre/modules/OpenSearchLoader.sys.mjs",
|
||||
UrlbarPrefs: "resource:///modules/UrlbarPrefs.sys.mjs",
|
||||
UrlbarProviderAutofill: "resource:///modules/UrlbarProviderAutofill.sys.mjs",
|
||||
UrlbarSearchUtils: "resource:///modules/UrlbarSearchUtils.sys.mjs",
|
||||
UrlbarTokenizer: "resource:///modules/UrlbarTokenizer.sys.mjs",
|
||||
});
|
||||
|
||||
const ENABLED_PREF = "contextualSearch.enabled";
|
||||
@@ -31,9 +33,15 @@ const CONTEXTUAL_SEARCH_ENGINE = "contextual-search-engine";
|
||||
* by the active view if it utilizes OpenSearch.
|
||||
*/
|
||||
class ProviderContextualSearch extends ActionsProvider {
|
||||
// Cache the results of engines looked up by host, these can be
|
||||
// expensive lookups and we don't want to redo the query every time
|
||||
// the user types when the result will not change.
|
||||
#hostEngines = new Map();
|
||||
// Store the engine returned to the user in case they select it.
|
||||
#resultEngine = null;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.engines = new Map();
|
||||
}
|
||||
|
||||
get name() {
|
||||
@@ -44,33 +52,36 @@ class ProviderContextualSearch extends ActionsProvider {
|
||||
return (
|
||||
queryContext.trimmedSearchString &&
|
||||
lazy.UrlbarPrefs.get(ENABLED_PREF) &&
|
||||
!queryContext.searchMode
|
||||
!queryContext.searchMode &&
|
||||
queryContext.tokens.length == 1 &&
|
||||
queryContext.tokens[0].type != lazy.UrlbarTokenizer.TYPE.URL &&
|
||||
lazy.UrlbarPrefs.get("suggest.engines")
|
||||
);
|
||||
}
|
||||
|
||||
async queryActions(queryContext) {
|
||||
let instance = this.queryInstance;
|
||||
const hostname = URL.parse(queryContext.currentPage)?.hostname;
|
||||
|
||||
// This happens on about pages, which won't have associated engines
|
||||
if (!hostname) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let { engine } = await this.fetchEngineDetails();
|
||||
let icon = engine?.icon || (await engine?.getIconURL?.());
|
||||
this.#resultEngine = await this.matchEngine(queryContext);
|
||||
let defaultEngine = lazy.UrlbarSearchUtils.getDefaultEngine();
|
||||
|
||||
if (
|
||||
!engine ||
|
||||
engine.name === defaultEngine?.name ||
|
||||
instance != this.queryInstance
|
||||
this.#resultEngine &&
|
||||
this.#resultEngine.engine?.name != defaultEngine?.name
|
||||
) {
|
||||
return [await this.createActionResult(this.#resultEngine)];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
return [
|
||||
new ActionsResult({
|
||||
onSearchSessionEnd() {
|
||||
// We cache the results for a host while the user is typing, clear
|
||||
// when the search session ends as the results for the host may
|
||||
// change by the next search session.
|
||||
this.#hostEngines.clear();
|
||||
}
|
||||
|
||||
async createActionResult({ type, engine }) {
|
||||
let icon = engine?.icon || (await engine?.getIconURL?.());
|
||||
return new ActionsResult({
|
||||
key: "contextual-search",
|
||||
l10nId: "urlbar-result-search-with",
|
||||
l10nArgs: { engine: engine.name || engine.title },
|
||||
@@ -78,56 +89,148 @@ class ProviderContextualSearch extends ActionsProvider {
|
||||
onPick: (context, controller) => {
|
||||
this.pickAction(context, controller);
|
||||
},
|
||||
}),
|
||||
];
|
||||
onSelection: async (result, element) => {
|
||||
// We don't enter preview searchMode unless the engine is installed.
|
||||
if (type != INSTALLED_ENGINE) {
|
||||
return;
|
||||
}
|
||||
result.payload.engine = engine.name;
|
||||
result.payload.query = "";
|
||||
element.ownerGlobal.gURLBar.maybeConfirmSearchModeFromResult({
|
||||
result,
|
||||
checkValue: false,
|
||||
startQuery: false,
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* Searches for engines that we want to present to the user based on their
|
||||
* current host and the search query they have entered.
|
||||
*/
|
||||
async matchEngine(queryContext) {
|
||||
// First find currently installed engines that match the current query
|
||||
// if the user has DuckDuckGo installed and types "duck", offer that.
|
||||
let engine = await this.#matchTabToSearchEngine(queryContext);
|
||||
if (engine) {
|
||||
return engine;
|
||||
}
|
||||
|
||||
async fetchEngineDetails() {
|
||||
let browser =
|
||||
lazy.BrowserWindowTracker.getTopWindow().gBrowser.selectedBrowser;
|
||||
let hostname;
|
||||
let host;
|
||||
try {
|
||||
// currentURI.host will throw on pages without a host ("about:" pages).
|
||||
hostname = browser.currentURI.host;
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (this.engines.has(hostname)) {
|
||||
return { type: INSTALLED_ENGINE, engine: this.engines.get(hostname) };
|
||||
}
|
||||
|
||||
// Strip www. to allow for partial matches when looking for an engine.
|
||||
const [host] = UrlbarUtils.stripPrefixAndTrim(hostname, {
|
||||
host = UrlbarUtils.stripPrefixAndTrim(browser.currentURI.host, {
|
||||
stripWww: true,
|
||||
});
|
||||
let engines = await lazy.UrlbarSearchUtils.enginesForDomainPrefix(host, {
|
||||
matchAllDomainLevels: true,
|
||||
});
|
||||
|
||||
if (engines.length) {
|
||||
return { type: INSTALLED_ENGINE, engine: engines[0] };
|
||||
})[0];
|
||||
} catch (e) {
|
||||
// about: pages will throw when access currentURI.host, ignore.
|
||||
}
|
||||
|
||||
// Find engines based on the current host.
|
||||
if (host && !this.#hostEngines.has(host)) {
|
||||
// Find currently installed engines that match the current host. If
|
||||
// the user is on wikipedia.com, offer that.
|
||||
let hostEngine = await this.#matchInstalledEngine(host);
|
||||
|
||||
if (!hostEngine) {
|
||||
// Find engines in the search configuration but not installed that match
|
||||
// the current host. If the user is on ecosia.com and starts searching
|
||||
// offer ecosia's search.
|
||||
let contextualEngineConfig =
|
||||
await Services.search.findContextualSearchEngineByHost(host);
|
||||
if (contextualEngineConfig) {
|
||||
return {
|
||||
hostEngine = {
|
||||
type: CONTEXTUAL_SEARCH_ENGINE,
|
||||
engine: contextualEngineConfig,
|
||||
};
|
||||
}
|
||||
}
|
||||
// Cache the result against this host so we do not need to rerun
|
||||
// the same query every keystroke.
|
||||
this.#hostEngines.set(host, hostEngine);
|
||||
if (hostEngine) {
|
||||
return hostEngine;
|
||||
}
|
||||
} else if (host) {
|
||||
let cachedEngine = this.#hostEngines.get(host);
|
||||
if (cachedEngine) {
|
||||
return cachedEngine;
|
||||
}
|
||||
}
|
||||
|
||||
// Lastly match any openSearch
|
||||
if (browser?.engines?.length) {
|
||||
return { type: OPEN_SEARCH_ENGINE, engine: browser.engines[0] };
|
||||
}
|
||||
|
||||
return {};
|
||||
return null;
|
||||
}
|
||||
|
||||
async #matchInstalledEngine(query) {
|
||||
let engines = await lazy.UrlbarSearchUtils.enginesForDomainPrefix(query, {
|
||||
matchAllDomainLevels: true,
|
||||
});
|
||||
if (engines.length) {
|
||||
return { type: INSTALLED_ENGINE, engine: engines[0] };
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* This logic is copied from `UrlbarProviderTabToSearch.sys.mjs` and
|
||||
* matches a users search query to an installed engine.
|
||||
*/
|
||||
async #matchTabToSearchEngine(queryContext) {
|
||||
let searchStr = queryContext.trimmedSearchString.toLocaleLowerCase();
|
||||
let engines = await lazy.UrlbarSearchUtils.enginesForDomainPrefix(
|
||||
searchStr,
|
||||
{
|
||||
matchAllDomainLevels: true,
|
||||
}
|
||||
);
|
||||
|
||||
if (!engines.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let partialMatchEnginesByHost = new Map();
|
||||
|
||||
for (let engine of engines) {
|
||||
let [host] = UrlbarUtils.stripPrefixAndTrim(engine.searchUrlDomain, {
|
||||
stripWww: true,
|
||||
});
|
||||
if (host.startsWith(searchStr)) {
|
||||
return { type: INSTALLED_ENGINE, engine };
|
||||
}
|
||||
if (host.includes("." + searchStr)) {
|
||||
partialMatchEnginesByHost.set(engine.searchUrlDomain, engine);
|
||||
}
|
||||
let baseDomain = Services.eTLD.getBaseDomainFromHost(
|
||||
engine.searchUrlDomain
|
||||
);
|
||||
if (baseDomain.startsWith(searchStr)) {
|
||||
partialMatchEnginesByHost.set(baseDomain, engine);
|
||||
}
|
||||
}
|
||||
|
||||
if (partialMatchEnginesByHost.size) {
|
||||
let host = await lazy.UrlbarProviderAutofill.getTopHostOverThreshold(
|
||||
queryContext,
|
||||
Array.from(partialMatchEnginesByHost.keys())
|
||||
);
|
||||
if (host) {
|
||||
let engine = partialMatchEnginesByHost.get(host);
|
||||
return { type: INSTALLED_ENGINE, engine };
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
async pickAction(queryContext, controller, _element) {
|
||||
let { type, engine } = await this.fetchEngineDetails();
|
||||
let enterSeachMode = true;
|
||||
let { type, engine } = this.#resultEngine;
|
||||
let enterSearchMode = true;
|
||||
let engineObj;
|
||||
|
||||
if (
|
||||
@@ -142,7 +245,7 @@ class ProviderContextualSearch extends ActionsProvider {
|
||||
engineObj = new lazy.OpenSearchEngine({
|
||||
engineData: openSearchEngineData,
|
||||
});
|
||||
enterSeachMode = false;
|
||||
enterSearchMode = false;
|
||||
} else if (type == INSTALLED_ENGINE || type == CONTEXTUAL_SEARCH_ENGINE) {
|
||||
engineObj = engine;
|
||||
}
|
||||
@@ -151,7 +254,7 @@ class ProviderContextualSearch extends ActionsProvider {
|
||||
engineObj,
|
||||
queryContext.searchString,
|
||||
controller.input,
|
||||
enterSeachMode
|
||||
enterSearchMode
|
||||
);
|
||||
}
|
||||
|
||||
@@ -168,6 +271,7 @@ class ProviderContextualSearch extends ActionsProvider {
|
||||
);
|
||||
}
|
||||
engineObj.setAttr("auto-installed", true);
|
||||
this.#hostEngines.clear();
|
||||
return engineObj;
|
||||
}
|
||||
|
||||
@@ -181,10 +285,6 @@ class ProviderContextualSearch extends ActionsProvider {
|
||||
});
|
||||
input.window.gBrowser.selectedBrowser.focus();
|
||||
}
|
||||
|
||||
resetForTesting() {
|
||||
this.engines = new Map();
|
||||
}
|
||||
}
|
||||
|
||||
export var ActionsProviderContextualSearch = new ProviderContextualSearch();
|
||||
|
||||
@@ -27,6 +27,8 @@ ChromeUtils.defineESModuleGetters(lazy, {
|
||||
UrlbarEventBufferer: "resource:///modules/UrlbarEventBufferer.sys.mjs",
|
||||
UrlbarPrefs: "resource:///modules/UrlbarPrefs.sys.mjs",
|
||||
UrlbarQueryContext: "resource:///modules/UrlbarUtils.sys.mjs",
|
||||
UrlbarProviderGlobalActions:
|
||||
"resource:///modules/UrlbarProviderGlobalActions.sys.mjs",
|
||||
UrlbarProviderOpenTabs: "resource:///modules/UrlbarProviderOpenTabs.sys.mjs",
|
||||
UrlbarSearchUtils: "resource:///modules/UrlbarSearchUtils.sys.mjs",
|
||||
UrlbarTokenizer: "resource:///modules/UrlbarTokenizer.sys.mjs",
|
||||
@@ -1035,9 +1037,11 @@ export class UrlbarInput {
|
||||
// manner was agreed on as a compromise between consistent UX and
|
||||
// engineering effort. See review discussion at bug 1667766.
|
||||
if (
|
||||
result.heuristic &&
|
||||
(this.searchMode?.isPreview &&
|
||||
result.providerName == lazy.UrlbarProviderGlobalActions.name) ||
|
||||
(result.heuristic &&
|
||||
this.searchMode?.isPreview &&
|
||||
this.view.oneOffSearchButtons.selectedButton
|
||||
this.view.oneOffSearchButtons.selectedButton)
|
||||
) {
|
||||
this.confirmSearchMode();
|
||||
this.search(this.value);
|
||||
@@ -2523,7 +2527,11 @@ export class UrlbarInput {
|
||||
let engine = Services.search.getEngineByName(this.searchMode.engineName);
|
||||
// If the host we are navigating to matches the host of the current
|
||||
// searchModes engine host then persist searchMode.
|
||||
try {
|
||||
return uri.host != engine.searchUrlDomain;
|
||||
} catch (e) {
|
||||
// Accessing .host will throw on about pages.
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ const SUGGESTED_INDEX = 1;
|
||||
|
||||
const SCOTCH_BONNET_PREF = "scotchBonnet.enableOverride";
|
||||
const ACTIONS_PREF = "secondaryActions.featureGate";
|
||||
const QUICK_ACTIONS_PREF = "suggest.quickactions";
|
||||
|
||||
ChromeUtils.defineESModuleGetters(lazy, {
|
||||
UrlbarPrefs: "resource:///modules/UrlbarPrefs.sys.mjs",
|
||||
@@ -54,8 +55,9 @@ class ProviderGlobalActions extends UrlbarProvider {
|
||||
|
||||
isActive() {
|
||||
return (
|
||||
lazy.UrlbarPrefs.get(SCOTCH_BONNET_PREF) ||
|
||||
lazy.UrlbarPrefs.get(ACTIONS_PREF)
|
||||
(lazy.UrlbarPrefs.get(SCOTCH_BONNET_PREF) ||
|
||||
lazy.UrlbarPrefs.get(ACTIONS_PREF)) &&
|
||||
lazy.UrlbarPrefs.get(QUICK_ACTIONS_PREF)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -87,6 +89,11 @@ class ProviderGlobalActions extends UrlbarProvider {
|
||||
addCallback(this, result);
|
||||
}
|
||||
|
||||
onSelection(result, element) {
|
||||
let key = element.dataset.action;
|
||||
this.#actions.get(key).onSelection(result, element);
|
||||
}
|
||||
|
||||
onEngagement(queryContext, controller, details) {
|
||||
let key = details.element.dataset.action;
|
||||
let options = this.#actions.get(key).onPick(queryContext, controller);
|
||||
@@ -96,6 +103,12 @@ class ProviderGlobalActions extends UrlbarProvider {
|
||||
controller.view.close();
|
||||
}
|
||||
|
||||
onSearchSessionEnd(queryContext, controller, details) {
|
||||
for (let provider of globalActionsProviders) {
|
||||
provider.onSearchSessionEnd?.(queryContext, controller, details);
|
||||
}
|
||||
}
|
||||
|
||||
getViewTemplate(result) {
|
||||
return {
|
||||
children: [
|
||||
|
||||
@@ -86,6 +86,9 @@ class ProviderRecentSearches extends UrlbarProvider {
|
||||
let engine = lazy.UrlbarSearchUtils.getDefaultEngine(
|
||||
queryContext.isPrivate
|
||||
);
|
||||
if (!engine) {
|
||||
return;
|
||||
}
|
||||
let results = await lazy.FormHistory.search(["value", "lastUsed"], {
|
||||
fieldname: "searchbar-history",
|
||||
source: engine.name,
|
||||
|
||||
@@ -15,9 +15,13 @@ import {
|
||||
const lazy = {};
|
||||
|
||||
ChromeUtils.defineESModuleGetters(lazy, {
|
||||
ActionsProviderContextualSearch:
|
||||
"resource:///modules/ActionsProviderContextualSearch.sys.mjs",
|
||||
UrlbarView: "resource:///modules/UrlbarView.sys.mjs",
|
||||
UrlbarPrefs: "resource:///modules/UrlbarPrefs.sys.mjs",
|
||||
UrlbarProviderAutofill: "resource:///modules/UrlbarProviderAutofill.sys.mjs",
|
||||
UrlbarProviderGlobalActions:
|
||||
"resource:///modules/UrlbarProviderGlobalActions.sys.mjs",
|
||||
UrlbarResult: "resource:///modules/UrlbarResult.sys.mjs",
|
||||
UrlbarSearchUtils: "resource:///modules/UrlbarSearchUtils.sys.mjs",
|
||||
UrlbarTokenizer: "resource:///modules/UrlbarTokenizer.sys.mjs",
|
||||
@@ -132,7 +136,11 @@ class ProviderTabToSearch extends UrlbarProvider {
|
||||
queryContext.searchString &&
|
||||
queryContext.tokens.length == 1 &&
|
||||
!queryContext.searchMode &&
|
||||
lazy.UrlbarPrefs.get("suggest.engines")
|
||||
lazy.UrlbarPrefs.get("suggest.engines") &&
|
||||
!(
|
||||
lazy.UrlbarProviderGlobalActions.isActive(queryContext) &&
|
||||
lazy.ActionsProviderContextualSearch.isActive(queryContext)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,15 @@ const CONFIG = [
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
identifier: "non-default-engine",
|
||||
base: {
|
||||
urls: {
|
||||
search: { base: "https://example.net", searchTermParamName: "q" },
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
identifier: "config-engine",
|
||||
base: {
|
||||
@@ -27,6 +36,8 @@ const CONFIG = [
|
||||
search: { base: "https://example.org", searchTermParamName: "q" },
|
||||
},
|
||||
},
|
||||
// Only enable in particular locale so it is not installed by default.
|
||||
variants: [{ environment: { locales: ["sl"] } }],
|
||||
},
|
||||
];
|
||||
|
||||
@@ -40,6 +51,13 @@ let loadUri = async uri => {
|
||||
await loaded;
|
||||
};
|
||||
|
||||
let updateConfig = async config => {
|
||||
await waitForIdle();
|
||||
await SearchTestUtils.setRemoteSettingsConfig(config);
|
||||
await Services.search.wrappedJSObject.reset();
|
||||
await Services.search.init();
|
||||
};
|
||||
|
||||
add_setup(async function setup() {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [
|
||||
@@ -48,26 +66,14 @@ add_setup(async function setup() {
|
||||
],
|
||||
});
|
||||
|
||||
let ext = await SearchTestUtils.installSearchExtension({
|
||||
name: "Contextual",
|
||||
search_url: "https://example.com/browser",
|
||||
registerCleanupFunction(async () => {
|
||||
await updateConfig(null);
|
||||
Services.search.restoreDefaultEngines();
|
||||
});
|
||||
await AddonTestUtils.waitForSearchProviderStartup(ext);
|
||||
});
|
||||
|
||||
add_task(async function test_no_engine() {
|
||||
const ENGINE_TEST_URL = "https://example.org/";
|
||||
let onLoaded = BrowserTestUtils.browserLoaded(
|
||||
gBrowser.selectedBrowser,
|
||||
false,
|
||||
ENGINE_TEST_URL
|
||||
);
|
||||
BrowserTestUtils.startLoadingURIString(
|
||||
gBrowser.selectedBrowser,
|
||||
ENGINE_TEST_URL
|
||||
);
|
||||
await onLoaded;
|
||||
|
||||
await loadUri("https://example.org/");
|
||||
await UrlbarTestUtils.promiseAutocompleteResultPopup({
|
||||
window,
|
||||
value: "test",
|
||||
@@ -80,17 +86,13 @@ add_task(async function test_no_engine() {
|
||||
});
|
||||
|
||||
add_task(async function test_selectContextualSearchResult_already_installed() {
|
||||
const ENGINE_TEST_URL = "https://example.com/";
|
||||
let onLoaded = BrowserTestUtils.browserLoaded(
|
||||
gBrowser.selectedBrowser,
|
||||
false,
|
||||
ENGINE_TEST_URL
|
||||
);
|
||||
BrowserTestUtils.startLoadingURIString(
|
||||
gBrowser.selectedBrowser,
|
||||
ENGINE_TEST_URL
|
||||
);
|
||||
await onLoaded;
|
||||
let ext = await SearchTestUtils.installSearchExtension({
|
||||
name: "Contextual",
|
||||
search_url: "https://example.com/browser",
|
||||
});
|
||||
await AddonTestUtils.waitForSearchProviderStartup(ext);
|
||||
|
||||
await loadUri("https://example.com/");
|
||||
|
||||
const query = "search";
|
||||
let engine = Services.search.getEngineByName("Contextual");
|
||||
@@ -103,24 +105,35 @@ add_task(async function test_selectContextualSearchResult_already_installed() {
|
||||
|
||||
await UrlbarTestUtils.promiseAutocompleteResultPopup({
|
||||
window,
|
||||
value: query,
|
||||
value: "contextual",
|
||||
});
|
||||
|
||||
let result = (await UrlbarTestUtils.waitForAutocompleteResultAt(window, 1))
|
||||
.result;
|
||||
Assert.equal(
|
||||
result.providerName,
|
||||
"UrlbarProviderGlobalActions",
|
||||
"We are shown contextual search action"
|
||||
);
|
||||
info("Focus and select the contextual search result");
|
||||
EventUtils.synthesizeKey("KEY_Tab");
|
||||
EventUtils.synthesizeKey("KEY_Enter");
|
||||
await UrlbarTestUtils.promisePopupClose(window);
|
||||
|
||||
await UrlbarTestUtils.assertSearchMode(window, {
|
||||
engineName: "Contextual",
|
||||
entry: "keywordoffer",
|
||||
});
|
||||
|
||||
let onLoad = BrowserTestUtils.browserLoaded(
|
||||
gBrowser.selectedBrowser,
|
||||
false,
|
||||
expectedUrl
|
||||
);
|
||||
|
||||
EventUtils.synthesizeKey("KEY_Tab");
|
||||
EventUtils.sendString(query);
|
||||
EventUtils.synthesizeKey("KEY_Enter");
|
||||
await onLoad;
|
||||
|
||||
await UrlbarTestUtils.assertSearchMode(window, {
|
||||
engineName: "Contextual",
|
||||
entry: "other",
|
||||
});
|
||||
Assert.equal(
|
||||
gBrowser.selectedBrowser.currentURI.spec,
|
||||
expectedUrl,
|
||||
@@ -134,17 +147,8 @@ add_task(async function test_selectContextualSearchResult_not_installed() {
|
||||
"http://mochi.test:8888/browser/browser/components/search/test/browser/opensearch.html";
|
||||
const EXPECTED_URL =
|
||||
"http://mochi.test:8888/browser/browser/components/search/test/browser/?search&test=search";
|
||||
let onLoaded = BrowserTestUtils.browserLoaded(
|
||||
gBrowser.selectedBrowser,
|
||||
false,
|
||||
ENGINE_TEST_URL
|
||||
);
|
||||
BrowserTestUtils.startLoadingURIString(
|
||||
gBrowser.selectedBrowser,
|
||||
ENGINE_TEST_URL
|
||||
);
|
||||
await onLoaded;
|
||||
|
||||
await loadUri(ENGINE_TEST_URL);
|
||||
const query = "search";
|
||||
|
||||
await UrlbarTestUtils.promiseAutocompleteResultPopup({
|
||||
@@ -190,16 +194,11 @@ add_task(async function test_selectContextualSearchResult_not_installed() {
|
||||
|
||||
window.document.querySelector("#searchmode-switcher-close").click();
|
||||
await UrlbarTestUtils.promisePopupClose(window);
|
||||
|
||||
await Services.search.removeEngine(engine);
|
||||
ActionsProviderContextualSearch.resetForTesting();
|
||||
});
|
||||
|
||||
add_task(async function test_contextual_search_engine() {
|
||||
await waitForIdle();
|
||||
SearchTestUtils.setRemoteSettingsConfig(CONFIG);
|
||||
await Services.search.wrappedJSObject.reset();
|
||||
await Services.search.init();
|
||||
await updateConfig(CONFIG);
|
||||
await loadUri("https://example.org/");
|
||||
|
||||
await UrlbarTestUtils.promiseAutocompleteResultPopup({
|
||||
@@ -231,11 +230,47 @@ add_task(async function test_contextual_search_engine() {
|
||||
|
||||
window.document.querySelector("#searchmode-switcher-close").click();
|
||||
await UrlbarTestUtils.promisePopupClose(window);
|
||||
await updateConfig(null);
|
||||
});
|
||||
|
||||
await Services.search.wrappedJSObject.reset();
|
||||
await Services.search.init();
|
||||
add_task(async function test_tab_to_search_engine() {
|
||||
await updateConfig(CONFIG);
|
||||
await loadUri("https://example.org/");
|
||||
|
||||
ActionsProviderContextualSearch.resetForTesting();
|
||||
await UrlbarTestUtils.promiseAutocompleteResultPopup({
|
||||
window,
|
||||
value: "example.ne",
|
||||
});
|
||||
|
||||
let expectedUrl = "https://example.net/?q=test";
|
||||
info("Focus and select the contextual search result");
|
||||
let onLoad = BrowserTestUtils.browserLoaded(
|
||||
gBrowser.selectedBrowser,
|
||||
false,
|
||||
expectedUrl
|
||||
);
|
||||
|
||||
EventUtils.synthesizeKey("KEY_Tab");
|
||||
|
||||
await UrlbarTestUtils.assertSearchMode(window, {
|
||||
engineName: "non-default-engine",
|
||||
entry: "keywordoffer",
|
||||
isPreview: true,
|
||||
source: 3,
|
||||
});
|
||||
|
||||
EventUtils.sendString("test");
|
||||
EventUtils.synthesizeKey("KEY_Enter");
|
||||
await onLoad;
|
||||
|
||||
Assert.equal(
|
||||
gBrowser.selectedBrowser.currentURI.spec,
|
||||
expectedUrl,
|
||||
"Selecting the contextual search result opens the search URL"
|
||||
);
|
||||
|
||||
window.document.querySelector("#searchmode-switcher-close").click();
|
||||
await updateConfig(null);
|
||||
});
|
||||
|
||||
async function waitForIdle() {
|
||||
|
||||
@@ -42,6 +42,7 @@ add_task(async function test_persist_searchmode() {
|
||||
info("Focus and select the contextual search result");
|
||||
let onLoad = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
|
||||
EventUtils.synthesizeKey("KEY_Tab");
|
||||
EventUtils.sendString("test");
|
||||
EventUtils.synthesizeKey("KEY_Enter");
|
||||
await onLoad;
|
||||
|
||||
@@ -94,6 +95,7 @@ add_task(async function test_escape_searchmode() {
|
||||
info("Focus and select the contextual search result");
|
||||
let onLoad = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
|
||||
EventUtils.synthesizeKey("KEY_Tab");
|
||||
EventUtils.sendString("test");
|
||||
EventUtils.synthesizeKey("KEY_Enter");
|
||||
await onLoad;
|
||||
|
||||
|
||||
@@ -71,7 +71,10 @@ async function checkDoesNotOpenOnFocus(win) {
|
||||
|
||||
add_setup(async function () {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["browser.urlbar.autoFill", true]],
|
||||
set: [
|
||||
["browser.urlbar.autoFill", true],
|
||||
["browser.urlbar.scotchBonnet.enableOverride", false],
|
||||
],
|
||||
});
|
||||
// Add some history for the empty panel and autofill.
|
||||
await PlacesTestUtils.addVisits([
|
||||
|
||||
@@ -162,9 +162,8 @@ add_task(async function test_sitesearch() {
|
||||
false,
|
||||
expectedUrl
|
||||
);
|
||||
gURLBar.value = query;
|
||||
UrlbarTestUtils.fireInputEvent(window);
|
||||
EventUtils.synthesizeKey("KEY_Tab");
|
||||
EventUtils.sendString(query);
|
||||
EventUtils.synthesizeKey("KEY_Enter");
|
||||
await onLoad;
|
||||
|
||||
|
||||
@@ -80,7 +80,10 @@ async function checkForTabToSearchResult(engineName, isOnboarding) {
|
||||
|
||||
add_setup(async function () {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["browser.urlbar.tabToSearch.onboard.interactionsLeft", 0]],
|
||||
set: [
|
||||
["browser.urlbar.tabToSearch.onboard.interactionsLeft", 0],
|
||||
["browser.urlbar.scotchBonnet.enableOverride", false],
|
||||
],
|
||||
});
|
||||
|
||||
await SearchTestUtils.installSearchExtension({
|
||||
|
||||
@@ -163,6 +163,8 @@ add_setup(async function init() {
|
||||
Ci.nsISearchService.CHANGE_REASON_UNKNOWN
|
||||
);
|
||||
|
||||
UrlbarPrefs.set("contextualSearch.enabled", false);
|
||||
|
||||
const testDataTypeResults = [
|
||||
Object.assign({}, REMOTE_SETTINGS_RESULTS[0], { title: "test-data-type" }),
|
||||
];
|
||||
|
||||
@@ -361,6 +361,7 @@ function testEngine_setup() {
|
||||
|
||||
registerCleanupFunction(async () => {
|
||||
Services.prefs.clearUserPref("browser.urlbar.suggest.searches");
|
||||
Services.prefs.clearUserPref("browser.urlbar.contextualSearch.enabled");
|
||||
Services.prefs.clearUserPref(
|
||||
"browser.search.separatePrivateDefault.ui.enabled"
|
||||
);
|
||||
@@ -379,6 +380,10 @@ function testEngine_setup() {
|
||||
false
|
||||
);
|
||||
Services.prefs.setBoolPref("browser.urlbar.suggest.searches", false);
|
||||
Services.prefs.setBoolPref(
|
||||
"browser.urlbar.contextualSearch.enabled",
|
||||
false
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
add_setup(() => {
|
||||
UrlbarPrefs.set("suggest.quickactions", false);
|
||||
});
|
||||
|
||||
// Testing that we dedupe results that have the same URL and title as another
|
||||
// except for their prefix (e.g. http://www.).
|
||||
add_task(async function dedupe_prefix() {
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
add_setup(() => {
|
||||
UrlbarPrefs.set("suggest.quickactions", false);
|
||||
});
|
||||
|
||||
add_task(async function test_encoded() {
|
||||
info("Searching for over encoded url should not break it");
|
||||
let url = "https://www.mozilla.com/search/top/?q=%25%32%35";
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
add_task(async function test() {
|
||||
// Disable search suggestions to avoid hitting the network.
|
||||
UrlbarPrefs.set("suggest.searches", false);
|
||||
UrlbarPrefs.set("suggest.quickactions", false);
|
||||
|
||||
let engine = await Services.search.getDefault();
|
||||
let pref = "browser.newtabpage.activity-stream.hideTopSitesWithSearchParam";
|
||||
|
||||
@@ -13,6 +13,8 @@ const { PromiseTestUtils } = ChromeUtils.importESModule(
|
||||
const searchService = Services.search.wrappedJSObject;
|
||||
|
||||
add_setup(async function setup() {
|
||||
UrlbarPrefs.set("suggest.quickactions", false);
|
||||
|
||||
searchService.errorToThrowInTest = "Settings";
|
||||
|
||||
// When search service fails, we want the promise rejection to be uncaught
|
||||
|
||||
@@ -7,8 +7,10 @@
|
||||
|
||||
add_setup(async function () {
|
||||
Services.prefs.setBoolPref("browser.urlbar.autoFill", false);
|
||||
Services.prefs.setBoolPref("browser.urlbar.suggest.quickactions", false);
|
||||
registerCleanupFunction(() => {
|
||||
Services.prefs.clearUserPref("browser.urlbar.autoFill");
|
||||
Services.prefs.clearUserPref("browser.urlbar.suggest.quickactions");
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -9,16 +9,19 @@
|
||||
|
||||
const SUGGEST_PREF = "browser.urlbar.suggest.searches";
|
||||
const SUGGEST_ENABLED_PREF = "browser.search.suggest.enabled";
|
||||
const QUICKACTIONS_PREF = "browser.urlbar.suggest.quickactions";
|
||||
|
||||
add_task(async function test_places() {
|
||||
Services.prefs.setBoolPref(SUGGEST_PREF, true);
|
||||
Services.prefs.setBoolPref(SUGGEST_ENABLED_PREF, true);
|
||||
Services.prefs.setBoolPref(QUICKACTIONS_PREF, false);
|
||||
let engine = await addTestSuggestionsEngine();
|
||||
Services.search.defaultEngine = engine;
|
||||
let oldCurrentEngine = Services.search.defaultEngine;
|
||||
registerCleanupFunction(() => {
|
||||
Services.prefs.clearUserPref(SUGGEST_PREF);
|
||||
Services.prefs.clearUserPref(SUGGEST_ENABLED_PREF);
|
||||
Services.prefs.clearUserPref(QUICKACTIONS_PREF);
|
||||
Services.search.defaultEngine = oldCurrentEngine;
|
||||
});
|
||||
|
||||
|
||||
@@ -13,6 +13,11 @@ let testEngine;
|
||||
add_setup(async () => {
|
||||
// Disable search suggestions for a less verbose test.
|
||||
Services.prefs.setBoolPref("browser.search.suggest.enabled", false);
|
||||
// Disable ScotchBonnet that provides its own tab to search implementation.
|
||||
Services.prefs.setBoolPref(
|
||||
"browser.urlbar.scotchBonnet.enableOverride",
|
||||
false
|
||||
);
|
||||
// Disable tab-to-search onboarding results. Those are covered in
|
||||
// browser/components/urlbar/tests/browser/browser_tabToSearch.js.
|
||||
Services.prefs.setIntPref(
|
||||
@@ -27,6 +32,7 @@ add_setup(async () => {
|
||||
"browser.urlbar.tabToSearch.onboard.interactionsLeft"
|
||||
);
|
||||
Services.prefs.clearUserPref("browser.search.suggest.enabled");
|
||||
Services.prefs.clearUserPref("browser.urlbar.scotchBonnet.enableOverride");
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -24,6 +24,8 @@ add_setup(async function () {
|
||||
engine = await addTestSuggestionsEngine();
|
||||
port = engine.getSubmission("abc").uri.port;
|
||||
|
||||
Services.prefs.setBoolPref("browser.urlbar.suggest.quickactions", false);
|
||||
|
||||
// Set a mock engine as the default so we don't hit the network below when we
|
||||
// do searches that return the default engine heuristic result.
|
||||
await SearchTestUtils.installSearchExtension(
|
||||
|
||||
@@ -5,8 +5,10 @@
|
||||
add_setup(async function () {
|
||||
registerCleanupFunction(async () => {
|
||||
Services.prefs.clearUserPref("browser.urlbar.suggest.searches");
|
||||
Services.prefs.clearUserPref("browser.urlbar.suggest.quickactions");
|
||||
});
|
||||
Services.prefs.setBoolPref("browser.urlbar.suggest.searches", false);
|
||||
Services.prefs.setBoolPref("browser.urlbar.suggest.quickactions", false);
|
||||
});
|
||||
|
||||
add_task(async function test_untrimmed_secure_www() {
|
||||
|
||||
Reference in New Issue
Block a user