Files
sousa-gecko/testing/web-platform/mozilla/tests/fullscreen/api/resources/recursive-iframe-fullscreen.html
T
Simon Farre 6a3dc6db5e Bug 2002289 Fix OOP-frame JSWA fullscreen problem r=edgar
This patch fixes a problem where we have fullscreened a subtree of
documents and now a request is made to fullscreen an element further
down in the tree, which may be out of process, with respect to the
already fullscreened elements and documents.

The bug triggers, because a check in the parent proess will see that the
browser tab, already has a chrome element that is fullscreen and then
aborts. We must also not do any actual work when we hit this issue,
because everything is already fullscreen.

The fix is to resume the JSWA "messaging chain" without doing any
Fullscreen API work and only do so when the in-process-requested
to-be-fullscreened-element is an iframe, or if we're the parent process,
otherwise the check should "fail" as normal and not do anything.

Added wpt-like tests. I guess there's a case to be made to change the
test testing/web-platform/tests/fullscreen/api/element-request-fullscreen-cross-origin.sub.html
to behave like the test I've provided here. It first requests
fullscreen inside B, which will make the body element go fullscreen,
then when a request goes for D (its body element), the iframe in B also
goes fullscreen and then the remainder of frames goes fullscreen. The
point being for us, that when doing fullscreen stuff and we're stuck on
JSWA, we must propagate the MozDOMFullscreen:Entered messages
properly, even if no work needs to be done.

Differential Revision: https://phabricator.services.mozilla.com/D274060
2025-12-15 09:06:14 +00:00

89 lines
2.5 KiB
HTML

<!DOCTYPE html>
<meta charset="utf-8" />
<title>Recursive IFrame Fullscreen API success reporter</title>
<body>
<script src="/resources/testdriver.js"></script>
<script src="/resources/testdriver-vendor.js"></script>
<script src="trusted-click.js"></script>
<script>
let child_frame = null;
let events = [];
document.onfullscreenchange = () => {
window.top.postMessage({ action: "fsEvent", name: window.name }, "*");
events.push("fullscreenchange");
};
document.onfullscreenerror = () => {
window.top.postMessage({ action: "fsEvent", name: window.name }, "*");
events.push("fullscreenerror");
};
function send_report() {
window.top.postMessage(
{
name: window.name,
action: "report",
report: {
frame: window.name,
fullscreenElementIsNull: document.fullscreenElement === null,
events,
},
},
"*"
);
events = [];
}
async function create_child_frame({ src, name, allow_fullscreen }) {
child_frame = document.createElement("iframe");
child_frame.allow = allow_fullscreen ? "fullscreen" : "";
child_frame.name = name;
child_frame.style.width = "100%";
child_frame.style.height = "100%";
document.body.appendChild(child_frame);
await new Promise((resolve) => {
child_frame.addEventListener("load", resolve, { once: true });
child_frame.src = src;
});
window.top.postMessage({ action: "load", name }, "*");
}
async function go_fullscreen() {
await trusted_click(document.body);
let error;
try {
await document.body.requestFullscreen();
} catch (err) {
error = err.name;
} finally {
window.top.postMessage(
{ action: "requestFullscreen", name: window.name, error },
"*"
);
}
}
window.addEventListener("message", async (e) => {
// Massage is not for us, try to pass it on...
if (e.data.name !== window.name) {
child_frame?.contentWindow.postMessage(e.data, "*");
return;
}
switch (e.data.action) {
case "requestReport":
send_report();
break;
case "requestFullscreen":
await go_fullscreen();
break;
case "addIframe":
await create_child_frame(e.data.iframe);
break;
default:
window.top.postMessage(e.data, "*");
}
});
</script>
</body>