gecko-dev/browser/base/content/test/general/browser_domFullscreen_fullscreenMode.js
Neil Deakin 75efe08ebc Bug 1595154, replace the frame script FormAutofillFrameScript.js with an actor and fix up setTimeout calls in places that were relying on Timer.jsm being loaded in that frame script, r=MattN
Differential Revision: https://phabricator.services.mozilla.com/D52721

--HG--
rename : browser/extensions/formautofill/content/FormAutofillFrameScript.js => browser/extensions/formautofill/FormAutofillChild.jsm
extra : moz-landing-system : lando
2019-12-11 13:37:51 +00:00

274 lines
8.2 KiB
JavaScript

/* eslint-env mozilla/frame-script */
/* eslint-disable mozilla/no-arbitrary-setTimeout */
"use strict";
// 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);
var gMessageManager;
function frameScript() {
addMessageListener("Test:RequestFullscreen", () => {
content.document.body.requestFullscreen();
});
addMessageListener("Test:ExitFullscreen", () => {
content.document.exitFullscreen();
});
addMessageListener("Test:QueryFullscreenState", () => {
sendAsyncMessage("Test:FullscreenState", {
inDOMFullscreen: !!content.document.fullscreenElement,
inFullscreen: content.fullScreen,
});
});
addMessageListener("Test:WaitActivated", () => {
waitUntilActive();
});
content.document.addEventListener("fullscreenchange", () => {
sendAsyncMessage("Test:FullscreenChanged", {
inDOMFullscreen: !!content.document.fullscreenElement,
inFullscreen: content.fullScreen,
});
});
function waitUntilActive() {
if (docShell.isActive && content.document.hasFocus()) {
sendAsyncMessage("Test:Activated");
} else {
content.setTimeout(waitUntilActive, 10);
}
}
waitUntilActive();
}
function listenOneMessage(aMsg, aListener) {
function listener({ data }) {
gMessageManager.removeMessageListener(aMsg, listener);
aListener(data);
}
gMessageManager.addMessageListener(aMsg, listener);
}
function listenOneEvent(aEvent, aListener) {
function listener(evt) {
removeEventListener(aEvent, listener);
aListener(evt);
}
addEventListener(aEvent, listener);
}
function queryFullscreenState() {
return new Promise(resolve => {
listenOneMessage("Test:FullscreenState", resolve);
gMessageManager.sendAsyncMessage("Test:QueryFullscreenState");
});
}
function captureUnexpectedFullscreenChange() {
ok(false, "catched an unexpected fullscreen change");
}
const FS_CHANGE_DOM = 1 << 0;
const FS_CHANGE_SIZE = 1 << 1;
const FS_CHANGE_BOTH = FS_CHANGE_DOM | FS_CHANGE_SIZE;
function waitForDocActivated() {
return new Promise(resolve => {
listenOneMessage("Test:Activated", resolve);
gMessageManager.sendAsyncMessage("Test:WaitActivated");
});
}
function waitForFullscreenChanges(aFlags) {
return new Promise(resolve => {
let fullscreenData = null;
let sizemodeChanged = false;
function tryResolve() {
if (
(!(aFlags & FS_CHANGE_DOM) || fullscreenData) &&
(!(aFlags & FS_CHANGE_SIZE) || sizemodeChanged)
) {
// In the platforms that support reporting occlusion state (e.g. Mac),
// enter/exit fullscreen mode will trigger docshell being set to
// non-activate and then set to activate back again.
// For those platform, we should wait until the docshell has been
// activated again, otherwise, the fullscreen request might be denied.
waitForDocActivated().then(() => {
if (!fullscreenData) {
queryFullscreenState().then(resolve);
} else {
resolve(fullscreenData);
}
});
}
}
if (aFlags & FS_CHANGE_SIZE) {
listenOneEvent("sizemodechange", () => {
sizemodeChanged = true;
tryResolve();
});
}
if (aFlags & FS_CHANGE_DOM) {
gMessageManager.removeMessageListener(
"Test:FullscreenChanged",
captureUnexpectedFullscreenChange
);
listenOneMessage("Test:FullscreenChanged", data => {
gMessageManager.addMessageListener(
"Test:FullscreenChanged",
captureUnexpectedFullscreenChange
);
fullscreenData = data;
tryResolve();
});
}
});
}
var gTests = [
{
desc: "document method",
affectsFullscreenMode: false,
exitFunc: () => {
gMessageManager.sendAsyncMessage("Test:ExitFullscreen");
},
},
{
desc: "escape key",
affectsFullscreenMode: false,
exitFunc: () => {
executeSoon(() => EventUtils.synthesizeKey("KEY_Escape"));
},
},
{
desc: "F11 key",
affectsFullscreenMode: true,
exitFunc() {
executeSoon(() => EventUtils.synthesizeKey("KEY_F11"));
},
},
];
function checkState(expectedStates, contentStates) {
is(
contentStates.inDOMFullscreen,
expectedStates.inDOMFullscreen,
"The DOM fullscreen state of the content should match"
);
// TODO window.fullScreen is not updated as soon as the fullscreen
// state flips in child process, hence checking it could cause
// anonying intermittent failure. As we just want to confirm the
// fullscreen state of the browser window, we can just check the
// that on the chrome window below.
// is(contentStates.inFullscreen, expectedStates.inFullscreen,
// "The fullscreen state of the content should match");
is(
!!document.fullscreenElement,
expectedStates.inDOMFullscreen,
"The DOM fullscreen state of the chrome should match"
);
is(
window.fullScreen,
expectedStates.inFullscreen,
"The fullscreen state of the chrome should match"
);
}
const kPage =
"http://example.org/browser/browser/" +
"base/content/test/general/dummy_page.html";
add_task(async function() {
await pushPrefs(
["full-screen-api.transition-duration.enter", "0 0"],
["full-screen-api.transition-duration.leave", "0 0"]
);
registerCleanupFunction(async function() {
if (window.fullScreen) {
executeSoon(() => BrowserFullScreen());
await waitForFullscreenChanges(FS_CHANGE_SIZE);
}
});
let tab = await BrowserTestUtils.openNewForegroundTab({
gBrowser,
url: kPage,
});
let browser = tab.linkedBrowser;
gMessageManager = browser.messageManager;
gMessageManager.loadFrameScript(
"data:,(" + frameScript.toString() + ")();",
false
);
gMessageManager.addMessageListener(
"Test:FullscreenChanged",
captureUnexpectedFullscreenChange
);
// Wait for the document being activated, so that
// fullscreen request won't be denied.
await new Promise(resolve => listenOneMessage("Test:Activated", resolve));
for (let test of gTests) {
let contentStates;
info("Testing exit DOM fullscreen via " + test.desc);
contentStates = await queryFullscreenState();
checkState({ inDOMFullscreen: false, inFullscreen: false }, contentStates);
/* DOM fullscreen without fullscreen mode */
info("> Enter DOM fullscreen");
gMessageManager.sendAsyncMessage("Test:RequestFullscreen");
contentStates = await waitForFullscreenChanges(FS_CHANGE_BOTH);
checkState({ inDOMFullscreen: true, inFullscreen: true }, contentStates);
info("> Exit DOM fullscreen");
test.exitFunc();
contentStates = await waitForFullscreenChanges(FS_CHANGE_BOTH);
checkState({ inDOMFullscreen: false, inFullscreen: false }, contentStates);
/* DOM fullscreen with fullscreen mode */
info("> Enter fullscreen mode");
// Need to be asynchronous because sizemodechange event could be
// dispatched synchronously, which would cause the event listener
// miss that event and wait infinitely.
executeSoon(() => BrowserFullScreen());
contentStates = await waitForFullscreenChanges(FS_CHANGE_SIZE);
checkState({ inDOMFullscreen: false, inFullscreen: true }, contentStates);
info("> Enter DOM fullscreen in fullscreen mode");
gMessageManager.sendAsyncMessage("Test:RequestFullscreen");
contentStates = await waitForFullscreenChanges(FS_CHANGE_DOM);
checkState({ inDOMFullscreen: true, inFullscreen: true }, contentStates);
info("> Exit DOM fullscreen in fullscreen mode");
test.exitFunc();
contentStates = await waitForFullscreenChanges(
test.affectsFullscreenMode ? FS_CHANGE_BOTH : FS_CHANGE_DOM
);
checkState(
{
inDOMFullscreen: false,
inFullscreen: !test.affectsFullscreenMode,
},
contentStates
);
/* Cleanup */
// Exit fullscreen mode if we are still in
if (window.fullScreen) {
info("> Cleanup");
executeSoon(() => BrowserFullScreen());
await waitForFullscreenChanges(FS_CHANGE_SIZE);
}
}
BrowserTestUtils.removeTab(tab);
});