forked from mirrors/gecko-dev
409 lines
13 KiB
JavaScript
409 lines
13 KiB
JavaScript
/* Any copyright is dedicated to the Public Domain.
|
|
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
|
|
|
/*
|
|
This test checks the recent-browsing view of open tabs in about:firefoxview next
|
|
presents the correct tab data in the correct order.
|
|
*/
|
|
|
|
const tabURL1 = "data:,Tab1";
|
|
const tabURL2 = "data:,Tab2";
|
|
const tabURL3 = "data:,Tab3";
|
|
const tabURL4 = "data:,Tab4";
|
|
|
|
let gInitialTab;
|
|
let gInitialTabURL;
|
|
const { NonPrivateTabs } = ChromeUtils.importESModule(
|
|
"resource:///modules/OpenTabs.sys.mjs"
|
|
);
|
|
|
|
add_setup(function () {
|
|
gInitialTab = gBrowser.selectedTab;
|
|
gInitialTabURL = tabUrl(gInitialTab);
|
|
});
|
|
|
|
function tabUrl(tab) {
|
|
return tab.linkedBrowser.currentURI?.spec;
|
|
}
|
|
|
|
async function minimizeWindow(win) {
|
|
let promiseSizeModeChange = BrowserTestUtils.waitForEvent(
|
|
win,
|
|
"sizemodechange"
|
|
);
|
|
win.minimize();
|
|
await promiseSizeModeChange;
|
|
ok(
|
|
!win.gBrowser.selectedTab.linkedBrowser.docShellIsActive,
|
|
"Docshell should be Inactive"
|
|
);
|
|
ok(win.document.hidden, "Top level window should be hidden");
|
|
}
|
|
|
|
async function restoreWindow(win) {
|
|
ok(win.document.hidden, "Top level window should be hidden");
|
|
let promiseSizeModeChange = BrowserTestUtils.waitForEvent(
|
|
win,
|
|
"sizemodechange"
|
|
);
|
|
|
|
// Check if we also need to wait for occlusion to be updated.
|
|
let promiseOcclusion;
|
|
let willWaitForOcclusion = win.isFullyOccluded;
|
|
if (willWaitForOcclusion) {
|
|
// Not only do we need to wait for the occlusionstatechange event,
|
|
// we also have to wait *one more event loop* to ensure that the
|
|
// other listeners to the occlusionstatechange events have fired.
|
|
// Otherwise, our browsing context might not have become active
|
|
// at the point where we receive the occlusionstatechange event.
|
|
promiseOcclusion = BrowserTestUtils.waitForEvent(
|
|
win,
|
|
"occlusionstatechange"
|
|
).then(() => new Promise(resolve => SimpleTest.executeSoon(resolve)));
|
|
} else {
|
|
promiseOcclusion = Promise.resolve();
|
|
}
|
|
|
|
info("Calling window.restore");
|
|
win.restore();
|
|
// From browser/base/content/test/general/browser_minimize.js:
|
|
// On Ubuntu `window.restore` doesn't seem to work, use a timer to make the
|
|
// test fail faster and more cleanly than with a test timeout.
|
|
info(
|
|
`Waiting for sizemodechange ${
|
|
willWaitForOcclusion ? "and occlusionstatechange " : ""
|
|
}event`
|
|
);
|
|
let timer;
|
|
await Promise.race([
|
|
Promise.all([promiseSizeModeChange, promiseOcclusion]),
|
|
new Promise((resolve, reject) => {
|
|
// eslint-disable-next-line mozilla/no-arbitrary-setTimeout
|
|
timer = setTimeout(() => {
|
|
reject(
|
|
`timed out waiting for sizemodechange sizemodechange ${
|
|
willWaitForOcclusion ? "and occlusionstatechange " : ""
|
|
}event`
|
|
);
|
|
}, 5000);
|
|
}),
|
|
]);
|
|
clearTimeout(timer);
|
|
ok(
|
|
win.gBrowser.selectedTab.linkedBrowser.docShellIsActive,
|
|
"Docshell should be active again"
|
|
);
|
|
ok(!win.document.hidden, "Top level window should be visible");
|
|
}
|
|
|
|
async function prepareOpenTabs(urls, win = window) {
|
|
const reusableTabURLs = ["about:newtab", "about:blank"];
|
|
const gBrowser = win.gBrowser;
|
|
|
|
for (let url of urls) {
|
|
if (
|
|
gBrowser.visibleTabs.length == 1 &&
|
|
reusableTabURLs.includes(gBrowser.selectedBrowser.currentURI.spec)
|
|
) {
|
|
// we'll load into this tab rather than opening a new one
|
|
info(
|
|
`Loading ${url} into blank tab: ${gBrowser.selectedBrowser.currentURI.spec}`
|
|
);
|
|
BrowserTestUtils.startLoadingURIString(gBrowser.selectedBrowser, url);
|
|
await BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser, null, url);
|
|
} else {
|
|
info(`Loading ${url} into new tab`);
|
|
await BrowserTestUtils.openNewForegroundTab(gBrowser, url);
|
|
}
|
|
await new Promise(res => win.requestAnimationFrame(res));
|
|
}
|
|
Assert.equal(
|
|
gBrowser.visibleTabs.length,
|
|
urls.length,
|
|
`Prepared ${urls.length} tabs as expected`
|
|
);
|
|
Assert.equal(
|
|
tabUrl(gBrowser.selectedTab),
|
|
urls[urls.length - 1],
|
|
"The selectedTab is the last of the URLs given as expected"
|
|
);
|
|
}
|
|
|
|
async function cleanup(...windowsToClose) {
|
|
await Promise.all(
|
|
windowsToClose.map(win => BrowserTestUtils.closeWindow(win))
|
|
);
|
|
|
|
while (gBrowser.visibleTabs.length > 1) {
|
|
await SessionStoreTestUtils.closeTab(gBrowser.tabs.at(-1));
|
|
}
|
|
if (gBrowser.selectedBrowser.currentURI.spec !== gInitialTabURL) {
|
|
BrowserTestUtils.startLoadingURIString(
|
|
gBrowser.selectedBrowser,
|
|
gInitialTabURL
|
|
);
|
|
await BrowserTestUtils.browserLoaded(
|
|
gBrowser.selectedBrowser,
|
|
null,
|
|
gInitialTabURL
|
|
);
|
|
}
|
|
}
|
|
|
|
function getOpenTabsComponent(browser) {
|
|
return browser.contentDocument.querySelector(
|
|
"view-recentbrowsing view-opentabs"
|
|
);
|
|
}
|
|
|
|
async function checkTabList(browser, expected) {
|
|
const tabsView = getOpenTabsComponent(browser);
|
|
const openTabsCard = tabsView.shadowRoot.querySelector("view-opentabs-card");
|
|
await tabsView.updateComplete;
|
|
const tabList = openTabsCard.shadowRoot.querySelector("fxview-tab-list");
|
|
await tabList.getUpdateComplete();
|
|
Assert.ok(tabList, "Found the tab list element");
|
|
await TestUtils.waitForCondition(() => tabList.rowEls.length);
|
|
let actual = Array.from(tabList.rowEls).map(row => row.url);
|
|
Assert.deepEqual(
|
|
actual,
|
|
expected,
|
|
"Tab list has items with URLs in the expected order"
|
|
);
|
|
}
|
|
|
|
add_task(async function test_single_window_tabs() {
|
|
await prepareOpenTabs([tabURL1, tabURL2]);
|
|
await openFirefoxViewTab(window).then(async viewTab => {
|
|
const browser = viewTab.linkedBrowser;
|
|
await checkTabList(browser, [tabURL2, tabURL1]);
|
|
|
|
// switch to the first tab
|
|
let promiseHidden = BrowserTestUtils.waitForEvent(
|
|
browser.contentDocument,
|
|
"visibilitychange"
|
|
);
|
|
|
|
let tabChangeRaised = BrowserTestUtils.waitForEvent(
|
|
NonPrivateTabs,
|
|
"TabRecencyChange"
|
|
);
|
|
await BrowserTestUtils.switchTab(gBrowser, gBrowser.visibleTabs[0]);
|
|
await promiseHidden;
|
|
await tabChangeRaised;
|
|
});
|
|
|
|
// and check the results in the open tabs section of Recent Browsing
|
|
await openFirefoxViewTab(window).then(async viewTab => {
|
|
const browser = viewTab.linkedBrowser;
|
|
await checkTabList(browser, [tabURL1, tabURL2]);
|
|
});
|
|
await cleanup();
|
|
});
|
|
|
|
add_task(async function test_multiple_window_tabs() {
|
|
const fxViewURL = getFirefoxViewURL();
|
|
const win1 = window;
|
|
let tabChangeRaised;
|
|
await prepareOpenTabs([tabURL1, tabURL2]);
|
|
const win2 = await BrowserTestUtils.openNewBrowserWindow();
|
|
await prepareOpenTabs([tabURL3, tabURL4], win2);
|
|
|
|
// to avoid confusing the results by activating different windows,
|
|
// check fxview in the current window - which is win2
|
|
info("Switching to fxview tab in win2");
|
|
await openFirefoxViewTab(win2).then(async viewTab => {
|
|
const browser = viewTab.linkedBrowser;
|
|
await checkTabList(browser, [tabURL4, tabURL3, tabURL2, tabURL1]);
|
|
|
|
Assert.equal(
|
|
tabUrl(win2.gBrowser.selectedTab),
|
|
fxViewURL,
|
|
`The selected tab in window 2 is ${fxViewURL}`
|
|
);
|
|
|
|
info("Switching to first tab (tab3) in win2");
|
|
tabChangeRaised = BrowserTestUtils.waitForEvent(
|
|
NonPrivateTabs,
|
|
"TabRecencyChange"
|
|
);
|
|
let promiseHidden = BrowserTestUtils.waitForEvent(
|
|
browser.contentDocument,
|
|
"visibilitychange"
|
|
);
|
|
await BrowserTestUtils.switchTab(
|
|
win2.gBrowser,
|
|
win2.gBrowser.visibleTabs[0]
|
|
);
|
|
Assert.equal(
|
|
tabUrl(win2.gBrowser.selectedTab),
|
|
tabURL3,
|
|
`The selected tab in window 2 is ${tabURL3}`
|
|
);
|
|
await tabChangeRaised;
|
|
await promiseHidden;
|
|
});
|
|
|
|
info("Opening fxview in win2 to confirm tab3 is most recent");
|
|
await openFirefoxViewTab(win2).then(async viewTab => {
|
|
const browser = viewTab.linkedBrowser;
|
|
info("Check result of selecting 1ist tab in window 2");
|
|
await checkTabList(browser, [tabURL3, tabURL4, tabURL2, tabURL1]);
|
|
});
|
|
|
|
info("Focusing win1, where tab2 should be selected");
|
|
tabChangeRaised = BrowserTestUtils.waitForEvent(
|
|
NonPrivateTabs,
|
|
"TabRecencyChange"
|
|
);
|
|
await SimpleTest.promiseFocus(win1);
|
|
await tabChangeRaised;
|
|
Assert.equal(
|
|
tabUrl(win1.gBrowser.selectedTab),
|
|
tabURL2,
|
|
`The selected tab in window 1 is ${tabURL2}`
|
|
);
|
|
|
|
info("Opening fxview in win1 to confirm tab2 is most recent");
|
|
await openFirefoxViewTab(win1).then(async viewTab => {
|
|
const browser = viewTab.linkedBrowser;
|
|
info(
|
|
"In fxview, check result of activating window 1, where tab 2 is selected"
|
|
);
|
|
await checkTabList(browser, [tabURL2, tabURL3, tabURL4, tabURL1]);
|
|
|
|
let promiseHidden = BrowserTestUtils.waitForEvent(
|
|
browser.contentDocument,
|
|
"visibilitychange"
|
|
);
|
|
tabChangeRaised = BrowserTestUtils.waitForEvent(
|
|
NonPrivateTabs,
|
|
"TabRecencyChange"
|
|
);
|
|
info("Switching to first visible tab (tab1) in win1");
|
|
await BrowserTestUtils.switchTab(
|
|
win1.gBrowser,
|
|
win1.gBrowser.visibleTabs[0]
|
|
);
|
|
await promiseHidden;
|
|
await tabChangeRaised;
|
|
});
|
|
|
|
// check result in the fxview in the 1st window
|
|
info("Opening fxview in win1 to confirm tab1 is most recent");
|
|
await openFirefoxViewTab(win1).then(async viewTab => {
|
|
const browser = viewTab.linkedBrowser;
|
|
info("Check result of selecting 1st tab in win1");
|
|
await checkTabList(browser, [tabURL1, tabURL2, tabURL3, tabURL4]);
|
|
});
|
|
|
|
await cleanup(win2);
|
|
});
|
|
|
|
add_task(async function test_windows_activation() {
|
|
const win1 = window;
|
|
await prepareOpenTabs([tabURL1], win1);
|
|
let fxViewTab;
|
|
let tabChangeRaised;
|
|
info("switch to firefox-view and leave it selected");
|
|
await openFirefoxViewTab(win1).then(tab => (fxViewTab = tab));
|
|
|
|
const win2 = await BrowserTestUtils.openNewBrowserWindow();
|
|
await prepareOpenTabs([tabURL2], win2);
|
|
|
|
const win3 = await BrowserTestUtils.openNewBrowserWindow();
|
|
await prepareOpenTabs([tabURL3], win3);
|
|
await tabChangeRaised;
|
|
|
|
tabChangeRaised = BrowserTestUtils.waitForEvent(
|
|
NonPrivateTabs,
|
|
"TabRecencyChange"
|
|
);
|
|
await SimpleTest.promiseFocus(win1);
|
|
await tabChangeRaised;
|
|
|
|
const browser = fxViewTab.linkedBrowser;
|
|
await checkTabList(browser, [tabURL3, tabURL2, tabURL1]);
|
|
|
|
info("switch to win2 and confirm its selected tab becomes most recent");
|
|
tabChangeRaised = BrowserTestUtils.waitForEvent(
|
|
NonPrivateTabs,
|
|
"TabRecencyChange"
|
|
);
|
|
await SimpleTest.promiseFocus(win2);
|
|
await tabChangeRaised;
|
|
await checkTabList(browser, [tabURL2, tabURL3, tabURL1]);
|
|
await cleanup(win2, win3);
|
|
});
|
|
|
|
add_task(async function test_minimize_restore_windows() {
|
|
const win1 = window;
|
|
let tabChangeRaised;
|
|
await prepareOpenTabs([tabURL1, tabURL2]);
|
|
const win2 = await BrowserTestUtils.openNewBrowserWindow();
|
|
await prepareOpenTabs([tabURL3, tabURL4], win2);
|
|
|
|
// to avoid confusing the results by activating different windows,
|
|
// check fxview in the current window - which is win2
|
|
info("Opening fxview in win2 to confirm tab4 is most recent");
|
|
await openFirefoxViewTab(win2).then(async viewTab => {
|
|
const browser = viewTab.linkedBrowser;
|
|
await checkTabList(browser, [tabURL4, tabURL3, tabURL2, tabURL1]);
|
|
|
|
let promiseHidden = BrowserTestUtils.waitForEvent(
|
|
browser.contentDocument,
|
|
"visibilitychange"
|
|
);
|
|
tabChangeRaised = BrowserTestUtils.waitForEvent(
|
|
NonPrivateTabs,
|
|
"TabRecencyChange"
|
|
);
|
|
info("Switching to the first tab (tab3) in 2nd window");
|
|
await BrowserTestUtils.switchTab(
|
|
win2.gBrowser,
|
|
win2.gBrowser.visibleTabs[0]
|
|
);
|
|
await promiseHidden;
|
|
await tabChangeRaised;
|
|
});
|
|
|
|
// then minimize the window, focusing the 1st window
|
|
info("Minimizing win2, leaving tab 3 selected");
|
|
tabChangeRaised = BrowserTestUtils.waitForEvent(
|
|
NonPrivateTabs,
|
|
"TabRecencyChange"
|
|
);
|
|
await minimizeWindow(win2);
|
|
info("Focusing win1, where tab2 is selected - making it most recent");
|
|
await SimpleTest.promiseFocus(win1);
|
|
await tabChangeRaised;
|
|
|
|
Assert.equal(
|
|
tabUrl(win1.gBrowser.selectedTab),
|
|
tabURL2,
|
|
`The selected tab in window 1 is ${tabURL2}`
|
|
);
|
|
|
|
info("Opening fxview in win1 to confirm tab2 is most recent");
|
|
await openFirefoxViewTab(win1).then(async viewTab => {
|
|
const browser = viewTab.linkedBrowser;
|
|
await checkTabList(browser, [tabURL2, tabURL3, tabURL4, tabURL1]);
|
|
info(
|
|
"Restoring win2 and focusing it - which should make its selected tab most recent"
|
|
);
|
|
tabChangeRaised = BrowserTestUtils.waitForEvent(
|
|
NonPrivateTabs,
|
|
"TabRecencyChange"
|
|
);
|
|
await restoreWindow(win2);
|
|
await SimpleTest.promiseFocus(win2);
|
|
await tabChangeRaised;
|
|
|
|
info(
|
|
"Checking tab order in fxview in win1, to confirm tab3 is most recent"
|
|
);
|
|
await checkTabList(browser, [tabURL3, tabURL2, tabURL4, tabURL1]);
|
|
});
|
|
|
|
await cleanup(win2);
|
|
});
|