From e688d45a19b264945b9960fc30007c1abd55d934 Mon Sep 17 00:00:00 2001 From: Edgar Chen Date: Wed, 19 Jan 2022 06:08:46 +0000 Subject: [PATCH] Bug 1741280 - Part 3: Add fullscreen tests for tab close; r=Gijs Depends on D132461 Differential Revision: https://phabricator.services.mozilla.com/D132582 --- dom/html/test/browser.ini | 15 +++ .../test/browser_fullscreen-tab-close-race.js | 101 ++++++++++++++++++ dom/html/test/browser_fullscreen-tab-close.js | 65 +++++++++++ dom/html/test/fullscreen_helpers.js | 32 ++++++ 4 files changed, 213 insertions(+) create mode 100644 dom/html/test/browser_fullscreen-tab-close-race.js create mode 100644 dom/html/test/browser_fullscreen-tab-close.js diff --git a/dom/html/test/browser.ini b/dom/html/test/browser.ini index ef139d11d662..9f537e2ece53 100644 --- a/dom/html/test/browser.ini +++ b/dom/html/test/browser.ini @@ -57,6 +57,21 @@ support-files = file_fullscreen-iframe-inner.html [browser_fullscreen-document-mutation-race.js] tags = fullscreen +support-files = + fullscreen_helpers.js + file_fullscreen-iframe-top.html + file_fullscreen-iframe-middle.html + file_fullscreen-iframe-inner.html +[browser_fullscreen-tab-close.js] +tags = fullscreen +support-files = + fullscreen_helpers.js + file_fullscreen-iframe-top.html + file_fullscreen-iframe-middle.html + file_fullscreen-iframe-inner.html +[browser_fullscreen-tab-close-race.js] +skip-if = !fission # Bug 1750901 +tags = fullscreen support-files = fullscreen_helpers.js file_fullscreen-iframe-top.html diff --git a/dom/html/test/browser_fullscreen-tab-close-race.js b/dom/html/test/browser_fullscreen-tab-close-race.js new file mode 100644 index 000000000000..ef296db6806d --- /dev/null +++ b/dom/html/test/browser_fullscreen-tab-close-race.js @@ -0,0 +1,101 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +requestLongerTimeout(2); + +// Import helpers +Services.scriptloader.loadSubScript( + "chrome://mochitests/content/browser/dom/html/test/fullscreen_helpers.js", + this +); + +// 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); + +add_task(async function init() { + await pushPrefs( + ["full-screen-api.transition-duration.enter", "0 0"], + ["full-screen-api.transition-duration.leave", "0 0"], + ["full-screen-api.allow-trusted-requests-only", false] + ); +}); + +async function startTests(setupFun, name) { + TEST_URLS.forEach(url => { + add_task(async () => { + info(`Test ${name}, url: ${url}`); + await BrowserTestUtils.withNewTab( + { + gBrowser, + url, + }, + async function(browser) { + let promiseFsState = waitForFullscreenExit(document); + setupFun(browser); + // Trigger click event in inner most iframe + SpecialPowers.spawn( + browser.browsingContext.children[0].children[0], + [], + function() { + content.setTimeout(() => { + content.document.getElementById("div").click(); + }, 0); + } + ); + await promiseFsState; + + // Ensure the browser exits fullscreen state. + ok( + !window.fullScreen, + "The chrome window should not be in fullscreen" + ); + ok( + !document.documentElement.hasAttribute("inDOMFullscreen"), + "The chrome document should not be in fullscreen" + ); + } + ); + }); + }); +} + +async function WaitRemoveDocumentAndCloseTab(aBrowser, aBrowsingContext) { + await SpecialPowers.spawn(aBrowsingContext, [], async function() { + return new Promise(resolve => { + content.document.addEventListener( + "fullscreenchange", + e => { + resolve(); + }, + { once: true } + ); + }); + }); + + // This should exit fullscreen + let tab = gBrowser.getTabForBrowser(aBrowser); + BrowserTestUtils.removeTab(tab); +} + +startTests(async browser => { + // toplevel + WaitRemoveDocumentAndCloseTab(browser, browser.browsingContext); +}, "tab_close_toplevel"); + +startTests(browser => { + // middle iframe + WaitRemoveDocumentAndCloseTab(browser, browser.browsingContext.children[0]); +}, "tab_close_middle_frame"); + +startTests(async browser => { + // innermost iframe + WaitRemoveDocumentAndCloseTab( + browser, + browser.browsingContext.children[0].children[0] + ); +}, "tab_close_inner_frame"); diff --git a/dom/html/test/browser_fullscreen-tab-close.js b/dom/html/test/browser_fullscreen-tab-close.js new file mode 100644 index 000000000000..e2ac4be572d8 --- /dev/null +++ b/dom/html/test/browser_fullscreen-tab-close.js @@ -0,0 +1,65 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +requestLongerTimeout(2); + +// Import helpers +Services.scriptloader.loadSubScript( + "chrome://mochitests/content/browser/dom/html/test/fullscreen_helpers.js", + this +); + +// 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); + +add_task(async function init() { + await pushPrefs( + ["full-screen-api.transition-duration.enter", "0 0"], + ["full-screen-api.transition-duration.leave", "0 0"], + ["full-screen-api.allow-trusted-requests-only", false] + ); +}); + +TEST_URLS.forEach(url => { + add_task(async () => { + info(`url: ${url}`); + await BrowserTestUtils.withNewTab( + { + gBrowser, + url, + }, + async function(browser) { + let promiseFsState = waitForFullscreenState(document, true); + // Trigger click event in inner most iframe + SpecialPowers.spawn( + browser.browsingContext.children[0].children[0], + [], + function() { + content.setTimeout(() => { + content.document.getElementById("div").click(); + }, 0); + } + ); + await promiseFsState; + + let promiseFsExit = waitForFullscreenExit(document, false); + // This should exit fullscreen + let tab = gBrowser.getTabForBrowser(browser); + BrowserTestUtils.removeTab(tab); + await promiseFsExit; + + // Ensure the browser exits fullscreen state. + ok(!window.fullScreen, "The chrome window should not be in fullscreen"); + ok( + !document.documentElement.hasAttribute("inDOMFullscreen"), + "The chrome document should not be in fullscreen" + ); + } + ); + }); +}); diff --git a/dom/html/test/fullscreen_helpers.js b/dom/html/test/fullscreen_helpers.js index e1387db857cf..9a16276a5bce 100644 --- a/dom/html/test/fullscreen_helpers.js +++ b/dom/html/test/fullscreen_helpers.js @@ -106,3 +106,35 @@ function waitForFullscreenState( waitForFullScreenObserver(aDocument, aIsInFullscreen, aWaitUntil), ]); } + +// Wait for fullscreenchange event for fullscreen exit. And wait for +// fullscreen-painted observed conditionally. +async function waitForFullscreenExit(aDocument) { + info(`waitForFullscreenExit`); + let promiseFsObserver = null; + let observer = function() { + if (aDocument.documentElement.hasAttribute("inDOMFullscreen")) { + info(`waitForFullscreenExit, fullscreen-painted, inDOMFullscreen`); + Services.obs.removeObserver(observer, "fullscreen-painted"); + promiseFsObserver = waitForFullScreenObserver(aDocument, false); + } + }; + Services.obs.addObserver(observer, "fullscreen-painted"); + + await waitFullscreenEvent(aDocument, false, true); + // If there is a fullscreen-painted observer notified for inDOMFullscreen set, + // we expect to have a subsequent fullscreen-painted observer notified with + // inDOMFullscreen unset. + if (promiseFsObserver) { + info(`waitForFullscreenExit, promiseFsObserver`); + return promiseFsObserver; + } + + Services.obs.removeObserver(observer, "fullscreen-painted"); + // If inDOMFullscreen is set we expect to have a subsequent fullscreen-painted + // observer notified with inDOMFullscreen unset. + if (aDocument.documentElement.hasAttribute("inDOMFullscreen")) { + info(`waitForFullscreenExit, inDOMFullscreen`); + return waitForFullScreenObserver(aDocument, false, true); + } +}