diff --git a/browser/base/content/test/urlbar/browser.ini b/browser/base/content/test/urlbar/browser.ini index 1a055c20aece..3820a61bce0b 100644 --- a/browser/base/content/test/urlbar/browser.ini +++ b/browser/base/content/test/urlbar/browser.ini @@ -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 diff --git a/browser/base/content/test/urlbar/browser_urlbar_search_speculative_connect.js b/browser/base/content/test/urlbar/browser_urlbar_search_speculative_connect.js index a50e243783b3..db22a493ff68 100644 --- a/browser/base/content/test/urlbar/browser_urlbar_search_speculative_connect.js +++ b/browser/base/content/test/urlbar/browser_urlbar_search_speculative_connect.js @@ -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"); +}); diff --git a/browser/base/content/test/urlbar/browser_urlbar_search_speculative_connect_engine.js b/browser/base/content/test/urlbar/browser_urlbar_search_speculative_connect_engine.js new file mode 100644 index 000000000000..4f4439570e0d --- /dev/null +++ b/browser/base/content/test/urlbar/browser_urlbar_search_speculative_connect_engine.js @@ -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); +}); + diff --git a/browser/base/content/test/urlbar/head.js b/browser/base/content/test/urlbar/head.js index 6d729d555422..5a5939f31716 100644 --- a/browser/base/content/test/urlbar/head.js +++ b/browser/base/content/test/urlbar/head.js @@ -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"); +} diff --git a/browser/base/content/test/urlbar/searchSuggestionEngine2.xml b/browser/base/content/test/urlbar/searchSuggestionEngine2.xml new file mode 100644 index 000000000000..23522c18994d --- /dev/null +++ b/browser/base/content/test/urlbar/searchSuggestionEngine2.xml @@ -0,0 +1,13 @@ + + + + +browser_searchSuggestionEngine searchSuggestionEngine.xml + + + + + + + diff --git a/browser/base/content/urlbarBindings.xml b/browser/base/content/urlbarBindings.xml index 8fb76828106a..e225775c22ff 100644 --- a/browser/base/content/urlbarBindings.xml +++ b/browser/base/content/urlbarBindings.xml @@ -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/. 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. diff --git a/testing/profiles/prefs_general.js b/testing/profiles/prefs_general.js index 88fcd90a5cce..c53bb1f74b09 100644 --- a/testing/profiles/prefs_general.js +++ b/testing/profiles/prefs_general.js @@ -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