зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1355443 - Speculatively connect to the current search engine. r=mak
when the first result is "Search with ...", we can preconnect to the search engine to speed up the possible search query. MozReview-Commit-ID: 1K1Vp5gVwmR --HG-- extra : rebase_source : ed83ece0dd1ba3c3ee8e0d8897706b7ad9306c5c
This commit is contained in:
Родитель
805e149605
Коммит
09b67e6c91
|
@ -111,6 +111,10 @@ support-files =
|
|||
file_urlbar_edit_dos.html
|
||||
[browser_urlbar_searchsettings.js]
|
||||
[browser_urlbar_search_speculative_connect.js]
|
||||
[browser_urlbar_search_speculative_connect_engine.js]
|
||||
support-files =
|
||||
searchSuggestionEngine2.xml
|
||||
searchSuggestionEngine.sjs
|
||||
[browser_urlbar_stop_pending.js]
|
||||
support-files =
|
||||
slow-page.sjs
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
// This test ensures that we setup a speculative network
|
||||
|
@ -8,6 +12,8 @@ let gHttpServer = null;
|
|||
let gScheme = "http";
|
||||
let gHost = "localhost"; // 'localhost' by default.
|
||||
let gPort = -1;
|
||||
let gPrivateWin = null;
|
||||
let gIsSpeculativeConnected = false;
|
||||
|
||||
add_task(async function setup() {
|
||||
if (!gHttpServer) {
|
||||
|
@ -24,7 +30,9 @@ add_task(async function setup() {
|
|||
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["browser.urlbar.autoFill", true],
|
||||
["browser.urlbar.speculativeConnection.enabled", true],
|
||||
// Turn off speculative connect to the search engine.
|
||||
["browser.search.suggest.enabled", false],
|
||||
["browser.urlbar.speculativeConnect.enabled", true],
|
||||
// In mochitest this number is 0 by default but we have to turn it on.
|
||||
["network.http.speculative-parallel-limit", 6],
|
||||
// The http server is using IPv4, so it's better to disable IPv6 to avoid weird
|
||||
|
@ -38,45 +46,56 @@ add_task(async function setup() {
|
|||
transition: Ci.nsINavHistoryService.TRANSITION_TYPED,
|
||||
}]);
|
||||
|
||||
gPrivateWin = await BrowserTestUtils.openNewBrowserWindow({private: true});
|
||||
is(PrivateBrowsingUtils.isWindowPrivate(gPrivateWin), true, "A private window created.");
|
||||
|
||||
// Bug 764062 - we can't get port number from autocomplete result, so we have to mock
|
||||
// this function to add it manually.
|
||||
let oldSpeculativeConnect = gURLBar.popup.maybeSetupSpeculativeConnect.bind(gURLBar.popup);
|
||||
gURLBar.popup.maybeSetupSpeculativeConnect = (uriString) => {
|
||||
let newSpeculativeConnect = (uriString) => {
|
||||
gIsSpeculativeConnected = true;
|
||||
info(`Original uri is ${uriString}`);
|
||||
let newUriString = uriString.substr(0, uriString.length - 1) +
|
||||
":" + gPort + "/";
|
||||
info(`New uri is ${newUriString}`);
|
||||
oldSpeculativeConnect(newUriString);
|
||||
};
|
||||
gURLBar.popup.maybeSetupSpeculativeConnect = newSpeculativeConnect;
|
||||
gPrivateWin.gURLBar.popup.maybeSetupSpeculativeConnect = newSpeculativeConnect;
|
||||
|
||||
registerCleanupFunction(async function() {
|
||||
await PlacesTestUtils.clearHistory();
|
||||
await PlacesUtils.history.clear();
|
||||
gURLBar.popup.maybeSetupSpeculativeConnect = oldSpeculativeConnect;
|
||||
gPrivateWin.gURLBar.popup.maybeSetupSpeculativeConnect = oldSpeculativeConnect;
|
||||
gHttpServer.identity.remove(gScheme, gHost, gPort);
|
||||
gHttpServer.stop(() => {
|
||||
gHttpServer = null;
|
||||
});
|
||||
await BrowserTestUtils.closeWindow(gPrivateWin);
|
||||
});
|
||||
});
|
||||
|
||||
add_task(async function autofill_tests() {
|
||||
const test = {
|
||||
search: gHost.substr(0, 2),
|
||||
autofilledValue: `${gHost}/`
|
||||
};
|
||||
const test = {
|
||||
search: gHost.substr(0, 2),
|
||||
autofilledValue: `${gHost}/`
|
||||
};
|
||||
|
||||
add_task(async function autofill_tests() {
|
||||
gIsSpeculativeConnected = false;
|
||||
info(`Searching for '${test.search}'`);
|
||||
await promiseAutocompleteResultPopup(test.search, window, true);
|
||||
is(gURLBar.inputField.value, test.autofilledValue,
|
||||
`Autofilled value is as expected for search '${test.search}'`);
|
||||
|
||||
await BrowserTestUtils.waitForCondition(() => {
|
||||
if (gHttpServer) {
|
||||
is(gHttpServer.connectionNumber, 1,
|
||||
`${gHttpServer.connectionNumber} speculative connection has been setup.`)
|
||||
return gHttpServer.connectionNumber == 1;
|
||||
}
|
||||
return false;
|
||||
}, "Waiting for connection setup");
|
||||
is(gIsSpeculativeConnected, true, "Speculative connection should be called");
|
||||
await promiseSpeculativeConnection(gHttpServer);
|
||||
});
|
||||
|
||||
add_task(async function privateContext_test() {
|
||||
info("In private context.");
|
||||
gIsSpeculativeConnected = false;
|
||||
info(`Searching for '${test.search}'`);
|
||||
await promiseAutocompleteResultPopup(test.search, gPrivateWin, true);
|
||||
is(gPrivateWin.gURLBar.inputField.value, test.autofilledValue,
|
||||
`Autofilled value is as expected for search '${test.search}'`);
|
||||
is(gIsSpeculativeConnected, false, "Speculative connection shouldn't be called");
|
||||
});
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
// This test ensures that we setup a speculative network connection to
|
||||
// current search engine if the first result is 'searchengine'.
|
||||
|
||||
let {HttpServer} = Cu.import("resource://testing-common/httpd.js", {});
|
||||
let gHttpServer = null;
|
||||
let gScheme = "http";
|
||||
let gHost = "localhost"; // 'localhost' by default.
|
||||
let gPort = 20709; // the port number must be identical to what we said in searchSuggestionEngine2.xml
|
||||
const TEST_ENGINE_BASENAME = "searchSuggestionEngine2.xml";
|
||||
|
||||
add_task(async function setup() {
|
||||
if (!gHttpServer) {
|
||||
gHttpServer = new HttpServer();
|
||||
try {
|
||||
gHttpServer.start(gPort);
|
||||
gPort = gHttpServer.identity.primaryPort;
|
||||
gHttpServer.identity.setPrimary(gScheme, gHost, gPort);
|
||||
} catch (ex) {
|
||||
info("We can't launch our http server successfully.")
|
||||
}
|
||||
}
|
||||
is(gHttpServer.identity.has(gScheme, gHost, gPort), true, "make sure we have this domain listed");
|
||||
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["browser.urlbar.autoFill", true],
|
||||
// Turn off speculative connect to the search engine.
|
||||
["browser.search.suggest.enabled", true],
|
||||
["browser.urlbar.suggest.searches", true],
|
||||
["browser.urlbar.speculativeConnect.enabled", true],
|
||||
// In mochitest this number is 0 by default but we have to turn it on.
|
||||
["network.http.speculative-parallel-limit", 6],
|
||||
// The http server is using IPv4, so it's better to disable IPv6 to avoid weird
|
||||
// networking problem.
|
||||
["network.dns.disableIPv6", true]],
|
||||
});
|
||||
|
||||
let engine = await promiseNewSearchEngine(TEST_ENGINE_BASENAME);
|
||||
let oldCurrentEngine = Services.search.currentEngine;
|
||||
Services.search.currentEngine = engine;
|
||||
|
||||
registerCleanupFunction(async function() {
|
||||
await PlacesUtils.history.clear();
|
||||
Services.search.currentEngine = oldCurrentEngine;
|
||||
gHttpServer.identity.remove(gScheme, gHost, gPort);
|
||||
gHttpServer.stop(() => {
|
||||
gHttpServer = null;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
add_task(async function autofill_tests() {
|
||||
info("Searching for 'foo'");
|
||||
await promiseAutocompleteResultPopup("foo", window, true);
|
||||
// Check if the first result is with type "searchengine"
|
||||
let controller = gURLBar.popup.input.controller;
|
||||
let style = controller.getStyleAt(0);
|
||||
is(style.includes("searchengine"), true, "The first result type is searchengine");
|
||||
await promiseSpeculativeConnection(gHttpServer);
|
||||
});
|
||||
|
|
@ -235,3 +235,14 @@ function promisePageActionViewShown() {
|
|||
}, { once: true });
|
||||
});
|
||||
}
|
||||
|
||||
function promiseSpeculativeConnection(httpserver) {
|
||||
return BrowserTestUtils.waitForCondition(() => {
|
||||
if (httpserver) {
|
||||
is(httpserver.connectionNumber, 1,
|
||||
`${httpserver.connectionNumber} speculative connection has been setup.`)
|
||||
return httpserver.connectionNumber == 1;
|
||||
}
|
||||
return false;
|
||||
}, "Waiting for connection setup");
|
||||
}
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
- http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
|
||||
<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
|
||||
<ShortName>browser_searchSuggestionEngine searchSuggestionEngine.xml</ShortName>
|
||||
<!-- Redirect the actual search request to the test-server because of proxy restriction -->
|
||||
<Url type="application/x-suggestions+json" method="GET" template="http://mochi.test:8888/browser/browser/base/content/test/urlbar/searchSuggestionEngine.sjs?{searchTerms}"/>
|
||||
<!-- Redirect speculative connect to a local http server we run for this test -->
|
||||
<Url type="text/html" method="GET" template="http://localhost:20709/" rel="searchform">
|
||||
<Param name="terms" value="{searchTerms}"/>
|
||||
</Url>
|
||||
</SearchPlugin>
|
|
@ -76,9 +76,14 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|||
.getService(Components.interfaces.nsIPrefService)
|
||||
.getDefaultBranch("browser.urlbar.");
|
||||
|
||||
Services.prefs.addObserver("browser.search.suggest.enabled", this);
|
||||
this.browserSearchSuggestEnabled = Services.prefs.getBoolPref("browser.search.suggest.enabled");
|
||||
|
||||
this.clickSelectsAll = this._prefs.getBoolPref("clickSelectsAll");
|
||||
this.doubleClickSelectsAll = this._prefs.getBoolPref("doubleClickSelectsAll");
|
||||
this.completeDefaultIndex = this._prefs.getBoolPref("autoFill");
|
||||
this.speculativeConnectEnabled = this._prefs.getBoolPref("speculativeConnect.enabled");
|
||||
this.urlbarSearchSuggestEnabled = this._prefs.getBoolPref("suggest.searches");
|
||||
this.timeout = this._prefs.getIntPref("delay");
|
||||
this._formattingEnabled = this._prefs.getBoolPref("formatting.enabled");
|
||||
this._mayTrimURLs = this._prefs.getBoolPref("trimURLs");
|
||||
|
@ -134,6 +139,7 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|||
<destructor><![CDATA[
|
||||
this._prefs.removeObserver("", this);
|
||||
this._prefs = null;
|
||||
Services.prefs.removeObserver("browser.search.suggest.enabled", this);
|
||||
this.inputField.controllers.removeController(this._copyCutController);
|
||||
this.inputField.removeEventListener("paste", this);
|
||||
this.inputField.removeEventListener("mousedown", this);
|
||||
|
@ -1082,12 +1088,19 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|||
case "formatting.enabled":
|
||||
this._formattingEnabled = this._prefs.getBoolPref(aData);
|
||||
break;
|
||||
case "speculativeConnect.enabled":
|
||||
this.speculativeConnectEnabled = this._prefs.getBoolPref(aData);
|
||||
break;
|
||||
case "browser.search.suggest.enabled":
|
||||
this.browserSearchSuggestEnabled = Services.prefs.getBoolPref(aData);
|
||||
break;
|
||||
case "suggest.searches":
|
||||
this.urlbarSearchSuggestEnabled = this._prefs.getBoolPref(aData);
|
||||
case "userMadeSearchSuggestionsChoice":
|
||||
// Mirror the value for future use, see the comment in the
|
||||
// binding's constructor.
|
||||
this._prefs.setBoolPref("searchSuggestionsChoice",
|
||||
this._prefs.getBoolPref("suggest.searches"));
|
||||
this.urlbarSearchSuggestEnabled);
|
||||
// Clear the cached value to allow changing conditions in tests.
|
||||
delete this._whichSearchSuggestionsNotification;
|
||||
break;
|
||||
|
@ -1381,8 +1394,7 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|||
return this._whichSearchSuggestionsNotification;
|
||||
}
|
||||
|
||||
if (Services.prefs.getBoolPref("browser.search.suggest.enabled") &&
|
||||
!this.inPrivateContext &&
|
||||
if (this.browserSearchSuggestEnabled && !this.inPrivateContext &&
|
||||
// In any case, if the user made a choice we should not nag him.
|
||||
!this._userMadeSearchSuggestionsChoice) {
|
||||
let enabledByDefault = this._defaultPrefs.getBoolPref("suggest.searches");
|
||||
|
@ -1392,7 +1404,7 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|||
}
|
||||
if (enabledByDefault &&
|
||||
// Has not been switched off.
|
||||
this._prefs.getBoolPref("suggest.searches") &&
|
||||
this.urlbarSearchSuggestEnabled &&
|
||||
this._prefs.getIntPref("timesBeforeHidingSuggestionsHint")) {
|
||||
return "opt-out";
|
||||
}
|
||||
|
@ -2124,11 +2136,6 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|||
<method name="maybeSetupSpeculativeConnect">
|
||||
<parameter name="aUriString"/>
|
||||
<body><![CDATA[
|
||||
// We shouldn't leak autocomplete result in the private context.
|
||||
if (!Services.prefs.getBoolPref("browser.urlbar.speculativeConnect.enabled") ||
|
||||
this.input.inPrivateContext) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
let uri = makeURI(aUriString);
|
||||
Services.io.speculativeConnect2(uri, gBrowser.contentPrincipal, null);
|
||||
|
@ -2152,18 +2159,29 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|||
this.richlistbox.suppressMenuItemEvent = false;
|
||||
}
|
||||
// If this is the first time we get the result from the current
|
||||
// search, and the result is an "autofill" result, that means it's
|
||||
// the site that user frequently visits. Then we could speculatively
|
||||
// connect to this site as a performance optimization.
|
||||
// search and we are not in the private context, we can speculatively
|
||||
// connect to the intended site as a performance optimization.
|
||||
if (!this.input.gotResultForCurrentQuery &&
|
||||
this.input.mController.matchCount > 0 &&
|
||||
this.input.mController.getStyleAt(0).includes("autofill")) {
|
||||
let uri = this.input.mController.getFinalCompleteValueAt(0);
|
||||
// "http" will be stripped out, but other scheme won't.
|
||||
if (!uri.includes("://")) {
|
||||
uri = "http://" + uri;
|
||||
this.input.speculativeConnectEnabled &&
|
||||
!this.input.inPrivateContext &&
|
||||
this.input.mController.matchCount > 0) {
|
||||
let firstStyle = this.input.mController.getStyleAt(0);
|
||||
if (firstStyle.includes("autofill")) {
|
||||
let uri = this.input.mController.getFinalCompleteValueAt(0);
|
||||
// "http" will be stripped out, but other scheme won't.
|
||||
if (!uri.includes("://")) {
|
||||
uri = "http://" + uri;
|
||||
}
|
||||
this.maybeSetupSpeculativeConnect(uri);
|
||||
} else if (firstStyle.includes("searchengine") &&
|
||||
this.input.browserSearchSuggestEnabled &&
|
||||
this.input.urlbarSearchSuggestEnabled) {
|
||||
// Preconnect to the current search engine only if the search
|
||||
// suggestions are enabled.
|
||||
let engine = Services.search.currentEngine;
|
||||
engine.speculativeConnect({window,
|
||||
originAttributes: gBrowser.contentPrincipal.originAttributes});
|
||||
}
|
||||
this.maybeSetupSpeculativeConnect(uri);
|
||||
}
|
||||
|
||||
// When a result is present the footer should always be visible.
|
||||
|
|
|
@ -7,7 +7,7 @@ user_pref("browser.firstrun.show.uidiscovery", false);
|
|||
user_pref("browser.startup.page", 0); // use about:blank, not browser.startup.homepage
|
||||
user_pref("browser.search.suggest.timeout", 10000); // use a 10s suggestion timeout in tests
|
||||
user_pref("browser.ui.layout.tablet", 0); // force tablet UI off
|
||||
user_pref("browser.urlbar.speculativeConnection.enabled", false);
|
||||
user_pref("browser.urlbar.speculativeConnect.enabled", false);
|
||||
user_pref("dom.allow_scripts_to_close_windows", true);
|
||||
user_pref("dom.disable_open_during_load", false);
|
||||
user_pref("dom.experimental_forms", true); // on for testing
|
||||
|
|
Загрузка…
Ссылка в новой задаче