зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1626946 - Remove search suggestions that dupe a search history result. r=adw
Differential Revision: https://phabricator.services.mozilla.com/D71094
This commit is contained in:
Родитель
17a76bc82d
Коммит
2a06a6f3c9
|
@ -273,6 +273,11 @@ pref("browser.urlbar.delay", 50);
|
||||||
// The maximum number of historical search results to show.
|
// The maximum number of historical search results to show.
|
||||||
pref("browser.urlbar.maxHistoricalSearchSuggestions", 0);
|
pref("browser.urlbar.maxHistoricalSearchSuggestions", 0);
|
||||||
|
|
||||||
|
// When true, URLs in the user's history that look like search result pages
|
||||||
|
// are styled to look like search engine results instead of the usual history
|
||||||
|
// results.
|
||||||
|
pref("browser.urlbar.restyleSearches", false);
|
||||||
|
|
||||||
// The default behavior for the urlbar can be configured to use any combination
|
// The default behavior for the urlbar can be configured to use any combination
|
||||||
// of the match filters with each additional filter adding more results (union).
|
// of the match filters with each additional filter adding more results (union).
|
||||||
pref("browser.urlbar.suggest.history", true);
|
pref("browser.urlbar.suggest.history", true);
|
||||||
|
|
|
@ -287,6 +287,7 @@ add_task(async function test_onProviderResultsRequested() {
|
||||||
engine: "Test engine",
|
engine: "Test engine",
|
||||||
suggestion: undefined,
|
suggestion: undefined,
|
||||||
keyword: undefined,
|
keyword: undefined,
|
||||||
|
isSearchHistory: false,
|
||||||
icon: "",
|
icon: "",
|
||||||
keywordOffer: false,
|
keywordOffer: false,
|
||||||
},
|
},
|
||||||
|
|
|
@ -55,9 +55,17 @@ class MuxerUnifiedComplete extends UrlbarMuxer {
|
||||||
* @param {UrlbarQueryContext} context The query context.
|
* @param {UrlbarQueryContext} context The query context.
|
||||||
*/
|
*/
|
||||||
sort(context) {
|
sort(context) {
|
||||||
|
// Remove search suggestions that are duplicates of search history results.
|
||||||
|
context.results = this._dedupeSearchHistoryAndSuggestions(context.results);
|
||||||
|
|
||||||
// A Search in a Private Window result should only be shown when there are
|
// A Search in a Private Window result should only be shown when there are
|
||||||
// other results, and all of them are searches. It should also not be shown
|
// other results, and all of them are searches. It should also not be shown
|
||||||
// if the user typed an alias, because it's an explicit search engine choice.
|
// if the user typed an alias, because it's an explicit search engine choice.
|
||||||
|
// We don't show it if there is a search history result. This is because
|
||||||
|
// search history results are RESULT_TYPE.SEARCH but they arrive faster than
|
||||||
|
// search suggestions in most cases because they are being fetched locally.
|
||||||
|
// This leads to the private search result flickering as the suggestions
|
||||||
|
// load in after the search history result.
|
||||||
let searchInPrivateWindowIndex = context.results.findIndex(
|
let searchInPrivateWindowIndex = context.results.findIndex(
|
||||||
r => r.type == UrlbarUtils.RESULT_TYPE.SEARCH && r.payload.inPrivateWindow
|
r => r.type == UrlbarUtils.RESULT_TYPE.SEARCH && r.payload.inPrivateWindow
|
||||||
);
|
);
|
||||||
|
@ -74,7 +82,6 @@ class MuxerUnifiedComplete extends UrlbarMuxer {
|
||||||
// Remove the result.
|
// Remove the result.
|
||||||
context.results.splice(searchInPrivateWindowIndex, 1);
|
context.results.splice(searchInPrivateWindowIndex, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!context.results.length) {
|
if (!context.results.length) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -135,6 +142,75 @@ class MuxerUnifiedComplete extends UrlbarMuxer {
|
||||||
}
|
}
|
||||||
context.results = sortedResults;
|
context.results = sortedResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Takes a list of results and dedupes search history and suggestions. Prefers
|
||||||
|
* search history. Also removes duplicate search history results.
|
||||||
|
* @param {array} results
|
||||||
|
* A list of results from a UrlbarQueryContext.
|
||||||
|
* @returns {array}
|
||||||
|
* The deduped list of results.
|
||||||
|
*/
|
||||||
|
_dedupeSearchHistoryAndSuggestions(results) {
|
||||||
|
if (
|
||||||
|
!UrlbarPrefs.get("restyleSearches") ||
|
||||||
|
!UrlbarPrefs.get("browser.search.suggest.enabled") ||
|
||||||
|
!UrlbarPrefs.get("suggest.searches")
|
||||||
|
) {
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
let suggestionResults = [];
|
||||||
|
// historyEnginesBySuggestion maps:
|
||||||
|
// suggestion ->
|
||||||
|
// set of engines providing that suggestion from search history
|
||||||
|
let historyEnginesBySuggestion = new Map();
|
||||||
|
for (let i = 0; i < results.length; i++) {
|
||||||
|
let result = results[i];
|
||||||
|
if (
|
||||||
|
!result.heuristic &&
|
||||||
|
groupFromResult(result) == UrlbarUtils.RESULT_GROUP.SUGGESTION
|
||||||
|
) {
|
||||||
|
if (result.payload.isSearchHistory) {
|
||||||
|
let historyEngines = historyEnginesBySuggestion.get(
|
||||||
|
result.payload.suggestion
|
||||||
|
);
|
||||||
|
if (!historyEngines) {
|
||||||
|
historyEngines = new Set();
|
||||||
|
historyEnginesBySuggestion.set(
|
||||||
|
result.payload.suggestion,
|
||||||
|
historyEngines
|
||||||
|
);
|
||||||
|
}
|
||||||
|
historyEngines.add(result.payload.engine);
|
||||||
|
} else {
|
||||||
|
// Unshift so that we iterate and remove in reverse order below.
|
||||||
|
suggestionResults.unshift([result, i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (
|
||||||
|
let i = 0;
|
||||||
|
historyEnginesBySuggestion.size && i < suggestionResults.length;
|
||||||
|
i++
|
||||||
|
) {
|
||||||
|
let [result, index] = suggestionResults[i];
|
||||||
|
let historyEngines = historyEnginesBySuggestion.get(
|
||||||
|
result.payload.suggestion
|
||||||
|
);
|
||||||
|
if (historyEngines && historyEngines.has(result.payload.engine)) {
|
||||||
|
// This suggestion result has the same suggestion and engine as a search
|
||||||
|
// history result.
|
||||||
|
results.splice(index, 1);
|
||||||
|
historyEngines.delete(result.payload.engine);
|
||||||
|
if (!historyEngines.size) {
|
||||||
|
historyEnginesBySuggestion.delete(result.payload.suggestion);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return results;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var UrlbarMuxerUnifiedComplete = new MuxerUnifiedComplete();
|
var UrlbarMuxerUnifiedComplete = new MuxerUnifiedComplete();
|
||||||
|
|
|
@ -358,6 +358,7 @@ class ProviderSearchSuggestions extends UrlbarProvider {
|
||||||
suggestion: [result.suggestion, UrlbarUtils.HIGHLIGHT.SUGGESTED],
|
suggestion: [result.suggestion, UrlbarUtils.HIGHLIGHT.SUGGESTED],
|
||||||
keyword: [alias ? alias : undefined, UrlbarUtils.HIGHLIGHT.TYPED],
|
keyword: [alias ? alias : undefined, UrlbarUtils.HIGHLIGHT.TYPED],
|
||||||
query: [searchString.trim(), UrlbarUtils.HIGHLIGHT.TYPED],
|
query: [searchString.trim(), UrlbarUtils.HIGHLIGHT.TYPED],
|
||||||
|
isSearchHistory: false,
|
||||||
icon: [
|
icon: [
|
||||||
engine.iconURI && !result.suggestion ? engine.iconURI.spec : "",
|
engine.iconURI && !result.suggestion ? engine.iconURI.spec : "",
|
||||||
],
|
],
|
||||||
|
|
|
@ -213,6 +213,7 @@ function makeUrlbarResult(tokens, info) {
|
||||||
action.params.searchQuery.trim(),
|
action.params.searchQuery.trim(),
|
||||||
UrlbarUtils.HIGHLIGHT.TYPED,
|
UrlbarUtils.HIGHLIGHT.TYPED,
|
||||||
],
|
],
|
||||||
|
isSearchHistory: !!action.params.isSearchHistory,
|
||||||
icon: [info.icon],
|
icon: [info.icon],
|
||||||
keywordOffer,
|
keywordOffer,
|
||||||
})
|
})
|
||||||
|
|
|
@ -609,6 +609,9 @@ UrlbarUtils.RESULT_PAYLOAD_SCHEMA = {
|
||||||
query: {
|
query: {
|
||||||
type: "string",
|
type: "string",
|
||||||
},
|
},
|
||||||
|
isSearchHistory: {
|
||||||
|
type: "boolean",
|
||||||
|
},
|
||||||
suggestion: {
|
suggestion: {
|
||||||
type: "string",
|
type: "string",
|
||||||
},
|
},
|
||||||
|
|
|
@ -1383,7 +1383,7 @@ class UrlbarView {
|
||||||
if (
|
if (
|
||||||
result.type != UrlbarUtils.RESULT_TYPE.SEARCH ||
|
result.type != UrlbarUtils.RESULT_TYPE.SEARCH ||
|
||||||
(!result.heuristic &&
|
(!result.heuristic &&
|
||||||
!result.payload.suggestion &&
|
(!result.payload.suggestion || result.payload.isSearchHistory) &&
|
||||||
(!result.payload.inPrivateWindow || result.payload.isPrivateEngine))
|
(!result.payload.inPrivateWindow || result.payload.isPrivateEngine))
|
||||||
) {
|
) {
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -160,6 +160,7 @@ var UrlbarTestUtils = {
|
||||||
keyword: result.payload.keyword,
|
keyword: result.payload.keyword,
|
||||||
query: result.payload.query,
|
query: result.payload.query,
|
||||||
suggestion: result.payload.suggestion,
|
suggestion: result.payload.suggestion,
|
||||||
|
isSearchHistory: result.payload.isSearchHistory,
|
||||||
inPrivateWindow: result.payload.inPrivateWindow,
|
inPrivateWindow: result.payload.inPrivateWindow,
|
||||||
isPrivateEngine: result.payload.isPrivateEngine,
|
isPrivateEngine: result.payload.isPrivateEngine,
|
||||||
};
|
};
|
||||||
|
|
|
@ -132,11 +132,14 @@ run-if = e10s
|
||||||
[browser_removeUnsafeProtocolsFromURLBarPaste.js]
|
[browser_removeUnsafeProtocolsFromURLBarPaste.js]
|
||||||
fail-if = (os == 'linux' && os_version == '18.04') # Bug 1600182
|
fail-if = (os == 'linux' && os_version == '18.04') # Bug 1600182
|
||||||
[browser_restoreEmptyInput.js]
|
[browser_restoreEmptyInput.js]
|
||||||
|
[browser_restyleSearches.js]
|
||||||
|
support-files =
|
||||||
|
searchSuggestionEngine.xml
|
||||||
|
searchSuggestionEngine2.xml
|
||||||
|
searchSuggestionEngine.sjs
|
||||||
[browser_resultSpan.js]
|
[browser_resultSpan.js]
|
||||||
[browser_retainedResultsOnFocus.js]
|
[browser_retainedResultsOnFocus.js]
|
||||||
[browser_revert.js]
|
[browser_revert.js]
|
||||||
[browser_search_favicon.js]
|
|
||||||
skip-if = true # Bug 1526222 - Doesn't currently work with QuantumBar
|
|
||||||
[browser_searchFunction.js]
|
[browser_searchFunction.js]
|
||||||
[browser_searchSettings.js]
|
[browser_searchSettings.js]
|
||||||
[browser_searchSingleWordNotification.js]
|
[browser_searchSingleWordNotification.js]
|
||||||
|
|
|
@ -56,6 +56,7 @@ async function testSearch(win, expectedName, expectedBaseUrl) {
|
||||||
keyword: undefined,
|
keyword: undefined,
|
||||||
query: "open a search",
|
query: "open a search",
|
||||||
suggestion: undefined,
|
suggestion: undefined,
|
||||||
|
isSearchHistory: false,
|
||||||
inPrivateWindow: undefined,
|
inPrivateWindow: undefined,
|
||||||
isPrivateEngine: undefined,
|
isPrivateEngine: undefined,
|
||||||
},
|
},
|
||||||
|
|
|
@ -107,6 +107,7 @@ const tests = [
|
||||||
searchParams: {
|
searchParams: {
|
||||||
engine: "Google",
|
engine: "Google",
|
||||||
query: "http://",
|
query: "http://",
|
||||||
|
isSearchHistory: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -118,6 +119,7 @@ const tests = [
|
||||||
searchParams: {
|
searchParams: {
|
||||||
engine: "Google",
|
engine: "Google",
|
||||||
query: "https://",
|
query: "https://",
|
||||||
|
isSearchHistory: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,357 @@
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests restyled search history results.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const RESTYLE_PREF = "browser.urlbar.restyleSearches";
|
||||||
|
const SUGGEST_URLBAR_PREF = "browser.urlbar.suggest.searches";
|
||||||
|
const PRIVATE_SEARCH_PREF = "browser.search.separatePrivateDefault.ui.enabled";
|
||||||
|
// We use the slow engine to ensure that the search history item appears in
|
||||||
|
// results before the equivalent suggestion, to better approximate real-world
|
||||||
|
// behavior.
|
||||||
|
const TEST_ENGINE_BASENAME = "searchSuggestionEngineSlow.xml";
|
||||||
|
const TEST_ENGINE_2_BASENAME = "searchSuggestionEngine2.xml";
|
||||||
|
const TEST_QUERY = "test query";
|
||||||
|
|
||||||
|
let gSearchUri;
|
||||||
|
|
||||||
|
add_task(async function setup() {
|
||||||
|
await SpecialPowers.pushPrefEnv({
|
||||||
|
set: [
|
||||||
|
[SUGGEST_URLBAR_PREF, true],
|
||||||
|
[RESTYLE_PREF, true],
|
||||||
|
[PRIVATE_SEARCH_PREF, false],
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
let engine = await SearchTestUtils.promiseNewSearchEngine(
|
||||||
|
getRootDirectory(gTestPath) + TEST_ENGINE_BASENAME
|
||||||
|
);
|
||||||
|
let oldDefaultEngine = await Services.search.getDefault();
|
||||||
|
await Services.search.setDefault(engine);
|
||||||
|
|
||||||
|
gSearchUri = (await Services.search.getDefault()).getSubmission(
|
||||||
|
`${TEST_QUERY}foo`
|
||||||
|
).uri;
|
||||||
|
|
||||||
|
await PlacesTestUtils.addVisits({
|
||||||
|
uri: gSearchUri.spec,
|
||||||
|
title: `${TEST_QUERY}foo`,
|
||||||
|
});
|
||||||
|
|
||||||
|
registerCleanupFunction(async () => {
|
||||||
|
Services.search.setDefault(oldDefaultEngine);
|
||||||
|
await PlacesUtils.history.clear();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that a search history item takes the place of and is restyled as its
|
||||||
|
* equivalent search suggestion.
|
||||||
|
*/
|
||||||
|
add_task(async function restyleSearches() {
|
||||||
|
await UrlbarTestUtils.promiseAutocompleteResultPopup({
|
||||||
|
window,
|
||||||
|
waitForFocus: SimpleTest.waitForFocus,
|
||||||
|
value: TEST_QUERY,
|
||||||
|
});
|
||||||
|
|
||||||
|
Assert.equal(UrlbarTestUtils.getResultCount(window), 3);
|
||||||
|
let result = await UrlbarTestUtils.getDetailsOfResultAt(window, 1);
|
||||||
|
Assert.equal(result.type, UrlbarUtils.RESULT_TYPE.SEARCH);
|
||||||
|
Assert.equal(result.displayed.title, `${TEST_QUERY}foo`);
|
||||||
|
Assert.ok(
|
||||||
|
result.searchParams.isSearchHistory,
|
||||||
|
"This result should be a restyled search history result."
|
||||||
|
);
|
||||||
|
Assert.equal(result.searchParams.suggestion, `${TEST_QUERY}foo`);
|
||||||
|
Assert.equal(
|
||||||
|
result.displayed.action,
|
||||||
|
UrlbarUtils.strings.formatStringFromName("searchWithEngine", [
|
||||||
|
"searchSuggestionEngineSlow.xml",
|
||||||
|
]),
|
||||||
|
"Should have the correct action text"
|
||||||
|
);
|
||||||
|
|
||||||
|
result = await UrlbarTestUtils.getDetailsOfResultAt(window, 2);
|
||||||
|
Assert.equal(result.type, UrlbarUtils.RESULT_TYPE.SEARCH);
|
||||||
|
Assert.equal(result.displayed.title, `${TEST_QUERY}bar`);
|
||||||
|
Assert.equal(result.searchParams.suggestion, `${TEST_QUERY}bar`);
|
||||||
|
Assert.ok(
|
||||||
|
!result.searchParams.isSearchHistory,
|
||||||
|
"This result should be a normal search suggestion."
|
||||||
|
);
|
||||||
|
Assert.equal(
|
||||||
|
result.displayed.action,
|
||||||
|
UrlbarUtils.strings.formatStringFromName("searchWithEngine", [
|
||||||
|
"searchSuggestionEngineSlow.xml",
|
||||||
|
]),
|
||||||
|
"Should have the correct action text"
|
||||||
|
);
|
||||||
|
|
||||||
|
await UrlbarTestUtils.promisePopupClose(window);
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that equivalent search history and search suggestions both appear when
|
||||||
|
* the restyleSearches pref is off.
|
||||||
|
*/
|
||||||
|
add_task(async function displaySearchHistoryAndSuggestions() {
|
||||||
|
await SpecialPowers.pushPrefEnv({
|
||||||
|
set: [[RESTYLE_PREF, false]],
|
||||||
|
});
|
||||||
|
|
||||||
|
await UrlbarTestUtils.promiseAutocompleteResultPopup({
|
||||||
|
window,
|
||||||
|
waitForFocus: SimpleTest.waitForFocus,
|
||||||
|
value: TEST_QUERY,
|
||||||
|
});
|
||||||
|
|
||||||
|
// We should now also have the search history result.
|
||||||
|
Assert.equal(UrlbarTestUtils.getResultCount(window), 4);
|
||||||
|
|
||||||
|
let result = await UrlbarTestUtils.getDetailsOfResultAt(window, 1);
|
||||||
|
Assert.equal(result.type, UrlbarUtils.RESULT_TYPE.SEARCH);
|
||||||
|
Assert.equal(result.displayed.title, `${TEST_QUERY}foo`);
|
||||||
|
Assert.equal(result.searchParams.suggestion, `${TEST_QUERY}foo`);
|
||||||
|
Assert.ok(
|
||||||
|
!result.searchParams.isSearchHistory,
|
||||||
|
"This result should be a normal search suggestion."
|
||||||
|
);
|
||||||
|
Assert.equal(
|
||||||
|
result.displayed.action,
|
||||||
|
UrlbarUtils.strings.formatStringFromName("searchWithEngine", [
|
||||||
|
"searchSuggestionEngineSlow.xml",
|
||||||
|
]),
|
||||||
|
"Should have the correct action text"
|
||||||
|
);
|
||||||
|
|
||||||
|
result = await UrlbarTestUtils.getDetailsOfResultAt(window, 2);
|
||||||
|
Assert.equal(result.type, UrlbarUtils.RESULT_TYPE.SEARCH);
|
||||||
|
Assert.equal(result.displayed.title, `${TEST_QUERY}bar`);
|
||||||
|
Assert.equal(result.searchParams.suggestion, `${TEST_QUERY}bar`);
|
||||||
|
Assert.ok(
|
||||||
|
!result.searchParams.isSearchHistory,
|
||||||
|
"This result should be a normal search suggestion."
|
||||||
|
);
|
||||||
|
Assert.equal(
|
||||||
|
result.displayed.action,
|
||||||
|
UrlbarUtils.strings.formatStringFromName("searchWithEngine", [
|
||||||
|
"searchSuggestionEngineSlow.xml",
|
||||||
|
]),
|
||||||
|
"Should have the correct action text"
|
||||||
|
);
|
||||||
|
|
||||||
|
result = await UrlbarTestUtils.getDetailsOfResultAt(window, 3);
|
||||||
|
Assert.equal(result.type, UrlbarUtils.RESULT_TYPE.URL);
|
||||||
|
Assert.equal(result.source, UrlbarUtils.RESULT_SOURCE.HISTORY);
|
||||||
|
Assert.equal(result.displayed.title, `${TEST_QUERY}foo`);
|
||||||
|
Assert.equal(result.url, gSearchUri.spec);
|
||||||
|
|
||||||
|
await SpecialPowers.popPrefEnv();
|
||||||
|
await UrlbarTestUtils.promisePopupClose(window);
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that search history results from non-default engines do not replace
|
||||||
|
* equivalent search suggestions from different engines.
|
||||||
|
*
|
||||||
|
* Note: The search history result from the original engine should still appear
|
||||||
|
* restyled.
|
||||||
|
*/
|
||||||
|
add_task(async function alternateEngine() {
|
||||||
|
let engine2 = await SearchTestUtils.promiseNewSearchEngine(
|
||||||
|
getRootDirectory(gTestPath) + TEST_ENGINE_2_BASENAME
|
||||||
|
);
|
||||||
|
let previousTestEngine = await Services.search.getDefault();
|
||||||
|
await Services.search.setDefault(engine2);
|
||||||
|
|
||||||
|
await UrlbarTestUtils.promiseAutocompleteResultPopup({
|
||||||
|
window,
|
||||||
|
waitForFocus: SimpleTest.waitForFocus,
|
||||||
|
value: TEST_QUERY,
|
||||||
|
});
|
||||||
|
|
||||||
|
// We should have the search history item from the original engine, restyled
|
||||||
|
// as a suggestion.
|
||||||
|
Assert.equal(UrlbarTestUtils.getResultCount(window), 4);
|
||||||
|
|
||||||
|
let result = await UrlbarTestUtils.getDetailsOfResultAt(window, 1);
|
||||||
|
Assert.equal(result.type, UrlbarUtils.RESULT_TYPE.SEARCH);
|
||||||
|
Assert.equal(result.displayed.title, `${TEST_QUERY}foo`);
|
||||||
|
Assert.equal(result.searchParams.suggestion, `${TEST_QUERY}foo`);
|
||||||
|
Assert.ok(
|
||||||
|
!result.searchParams.isSearchHistory,
|
||||||
|
"This result should be a normal search suggestion."
|
||||||
|
);
|
||||||
|
Assert.equal(
|
||||||
|
result.displayed.action,
|
||||||
|
UrlbarUtils.strings.formatStringFromName("searchWithEngine", [
|
||||||
|
"browser_searchSuggestionEngine2 searchSuggestionEngine2.xml",
|
||||||
|
]),
|
||||||
|
"Should have the correct action text"
|
||||||
|
);
|
||||||
|
|
||||||
|
result = await UrlbarTestUtils.getDetailsOfResultAt(window, 2);
|
||||||
|
Assert.equal(result.type, UrlbarUtils.RESULT_TYPE.SEARCH);
|
||||||
|
Assert.equal(result.displayed.title, `${TEST_QUERY}bar`);
|
||||||
|
Assert.equal(result.searchParams.suggestion, `${TEST_QUERY}bar`);
|
||||||
|
Assert.ok(
|
||||||
|
!result.searchParams.isSearchHistory,
|
||||||
|
"This result should be a normal search suggestion."
|
||||||
|
);
|
||||||
|
Assert.equal(
|
||||||
|
result.displayed.action,
|
||||||
|
UrlbarUtils.strings.formatStringFromName("searchWithEngine", [
|
||||||
|
"browser_searchSuggestionEngine2 searchSuggestionEngine2.xml",
|
||||||
|
]),
|
||||||
|
"Should have the correct action text"
|
||||||
|
);
|
||||||
|
|
||||||
|
result = await UrlbarTestUtils.getDetailsOfResultAt(window, 3);
|
||||||
|
Assert.equal(result.type, UrlbarUtils.RESULT_TYPE.SEARCH);
|
||||||
|
Assert.equal(result.displayed.title, `${TEST_QUERY}foo`);
|
||||||
|
Assert.ok(
|
||||||
|
result.searchParams.isSearchHistory,
|
||||||
|
"This result should be a restyled search history result."
|
||||||
|
);
|
||||||
|
Assert.equal(result.searchParams.suggestion, `${TEST_QUERY}foo`);
|
||||||
|
// Note the comparison with searchSuggestionEngineSlow.xml, not
|
||||||
|
// searchSuggestionEngine2.xml.
|
||||||
|
Assert.equal(
|
||||||
|
result.displayed.action,
|
||||||
|
UrlbarUtils.strings.formatStringFromName("searchWithEngine", [
|
||||||
|
"searchSuggestionEngineSlow.xml",
|
||||||
|
]),
|
||||||
|
"Should have the correct action text"
|
||||||
|
);
|
||||||
|
|
||||||
|
await Services.search.setDefault(previousTestEngine);
|
||||||
|
await UrlbarTestUtils.promisePopupClose(window);
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that when the user types part of a search history URL but not the query
|
||||||
|
* in that URL, we show a normal history result that is not restyled.
|
||||||
|
*/
|
||||||
|
add_task(async function onlyRestyleWhenQueriesMatch() {
|
||||||
|
await UrlbarTestUtils.promiseAutocompleteResultPopup({
|
||||||
|
window,
|
||||||
|
waitForFocus: SimpleTest.waitForFocus,
|
||||||
|
value: "mochi",
|
||||||
|
});
|
||||||
|
|
||||||
|
// We should now also have the search history result.
|
||||||
|
Assert.equal(UrlbarTestUtils.getResultCount(window), 4);
|
||||||
|
|
||||||
|
let result = await UrlbarTestUtils.getDetailsOfResultAt(window, 1);
|
||||||
|
Assert.equal(result.type, UrlbarUtils.RESULT_TYPE.SEARCH);
|
||||||
|
Assert.equal(result.displayed.title, "mochifoo");
|
||||||
|
Assert.equal(result.searchParams.suggestion, "mochifoo");
|
||||||
|
Assert.ok(
|
||||||
|
!result.searchParams.isSearchHistory,
|
||||||
|
"This result should be a normal search suggestion."
|
||||||
|
);
|
||||||
|
Assert.equal(
|
||||||
|
result.displayed.action,
|
||||||
|
UrlbarUtils.strings.formatStringFromName("searchWithEngine", [
|
||||||
|
"searchSuggestionEngineSlow.xml",
|
||||||
|
]),
|
||||||
|
"Should have the correct action text"
|
||||||
|
);
|
||||||
|
|
||||||
|
result = await UrlbarTestUtils.getDetailsOfResultAt(window, 2);
|
||||||
|
Assert.equal(result.type, UrlbarUtils.RESULT_TYPE.SEARCH);
|
||||||
|
Assert.equal(result.displayed.title, "mochibar");
|
||||||
|
Assert.equal(result.searchParams.suggestion, "mochibar");
|
||||||
|
Assert.ok(
|
||||||
|
!result.searchParams.isSearchHistory,
|
||||||
|
"This result should be a normal search suggestion."
|
||||||
|
);
|
||||||
|
Assert.equal(
|
||||||
|
result.displayed.action,
|
||||||
|
UrlbarUtils.strings.formatStringFromName("searchWithEngine", [
|
||||||
|
"searchSuggestionEngineSlow.xml",
|
||||||
|
]),
|
||||||
|
"Should have the correct action text"
|
||||||
|
);
|
||||||
|
|
||||||
|
result = await UrlbarTestUtils.getDetailsOfResultAt(window, 3);
|
||||||
|
Assert.equal(result.type, UrlbarUtils.RESULT_TYPE.URL);
|
||||||
|
Assert.equal(result.source, UrlbarUtils.RESULT_SOURCE.HISTORY);
|
||||||
|
Assert.equal(result.displayed.title, `${TEST_QUERY}foo`);
|
||||||
|
Assert.equal(result.url, gSearchUri.spec);
|
||||||
|
|
||||||
|
await UrlbarTestUtils.promisePopupClose(window);
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that search history items that do not exactly match a search suggestion
|
||||||
|
* URL still appear in results, do not replace suggestions, and are not restyled.
|
||||||
|
*
|
||||||
|
* Note: This test should run last because it adds a new history item.
|
||||||
|
*/
|
||||||
|
add_task(async function searchHistoryNotExactMatch() {
|
||||||
|
let irrelevantSearchUri = `${gSearchUri.spec}&irrelevantParameter=1`;
|
||||||
|
|
||||||
|
// This history item will be removed when the setup test runs the cleanup
|
||||||
|
// function.
|
||||||
|
await PlacesTestUtils.addVisits({
|
||||||
|
uri: irrelevantSearchUri,
|
||||||
|
title: `${TEST_QUERY}foo irrelevant`,
|
||||||
|
});
|
||||||
|
|
||||||
|
await UrlbarTestUtils.promiseAutocompleteResultPopup({
|
||||||
|
window,
|
||||||
|
waitForFocus: SimpleTest.waitForFocus,
|
||||||
|
value: TEST_QUERY,
|
||||||
|
});
|
||||||
|
|
||||||
|
// We should have the irrelevant history result, but the history result that
|
||||||
|
// is an exact match should have replaced the equivalent suggestion.
|
||||||
|
Assert.equal(UrlbarTestUtils.getResultCount(window), 4);
|
||||||
|
|
||||||
|
let result = await UrlbarTestUtils.getDetailsOfResultAt(window, 1);
|
||||||
|
Assert.equal(result.type, UrlbarUtils.RESULT_TYPE.SEARCH);
|
||||||
|
Assert.equal(result.displayed.title, `${TEST_QUERY}foo`);
|
||||||
|
Assert.ok(
|
||||||
|
result.searchParams.isSearchHistory,
|
||||||
|
"This result should be a restyled search history result."
|
||||||
|
);
|
||||||
|
Assert.equal(result.searchParams.suggestion, `${TEST_QUERY}foo`);
|
||||||
|
Assert.equal(
|
||||||
|
result.displayed.action,
|
||||||
|
UrlbarUtils.strings.formatStringFromName("searchWithEngine", [
|
||||||
|
"searchSuggestionEngineSlow.xml",
|
||||||
|
]),
|
||||||
|
"Should have the correct action text"
|
||||||
|
);
|
||||||
|
|
||||||
|
result = await UrlbarTestUtils.getDetailsOfResultAt(window, 2);
|
||||||
|
Assert.equal(result.type, UrlbarUtils.RESULT_TYPE.SEARCH);
|
||||||
|
Assert.equal(result.displayed.title, `${TEST_QUERY}bar`);
|
||||||
|
Assert.equal(result.searchParams.suggestion, `${TEST_QUERY}bar`);
|
||||||
|
Assert.ok(
|
||||||
|
!result.searchParams.isSearchHistory,
|
||||||
|
"This result should be a normal search suggestion."
|
||||||
|
);
|
||||||
|
Assert.equal(
|
||||||
|
result.displayed.action,
|
||||||
|
UrlbarUtils.strings.formatStringFromName("searchWithEngine", [
|
||||||
|
"searchSuggestionEngineSlow.xml",
|
||||||
|
]),
|
||||||
|
"Should have the correct action text"
|
||||||
|
);
|
||||||
|
|
||||||
|
result = await UrlbarTestUtils.getDetailsOfResultAt(window, 3);
|
||||||
|
Assert.equal(result.type, UrlbarUtils.RESULT_TYPE.URL);
|
||||||
|
Assert.equal(result.source, UrlbarUtils.RESULT_SOURCE.HISTORY);
|
||||||
|
Assert.equal(result.displayed.title, `${TEST_QUERY}foo irrelevant`);
|
||||||
|
Assert.equal(result.url, irrelevantSearchUri);
|
||||||
|
|
||||||
|
await UrlbarTestUtils.promisePopupClose(window);
|
||||||
|
});
|
|
@ -1,67 +0,0 @@
|
||||||
/* Any copyright is dedicated to the Public Domain.
|
|
||||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
|
||||||
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests that a restyled search result is correctly displayed.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var gOriginalEngine;
|
|
||||||
var gEngine;
|
|
||||||
var gRestyleSearchesPref = "browser.urlbar.restyleSearches";
|
|
||||||
|
|
||||||
registerCleanupFunction(async () => {
|
|
||||||
Services.prefs.clearUserPref(gRestyleSearchesPref);
|
|
||||||
await Services.search.setDefault(gOriginalEngine);
|
|
||||||
await Services.search.removeEngine(gEngine);
|
|
||||||
return PlacesUtils.history.clear();
|
|
||||||
});
|
|
||||||
|
|
||||||
add_task(async function() {
|
|
||||||
Services.prefs.setBoolPref(gRestyleSearchesPref, true);
|
|
||||||
|
|
||||||
// This test is sensitive to the mouse position hovering awesome
|
|
||||||
// bar elements, so make sure it doesnt
|
|
||||||
await EventUtils.synthesizeNativeMouseMove(document.documentElement, 0, 0);
|
|
||||||
});
|
|
||||||
|
|
||||||
add_task(async function() {
|
|
||||||
await Services.search.addEngineWithDetails("SearchEngine", {
|
|
||||||
method: "GET",
|
|
||||||
template: "http://s.example.com/search",
|
|
||||||
});
|
|
||||||
gEngine = Services.search.getEngineByName("SearchEngine");
|
|
||||||
gEngine.addParam("q", "{searchTerms}", null);
|
|
||||||
gOriginalEngine = await Services.search.getDefault();
|
|
||||||
await Services.search.setDefault(gEngine);
|
|
||||||
|
|
||||||
await PlacesTestUtils.addVisits({
|
|
||||||
uri: "http://s.example.com/search?q=foobar&client=1",
|
|
||||||
title: "Foo - SearchEngine Search",
|
|
||||||
});
|
|
||||||
|
|
||||||
await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:mozilla");
|
|
||||||
|
|
||||||
// The first autocomplete result has the action searchengine, while
|
|
||||||
// the second result is the "search favicon" element.
|
|
||||||
await UrlbarTestUtils.promiseAutocompleteResultPopup({
|
|
||||||
window,
|
|
||||||
waitForFocus: SimpleTest.waitForFocus,
|
|
||||||
value: "foo",
|
|
||||||
});
|
|
||||||
let result = await UrlbarTestUtils.getDetailsOfResultAt(window, 1);
|
|
||||||
|
|
||||||
Assert.equal(result.type, UrlbarUtils.RESULT_TYPE.SEARCH);
|
|
||||||
Assert.equal(result.displayed.title, "foobar");
|
|
||||||
|
|
||||||
Assert.equal(
|
|
||||||
result.displayed.action,
|
|
||||||
UrlbarUtils.strings.formatStringFromName("searchWithEngine", [
|
|
||||||
"SearchEngine",
|
|
||||||
]),
|
|
||||||
"Should have the correct action text"
|
|
||||||
);
|
|
||||||
|
|
||||||
gBrowser.removeCurrentTab();
|
|
||||||
});
|
|
|
@ -278,6 +278,7 @@ function makeSearchResult(
|
||||||
typeof query != "undefined" ? query : queryContext.searchString.trim(),
|
typeof query != "undefined" ? query : queryContext.searchString.trim(),
|
||||||
UrlbarUtils.HIGHLIGHT.TYPED,
|
UrlbarUtils.HIGHLIGHT.TYPED,
|
||||||
],
|
],
|
||||||
|
isSearchHistory: false,
|
||||||
icon: [engineIconUri ? engineIconUri : ""],
|
icon: [engineIconUri ? engineIconUri : ""],
|
||||||
keywordOffer,
|
keywordOffer,
|
||||||
})
|
})
|
||||||
|
|
|
@ -299,8 +299,9 @@ var PlacesSearchAutocompleteProvider = Object.freeze({
|
||||||
* @return An object with the following properties, or null if the URL does
|
* @return An object with the following properties, or null if the URL does
|
||||||
* not represent a search result:
|
* not represent a search result:
|
||||||
* {
|
* {
|
||||||
* engineName: The display name of the search engine.
|
* engine: The search engine, as an nsISearchEngine.
|
||||||
* terms: The originally sought terms extracted from the URI.
|
* terms: The originally sought terms extracted from the URI.
|
||||||
|
* termsParameterName: The engine's search-string parameter.
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* @remarks The asynchronous ensureInitialized function must be called before
|
* @remarks The asynchronous ensureInitialized function must be called before
|
||||||
|
@ -317,8 +318,9 @@ var PlacesSearchAutocompleteProvider = Object.freeze({
|
||||||
let parseUrlResult = Services.search.parseSubmissionURL(url);
|
let parseUrlResult = Services.search.parseSubmissionURL(url);
|
||||||
return (
|
return (
|
||||||
parseUrlResult.engine && {
|
parseUrlResult.engine && {
|
||||||
engineName: parseUrlResult.engine.name,
|
engine: parseUrlResult.engine,
|
||||||
terms: parseUrlResult.terms,
|
terms: parseUrlResult.terms,
|
||||||
|
termsParameterName: parseUrlResult.termsParameterName,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
|
@ -1913,10 +1913,8 @@ Search.prototype = {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do not apply the special style if the user is doing a search from the
|
// Here we check that the user typed all or part of the search string in the
|
||||||
// location bar but the entered terms match an irrelevant portion of the
|
// search history result.
|
||||||
// URL. For example, "https://www.google.com/search?q=terms&client=firefox"
|
|
||||||
// when searching for "Firefox".
|
|
||||||
let terms = parseResult.terms.toLowerCase();
|
let terms = parseResult.terms.toLowerCase();
|
||||||
if (
|
if (
|
||||||
this._searchTokens.length &&
|
this._searchTokens.length &&
|
||||||
|
@ -1925,15 +1923,46 @@ Search.prototype = {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The URL for the search suggestion formed by the user's typed query.
|
||||||
|
let [typedSuggestionUrl] = UrlbarUtils.getSearchQueryUrl(
|
||||||
|
parseResult.engine,
|
||||||
|
this._searchTokens.map(t => t.value).join(" ")
|
||||||
|
);
|
||||||
|
|
||||||
|
let historyParams = new URL(match.value).searchParams;
|
||||||
|
let typedParams = new URL(typedSuggestionUrl).searchParams;
|
||||||
|
|
||||||
|
// Checking the two URLs have the same query parameters with the same
|
||||||
|
// values, or a subset value in the case of the query parameter.
|
||||||
|
// Parameter order doesn't matter.
|
||||||
|
if (
|
||||||
|
Array.from(historyParams).length != Array.from(typedParams).length ||
|
||||||
|
!Array.from(historyParams.entries()).every(
|
||||||
|
([key, value]) =>
|
||||||
|
// We want to match all non-search-string GET parameters exactly, to avoid
|
||||||
|
// restyling non-first pages of search results, or image results as web
|
||||||
|
// results.
|
||||||
|
// We let termsParameterName through because we already checked that the
|
||||||
|
// typed query is a subset of the search history query above with
|
||||||
|
// this._searchTokens.every(...).
|
||||||
|
key == parseResult.termsParameterName ||
|
||||||
|
value === typedParams.get(key)
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Turn the match into a searchengine action with a favicon.
|
// Turn the match into a searchengine action with a favicon.
|
||||||
match.value = makeActionUrl("searchengine", {
|
match.value = makeActionUrl("searchengine", {
|
||||||
engineName: parseResult.engineName,
|
engineName: parseResult.engine.name,
|
||||||
input: parseResult.terms,
|
input: parseResult.terms,
|
||||||
|
searchSuggestion: parseResult.terms,
|
||||||
searchQuery: parseResult.terms,
|
searchQuery: parseResult.terms,
|
||||||
|
isSearchHistory: true,
|
||||||
});
|
});
|
||||||
match.comment = parseResult.engineName;
|
match.comment = parseResult.engine.name;
|
||||||
match.icon = match.icon || match.iconUrl;
|
match.icon = match.icon || match.iconUrl;
|
||||||
match.style = "action searchengine favicon";
|
match.style = "action searchengine favicon suggestion";
|
||||||
},
|
},
|
||||||
|
|
||||||
_addMatch(match) {
|
_addMatch(match) {
|
||||||
|
|
|
@ -445,6 +445,9 @@ function makeSearchMatch(input, extra = {}) {
|
||||||
params.searchSuggestion = extra.searchSuggestion;
|
params.searchSuggestion = extra.searchSuggestion;
|
||||||
style.push("suggestion");
|
style.push("suggestion");
|
||||||
}
|
}
|
||||||
|
if ("isSearchHistory" in extra) {
|
||||||
|
params.isSearchHistory = extra.isSearchHistory;
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
uri: makeActionURI("searchengine", params),
|
uri: makeActionURI("searchengine", params),
|
||||||
title: params.engineName,
|
title: params.engineName,
|
||||||
|
|
|
@ -163,7 +163,7 @@ add_task(async function test_parseSubmissionURL_basic() {
|
||||||
let result = PlacesSearchAutocompleteProvider.parseSubmissionURL(
|
let result = PlacesSearchAutocompleteProvider.parseSubmissionURL(
|
||||||
submissionURL
|
submissionURL
|
||||||
);
|
);
|
||||||
Assert.equal(result.engineName, engine.name);
|
Assert.equal(result.engine.name, engine.name);
|
||||||
Assert.equal(result.terms, "terms");
|
Assert.equal(result.terms, "terms");
|
||||||
|
|
||||||
result = PlacesSearchAutocompleteProvider.parseSubmissionURL(
|
result = PlacesSearchAutocompleteProvider.parseSubmissionURL(
|
||||||
|
|
|
@ -11,42 +11,50 @@ add_task(async function test_searchEngine() {
|
||||||
engine.addParam("q", "{searchTerms}", null);
|
engine.addParam("q", "{searchTerms}", null);
|
||||||
registerCleanupFunction(async () => Services.search.removeEngine(engine));
|
registerCleanupFunction(async () => Services.search.removeEngine(engine));
|
||||||
|
|
||||||
let uri1 = NetUtil.newURI("http://s.example.com/search?q=Terms&client=1");
|
let uri = NetUtil.newURI("http://s.example.com/search?q=Terms");
|
||||||
let uri2 = NetUtil.newURI("http://s.example.com/search?q=Terms&client=2");
|
|
||||||
await PlacesTestUtils.addVisits({
|
await PlacesTestUtils.addVisits({
|
||||||
uri: uri1,
|
uri,
|
||||||
title: "Terms - SearchEngine Search",
|
|
||||||
});
|
|
||||||
await PlacesTestUtils.addBookmarkWithDetails({
|
|
||||||
uri: uri2,
|
|
||||||
title: "Terms - SearchEngine Search",
|
title: "Terms - SearchEngine Search",
|
||||||
});
|
});
|
||||||
|
|
||||||
info("Past search terms should be styled, unless bookmarked");
|
info("Past search terms should be styled.");
|
||||||
Services.prefs.setBoolPref("browser.urlbar.restyleSearches", true);
|
Services.prefs.setBoolPref("browser.urlbar.restyleSearches", true);
|
||||||
await check_autocomplete({
|
await check_autocomplete({
|
||||||
search: "term",
|
search: "term",
|
||||||
matches: [
|
matches: [
|
||||||
makeSearchMatch("Terms", {
|
makeSearchMatch("Terms", {
|
||||||
engineName: "SearchEngine",
|
engineName: "SearchEngine",
|
||||||
|
searchSuggestion: "Terms",
|
||||||
|
isSearchHistory: true,
|
||||||
style: ["favicon"],
|
style: ["favicon"],
|
||||||
}),
|
}),
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
info("Bookmarked past searches should not be restyled");
|
||||||
|
await PlacesTestUtils.addBookmarkWithDetails({
|
||||||
|
uri,
|
||||||
|
title: "Terms - SearchEngine Search",
|
||||||
|
});
|
||||||
|
|
||||||
|
await check_autocomplete({
|
||||||
|
search: "term",
|
||||||
|
matches: [
|
||||||
{
|
{
|
||||||
uri: uri2,
|
uri,
|
||||||
title: "Terms - SearchEngine Search",
|
title: "Terms - SearchEngine Search",
|
||||||
style: ["bookmark"],
|
style: ["bookmark"],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await PlacesUtils.bookmarks.eraseEverything();
|
||||||
|
|
||||||
info("Past search terms should not be styled if restyling is disabled");
|
info("Past search terms should not be styled if restyling is disabled");
|
||||||
Services.prefs.setBoolPref("browser.urlbar.restyleSearches", false);
|
Services.prefs.setBoolPref("browser.urlbar.restyleSearches", false);
|
||||||
await check_autocomplete({
|
await check_autocomplete({
|
||||||
search: "term",
|
search: "term",
|
||||||
matches: [
|
matches: [{ uri, title: "Terms - SearchEngine Search" }],
|
||||||
{ uri: uri1, title: "Terms - SearchEngine Search" },
|
|
||||||
{ uri: uri2, title: "Terms - SearchEngine Search", style: ["bookmark"] },
|
|
||||||
],
|
|
||||||
});
|
});
|
||||||
|
|
||||||
await cleanup();
|
await cleanup();
|
||||||
|
|
|
@ -481,9 +481,16 @@ var gInitialized = false;
|
||||||
var gReinitializing = false;
|
var gReinitializing = false;
|
||||||
|
|
||||||
// nsISearchParseSubmissionResult
|
// nsISearchParseSubmissionResult
|
||||||
function ParseSubmissionResult(engine, terms, termsOffset, termsLength) {
|
function ParseSubmissionResult(
|
||||||
|
engine,
|
||||||
|
terms,
|
||||||
|
termsParameterName,
|
||||||
|
termsOffset,
|
||||||
|
termsLength
|
||||||
|
) {
|
||||||
this._engine = engine;
|
this._engine = engine;
|
||||||
this._terms = terms;
|
this._terms = terms;
|
||||||
|
this._termsParameterName = termsParameterName;
|
||||||
this._termsOffset = termsOffset;
|
this._termsOffset = termsOffset;
|
||||||
this._termsLength = termsLength;
|
this._termsLength = termsLength;
|
||||||
}
|
}
|
||||||
|
@ -494,6 +501,9 @@ ParseSubmissionResult.prototype = {
|
||||||
get terms() {
|
get terms() {
|
||||||
return this._terms;
|
return this._terms;
|
||||||
},
|
},
|
||||||
|
get termsParameterName() {
|
||||||
|
return this._termsParameterName;
|
||||||
|
},
|
||||||
get termsOffset() {
|
get termsOffset() {
|
||||||
return this._termsOffset;
|
return this._termsOffset;
|
||||||
},
|
},
|
||||||
|
@ -504,7 +514,7 @@ ParseSubmissionResult.prototype = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const gEmptyParseSubmissionResult = Object.freeze(
|
const gEmptyParseSubmissionResult = Object.freeze(
|
||||||
new ParseSubmissionResult(null, "", -1, 0)
|
new ParseSubmissionResult(null, "", "", -1, 0)
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -3577,7 +3587,14 @@ SearchService.prototype = {
|
||||||
return gEmptyParseSubmissionResult;
|
return gEmptyParseSubmissionResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ParseSubmissionResult(mapEntry.engine, terms, offset, length);
|
let submission = new ParseSubmissionResult(
|
||||||
|
mapEntry.engine,
|
||||||
|
terms,
|
||||||
|
mapEntry.termsParameterName,
|
||||||
|
offset,
|
||||||
|
length
|
||||||
|
);
|
||||||
|
return submission;
|
||||||
},
|
},
|
||||||
|
|
||||||
// nsIObserver
|
// nsIObserver
|
||||||
|
|
|
@ -197,6 +197,11 @@ interface nsISearchParseSubmissionResult : nsISupports
|
||||||
*/
|
*/
|
||||||
readonly attribute AString terms;
|
readonly attribute AString terms;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the query parameter used by `engine` for queries. E.g. "q".
|
||||||
|
*/
|
||||||
|
readonly attribute AString termsParameterName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The offset of the string |terms| in the URL passed in to
|
* The offset of the string |terms| in the URL passed in to
|
||||||
* nsISearchEngine::parseSubmissionURL, or -1 if the URL does not represent
|
* nsISearchEngine::parseSubmissionURL, or -1 if the URL does not represent
|
||||||
|
|
Загрузка…
Ссылка в новой задаче