Source code

Revision control

Copy as Markdown

Other Tools

Test Info:

/* Any copyright is dedicated to the Public Domain.
"use strict";
async function getVisibility(tab) {
return SpecialPowers.spawn(
tab.linkedBrowser,
[],
() => content.document.visibilityState
);
}
async function isThrottled(tab) {
return SpecialPowers.spawn(
tab.linkedBrowser,
[],
() => SpecialPowers.DOMWindowUtils.effectivelyThrottlesFrameRequests
);
}
// Wait for the tab to be active / inactive
async function ensureActivity(tab, activity = true) {
await TestUtils.waitForCondition(
() => tab.linkedBrowser.browsingContext.isActive == activity,
`Waiting for tab isActive = ${activity}`
);
}
add_task(async function test_pip_opener_not_throttled() {
const [tab, chromePiP] = await newTabWithPiP();
// Baseline: Active tab with PiP
ok(tab.linkedBrowser.browsingContext.isActive, "Foreground opener is active");
ok(!(await isThrottled(tab)), "Foreground opener not throttled");
// Background tab with PiP, i.e. switch away from opener
info("Move opener to background by switching tabs");
const tab2 = await BrowserTestUtils.openNewForegroundTab({
gBrowser,
opening: "https://example.org",
waitForLoad: true,
});
ok(tab.linkedBrowser.browsingContext.isActive, "Background opener is active");
ok(!(await isThrottled(tab)), "Background opener not throttled");
is(await getVisibility(tab), "visible", "Background opener is visible");
// Verify switching back keeps opener visible, active etc.
info("Switch back to opener to ensure nothing breaks");
await BrowserTestUtils.switchTab(gBrowser, tab);
ok(
tab.linkedBrowser.browsingContext.isActive,
"Foreground opener stays active"
);
ok(!(await isThrottled(tab)), "Foreground opener stays unthrottled");
is(await getVisibility(tab), "visible", "Foreground opener stays visible");
// Move opener to background again and close PiP
info("Move back to other tab, close PiP, ensure throttling");
await BrowserTestUtils.switchTab(gBrowser, tab2);
ok(tab.linkedBrowser.browsingContext.isActive, "Background opener is active");
await BrowserTestUtils.closeWindow(chromePiP);
await ensureActivity(tab, false);
ok(!tab.linkedBrowser.browsingContext.isActive, "Background tab is inactive");
ok(await isThrottled(tab), "Background tab throttled");
is(await getVisibility(tab), "hidden", "Background tab is hidden");
// Verify switching back makes tab visible, active etc.
info("Move back to opener tab, ensure it becomes active");
await BrowserTestUtils.switchTab(gBrowser, tab);
await ensureActivity(tab);
ok(tab.linkedBrowser.browsingContext.isActive, "Tab becomes active again");
ok(!(await isThrottled(tab)), "Tab stopes being throttled");
is(await getVisibility(tab), "visible", "Tab becomes visible");
// Cleanup
BrowserTestUtils.removeTab(tab);
BrowserTestUtils.removeTab(tab2);
});
// Minimize / Restore app window
async function setMinimized(window, minimized = true) {
const promiseSizeModeChange = BrowserTestUtils.waitForEvent(
window,
"sizemodechange"
);
if (minimized) {
window.minimize();
} else {
window.restore();
}
await promiseSizeModeChange;
}
add_task(async function test_pip_throttling_window_hidden() {
const [tab, chromePiP] = await newTabWithPiP();
// Hide app window
await setMinimized(tab.ownerGlobal);
ok(tab.linkedBrowser.browsingContext.isActive, "Hidden opener is active");
ok(!(await isThrottled(tab)), "Hidden opener not throttled");
is(await getVisibility(tab), "visible", "Hidden opener is visible");
// Restore visibility
await setMinimized(tab.ownerGlobal, false);
ok(tab.linkedBrowser.browsingContext.isActive, "Visible opener is active");
ok(!(await isThrottled(tab)), "Visible opener not throttled");
is(await getVisibility(tab), "visible", "Visible opener is visible");
// Hide and close PiP
await setMinimized(tab.ownerGlobal);
ok(tab.linkedBrowser.browsingContext.isActive, "Hidden opener is active");
await BrowserTestUtils.closeWindow(chromePiP);
await ensureActivity(tab, false);
ok(!tab.linkedBrowser.browsingContext.isActive, "Hidden tab is inactive");
ok(await isThrottled(tab), "Hidden tab throttled");
is(await getVisibility(tab), "hidden", "Hidden tab is hidden");
// Restore visibility
await setMinimized(tab.ownerGlobal, false);
// Tab isn't immediately unthrottled after window is restored
await TestUtils.waitForCondition(
async () => !(await isThrottled(tab)),
"Wait for tab not throttled"
);
ok(tab.linkedBrowser.browsingContext.isActive, "Visible tab is active");
ok(!(await isThrottled(tab)), "Visible tab not throttled");
is(await getVisibility(tab), "visible", "Visible tab is visible");
// Cleanup
BrowserTestUtils.removeTab(tab);
});
add_task(async function test_pip_throttling_opener_tab_adoption() {
// Open a PiP and adopt the opener into a new window
// Request a small window to avoid timeouts from the other window not getting visible.
const [originalTab, chromePiP] = await newTabWithPiP({
width: 100,
height: 100,
});
const tab2win1 = await BrowserTestUtils.openNewForegroundTab({
gBrowser,
opening: "https://example.org",
waitForLoad: true,
});
const win2 = await BrowserTestUtils.openNewBrowserWindow();
const adoptedTab = win2.gBrowser.adoptTab(originalTab, 0, true);
// Minimize old window to ensure it's being throttled as the PiP was adopted away
await setMinimized(tab2win1.ownerGlobal);
ok(
!tab2win1.linkedBrowser.browsingContext.isActive,
"Hidden tab is inactive"
);
ok(await isThrottled(tab2win1), "Hidden tab throttled");
is(await getVisibility(tab2win1), "hidden", "Hidden tab is hidden");
// Adoping the opener currently closes the PiP (bug 2009192).
// So we cannot test that the new window isn't throttled.
// Cleanup
await setMinimized(tab2win1.ownerGlobal, false);
if (chromePiP && !chromePiP.closed) {
// See bug 2009192
await BrowserTestUtils.closeWindow(chromePiP);
}
BrowserTestUtils.removeTab(adoptedTab);
await BrowserTestUtils.closeWindow(win2);
BrowserTestUtils.removeTab(tab2win1);
});