mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-03 18:47:53 +00:00
Bug 1719183 - part2 : expose the suspended state of window to chrome window for testing. r=nika
Before we use AudioContext's state as a hack to know the suspend status of window, but now we will prevent AudioContext from being suspended in the following patch. So we need to add a chrome-only attribute to expose that to the test. Differential Revision: https://phabricator.services.mozilla.com/D119838
This commit is contained in:
parent
1c18fb5f4d
commit
683790582e
@ -4851,3 +4851,15 @@ nsDOMWindowUtils::ResetMobileViewportManager() {
|
||||
// Unable to reset, so let's error out
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWindowUtils::GetSuspendedByBrowsingContextGroup(bool* aResult) {
|
||||
nsCOMPtr<nsPIDOMWindowOuter> window = do_QueryReferent(mWindow);
|
||||
NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<nsPIDOMWindowInner> inner = window->GetCurrentInnerWindow();
|
||||
NS_ENSURE_TRUE(inner, NS_ERROR_FAILURE);
|
||||
|
||||
*aResult = inner->GetWasSuspendedByGroup();
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -753,7 +753,7 @@ interface nsIDOMWindowUtils : nsISupports {
|
||||
/**
|
||||
* Send a native event as if the user double tapped the touchpad with two
|
||||
* fingers.
|
||||
*
|
||||
*
|
||||
* Widget support: macOS.
|
||||
* @param aScreenX, aScreenY screen coords of the focus point of this event.
|
||||
* @param aModifierFlags is expected to contain native modifier values.
|
||||
@ -2228,6 +2228,9 @@ interface nsIDOMWindowUtils : nsISupports {
|
||||
// will intentionally crash any non-parent process that tries to access
|
||||
// it.
|
||||
readonly attribute AString webrtcRawDeviceId;
|
||||
|
||||
// Used for testing to check the suspend status.
|
||||
readonly attribute bool suspendedByBrowsingContextGroup;
|
||||
};
|
||||
|
||||
[scriptable, uuid(c694e359-7227-4392-a138-33c0cc1f15a6)]
|
||||
|
@ -28,11 +28,11 @@ add_task(async function setupTestingPref() {
|
||||
add_task(async function testInactiveTabWouldBeSuspended() {
|
||||
info(`open a tab`);
|
||||
const tab = await createTab(PAGE_NON_AUTOPLAY);
|
||||
await shouldTabStateEqualTo(tab, "running");
|
||||
await assertIfWindowGetSuspended(tab, { shouldBeSuspended: false });
|
||||
|
||||
info(`tab should be suspended when it becomes inactive`);
|
||||
setTabActive(tab, false);
|
||||
await shouldTabStateEqualTo(tab, "suspended");
|
||||
await assertIfWindowGetSuspended(tab, { shouldBeSuspended: true });
|
||||
|
||||
info(`remove tab`);
|
||||
await tab.close();
|
||||
@ -41,28 +41,28 @@ add_task(async function testInactiveTabWouldBeSuspended() {
|
||||
add_task(async function testInactiveTabEverStartPlayingWontBeSuspended() {
|
||||
info(`open tab1 and play media`);
|
||||
const tab1 = await createTab(PAGE_NON_AUTOPLAY, { needCheck: true });
|
||||
await shouldTabStateEqualTo(tab1, "running");
|
||||
await assertIfWindowGetSuspended(tab1, { shouldBeSuspended: false });
|
||||
await playMedia(tab1, VIDEO_ID);
|
||||
|
||||
info(`tab with playing media won't be suspended when it becomes inactive`);
|
||||
setTabActive(tab1, false);
|
||||
await shouldTabStateEqualTo(tab1, "running");
|
||||
await assertIfWindowGetSuspended(tab1, { shouldBeSuspended: false });
|
||||
|
||||
info(
|
||||
`even if media is paused, keep tab running so that it could listen to media keys to control media in the future`
|
||||
);
|
||||
await pauseMedia(tab1, VIDEO_ID);
|
||||
await shouldTabStateEqualTo(tab1, "running");
|
||||
await assertIfWindowGetSuspended(tab1, { shouldBeSuspended: false });
|
||||
|
||||
info(`open tab2 and play media`);
|
||||
const tab2 = await createTab(PAGE_NON_AUTOPLAY, { needCheck: true });
|
||||
await shouldTabStateEqualTo(tab2, "running");
|
||||
await assertIfWindowGetSuspended(tab2, { shouldBeSuspended: false });
|
||||
await playMedia(tab2, VIDEO_ID);
|
||||
|
||||
info(
|
||||
`as inactive tab1 doesn't own main controller, it should be suspended again`
|
||||
);
|
||||
await shouldTabStateEqualTo(tab1, "suspended");
|
||||
await assertIfWindowGetSuspended(tab1, { shouldBeSuspended: true });
|
||||
|
||||
info(`remove tabs`);
|
||||
await Promise.all([tab1.close(), tab2.close()]);
|
||||
@ -73,43 +73,24 @@ add_task(async function testInactiveTabEverStartPlayingWontBeSuspended() {
|
||||
*/
|
||||
async function createTab(url, needCheck = false) {
|
||||
const tab = await createLoadedTabWrapper(url, { needCheck });
|
||||
await createStateObserver(tab);
|
||||
return tab;
|
||||
}
|
||||
|
||||
function createStateObserver(tab) {
|
||||
return SpecialPowers.spawn(tab.linkedBrowser, [], _ => {
|
||||
/**
|
||||
* Currently there is no API allowing us to observe tab's suspend state
|
||||
* directly, so we use a tricky way to observe that by checking AudioContext
|
||||
* state. Because AudioContext would change its state when tab is being
|
||||
* suspended or resumed.
|
||||
*/
|
||||
class StateObserver {
|
||||
constructor() {
|
||||
this.ac = new content.AudioContext();
|
||||
}
|
||||
getState() {
|
||||
return this.ac.state;
|
||||
}
|
||||
async waitUntilStateEqualTo(expectedState) {
|
||||
while (this.ac.state != expectedState) {
|
||||
info(`wait until tab state changes to '${expectedState}'`);
|
||||
await new Promise(r => (this.ac.onstatechange = r));
|
||||
}
|
||||
}
|
||||
function assertIfWindowGetSuspended(tab, { shouldBeSuspended }) {
|
||||
return SpecialPowers.spawn(
|
||||
tab.linkedBrowser,
|
||||
[shouldBeSuspended],
|
||||
expectedSuspend => {
|
||||
const isSuspended = content.windowUtils.suspendedByBrowsingContextGroup;
|
||||
is(
|
||||
expectedSuspend,
|
||||
isSuspended,
|
||||
`window suspended state (${isSuspended}) is equal to the expected`
|
||||
);
|
||||
}
|
||||
content.obs = new StateObserver();
|
||||
});
|
||||
);
|
||||
}
|
||||
|
||||
function setTabActive(tab, isActive) {
|
||||
tab.linkedBrowser.docShellIsActive = isActive;
|
||||
}
|
||||
|
||||
function shouldTabStateEqualTo(tab, state) {
|
||||
return SpecialPowers.spawn(tab.linkedBrowser, [state], async state => {
|
||||
await content.obs.waitUntilStateEqualTo(state);
|
||||
ok(content.obs.getState() == state, `correct tab state '${state}'`);
|
||||
});
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user