summaryrefslogtreecommitdiffstats
path: root/browser/base/content/test/general/browser_domFullscreen_fullscreenMode.js
diff options
context:
space:
mode:
Diffstat (limited to 'browser/base/content/test/general/browser_domFullscreen_fullscreenMode.js')
-rw-r--r--browser/base/content/test/general/browser_domFullscreen_fullscreenMode.js237
1 files changed, 237 insertions, 0 deletions
diff --git a/browser/base/content/test/general/browser_domFullscreen_fullscreenMode.js b/browser/base/content/test/general/browser_domFullscreen_fullscreenMode.js
new file mode 100644
index 0000000000..c96fa6cf7b
--- /dev/null
+++ b/browser/base/content/test/general/browser_domFullscreen_fullscreenMode.js
@@ -0,0 +1,237 @@
+/* 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);
+
+function listenOneEvent(aEvent, aListener) {
+ function listener(evt) {
+ removeEventListener(aEvent, listener);
+ aListener(evt);
+ }
+ addEventListener(aEvent, listener);
+}
+
+function queryFullscreenState(browser) {
+ return SpecialPowers.spawn(browser, [], () => {
+ return {
+ inDOMFullscreen: !!content.document.fullscreenElement,
+ inFullscreen: content.fullScreen,
+ };
+ });
+}
+
+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(aBrowser) {
+ return SpecialPowers.spawn(aBrowser, [], () => {
+ return ContentTaskUtils.waitForCondition(
+ () => content.browsingContext.isActive && content.document.hasFocus()
+ );
+ });
+}
+
+function waitForFullscreenChanges(aBrowser, 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(aBrowser).then(() => {
+ if (!fullscreenData) {
+ queryFullscreenState(aBrowser).then(resolve);
+ } else {
+ resolve(fullscreenData);
+ }
+ });
+ }
+ }
+ if (aFlags & FS_CHANGE_SIZE) {
+ listenOneEvent("sizemodechange", () => {
+ sizemodeChanged = true;
+ tryResolve();
+ });
+ }
+ if (aFlags & FS_CHANGE_DOM) {
+ BrowserTestUtils.waitForContentEvent(aBrowser, "fullscreenchange").then(
+ async () => {
+ fullscreenData = await queryFullscreenState(aBrowser);
+ tryResolve();
+ }
+ );
+ }
+ });
+}
+
+var gTests = [
+ {
+ desc: "document method",
+ affectsFullscreenMode: false,
+ exitFunc: browser => {
+ SpecialPowers.spawn(browser, [], () => {
+ content.document.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 =
+ // eslint-disable-next-line @microsoft/sdl/no-insecure-url
+ "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) {
+ let fullscreenPromise = waitForFullscreenChanges(
+ gBrowser.selectedBrowser,
+ FS_CHANGE_SIZE
+ );
+ executeSoon(() => BrowserFullScreen());
+ await fullscreenPromise;
+ }
+ });
+
+ let tab = await BrowserTestUtils.openNewForegroundTab({
+ gBrowser,
+ url: kPage,
+ });
+ let browser = tab.linkedBrowser;
+
+ // As requestFullscreen checks the active state of the docshell,
+ // wait for the document to be activated, just to be sure that
+ // the fullscreen request won't be denied.
+ await waitForDocActivated(browser);
+
+ for (let test of gTests) {
+ let contentStates;
+ info("Testing exit DOM fullscreen via " + test.desc);
+
+ contentStates = await queryFullscreenState(browser);
+ checkState({ inDOMFullscreen: false, inFullscreen: false }, contentStates);
+
+ /* DOM fullscreen without fullscreen mode */
+
+ info("> Enter DOM fullscreen");
+ let fullscreenPromise = waitForFullscreenChanges(browser, FS_CHANGE_BOTH);
+ await SpecialPowers.spawn(browser, [], () => {
+ content.document.body.requestFullscreen();
+ });
+ contentStates = await fullscreenPromise;
+ checkState({ inDOMFullscreen: true, inFullscreen: true }, contentStates);
+
+ info("> Exit DOM fullscreen");
+ fullscreenPromise = waitForFullscreenChanges(browser, FS_CHANGE_BOTH);
+ test.exitFunc(browser);
+ contentStates = await fullscreenPromise;
+ 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.
+ fullscreenPromise = waitForFullscreenChanges(browser, FS_CHANGE_SIZE);
+ executeSoon(() => BrowserFullScreen());
+ contentStates = await fullscreenPromise;
+ checkState({ inDOMFullscreen: false, inFullscreen: true }, contentStates);
+
+ info("> Enter DOM fullscreen in fullscreen mode");
+ fullscreenPromise = waitForFullscreenChanges(browser, FS_CHANGE_DOM);
+ await SpecialPowers.spawn(browser, [], () => {
+ content.document.body.requestFullscreen();
+ });
+ contentStates = await fullscreenPromise;
+ checkState({ inDOMFullscreen: true, inFullscreen: true }, contentStates);
+
+ info("> Exit DOM fullscreen in fullscreen mode");
+ fullscreenPromise = waitForFullscreenChanges(
+ browser,
+ test.affectsFullscreenMode ? FS_CHANGE_BOTH : FS_CHANGE_DOM
+ );
+ test.exitFunc(browser);
+ contentStates = await fullscreenPromise;
+ checkState(
+ {
+ inDOMFullscreen: false,
+ inFullscreen: !test.affectsFullscreenMode,
+ },
+ contentStates
+ );
+
+ /* Cleanup */
+
+ // Exit fullscreen mode if we are still in
+ if (window.fullScreen) {
+ info("> Cleanup");
+ fullscreenPromise = waitForFullscreenChanges(browser, FS_CHANGE_SIZE);
+ executeSoon(() => BrowserFullScreen());
+ await fullscreenPromise;
+ }
+ }
+
+ BrowserTestUtils.removeTab(tab);
+});