Bug 1028985 - Provide search suggestions on Firefox new tab page (about:newtab). r=MattN

This commit is contained in:
Drew Willcoxon 2014-08-01 12:00:49 -07:00
parent 36e8411bbb
commit eabe2c3534
5 changed files with 78 additions and 3 deletions

View File

@ -392,3 +392,8 @@ input[type=button] {
.newtab-search-panel-engine[selected] {
background: url("chrome://global/skin/menu/shared-menu-check.png") center left 4px no-repeat transparent;
}
.searchSuggestionTable {
font: message-box;
font-size: 16px;
}

View File

@ -5,6 +5,7 @@
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<?xml-stylesheet href="chrome://browser/content/searchSuggestionUI.css" type="text/css"?>
<?xml-stylesheet href="chrome://browser/content/newtab/newTab.css" type="text/css"?>
<?xml-stylesheet href="chrome://browser/skin/newtab/newTab.css" type="text/css"?>
@ -97,4 +98,6 @@
<xul:script type="text/javascript;version=1.8"
src="chrome://browser/content/newtab/newTab.js"/>
<xul:script type="text/javascript;version=1.8"
src="chrome://browser/content/searchSuggestionUI.js"/>
</xul:window>

View File

@ -30,7 +30,9 @@ let gSearch = {
},
search: function (event) {
if (event) {
event.preventDefault();
}
let searchStr = this._nodes.text.value;
if (this.currentEngineName && searchStr.length) {
this._send("Search", {
@ -39,6 +41,7 @@ let gSearch = {
whence: "newtab",
});
}
this._suggestionController.addInputValueToFormHistory();
},
manageEngines: function () {
@ -47,7 +50,10 @@ let gSearch = {
},
handleEvent: function (event) {
this["on" + event.detail.type](event.detail.data);
let methodName = "on" + event.detail.type;
if (this.hasOwnProperty(methodName)) {
this[methodName](event.detail.data);
}
},
onState: function (data) {
@ -183,5 +189,14 @@ let gSearch = {
this._nodes.logo.hidden = true;
this._nodes.text.placeholder = engine.name;
}
// Set up the suggestion controller.
if (!this._suggestionController) {
let parent = document.getElementById("newtab-scrollbox");
this._suggestionController =
new SearchSuggestionUIController(this._nodes.text, parent,
() => this.search());
}
this._suggestionController.engineName = engine.name;
},
};

View File

@ -34,6 +34,8 @@ support-files =
searchEngine1xLogo.xml
searchEngine2xLogo.xml
searchEngine1x2xLogo.xml
../general/searchSuggestionEngine.xml
../general/searchSuggestionEngine.sjs
[browser_newtab_sponsored_icon_click.js]
[browser_newtab_tabsync.js]
[browser_newtab_undo.js]

View File

@ -8,6 +8,7 @@ const ENGINE_NO_LOGO = "searchEngineNoLogo.xml";
const ENGINE_1X_LOGO = "searchEngine1xLogo.xml";
const ENGINE_2X_LOGO = "searchEngine2xLogo.xml";
const ENGINE_1X_2X_LOGO = "searchEngine1x2xLogo.xml";
const ENGINE_SUGGESTIONS = "searchSuggestionEngine.xml";
const SERVICE_EVENT_NAME = "ContentSearchService";
@ -141,6 +142,50 @@ function runTests() {
promiseClick(manageBox),
]).then(TestRunner.next);
// Add the engine that provides search suggestions and switch to it.
let suggestionEngine = null;
yield promiseNewSearchEngine(ENGINE_SUGGESTIONS, 0).then(engine => {
suggestionEngine = engine;
TestRunner.next();
});
Services.search.currentEngine = suggestionEngine;
yield promiseSearchEvents(["CurrentEngine"]).then(TestRunner.next);
yield checkCurrentEngine(ENGINE_SUGGESTIONS, false, false);
// Avoid intermittent failures.
gSearch()._suggestionController.remoteTimeout = 5000;
// Type an X in the search input. This is only a smoke test. See
// browser_searchSuggestionUI.js for comprehensive content search suggestion
// UI tests.
let input = $("text");
input.focus();
EventUtils.synthesizeKey("x", {});
let suggestionsPromise = promiseSearchEvents(["Suggestions"]);
// Wait for the search suggestions to become visible and for the Suggestions
// message.
let table = getContentDocument().getElementById("searchSuggestionTable");
info("Waiting for suggestions table to open");
let observer = new MutationObserver(() => {
if (input.getAttribute("aria-expanded") == "true") {
observer.disconnect();
ok(!table.hidden, "Search suggestion table unhidden");
TestRunner.next();
}
});
observer.observe(input, {
attributes: true,
attributeFilter: ["aria-expanded"],
});
yield undefined;
yield suggestionsPromise.then(TestRunner.next);
// Empty the search input, causing the suggestions to be hidden.
EventUtils.synthesizeKey("a", { accelKey: true });
EventUtils.synthesizeKey("VK_DELETE", {});
ok(table.hidden, "Search suggestion table hidden");
// Done. Revert the current engine and remove the new engines.
Services.search.currentEngine = oldCurrentEngine;
yield promiseSearchEvents(["CurrentEngine"]).then(TestRunner.next);
@ -264,6 +309,11 @@ function checkCurrentEngine(basename, has1xLogo, has2xLogo) {
ok(/^url\("blob:/.test(logo.style.backgroundImage), "Logo URI"); //"
}
if (logo.hidden) {
executeSoon(TestRunner.next);
return;
}
// "selected" attributes of engines in the panel
let panel = searchPanel();
promisePanelShown(panel).then(() => {
@ -283,7 +333,7 @@ function checkCurrentEngine(basename, has1xLogo, has2xLogo) {
}
TestRunner.next();
});
panel.openPopup(logoImg());
panel.openPopup(logo);
}
function promisePanelShown(panel) {