diff options
Diffstat (limited to 'dom/base/test/browser_bug1303838.js')
-rw-r--r-- | dom/base/test/browser_bug1303838.js | 374 |
1 files changed, 374 insertions, 0 deletions
diff --git a/dom/base/test/browser_bug1303838.js b/dom/base/test/browser_bug1303838.js new file mode 100644 index 0000000000..357167394d --- /dev/null +++ b/dom/base/test/browser_bug1303838.js @@ -0,0 +1,374 @@ +/* -*- Mode: JavaScript; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +/** + * Test for bug 1303838. + * Load a tab with some links, emulate link clicks and check if the + * browser would switch to the existing target tab opened by previous + * link click if loadDivertedInBackground is set to true. + */ + +"use strict"; + +const BASE_URL = "http://mochi.test:8888/browser/dom/base/test/"; + +add_task(async function() { + // On Linux, in our test automation, the mouse cursor floats over + // the first tab, which causes it to be warmed up when tab warming + // is enabled. The TabSwitchDone event doesn't fire until the warmed + // tab is evicted, which is after a few seconds. That means that + // this test ends up taking longer than we'd like, since its waiting + // for the TabSwitchDone event between tab switches. + // + // So now we make sure that warmed tabs are evicted very shortly + // after warming to avoid the test running too long. + await SpecialPowers.pushPrefEnv({ + set: [["browser.tabs.remote.warmup.unloadDelayMs", 50]], + }); + await testLinkClick(false, false); + await testLinkClick(false, true); + await testLinkClick(true, false); + await testLinkClick(true, true); +}); + +async function waitForTestReady(loadDivertedInBackground, tab) { + if (!loadDivertedInBackground) { + await BrowserTestUtils.switchTab(gBrowser, tab); + } else { + await new Promise(resolve => setTimeout(resolve, 0)); + } +} + +async function testLinkClick(withFrame, loadDivertedInBackground) { + await SpecialPowers.pushPrefEnv({ + set: [["browser.tabs.loadDivertedInBackground", loadDivertedInBackground]], + }); + + let tab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + BASE_URL + + (withFrame ? "file_bug1303838_with_iframe.html" : "file_bug1303838.html") + ); + is(gBrowser.tabs.length, 2, "check tabs.length"); + is(gBrowser.selectedTab, tab, "check selectedTab"); + + info( + "Test normal links with loadDivertedInBackground=" + + loadDivertedInBackground + + ", withFrame=" + + withFrame + ); + + let testTabPromise = BrowserTestUtils.waitForNewTab(gBrowser); + await clickLink(withFrame, "#link-1", tab.linkedBrowser); + let testTab = await testTabPromise; + is(gBrowser.tabs.length, 3, "check tabs.length"); + is( + gBrowser.selectedTab, + loadDivertedInBackground ? tab : testTab, + "check selectedTab" + ); + + await waitForTestReady(loadDivertedInBackground, tab); + await clickLink( + withFrame, + "#link-2", + tab.linkedBrowser, + testTab.linkedBrowser, + !loadDivertedInBackground + ); + is(gBrowser.tabs.length, 3, "check tabs.length"); + is( + gBrowser.selectedTab, + loadDivertedInBackground ? tab : testTab, + "check selectedTab" + ); + + await waitForTestReady(loadDivertedInBackground, tab); + await clickLink( + withFrame, + "#link-3", + tab.linkedBrowser, + testTab.linkedBrowser, + !loadDivertedInBackground + ); + is(gBrowser.tabs.length, 3, "check tabs.length"); + is( + gBrowser.selectedTab, + loadDivertedInBackground ? tab : testTab, + "check selectedTab" + ); + + await waitForTestReady(loadDivertedInBackground, tab); + await clickLink( + withFrame, + "#link-4", + tab.linkedBrowser, + testTab.linkedBrowser, + !loadDivertedInBackground + ); + is(gBrowser.tabs.length, 3, "check tabs.length"); + is( + gBrowser.selectedTab, + loadDivertedInBackground ? tab : testTab, + "check selectedTab" + ); + + // Location APIs shouldn't steal focus. + await waitForTestReady(loadDivertedInBackground, tab); + await clickLink( + withFrame, + "#link-5", + tab.linkedBrowser, + testTab.linkedBrowser, + /* awaitTabSwitch = */ false + ); + is(gBrowser.tabs.length, 3, "check tabs.length"); + is(gBrowser.selectedTab, tab, "check selectedTab"); + + await waitForTestReady(/* diverted = */ true, tab); + await clickLink( + withFrame, + "#link-6", + tab.linkedBrowser, + testTab.linkedBrowser, + /* awaitTabSwitch = */ false + ); + is(gBrowser.tabs.length, 3, "check tabs.length"); + is(gBrowser.selectedTab, tab, "check selectedTab"); + + await waitForTestReady(/* diverted = */ true, tab); + let loaded = BrowserTestUtils.browserLoaded( + testTab.linkedBrowser, + true, + "data:text/html;charset=utf-8,testFrame" + ); + await clickLink( + withFrame, + "#link-7", + tab.linkedBrowser, + testTab.linkedBrowser, + !loadDivertedInBackground, + false + ); + await loaded; + is(gBrowser.tabs.length, 3, "check tabs.length"); + is( + gBrowser.selectedTab, + loadDivertedInBackground ? tab : testTab, + "check selectedTab" + ); + + info( + "Test anchor links with loadDivertedInBackground=" + + loadDivertedInBackground + + ", withFrame=" + + withFrame + ); + + await waitForTestReady(loadDivertedInBackground, tab); + await clickLink( + withFrame, + "#anchor-link-1", + tab.linkedBrowser, + testTab.linkedBrowser, + !loadDivertedInBackground + ); + is(gBrowser.tabs.length, 3, "check tabs.length"); + is( + gBrowser.selectedTab, + loadDivertedInBackground ? tab : testTab, + "check selectedTab" + ); + + await waitForTestReady(loadDivertedInBackground, tab); + await clickLink( + withFrame, + "#anchor-link-2", + tab.linkedBrowser, + testTab.linkedBrowser, + !loadDivertedInBackground + ); + is(gBrowser.tabs.length, 3, "check tabs.length"); + is( + gBrowser.selectedTab, + loadDivertedInBackground ? tab : testTab, + "check selectedTab" + ); + + await waitForTestReady(loadDivertedInBackground, tab); + await clickLink( + withFrame, + "#anchor-link-3", + tab.linkedBrowser, + testTab.linkedBrowser, + !loadDivertedInBackground + ); + is(gBrowser.tabs.length, 3, "check tabs.length"); + is( + gBrowser.selectedTab, + loadDivertedInBackground ? tab : testTab, + "check selectedTab" + ); + + info( + "Test iframe links with loadDivertedInBackground=" + + loadDivertedInBackground + + ", withFrame=" + + withFrame + ); + + await waitForTestReady(loadDivertedInBackground, tab); + await clickLink( + withFrame, + "#frame-link-1", + tab.linkedBrowser, + testTab.linkedBrowser, + !loadDivertedInBackground, + true + ); + is(gBrowser.tabs.length, 3, "check tabs.length"); + is( + gBrowser.selectedTab, + loadDivertedInBackground ? tab : testTab, + "check selectedTab" + ); + + await waitForTestReady(loadDivertedInBackground, tab); + await clickLink( + withFrame, + "#frame-link-2", + tab.linkedBrowser, + testTab.linkedBrowser, + !loadDivertedInBackground, + true + ); + is(gBrowser.tabs.length, 3, "check tabs.length"); + is( + gBrowser.selectedTab, + loadDivertedInBackground ? tab : testTab, + "check selectedTab" + ); + + await waitForTestReady(loadDivertedInBackground, tab); + await clickLink( + withFrame, + "#frame-link-3", + tab.linkedBrowser, + testTab.linkedBrowser, + !loadDivertedInBackground, + true + ); + is(gBrowser.tabs.length, 3, "check tabs.length"); + is( + gBrowser.selectedTab, + loadDivertedInBackground ? tab : testTab, + "check selectedTab" + ); + + BrowserTestUtils.removeTab(testTab); + BrowserTestUtils.removeTab(tab); +} + +function clickLink( + isFrame, + linkId, + browser, + testBrowser, + awaitTabSwitch = false, + targetsFrame = false, + locationChangeNum = 1 +) { + let promises = []; + if (awaitTabSwitch) { + promises.push(waitForTabSwitch(gBrowser)); + } + if (testBrowser) { + promises.push( + waitForLocationChange(targetsFrame, testBrowser, locationChangeNum) + ); + } + promises.push( + SpecialPowers.spawn( + browser, + [[isFrame, linkId]], + ([contentIsFrame, contentLinkId]) => { + let doc = content.document; + if (contentIsFrame) { + let frame = content.document.getElementById("frame"); + doc = frame.contentDocument; + } + info("Clicking " + contentLinkId); + doc.querySelector(contentLinkId).click(); + } + ) + ); + return Promise.all(promises); +} + +function waitForTabSwitch(tabbrowser) { + info("Waiting for TabSwitch"); + return new Promise(resolve => { + tabbrowser.addEventListener("TabSwitchDone", function onSwitch() { + info("TabSwitch done"); + tabbrowser.removeEventListener("TabSwitchDone", onSwitch); + resolve(tabbrowser.selectedTab); + }); + }); +} + +let locationChangeListener; +function waitForLocationChange(isFrame, browser, locationChangeNum) { + if (isFrame) { + return waitForFrameLocationChange(browser, locationChangeNum); + } + + info("Waiting for " + locationChangeNum + " LocationChange"); + return new Promise(resolve => { + let seen = 0; + locationChangeListener = { + onLocationChange(aWebProgress, aRequest, aLocation, aFlags) { + info("LocationChange: " + aLocation.spec); + if (++seen == locationChangeNum) { + browser.removeProgressListener(this); + resolve(); + } + }, + QueryInterface: ChromeUtils.generateQI([ + "nsIWebProgressListener", + "nsISupportsWeakReference", + ]), + }; + browser.addProgressListener(locationChangeListener); + }); +} + +function waitForFrameLocationChange(browser, locationChangeNum) { + info("Waiting for " + locationChangeNum + " LocationChange in subframe"); + return SpecialPowers.spawn(browser, [locationChangeNum], async changeNum => { + let seen = 0; + let webprogress = content.docShell.QueryInterface(Ci.nsIWebProgress); + await new Promise(resolve => { + locationChangeListener = { + onLocationChange(aWebProgress, aRequest, aLocation, aFlags) { + info("LocationChange: " + aLocation.spec); + if (++seen == changeNum) { + resolve(); + } + }, + QueryInterface: ChromeUtils.generateQI([ + "nsIWebProgressListener", + "nsISupportsWeakReference", + ]), + }; + webprogress.addProgressListener( + locationChangeListener, + Ci.nsIWebProgress.NOTIFY_LOCATION + ); + }); + webprogress.removeProgressListener(locationChangeListener); + }); +} |