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
89 lines
2.5 KiB
HTML
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>
|