forked from mirrors/gecko-dev
This adds an additional action that is triggered when the fullscreen transition event is received. That interim action is used to re-focus the original tab. Without this change, an asynchronous fullscreen transition will silently swallow the MozAfterPaint event that is necessary to detect the end of fullscreen. Before this change, with asynchronous transitions, here's the flow: 1) The test opens Tab 1 which opens Tab 2. 2) Tab 1 enters fullscreen. This transition takes awhile but signals success early. This is intentional because we want web content to be able to be fully layed out when the fullscreen transition is complete. 3) Thinking that it has reached fullscreen, the test focuses Tab 2, which causes a fullscreen exit transition to be queued up but not yet run. Then Tab 1 is unfocused and a MozAfterPaint message is sent, but nobody is listening for it so it has no effect. If the fullscreen transition was synchronous, the actions of Step 6 (below) would happen before the change in focus and there would be an event listener ready for the MozAfterPaint event. 4) The test waits for the DOMFullscreenChild to send the DOMFullscreen:Painted message, which it will do when it receives a MozAfterPaint event. 5) Enter fullscreen transition completes, exit fullscreen transition starts. 6) The MozDOMFullscreen:Exited event is sent to the DOMFullscreenChild, which starts listening for the MozAfterPaint event. This event has already been sent. 7) Test times out. This change adds an additional action to take place between steps 6 and 7. That additional action refocuses Tab 1. This makes it send another MozAfterPaint event which the DOMFullscreenChild is ready to receive. Differential Revision: https://phabricator.services.mozilla.com/D180884
136 lines
4.1 KiB
JavaScript
136 lines
4.1 KiB
JavaScript
/* Any copyright is dedicated to the Public Domain.
|
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
|
|
|
"use strict";
|
|
|
|
async function pause() {
|
|
/* eslint-disable mozilla/no-arbitrary-setTimeout */
|
|
return new Promise(resolve => setTimeout(resolve, 500));
|
|
}
|
|
|
|
// This test tends to trigger a race in the fullscreen time telemetry,
|
|
// where the fullscreen enter and fullscreen exit events (which use the
|
|
// same histogram ID) overlap. That causes TelemetryStopwatch to log an
|
|
// error.
|
|
SimpleTest.ignoreAllUncaughtExceptions(true);
|
|
|
|
const IFRAME_ID = "testIframe";
|
|
|
|
async function testWindowFocus(isPopup, iframeID) {
|
|
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_URL);
|
|
|
|
info("Calling window.open()");
|
|
let openedWindow = await jsWindowOpen(tab.linkedBrowser, isPopup, iframeID);
|
|
info("Letting OOP focus to stabilize");
|
|
await pause(); // Bug 1719659 for proper fix
|
|
info("re-focusing main window");
|
|
await waitForFocus(tab.linkedBrowser);
|
|
|
|
info("Entering full-screen");
|
|
await changeFullscreen(tab.linkedBrowser, true);
|
|
|
|
await testExpectFullScreenExit(
|
|
tab.linkedBrowser,
|
|
true,
|
|
async () => {
|
|
info("Calling window.focus()");
|
|
await jsWindowFocus(tab.linkedBrowser, iframeID);
|
|
},
|
|
() => {
|
|
// Async fullscreen transitions will swallow the repaint of the tab,
|
|
// preventing us from detecting that we've successfully changed
|
|
// fullscreen. Supply an action to switch back to the tab after the
|
|
// fullscreen event has been received, which will ensure that the
|
|
// tab is repainted when the DOMFullscreenChild is listening for it.
|
|
info("Calling switchTab()");
|
|
BrowserTestUtils.switchTab(gBrowser, tab);
|
|
}
|
|
);
|
|
|
|
// Cleanup
|
|
if (isPopup) {
|
|
openedWindow.close();
|
|
} else {
|
|
BrowserTestUtils.removeTab(openedWindow);
|
|
}
|
|
BrowserTestUtils.removeTab(tab);
|
|
}
|
|
|
|
async function testWindowElementFocus(isPopup) {
|
|
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_URL);
|
|
|
|
info("Calling window.open()");
|
|
let openedWindow = await jsWindowOpen(tab.linkedBrowser, isPopup);
|
|
info("Letting OOP focus to stabilize");
|
|
await pause(); // Bug 1719659 for proper fix
|
|
info("re-focusing main window");
|
|
await waitForFocus(tab.linkedBrowser);
|
|
|
|
info("Entering full-screen");
|
|
await changeFullscreen(tab.linkedBrowser, true);
|
|
|
|
await testExpectFullScreenExit(
|
|
tab.linkedBrowser,
|
|
false,
|
|
async () => {
|
|
info("Calling element.focus() on popup");
|
|
await ContentTask.spawn(tab.linkedBrowser, {}, async args => {
|
|
await content.wrappedJSObject.sendMessage(
|
|
content.wrappedJSObject.openedWindow,
|
|
"elementfocus"
|
|
);
|
|
});
|
|
},
|
|
() => {
|
|
// Async fullscreen transitions will swallow the repaint of the tab,
|
|
// preventing us from detecting that we've successfully changed
|
|
// fullscreen. Supply an action to switch back to the tab after the
|
|
// fullscreen event has been received, which will ensure that the
|
|
// tab is repainted when the DOMFullscreenChild is listening for it.
|
|
info("Calling switchTab()");
|
|
BrowserTestUtils.switchTab(gBrowser, tab);
|
|
}
|
|
);
|
|
|
|
// Cleanup
|
|
await changeFullscreen(tab.linkedBrowser, false);
|
|
if (isPopup) {
|
|
openedWindow.close();
|
|
} else {
|
|
BrowserTestUtils.removeTab(openedWindow);
|
|
}
|
|
BrowserTestUtils.removeTab(tab);
|
|
}
|
|
|
|
add_setup(async function () {
|
|
await SpecialPowers.pushPrefEnv({
|
|
set: [
|
|
["dom.disable_open_during_load", false], // Allow window.focus calls without user interaction
|
|
["browser.link.open_newwindow.disabled_in_fullscreen", false],
|
|
],
|
|
});
|
|
});
|
|
|
|
add_task(function test_popupWindowFocus() {
|
|
return testWindowFocus(true);
|
|
});
|
|
|
|
add_task(function test_iframePopupWindowFocus() {
|
|
return testWindowFocus(true, IFRAME_ID);
|
|
});
|
|
|
|
add_task(function test_popupWindowElementFocus() {
|
|
return testWindowElementFocus(true);
|
|
});
|
|
|
|
add_task(function test_backgroundTabFocus() {
|
|
return testWindowFocus(false);
|
|
});
|
|
|
|
add_task(function test_iframebackgroundTabFocus() {
|
|
return testWindowFocus(false, IFRAME_ID);
|
|
});
|
|
|
|
add_task(function test_backgroundTabElementFocus() {
|
|
return testWindowElementFocus(false);
|
|
});
|