Bug 1067888 - Add autocomplete result type for searching via current search engine. r=mak

--HG--
rename : toolkit/components/places/tests/unifiedcomplete/test_searchEngine.js => toolkit/components/places/tests/unifiedcomplete/test_searchEngine_restyle.js
extra : transplant_source : %851%B0%7BmD%40w/%86%89%CA%AF%25%60k%FE%9Am%F7
This commit is contained in:
Blair McBride 2014-09-24 05:21:48 +12:00
Родитель 45d8ab044c
Коммит 98c98f59f7
21 изменённых файлов: 245 добавлений и 24 удалений

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

@ -102,6 +102,7 @@ skip-if = os == "linux" # Bug 924307
skip-if = e10s # Bug ?????? - no about:home support yet
[browser_aboutSyncProgress.js]
[browser_action_keyword.js]
[browser_action_searchengine.js]
[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", "", "", "", "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();
});
let searchDeferred = promiseSearchComplete();
gURLBar.focus();
gURLBar.value = "open a searc";
EventUtils.synthesizeKey("h" , {});
yield searchDeferred.promise;
EventUtils.synthesizeKey("VK_RETURN" , { });
yield promiseTabLoaded(gBrowser.selectedTab);
is(gBrowser.selectedBrowser.currentURI.spec, "http://example.com/?q=open+a+search");
});

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

@ -10,9 +10,10 @@ function* check_a11y_label(inputText, expectedLabel) {
// additional checks to ensure we wait long enough.
yield promisePopupShown(gURLBar.popup);
let firstResult = gURLBar.popup.richlistbox.firstChild;
is(firstResult.getAttribute("type"), "action switchtab", "Expect right type attribute");
is(firstResult.label, expectedLabel, "Result a11y label should be as expected");
ok(gURLBar.popup.richlistbox.children.length > 1, "Should get at least 2 results");
let result = gURLBar.popup.richlistbox.children[1];
is(result.getAttribute("type"), "action switchtab", "Expect right type attribute");
is(result.label, expectedLabel, "Result a11y label should be as expected");
}
add_task(function*() {

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

@ -3,6 +3,10 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
add_task(function* test_switchtab_override() {
// This test is only relevant if UnifiedComplete is enabled.
if (!Services.prefs.getBoolPref("browser.urlbar.unifiedcomplete"))
return;
let testURL = "http://example.org/browser/browser/base/content/test/general/dummy_page.html";
info("Opening first tab");
@ -37,7 +41,8 @@ add_task(function* test_switchtab_override() {
EventUtils.synthesizeKey("e" , {});
yield deferred.promise;
info("Select first autocomplete popup entry");
info("Select second autocomplete popup entry");
EventUtils.synthesizeKey("VK_DOWN" , {});
EventUtils.synthesizeKey("VK_DOWN" , {});
ok(/moz-action:switchtab/.test(gURLBar.value), "switch to tab entry found");

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

@ -38,7 +38,8 @@ add_task(function* test_switchtab_override_keynav() {
EventUtils.synthesizeKey("e" , {});
yield searchDeferred.promise;
info("Select first autocomplete popup entry");
info("Select second autocomplete popup entry");
EventUtils.synthesizeKey("VK_DOWN" , {});
EventUtils.synthesizeKey("VK_DOWN" , {});
ok(/moz-action:switchtab/.test(gURLBar.value), "switch to tab entry found");

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

@ -155,7 +155,8 @@
returnValue = action.params.url;
break;
}
case "keyword": {
case "keyword": // Fall through.
case "searchengine": {
returnValue = action.params.input;
break;
}
@ -320,6 +321,12 @@
return;
} else if (action.type == "keyword") {
url = action.params.url;
} else if (action.type == "searchengine") {
let engine = Services.search.getEngineByName(action.params.engineName);
let submission = engine.getSubmission(action.params.searchQuery);
url = submission.uri.spec;
postData = submission.postData;
}
}
continueOperation.call(this);
@ -1003,6 +1010,7 @@
// Check for middle-click or modified clicks on the URL bar
if (gURLBar && this.mInput == gURLBar) {
var url = controller.getValueAt(this.selectedIndex);
var options = {};
// close the autocomplete popup and revert the entered address
this.closePopup();
@ -1019,6 +1027,13 @@
url = action.params.url;
break;
}
case "searchengine": {
let engine = Services.search.getEngineByName(action.params.engineName);
let submission = engine.getSubmission(action.params.searchQuery);
url = submission.uri.spec;
options.postData = submission.postData;
break;
}
default: {
return;
}
@ -1026,7 +1041,7 @@
}
// respect the usual clicking subtleties
openUILink(url, aEvent);
openUILink(url, aEvent, options);
}
]]>
</body>

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

@ -76,7 +76,7 @@ OrganizerQueryAllBookmarks=All Bookmarks
OrganizerQueryTags=Tags
# LOCALIZATION NOTE (tagResultLabel, bookmarkResultLabel, switchtabResultLabel,
# keywordResultLabel)
# keywordResultLabel, searchengineResultLabel)
# Noun used to describe the location bar autocomplete result type
# to users with screen readers
# See createResultLabel() in urlbarBindings.xml
@ -84,6 +84,8 @@ tagResultLabel=Tag
bookmarkResultLabel=Bookmark
switchtabResultLabel=Tab
keywordResultLabel=Keyword
searchengineResultLabel=Search
# LOCALIZATION NOTE (lockPrompt.text)
# %S will be replaced with the application name.

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

@ -1505,6 +1505,14 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-
padding: 0 3px;
}
richlistitem[type~="action"][actiontype="searchengine"] > .ac-title-box > .ac-site-icon {
list-style-image: url("chrome://global/skin/icons/autocomplete-search.svg#search-icon");
}
richlistitem[type~="action"][actiontype="searchengine"][selected="true"] > .ac-title-box > .ac-site-icon {
list-style-image: url("chrome://global/skin/icons/autocomplete-search.svg#search-icon-inverted");
}
.autocomplete-treebody::-moz-tree-cell-text(treecolAutoCompleteComment) {
color: GrayText;
}

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

@ -2218,6 +2218,14 @@ richlistitem[type~="action"][actiontype="switchtab"][selected="true"] > .ac-url-
-moz-image-region: rect(11px, 16px, 22px, 0);
}
richlistitem[type~="action"][actiontype="searchengine"] > .ac-title-box > .ac-site-icon {
list-style-image: url("chrome://global/skin/icons/autocomplete-search.svg#search-icon");
}
richlistitem[type~="action"][actiontype="searchengine"][selected="true"] > .ac-title-box > .ac-site-icon {
list-style-image: url("chrome://global/skin/icons/autocomplete-search.svg#search-icon-inverted");
}
@media (min-resolution: 2dppx) {
.ac-result-type-bookmark {
list-style-image: url("chrome://browser/skin/places/star-icons@2x.png");

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

@ -1463,6 +1463,20 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-
}
%endif
richlistitem[type~="action"][actiontype="searchengine"] > .ac-title-box > .ac-site-icon {
list-style-image: url("chrome://global/skin/icons/autocomplete-search.svg#search-icon");
}
%ifdef WINDOWS_AERO
@media not all and (-moz-windows-default-theme) {
%endif
richlistitem[type~="action"][actiontype="searchengine"][selected="true"] > .ac-title-box > .ac-site-icon {
list-style-image: url("chrome://global/skin/icons/autocomplete-search.svg#search-icon-inverted");
}
%ifdef WINDOWS_AERO
}
%endif
.autocomplete-treebody::-moz-tree-cell-text(treecolAutoCompleteComment) {
color: GrayText;
}

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

@ -25,6 +25,11 @@ const SearchAutocompleteProviderInternal = {
*/
priorityMatches: null,
/**
* Object for the default search match.
**/
defaultMatch: null,
initialize: function () {
return new Promise((resolve, reject) => {
Services.search.init(status => {
@ -60,6 +65,16 @@ const SearchAutocompleteProviderInternal = {
_refresh: function () {
this.priorityMatches = [];
this.defaultMatch = null;
let currentEngine = Services.search.currentEngine;
// This can be null in XCPShell.
if (currentEngine) {
this.defaultMatch = {
engineName: currentEngine.name,
iconUrl: currentEngine.iconURI ? currentEngine.iconURI.spec : null,
}
}
// The search engines will always be processed in the order returned by the
// search service, which can be defined by the user.
@ -126,6 +141,12 @@ this.PlacesSearchAutocompleteProvider = Object.freeze({
.find(m => m.token.startsWith(searchToken));
}),
getDefaultMatch: Task.async(function* () {
yield this.ensureInitialized();
return SearchAutocompleteProviderInternal.defaultMatch;
}),
/**
* Synchronously determines if the provided URL represents results from a
* search engine, and provides details about the match.

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

@ -719,6 +719,11 @@ Search.prototype = {
hasFirstResult = yield this._matchKnownUrl(conn, queries);
}
if (this.pending && this._enableActions && !hasFirstResult) {
// When all else fails, we search using the current search engine.
yield this._matchCurrentSearchEngine();
}
yield this._sleep(Prefs.delay);
if (!this.pending)
return;
@ -836,6 +841,33 @@ Search.prototype = {
return true;
},
_matchCurrentSearchEngine: function* () {
let match = yield PlacesSearchAutocompleteProvider.getDefaultMatch();
if (!match)
return;
let query = this._originalSearchString;
yield this._addSearchEngineMatch(match, query);
},
_addSearchEngineMatch: function* (match, query) {
let value = makeActionURL("searchengine", {
engineName: match.engineName,
input: this._originalSearchString,
searchQuery: query,
});
this._addMatch({
value: value,
comment: match.engineName,
icon: match.iconUrl,
style: "action searchengine",
finalCompleteValue: this._trimmedOriginalSearchString,
frecency: FRECENCY_SEARCHENGINES_DEFAULT,
});
},
_onResultRow: function (row) {
TelemetryStopwatch.finish(TELEMETRY_1ST_RESULT);
let queryType = row.getResultByIndex(QUERYINDEX_QUERYTYPE);

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

@ -0,0 +1,35 @@
/* 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");
do_log_info("search engine");
yield check_autocomplete({
search: "mozilla",
searchParam: "enable-actions",
matches: [ { uri: makeActionURI("searchengine", {engineName: "MozSearch", input: "mozilla", searchQuery: "mozilla"}), title: "MozSearch" }, ]
});
do_log_info("search engine, uri-like input");
yield check_autocomplete({
search: "http:///",
searchParam: "enable-actions",
matches: [ { uri: makeActionURI("searchengine", {engineName: "MozSearch", input: "http:///", searchQuery: "http:///"}), title: "MozSearch" }, ]
});
do_log_info("search engine, multiple words");
yield check_autocomplete({
search: "mozzarella cheese",
searchParam: "enable-actions",
matches: [ { uri: makeActionURI("searchengine", {engineName: "MozSearch", input: "mozzarella cheese", searchQuery: "mozzarella cheese"}), title: "MozSearch" }, ]
});
yield cleanup();
});

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

@ -7,6 +7,11 @@
let gTabRestrictChar = "%";
add_task(function* test_tab_matches() {
Services.search.addEngineWithDetails("MozSearch", "", "", "", "GET",
"http://s.example.com/search");
let engine = Services.search.getEngineByName("MozSearch");
Services.search.currentEngine = engine;
let uri1 = NetUtil.newURI("http://abc.com/");
let uri2 = NetUtil.newURI("http://xyz.net/");
let uri3 = NetUtil.newURI("about:mozilla");
@ -18,46 +23,51 @@ add_task(function* test_tab_matches() {
addOpenPages(uri3, 1);
addOpenPages(uri4, 1);
do_log_info("single result, that is also a tab match");
do_log_info("two results, normal result is a tab match");
yield check_autocomplete({
search: "abc.com",
searchParam: "enable-actions",
matches: [ { uri: makeActionURI("switchtab", {url: "http://abc.com/"}), title: "ABC rocks" } ]
matches: [ { uri: makeActionURI("searchengine", {engineName: "MozSearch", input: "abc.com", searchQuery: "abc.com"}), title: "MozSearch" },
{ uri: makeActionURI("switchtab", {url: "http://abc.com/"}), title: "ABC rocks" } ]
});
do_log_info("two results, one tab match");
do_log_info("three results, one tab match");
yield check_autocomplete({
search: "abc",
searchParam: "enable-actions",
matches: [ { uri: makeActionURI("switchtab", {url: "http://abc.com/"}), title: "ABC rocks" },
matches: [ { uri: makeActionURI("searchengine", {engineName: "MozSearch", input: "abc", searchQuery: "abc"}), title: "MozSearch" },
{ uri: makeActionURI("switchtab", {url: "http://abc.com/"}), title: "ABC rocks" },
{ uri: uri2, title: "xyz.net - we're better than ABC" } ]
});
do_log_info("two results, both tab matches");
do_log_info("three results, both normal results are tab matches");
addOpenPages(uri2, 1);
yield check_autocomplete({
search: "abc",
searchParam: "enable-actions",
matches: [ { uri: makeActionURI("switchtab", {url: "http://abc.com/"}), title: "ABC rocks" },
matches: [ { uri: makeActionURI("searchengine", {engineName: "MozSearch", input: "abc", searchQuery: "abc"}), title: "MozSearch" },
{ uri: makeActionURI("switchtab", {url: "http://abc.com/"}), title: "ABC rocks" },
{ uri: makeActionURI("switchtab", {url: "http://xyz.net/"}), title: "xyz.net - we're better than ABC" } ]
});
do_log_info("two results, both tab matches, one has multiple tabs");
do_log_info("three results, both normal results are tab matches, one has multiple tabs");
addOpenPages(uri2, 5);
yield check_autocomplete({
search: "abc",
searchParam: "enable-actions",
matches: [ { uri: makeActionURI("switchtab", {url: "http://abc.com/"}), title: "ABC rocks" },
matches: [ { uri: makeActionURI("searchengine", {engineName: "MozSearch", input: "abc", searchQuery: "abc"}), title: "MozSearch" },
{ uri: makeActionURI("switchtab", {url: "http://abc.com/"}), title: "ABC rocks" },
{ uri: makeActionURI("switchtab", {url: "http://xyz.net/"}), title: "xyz.net - we're better than ABC" } ]
});
do_log_info("two results, no tab matches");
do_log_info("three results, no tab matches");
removeOpenPages(uri1, 1);
removeOpenPages(uri2, 6);
yield check_autocomplete({
search: "abc",
searchParam: "enable-actions",
matches: [ { uri: uri1, title: "ABC rocks" },
matches: [ { uri: makeActionURI("searchengine", {engineName: "MozSearch", input: "abc", searchQuery: "abc"}), title: "MozSearch" },
{ uri: uri1, title: "ABC rocks" },
{ uri: uri2, title: "xyz.net - we're better than ABC" } ]
});
@ -66,28 +76,32 @@ add_task(function* test_tab_matches() {
yield check_autocomplete({
search: gTabRestrictChar + " abc",
searchParam: "enable-actions",
matches: [ { uri: makeActionURI("switchtab", {url: "http://abc.com/"}), title: "ABC rocks" } ]
matches: [ { uri: makeActionURI("searchengine", {engineName: "MozSearch", input: gTabRestrictChar + " abc", searchQuery: gTabRestrictChar + " abc"}), title: "MozSearch" },
{ uri: makeActionURI("switchtab", {url: "http://abc.com/"}), title: "ABC rocks" } ]
});
do_log_info("tab match with not-addable pages");
yield check_autocomplete({
search: "mozilla",
searchParam: "enable-actions",
matches: [ { uri: makeActionURI("switchtab", {url: "about:mozilla"}), title: "about:mozilla" } ]
matches: [ { uri: makeActionURI("searchengine", {engineName: "MozSearch", input: "mozilla", searchQuery: "mozilla"}), title: "MozSearch" },
{ uri: makeActionURI("switchtab", {url: "about:mozilla"}), title: "about:mozilla" } ]
});
do_log_info("tab match with not-addable pages and restriction character");
yield check_autocomplete({
search: gTabRestrictChar + " mozilla",
searchParam: "enable-actions",
matches: [ { uri: makeActionURI("switchtab", {url: "about:mozilla"}), title: "about:mozilla" } ]
matches: [ { uri: makeActionURI("searchengine", {engineName: "MozSearch", input: gTabRestrictChar + " mozilla", searchQuery: gTabRestrictChar + " mozilla"}), title: "MozSearch" },
{ uri: makeActionURI("switchtab", {url: "about:mozilla"}), title: "about:mozilla" } ]
});
do_log_info("tab match with not-addable pages and only restriction character");
yield check_autocomplete({
search: gTabRestrictChar,
searchParam: "enable-actions",
matches: [ { uri: makeActionURI("switchtab", {url: "http://abc.com/"}), title: "ABC rocks" },
matches: [ { uri: makeActionURI("searchengine", {engineName: "MozSearch", input: gTabRestrictChar, searchQuery: gTabRestrictChar}), title: "MozSearch" },
{ uri: makeActionURI("switchtab", {url: "http://abc.com/"}), title: "ABC rocks" },
{ uri: makeActionURI("switchtab", {url: "about:mozilla"}), title: "about:mozilla" },
{ uri: makeActionURI("switchtab", {url: "data:text/html,test"}), title: "data:text/html,test" } ]
});

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

@ -26,7 +26,8 @@ tail =
[test_match_beginning.js]
[test_multi_word_search.js]
[test_queryurl.js]
[test_searchEngine.js]
[test_searchEngine_restyle.js]
[test_searchEngine_current.js]
[test_special_search.js]
[test_swap_protocol.js]
[test_tabmatches.js]

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

@ -1577,6 +1577,17 @@ extends="chrome://global/content/bindings/popup.xml#popup">
url = action.params.url;
let desc = this._stringBundle.GetStringFromName("switchToTab");
this._setUpDescription(this._action, desc, true);
} else if (action.type == "searchengine") {
emphasiseUrl = false;
let sourceStr = this._stringBundle.GetStringFromName("searchWithEngineForQuery");
title = this._generateEmphasisPairs(sourceStr, [
[action.params.engineName, false],
[action.params.searchQuery, true]
]);
// Remove the image, so we can style it ourselves with a generic
// search icon.
this.removeAttribute("image");
}
// Remove the "action" substring so that the correct style, if any,
@ -1699,7 +1710,6 @@ extends="chrome://global/content/bindings/popup.xml#popup">
// URL is in the format moz-action:ACTION,PARAMS
// Where PARAMS is a JSON encoded object.
aUrl = decodeURI(aUrl);
let [, type, params] = aUrl.match(/^moz-action:([^,]+),(.*)$/);
let action = {

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

@ -6,6 +6,11 @@
# the search engine provider's name. This format was chosen because
# the provider can also end with "Search" (e.g.: MSN Search).
searchWithEngine = Search with %S
# LOCALIZATION NOTE (searchWithEngineForQuery):
# %1$S is the search engine's name, %2$S is the search query.
# This format was chosen because the provider can also end with "Search"
# (e.g.: MSN Search).
searchWithEngineForQuery = %2$S — Search with %1$S
switchToTab = Switch to tab
# LOCALIZATION NOTE (visitURL):
# %S is the URL to visit.

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

@ -118,11 +118,13 @@ treechildren.autocomplete-treebody::-moz-tree-cell-text(selected) {
}
.autocomplete-richlistitem[actiontype="keyword"] .ac-url-box,
.autocomplete-richlistitem[actiontype="searchengine"] .ac-url-box,
.autocomplete-richlistitem[type~="autofill"] .ac-url-box {
display: none;
}
.autocomplete-richlistitem[actiontype="keyword"] .ac-title-box,
.autocomplete-richlistitem[actiontype="searchengine"] .ac-title-box,
.autocomplete-richlistitem[type~="autofill"] .ac-title-box {
margin-top: 12px;
margin-bottom: 12px;

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

@ -103,11 +103,13 @@ treechildren.autocomplete-treebody::-moz-tree-cell-text(selected) {
}
.autocomplete-richlistitem[actiontype="keyword"] .ac-url-box,
.autocomplete-richlistitem[actiontype="searchengine"] .ac-url-box,
.autocomplete-richlistitem[type~="autofill"] .ac-url-box {
display: none;
}
.autocomplete-richlistitem[actiontype="keyword"] .ac-title-box,
.autocomplete-richlistitem[actiontype="searchengine"] .ac-title-box,
.autocomplete-richlistitem[type~="autofill"] .ac-title-box {
margin-top: 12px;
margin-bottom: 12px;

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

@ -131,11 +131,13 @@ treechildren.autocomplete-treebody::-moz-tree-cell-text(selected) {
%endif
.autocomplete-richlistitem[actiontype="keyword"] .ac-url-box,
.autocomplete-richlistitem[actiontype="searchengine"] .ac-url-box,
.autocomplete-richlistitem[type~="autofill"] .ac-url-box {
display: none;
}
.autocomplete-richlistitem[actiontype="keyword"] .ac-title-box,
.autocomplete-richlistitem[actiontype="searchengine"] .ac-title-box,
.autocomplete-richlistitem[type~="autofill"] .ac-title-box {
margin-top: 12px;
margin-bottom: 12px;