diff --git a/browser/base/content/test/general/browser.ini b/browser/base/content/test/general/browser.ini index f8bf8866f2a..8aab62da6ac 100644 --- a/browser/base/content/test/general/browser.ini +++ b/browser/base/content/test/general/browser.ini @@ -427,6 +427,8 @@ skip-if = e10s [browser_tabs_isActive.js] skip-if = e10s # Bug 1100664 - test relies on linkedBrowser.docShell [browser_tabs_owner.js] +[browser_testOpenNewRemoteTabsFromNonRemoteBrowsers.js] +skip-if = !e10s && os == "linux" # Bug 994541 - Need OMTC enabled by default on Linux, or else we get blocked by an alert dialog when opening e10s window. [browser_trackingUI.js] support-files = trackingPage.html diff --git a/browser/base/content/test/general/browser_testOpenNewRemoteTabsFromNonRemoteBrowsers.js b/browser/base/content/test/general/browser_testOpenNewRemoteTabsFromNonRemoteBrowsers.js new file mode 100644 index 00000000000..dcdf203e4d5 --- /dev/null +++ b/browser/base/content/test/general/browser_testOpenNewRemoteTabsFromNonRemoteBrowsers.js @@ -0,0 +1,124 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +const OPEN_LOCATION_PREF = "browser.link.open_newwindow"; +const NON_REMOTE_PAGE = "about:welcomeback"; + +Cu.import("resource://gre/modules/PrivateBrowsingUtils.jsm"); + +function frame_script() { + content.document.body.innerHTML = ` + Open a window + `; + + let element = content.document.getElementById("testAnchor"); + element.click(); +} + +/** + * Takes some browser in some window, and forces that browser + * to become non-remote, and then navigates it to a page that + * we're not supposed to be displaying remotely. Returns a + * Promise that resolves when the browser is no longer remote. + */ +function prepareNonRemoteBrowser(aWindow, browser) { + browser.loadURI(NON_REMOTE_PAGE); + return waitForDocLoadComplete(browser); +} + +registerCleanupFunction(() => { + Services.prefs.clearUserPref(OPEN_LOCATION_PREF); +}); + +/** + * Test that if we open a new tab from a link in a non-remote + * browser in an e10s window, that the new tab will load properly. + */ +add_task(function* test_new_tab() { + let normalWindow = yield promiseOpenAndLoadWindow({ + remote: true + }, true); + let privateWindow = yield promiseOpenAndLoadWindow({ + remote: true, + private: true, + }, true); + + for (let testWindow of [normalWindow, privateWindow]) { + yield promiseWaitForFocus(testWindow); + let testBrowser = testWindow.gBrowser.selectedBrowser; + info("Preparing non-remote browser"); + yield prepareNonRemoteBrowser(testWindow, testBrowser); + info("Non-remote browser prepared - sending frame script"); + + // Get our framescript ready + let mm = testBrowser.messageManager; + mm.loadFrameScript("data:,(" + frame_script.toString() + ")();", true); + + let tabOpenEvent = yield waitForNewTabEvent(testWindow.gBrowser); + let newTab = tabOpenEvent.target; + + yield promiseTabLoadEvent(newTab); + + // Our framescript opens to about:home which means that the + // tab should eventually become remote. + ok(newTab.linkedBrowser.isRemoteBrowser, + "The opened browser never became remote."); + + testWindow.gBrowser.removeTab(newTab); + } + + normalWindow.close(); + privateWindow.close(); +}); + +/** + * Test that if we open a new window from a link in a non-remote + * browser in an e10s window, that the new window is not an e10s + * window. Also tests with a private browsing window. + */ +add_task(function* test_new_window() { + let normalWindow = yield promiseOpenAndLoadWindow({ + remote: true + }, true); + let privateWindow = yield promiseOpenAndLoadWindow({ + remote: true, + private: true, + }, true); + + // Fiddle with the prefs so that we open target="_blank" links + // in new windows instead of new tabs. + Services.prefs.setIntPref(OPEN_LOCATION_PREF, + Ci.nsIBrowserDOMWindow.OPEN_NEWWINDOW); + + for (let testWindow of [normalWindow, privateWindow]) { + yield promiseWaitForFocus(testWindow); + let testBrowser = testWindow.gBrowser.selectedBrowser; + yield prepareNonRemoteBrowser(testWindow, testBrowser); + + // Get our framescript ready + let mm = testBrowser.messageManager; + mm.loadFrameScript("data:,(" + frame_script.toString() + ")();", true); + + // Click on the link in the browser, and wait for the new window. + let {subject: newWindow} = + yield promiseTopicObserved("browser-delayed-startup-finished"); + + is(PrivateBrowsingUtils.isWindowPrivate(testWindow), + PrivateBrowsingUtils.isWindowPrivate(newWindow), + "Private browsing state of new window does not match the original!"); + + let newTab = newWindow.gBrowser.selectedTab; + + yield promiseTabLoadEvent(newTab); + + // Our framescript opens to about:home which means that the + // tab should eventually become remote. + ok(newTab.linkedBrowser.isRemoteBrowser, + "The opened browser never became remote."); + newWindow.close(); + } + + normalWindow.close(); + privateWindow.close(); +}); diff --git a/browser/base/content/test/general/head.js b/browser/base/content/test/general/head.js index a4fffd65df2..8b5c89c6e8c 100644 --- a/browser/base/content/test/general/head.js +++ b/browser/base/content/test/general/head.js @@ -123,6 +123,23 @@ function promiseWaitForEvent(object, eventName, capturing = false, chrome = fals }); } +/** + * Allows setting focus on a window, and waiting for that window to achieve + * focus. + * + * @param aWindow + * The window to focus and wait for. + * + * @return {Promise} + * @resolves When the window is focused. + * @rejects Never. + */ +function promiseWaitForFocus(aWindow) { + return new Promise((resolve) => { + waitForFocus(resolve, aWindow); + }); +} + function getTestPlugin(aName) { var pluginName = aName || "Test Plug-in"; var ph = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost); @@ -611,6 +628,21 @@ function promiseTabLoadEvent(tab, url, eventType="load") return deferred.promise; } +/** + * Returns a Promise that resolves once a new tab has been opened in + * a xul:tabbrowser. + * + * @param aTabBrowser + * The xul:tabbrowser to monitor for a new tab. + * @return {Promise} + * Resolved when the new tab has been opened. + * @resolves to the TabOpen event that was fired. + * @rejects Never. + */ +function waitForNewTabEvent(aTabBrowser) { + return promiseWaitForEvent(aTabBrowser.tabContainer, "TabOpen"); +} + function assertWebRTCIndicatorStatus(expected) { let ui = Cu.import("resource:///modules/webrtcUI.jsm", {}).webrtcUI; let expectedState = expected ? "visible" : "hidden"; @@ -784,3 +816,26 @@ function promiseAutocompleteResultPopup(inputText, win = window) { return promiseSearchComplete(win); } + +/** + * Allows waiting for an observer notification once. + * + * @param aTopic + * Notification topic to observe. + * + * @return {Promise} + * @resolves An object with subject and data properties from the observed + * notification. + * @rejects Never. + */ +function promiseTopicObserved(aTopic) +{ + return new Promise((resolve) => { + Services.obs.addObserver( + function PTO_observe(aSubject, aTopic, aData) { + Services.obs.removeObserver(PTO_observe, aTopic); + resolve({subject: aSubject, data: aData}); + }, aTopic, false); + }); +} +