From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- .../fullscreen/browser_fullscreen_api_fission.js | 252 +++++++++++++++++++++ 1 file changed, 252 insertions(+) create mode 100644 browser/base/content/test/fullscreen/browser_fullscreen_api_fission.js (limited to 'browser/base/content/test/fullscreen/browser_fullscreen_api_fission.js') diff --git a/browser/base/content/test/fullscreen/browser_fullscreen_api_fission.js b/browser/base/content/test/fullscreen/browser_fullscreen_api_fission.js new file mode 100644 index 0000000000..03b65ddc0e --- /dev/null +++ b/browser/base/content/test/fullscreen/browser_fullscreen_api_fission.js @@ -0,0 +1,252 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/* This test checks that `document.fullscreenElement` is set correctly and + * proper fullscreenchange events fire when an element inside of a + * multi-origin tree of iframes calls `requestFullscreen()`. It is designed + * to make sure the fullscreen API is working properly in fission when the + * frame tree spans multiple processes. + * + * A similarly purposed Web Platform Test exists, but at the time of writing + * is manual, so it cannot be run in CI: + * `element-request-fullscreen-cross-origin-manual.sub.html` + */ + +"use strict"; + +const actorModuleURI = getRootDirectory(gTestPath) + "FullscreenFrame.sys.mjs"; +const actorName = "FullscreenFrame"; + +const fullscreenPath = + getRootDirectory(gTestPath).replace("chrome://mochitests/content", "") + + "fullscreen.html"; + +const fullscreenTarget = "D"; +// TOP +// | \ +// A B +// | +// C +// | +// D +// | +// E +const frameTree = { + name: "TOP", + // eslint-disable-next-line @microsoft/sdl/no-insecure-url + url: `http://example.com${fullscreenPath}`, + allow_fullscreen: true, + children: [ + { + name: "A", + // eslint-disable-next-line @microsoft/sdl/no-insecure-url + url: `http://example.org${fullscreenPath}`, + allow_fullscreen: true, + children: [ + { + name: "C", + // eslint-disable-next-line @microsoft/sdl/no-insecure-url + url: `http://example.com${fullscreenPath}`, + allow_fullscreen: true, + children: [ + { + name: "D", + // eslint-disable-next-line @microsoft/sdl/no-insecure-url + url: `http://example.com${fullscreenPath}?different-uri=1`, + allow_fullscreen: true, + children: [ + { + name: "E", + // eslint-disable-next-line @microsoft/sdl/no-insecure-url + url: `http://example.org${fullscreenPath}`, + allow_fullscreen: true, + children: [], + }, + ], + }, + ], + }, + ], + }, + { + name: "B", + // eslint-disable-next-line @microsoft/sdl/no-insecure-url + url: `http://example.net${fullscreenPath}`, + allow_fullscreen: true, + children: [], + }, + ], +}; + +add_task(async function test_fullscreen_api_cross_origin_tree() { + await new Promise(r => { + SpecialPowers.pushPrefEnv( + { + set: [ + ["full-screen-api.enabled", true], + ["full-screen-api.allow-trusted-requests-only", false], + ["full-screen-api.transition-duration.enter", "0 0"], + ["full-screen-api.transition-duration.leave", "0 0"], + ["dom.security.featurePolicy.header.enabled", true], + ["dom.security.featurePolicy.webidl.enabled", true], + ], + }, + r + ); + }); + + // Register a custom window actor to handle tracking events + // and constructing subframes + ChromeUtils.registerWindowActor(actorName, { + child: { + esModuleURI: actorModuleURI, + events: { + fullscreenchange: { mozSystemGroup: true, capture: true }, + fullscreenerror: { mozSystemGroup: true, capture: true }, + }, + }, + allFrames: true, + }); + + let tab = await BrowserTestUtils.openNewForegroundTab({ + gBrowser, + url: frameTree.url, + }); + + let frames = new Map(); + async function construct_frame_children(browsingContext, tree) { + let actor = browsingContext.currentWindowGlobal.getActor(actorName); + frames.set(tree.name, { + browsingContext, + actor, + }); + + for (let child of tree.children) { + // Create the child IFrame and wait for it to load. + let childBC = await actor.sendQuery("CreateChild", child); + await construct_frame_children(childBC, child); + } + } + + await construct_frame_children(tab.linkedBrowser.browsingContext, frameTree); + + async function check_events(expected_events) { + for (let [name, expected] of expected_events) { + let actor = frames.get(name).actor; + + // Each content process fires the fullscreenchange + // event independently and in parallel making it + // possible for the promises returned by + // `requestFullscreen` or `exitFullscreen` to + // resolve before all events have fired. We wait + // for the number of events to match before + // continuing to ensure we don't miss an expected + // event that hasn't fired yet. + let events; + await TestUtils.waitForCondition(async () => { + events = await actor.sendQuery("GetEvents"); + return events.length == expected.length; + }, `Waiting for number of events to match`); + + Assert.equal(events.length, expected.length, "Number of events equal"); + events.forEach((value, i) => { + Assert.equal(value, expected[i], "Event type matches"); + }); + } + } + + async function check_fullscreenElement(expected_elements) { + for (let [name, expected] of expected_elements) { + let element = await frames + .get(name) + .actor.sendQuery("GetFullscreenElement"); + Assert.equal(element, expected, "The fullScreenElement matches"); + } + } + + // Trigger fullscreen from the target frame. + let target = frames.get(fullscreenTarget); + await target.actor.sendQuery("RequestFullscreen"); + // true is fullscreenchange and false is fullscreenerror. + await check_events( + new Map([ + ["TOP", [true]], + ["A", [true]], + ["B", []], + ["C", [true]], + ["D", [true]], + ["E", []], + ]) + ); + await check_fullscreenElement( + new Map([ + ["TOP", "child_iframe"], + ["A", "child_iframe"], + ["B", "null"], + ["C", "child_iframe"], + ["D", "body"], + ["E", "null"], + ]) + ); + + await target.actor.sendQuery("ExitFullscreen"); + // fullscreenchange should have fired on exit as well. + // true is fullscreenchange and false is fullscreenerror. + await check_events( + new Map([ + ["TOP", [true, true]], + ["A", [true, true]], + ["B", []], + ["C", [true, true]], + ["D", [true, true]], + ["E", []], + ]) + ); + await check_fullscreenElement( + new Map([ + ["TOP", "null"], + ["A", "null"], + ["B", "null"], + ["C", "null"], + ["D", "null"], + ["E", "null"], + ]) + ); + + // Clear previous events before testing exiting fullscreen with ESC. + for (const frame of frames.values()) { + frame.actor.sendQuery("ClearEvents"); + } + await target.actor.sendQuery("RequestFullscreen"); + + // Escape should cause the proper events to fire and + // document.fullscreenElement should be cleared. + let finished_exiting = target.actor.sendQuery("WaitForChange"); + EventUtils.sendKey("ESCAPE"); + await finished_exiting; + // true is fullscreenchange and false is fullscreenerror. + await check_events( + new Map([ + ["TOP", [true, true]], + ["A", [true, true]], + ["B", []], + ["C", [true, true]], + ["D", [true, true]], + ["E", []], + ]) + ); + await check_fullscreenElement( + new Map([ + ["TOP", "null"], + ["A", "null"], + ["B", "null"], + ["C", "null"], + ["D", "null"], + ["E", "null"], + ]) + ); + + // Remove the tests custom window actor. + ChromeUtils.unregisterWindowActor("FullscreenFrame"); + BrowserTestUtils.removeTab(tab); +}); -- cgit v1.2.3