зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1176107 - Search suggestions in awesomebar: update input and perform search with selected suggestion. r=mak
This commit is contained in:
Родитель
bd3d49eb70
Коммит
fd34e282bf
|
@ -330,7 +330,9 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|||
url = action.params.url;
|
||||
} else if (action.type == "searchengine") {
|
||||
let engine = Services.search.getEngineByName(action.params.engineName);
|
||||
let submission = engine.getSubmission(action.params.searchQuery);
|
||||
let query = action.params.searchSuggestion ||
|
||||
action.params.searchQuery;
|
||||
let submission = engine.getSubmission(query);
|
||||
|
||||
url = submission.uri.spec;
|
||||
postData = submission.postData;
|
||||
|
@ -790,12 +792,6 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|||
|
||||
try {
|
||||
action.params = JSON.parse(params);
|
||||
if (action.params.input) {
|
||||
action.params.input = decodeURIComponent(action.params.input);
|
||||
}
|
||||
if (action.params.searchQuery) {
|
||||
action.params.searchQuery = decodeURIComponent(action.params.searchQuery);
|
||||
}
|
||||
} catch (e) {
|
||||
// If this failed, we assume that params is not a JSON object, and
|
||||
// is instead just a flat string. This will happen when
|
||||
|
@ -804,6 +800,17 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|||
action.params = {
|
||||
url: params,
|
||||
}
|
||||
return action;
|
||||
}
|
||||
|
||||
for (let key of [
|
||||
"input",
|
||||
"searchQuery",
|
||||
"searchSuggestion",
|
||||
]) {
|
||||
if (action.params[key]) {
|
||||
action.params[key] = decodeURIComponent(action.params[key]);
|
||||
}
|
||||
}
|
||||
|
||||
return action;
|
||||
|
@ -1577,7 +1584,9 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|||
}
|
||||
case "searchengine": {
|
||||
let engine = Services.search.getEngineByName(action.params.engineName);
|
||||
let submission = engine.getSubmission(action.params.searchQuery);
|
||||
let query = action.params.searchSuggestion ||
|
||||
action.params.searchQuery;
|
||||
let submission = engine.getSubmission(query);
|
||||
url = submission.uri.spec;
|
||||
options.postData = submission.postData;
|
||||
break;
|
||||
|
|
|
@ -1038,7 +1038,7 @@ Search.prototype = {
|
|||
_addSearchEngineMatch(match, query, suggestion) {
|
||||
let actionURLParams = {
|
||||
engineName: match.engineName,
|
||||
input: this._originalSearchString,
|
||||
input: suggestion || this._originalSearchString,
|
||||
searchQuery: query,
|
||||
};
|
||||
if (suggestion)
|
||||
|
@ -1190,8 +1190,9 @@ Search.prototype = {
|
|||
if (this._searchSuggestionController) {
|
||||
let [match, suggestion] = this._searchSuggestionController.consume();
|
||||
if (suggestion) {
|
||||
this._addSearchEngineMatch(match, this._originalSearchString,
|
||||
suggestion);
|
||||
// Don't include the restrict token, if present.
|
||||
let searchString = this._searchTokens.join(" ");
|
||||
this._addSearchEngineMatch(match, searchString, suggestion);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,12 +5,21 @@ const SERVER_PORT = 9000;
|
|||
const SUGGEST_PREF = "browser.urlbar.suggest.searches";
|
||||
const SUGGEST_RESTRICT_TOKEN = "$";
|
||||
|
||||
// Set this to some other function to change how the server converts search
|
||||
// strings into suggestions.
|
||||
let suggestionsFromSearchString = searchStr => {
|
||||
let suffixes = ["foo", "bar"];
|
||||
return suffixes.map(s => searchStr + " " + s);
|
||||
};
|
||||
let suggestionsFn;
|
||||
let previousSuggestionsFn;
|
||||
|
||||
function setSuggestionsFn(fn) {
|
||||
previousSuggestionsFn = suggestionsFn;
|
||||
suggestionsFn = fn;
|
||||
}
|
||||
|
||||
function* cleanUpSuggestions() {
|
||||
yield cleanup();
|
||||
if (previousSuggestionsFn) {
|
||||
suggestionsFn = previousSuggestionsFn;
|
||||
previousSuggestionsFn = null;
|
||||
}
|
||||
}
|
||||
|
||||
add_task(function* setUp() {
|
||||
// Set up a server that provides some suggestions by appending strings onto
|
||||
|
@ -20,19 +29,21 @@ add_task(function* setUp() {
|
|||
// URL query params are x-www-form-urlencoded, which converts spaces into
|
||||
// plus signs, so un-convert any plus signs back to spaces.
|
||||
let searchStr = decodeURIComponent(req.queryString.replace(/\+/g, " "));
|
||||
let suggestions = suggestionsFromSearchString(searchStr);
|
||||
let suggestions = suggestionsFn(searchStr);
|
||||
let data = [searchStr, suggestions];
|
||||
resp.setHeader("Content-Type", "application/json", false);
|
||||
resp.write(JSON.stringify(data));
|
||||
});
|
||||
setSuggestionsFn(searchStr => {
|
||||
let suffixes = ["foo", "bar"];
|
||||
return suffixes.map(s => searchStr + " " + s);
|
||||
});
|
||||
|
||||
// Install the test engine.
|
||||
let oldCurrentEngine = Services.search.currentEngine;
|
||||
do_register_cleanup(() => Services.search.currentEngine = oldCurrentEngine);
|
||||
let engine = yield addTestEngine(ENGINE_NAME, server);
|
||||
Services.search.currentEngine = engine;
|
||||
|
||||
yield cleanup();
|
||||
});
|
||||
|
||||
add_task(function* disabled() {
|
||||
|
@ -41,20 +52,19 @@ add_task(function* disabled() {
|
|||
search: "hello",
|
||||
matches: [],
|
||||
});
|
||||
yield cleanup();
|
||||
yield cleanUpSuggestions();
|
||||
});
|
||||
|
||||
add_task(function* singleWordQuery() {
|
||||
Services.prefs.setBoolPref(SUGGEST_PREF, true);
|
||||
|
||||
let searchStr = "hello";
|
||||
yield check_autocomplete({
|
||||
search: searchStr,
|
||||
search: "hello",
|
||||
matches: [{
|
||||
uri: makeActionURI(("searchengine"), {
|
||||
engineName: ENGINE_NAME,
|
||||
input: searchStr,
|
||||
searchQuery: searchStr,
|
||||
input: "hello foo",
|
||||
searchQuery: "hello",
|
||||
searchSuggestion: "hello foo",
|
||||
}),
|
||||
title: ENGINE_NAME,
|
||||
|
@ -63,8 +73,8 @@ add_task(function* singleWordQuery() {
|
|||
}, {
|
||||
uri: makeActionURI(("searchengine"), {
|
||||
engineName: ENGINE_NAME,
|
||||
input: searchStr,
|
||||
searchQuery: searchStr,
|
||||
input: "hello bar",
|
||||
searchQuery: "hello",
|
||||
searchSuggestion: "hello bar",
|
||||
}),
|
||||
title: ENGINE_NAME,
|
||||
|
@ -73,20 +83,19 @@ add_task(function* singleWordQuery() {
|
|||
}],
|
||||
});
|
||||
|
||||
yield cleanup();
|
||||
yield cleanUpSuggestions();
|
||||
});
|
||||
|
||||
add_task(function* multiWordQuery() {
|
||||
Services.prefs.setBoolPref(SUGGEST_PREF, true);
|
||||
|
||||
let searchStr = "hello world";
|
||||
yield check_autocomplete({
|
||||
search: searchStr,
|
||||
search: "hello world",
|
||||
matches: [{
|
||||
uri: makeActionURI(("searchengine"), {
|
||||
engineName: ENGINE_NAME,
|
||||
input: searchStr,
|
||||
searchQuery: searchStr,
|
||||
input: "hello world foo",
|
||||
searchQuery: "hello world",
|
||||
searchSuggestion: "hello world foo",
|
||||
}),
|
||||
title: ENGINE_NAME,
|
||||
|
@ -95,8 +104,8 @@ add_task(function* multiWordQuery() {
|
|||
}, {
|
||||
uri: makeActionURI(("searchengine"), {
|
||||
engineName: ENGINE_NAME,
|
||||
input: searchStr,
|
||||
searchQuery: searchStr,
|
||||
input: "hello world bar",
|
||||
searchQuery: "hello world",
|
||||
searchSuggestion: "hello world bar",
|
||||
}),
|
||||
title: ENGINE_NAME,
|
||||
|
@ -105,26 +114,24 @@ add_task(function* multiWordQuery() {
|
|||
}],
|
||||
});
|
||||
|
||||
yield cleanup();
|
||||
yield cleanUpSuggestions();
|
||||
});
|
||||
|
||||
add_task(function* suffixMatch() {
|
||||
Services.prefs.setBoolPref(SUGGEST_PREF, true);
|
||||
|
||||
let oldFn = suggestionsFromSearchString;
|
||||
suggestionsFromSearchString = searchStr => {
|
||||
setSuggestionsFn(searchStr => {
|
||||
let prefixes = ["baz", "quux"];
|
||||
return prefixes.map(p => p + " " + searchStr);
|
||||
};
|
||||
});
|
||||
|
||||
let searchStr = "hello";
|
||||
yield check_autocomplete({
|
||||
search: searchStr,
|
||||
search: "hello",
|
||||
matches: [{
|
||||
uri: makeActionURI(("searchengine"), {
|
||||
engineName: ENGINE_NAME,
|
||||
input: searchStr,
|
||||
searchQuery: searchStr,
|
||||
input: "baz hello",
|
||||
searchQuery: "hello",
|
||||
searchSuggestion: "baz hello",
|
||||
}),
|
||||
title: ENGINE_NAME,
|
||||
|
@ -133,8 +140,8 @@ add_task(function* suffixMatch() {
|
|||
}, {
|
||||
uri: makeActionURI(("searchengine"), {
|
||||
engineName: ENGINE_NAME,
|
||||
input: searchStr,
|
||||
searchQuery: searchStr,
|
||||
input: "quux hello",
|
||||
searchQuery: "hello",
|
||||
searchSuggestion: "quux hello",
|
||||
}),
|
||||
title: ENGINE_NAME,
|
||||
|
@ -143,8 +150,42 @@ add_task(function* suffixMatch() {
|
|||
}],
|
||||
});
|
||||
|
||||
suggestionsFromSearchString = oldFn;
|
||||
yield cleanup();
|
||||
yield cleanUpSuggestions();
|
||||
});
|
||||
|
||||
add_task(function* queryIsNotASubstring() {
|
||||
Services.prefs.setBoolPref(SUGGEST_PREF, true);
|
||||
|
||||
setSuggestionsFn(searchStr => {
|
||||
return ["aaa", "bbb"];
|
||||
});
|
||||
|
||||
yield check_autocomplete({
|
||||
search: "hello",
|
||||
matches: [{
|
||||
uri: makeActionURI(("searchengine"), {
|
||||
engineName: ENGINE_NAME,
|
||||
input: "aaa",
|
||||
searchQuery: "hello",
|
||||
searchSuggestion: "aaa",
|
||||
}),
|
||||
title: ENGINE_NAME,
|
||||
style: ["action", "searchengine"],
|
||||
icon: "",
|
||||
}, {
|
||||
uri: makeActionURI(("searchengine"), {
|
||||
engineName: ENGINE_NAME,
|
||||
input: "bbb",
|
||||
searchQuery: "hello",
|
||||
searchSuggestion: "bbb",
|
||||
}),
|
||||
title: ENGINE_NAME,
|
||||
style: ["action", "searchengine"],
|
||||
icon: "",
|
||||
}],
|
||||
});
|
||||
|
||||
yield cleanUpSuggestions();
|
||||
});
|
||||
|
||||
add_task(function* restrictToken() {
|
||||
|
@ -171,9 +212,8 @@ add_task(function* restrictToken() {
|
|||
|
||||
// Do an unrestricted search to make sure everything appears in it, including
|
||||
// the visit and bookmark.
|
||||
let searchStr = "hello";
|
||||
yield check_autocomplete({
|
||||
search: searchStr,
|
||||
search: "hello",
|
||||
matches: [
|
||||
{
|
||||
uri: NetUtil.newURI("http://example.com/hello-visit"),
|
||||
|
@ -187,8 +227,8 @@ add_task(function* restrictToken() {
|
|||
{
|
||||
uri: makeActionURI(("searchengine"), {
|
||||
engineName: ENGINE_NAME,
|
||||
input: searchStr,
|
||||
searchQuery: searchStr,
|
||||
input: "hello foo",
|
||||
searchQuery: "hello",
|
||||
searchSuggestion: "hello foo",
|
||||
}),
|
||||
title: ENGINE_NAME,
|
||||
|
@ -198,8 +238,8 @@ add_task(function* restrictToken() {
|
|||
{
|
||||
uri: makeActionURI(("searchengine"), {
|
||||
engineName: ENGINE_NAME,
|
||||
input: searchStr,
|
||||
searchQuery: searchStr,
|
||||
input: "hello bar",
|
||||
searchQuery: "hello",
|
||||
searchSuggestion: "hello bar",
|
||||
}),
|
||||
title: ENGINE_NAME,
|
||||
|
@ -210,15 +250,14 @@ add_task(function* restrictToken() {
|
|||
});
|
||||
|
||||
// Now do a restricted search to make sure only suggestions appear.
|
||||
searchStr = SUGGEST_RESTRICT_TOKEN + " hello";
|
||||
yield check_autocomplete({
|
||||
search: searchStr,
|
||||
search: SUGGEST_RESTRICT_TOKEN + " hello",
|
||||
matches: [
|
||||
{
|
||||
uri: makeActionURI(("searchengine"), {
|
||||
engineName: ENGINE_NAME,
|
||||
input: searchStr,
|
||||
searchQuery: searchStr,
|
||||
input: "hello foo",
|
||||
searchQuery: "hello",
|
||||
searchSuggestion: "hello foo",
|
||||
}),
|
||||
title: ENGINE_NAME,
|
||||
|
@ -228,8 +267,8 @@ add_task(function* restrictToken() {
|
|||
{
|
||||
uri: makeActionURI(("searchengine"), {
|
||||
engineName: ENGINE_NAME,
|
||||
input: searchStr,
|
||||
searchQuery: searchStr,
|
||||
input: "hello bar",
|
||||
searchQuery: "hello",
|
||||
searchSuggestion: "hello bar",
|
||||
}),
|
||||
title: ENGINE_NAME,
|
||||
|
@ -239,5 +278,5 @@ add_task(function* restrictToken() {
|
|||
],
|
||||
});
|
||||
|
||||
yield cleanup();
|
||||
yield cleanUpSuggestions();
|
||||
});
|
||||
|
|
|
@ -1651,14 +1651,36 @@ extends="chrome://global/content/bindings/popup.xml#popup">
|
|||
let engineStr = "- " +
|
||||
this._stringBundle.formatStringFromName("searchWithEngine",
|
||||
[engineName], 1);
|
||||
let suggestedPart = "";
|
||||
|
||||
// Make the title by generating an array of pairs and its
|
||||
// corresponding interpolation string (e.g., "%1$S") to pass to
|
||||
// _generateEmphasisPairs.
|
||||
let pairs;
|
||||
if (searchSuggestion) {
|
||||
suggestedPart = searchSuggestion.substr(searchQuery.length);
|
||||
// Check if the search query appears in the suggestion. It may
|
||||
// not. If it does, then emphasize the query in the suggestion
|
||||
// and otherwise just include the suggestion without emphasis.
|
||||
let idx = searchSuggestion.indexOf(searchQuery);
|
||||
if (idx >= 0) {
|
||||
pairs = [
|
||||
[searchSuggestion.substring(0, idx), ""],
|
||||
[searchQuery, "match"],
|
||||
[searchSuggestion.substring(idx + searchQuery.length), ""],
|
||||
];
|
||||
} else {
|
||||
pairs = [
|
||||
[searchSuggestion, ""],
|
||||
];
|
||||
}
|
||||
} else {
|
||||
pairs = [
|
||||
[searchQuery, ""],
|
||||
];
|
||||
}
|
||||
title = this._generateEmphasisPairs(`%1$S${suggestedPart} %2$S`, [
|
||||
[searchQuery, "match"],
|
||||
[engineStr, "selected"],
|
||||
]);
|
||||
pairs.push([engineStr, "selected"]);
|
||||
let interpStr = pairs.map((pair, i) => `%${i + 1}$S`).join("");
|
||||
title = this._generateEmphasisPairs(interpStr, pairs);
|
||||
|
||||
// If this is a default search match, we remove the image so we
|
||||
// can style it ourselves with a generic search icon.
|
||||
// We don't do this when matching an aliased search engine,
|
||||
|
|
Загрузка…
Ссылка в новой задаче