Bug 1067896 - Add autocomplete result type for searching via alias of a search engine. r=mak

--HG--
extra : transplant_source : %16%CB%E8%D5%3F%3D%B6%2C%90%1F%0F4%0B%1C%ED%DFvC%F1%28
This commit is contained in:
Blair McBride 2014-09-26 15:32:07 +12:00
Родитель d31c4e8e2f
Коммит 62fda02841
7 изменённых файлов: 156 добавлений и 13 удалений

Просмотреть файл

@ -105,6 +105,8 @@ skip-if = e10s # Bug ?????? - no about:home support yet
skip-if = os == "linux" # Bug 1073339 - Investigate autocomplete test unreliability on Linux
[browser_action_searchengine.js]
skip-if = os == "linux" # Bug 1073339 - Investigate autocomplete test unreliability on Linux
[browser_action_searchengine_alias.js]
skip-if = os == "linux" # Bug 1073339 - Investigate autocomplete test unreliability on Linux
[browser_addKeywordSearch.js]
skip-if = e10s
[browser_alltabslistener.js]

Просмотреть файл

@ -0,0 +1,42 @@
/**
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
**/
let gOriginalEngine;
add_task(function* () {
// This test is only relevant if UnifiedComplete is enabled.
if (!Services.prefs.getBoolPref("browser.urlbar.unifiedcomplete"))
return;
Services.search.addEngineWithDetails("MozSearch", "", "moz", "", "GET",
"http://example.com/?q={searchTerms}");
let engine = Services.search.getEngineByName("MozSearch");
gOriginalEngine = Services.search.currentEngine;
Services.search.currentEngine = engine;
let tab = gBrowser.selectedTab = gBrowser.addTab();
registerCleanupFunction(() => {
Services.search.currentEngine = gOriginalEngine;
let engine = Services.search.getEngineByName("MozSearch");
Services.search.removeEngine(engine);
try {
gBrowser.removeTab(tab);
} catch(ex) { /* tab may have already been closed in case of failure */ }
return promiseClearHistory();
});
gURLBar.focus();
gURLBar.value = "moz open a searc";
EventUtils.synthesizeKey("h" , {});
yield promiseSearchComplete();
EventUtils.synthesizeKey("VK_RETURN" , { });
yield promiseTabLoaded(gBrowser.selectedTab);
is(gBrowser.selectedBrowser.currentURI.spec, "http://example.com/?q=open+a+search");
});

Просмотреть файл

@ -25,6 +25,11 @@ const SearchAutocompleteProviderInternal = {
*/
priorityMatches: null,
/**
* Array of objects in the format returned by findMatchByAlias.
*/
aliasMatches: null,
/**
* Object for the default search match.
**/
@ -65,6 +70,7 @@ const SearchAutocompleteProviderInternal = {
_refresh: function () {
this.priorityMatches = [];
this.aliasMatches = [];
this.defaultMatch = null;
let currentEngine = Services.search.currentEngine;
@ -82,19 +88,25 @@ const SearchAutocompleteProviderInternal = {
},
_addEngine: function (engine) {
let token = engine.getResultDomain();
if (!token) {
return;
if (engine.alias) {
this.aliasMatches.push({
alias: engine.alias,
engineName: engine.name,
iconUrl: engine.iconURI ? engine.iconURI.spec : null,
});
}
this.priorityMatches.push({
token: token,
// The searchForm property returns a simple URL for the search engine, but
// we may need an URL which includes an affiliate code (bug 990799).
url: engine.searchForm,
engineName: engine.name,
iconUrl: engine.iconURI ? engine.iconURI.spec : null,
});
let domain = engine.getResultDomain();
if (domain) {
this.priorityMatches.push({
token: domain,
// The searchForm property returns a simple URL for the search engine, but
// we may need an URL which includes an affiliate code (bug 990799).
url: engine.searchForm,
engineName: engine.name,
iconUrl: engine.iconURI ? engine.iconURI.spec : null,
});
}
},
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
@ -138,7 +150,30 @@ this.PlacesSearchAutocompleteProvider = Object.freeze({
// Match at the beginning for now. In the future, an "options" argument may
// allow the matching behavior to be tuned.
return SearchAutocompleteProviderInternal.priorityMatches
.find(m => m.token.startsWith(searchToken));
.find(m => m.token.startsWith(searchToken));
}),
/**
* Matches a given search string to an item that should be included by
* components wishing to search using search engine aliases, like
* autocomple.
*
* @param searchToken
* Search string to match exactly a search engine alias.
*
* @return An object with the following properties, or undefined if the token
* does not match any relevant URL:
* {
* alias: The matched search engine's alias.
* engineName: The display name of the search engine.
* iconUrl: Icon associated to the match, or null if not available.
* }
*/
findMatchByAlias: Task.async(function* (searchToken) {
yield this.ensureInitialized();
return SearchAutocompleteProviderInternal.aliasMatches
.find(m => m.alias == searchToken);
}),
getDefaultMatch: Task.async(function* () {

Просмотреть файл

@ -706,6 +706,12 @@ Search.prototype = {
hasFirstResult = true;
}
if (this._enableActions && !hasFirstResult) {
// If it's not a bookmarked keyword, then it may be a search engine
// with an alias - which works like a keyword.
hasFirstResult = yield this._matchSearchEngineAlias();
}
let shouldAutofill = this._shouldAutofill;
if (this.pending && !hasFirstResult && shouldAutofill) {
// Or it may look like a URL we know about from search engines.
@ -833,6 +839,21 @@ Search.prototype = {
return true;
},
_matchSearchEngineAlias: function* () {
if (this._searchTokens.length < 2)
return false;
let match = yield PlacesSearchAutocompleteProvider.findMatchByAlias(
this._searchTokens[0]);
if (!match)
return false;
let query = this._searchTokens.slice(1).join(" ");
yield this._addSearchEngineMatch(match, query);
return true;
},
_matchCurrentSearchEngine: function* () {
let match = yield PlacesSearchAutocompleteProvider.getDefaultMatch();
if (!match)

Просмотреть файл

@ -0,0 +1,33 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
add_task(function*() {
Services.search.addEngineWithDetails("MozSearch", "", "", "", "GET",
"http://s.example.com/search");
let engine = Services.search.getEngineByName("MozSearch");
Services.search.currentEngine = engine;
Services.search.addEngineWithDetails("AliasedMozSearch", "", "doit", "",
"GET", "http://s.example.com/search");
yield check_autocomplete({
search: "doit",
searchParam: "enable-actions",
matches: [ { uri: makeActionURI("searchengine", {engineName: "MozSearch", input: "doit", searchQuery: "doit"}), title: "MozSearch" }, ]
});
yield check_autocomplete({
search: "doit mozilla",
searchParam: "enable-actions",
matches: [ { uri: makeActionURI("searchengine", {engineName: "AliasedMozSearch", input: "doit mozilla", searchQuery: "mozilla"}), title: "AliasedMozSearch" }, ]
});
yield check_autocomplete({
search: "doit mozzarella mozilla",
searchParam: "enable-actions",
matches: [ { uri: makeActionURI("searchengine", {engineName: "AliasedMozSearch", input: "doit mozzarella mozilla", searchQuery: "mozzarella mozilla"}), title: "AliasedMozSearch" }, ]
});
yield cleanup();
});

Просмотреть файл

@ -26,6 +26,7 @@ tail =
[test_match_beginning.js]
[test_multi_word_search.js]
[test_queryurl.js]
[test_searchEngine_alias.js]
[test_searchEngine_current.js]
[test_searchEngine_host.js]
[test_searchEngine_restyle.js]

Просмотреть файл

@ -34,7 +34,7 @@ add_task(function* hide_search_engine_nomatch() {
add_task(function* add_search_engine_match() {
let promiseTopic = promiseSearchTopic("engine-added");
do_check_eq(null, yield PlacesSearchAutocompleteProvider.findMatchByToken("bacon"));
Services.search.addEngineWithDetails("bacon", "", "bacon", "Search Bacon",
Services.search.addEngineWithDetails("bacon", "", "pork", "Search Bacon",
"GET", "http://www.bacon.moz/?search={searchTerms}");
yield promiseSearchTopic;
let match = yield PlacesSearchAutocompleteProvider.findMatchByToken("bacon");
@ -43,6 +43,15 @@ add_task(function* add_search_engine_match() {
do_check_eq(match.iconUrl, null);
});
add_task(function* test_aliased_search_engine_match() {
do_check_eq(null, yield PlacesSearchAutocompleteProvider.findMatchByAlias("sober"));
let match = yield PlacesSearchAutocompleteProvider.findMatchByAlias("pork");
do_check_eq(match.engineName, "bacon");
do_check_eq(match.alias, "pork");
do_check_eq(match.iconUrl, null);
});
add_task(function* remove_search_engine_nomatch() {
let engine = Services.search.getEngineByName("bacon");
let promiseTopic = promiseSearchTopic("engine-removed");