Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Errors

/* -*- 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";
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)
);
}
info("BC children: " + browser.browsingContext.children.length);
promises.push(
BrowserTestUtils.synthesizeMouseAtCenter(
linkId,
{},
isFrame ? browser.browsingContext.children[0] : browser
)
);
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);
});
}