tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit fd1c94fadb4403faac2c29eb33d9aaf24c87c159
parent 47fddd61988c0427ef186b069c785e0de1d2e9f1
Author: Atila Butkovits <abutkovits@mozilla.com>
Date:   Mon,  1 Dec 2025 14:03:25 +0200

Revert "Bug 2002289 Fix OOP-frame JSWA fullscreen problem r=edgar" for causing failures at element-request-fullscreen-cross-origin-multi-steps.sub.html.

This reverts commit 8dcaa274e8e4b84231ddffaab33f86d52aa96262.

Diffstat:
Mdom/base/Document.cpp | 46+++++-----------------------------------------
Dtesting/web-platform/mozilla/tests/fullscreen/api/element-request-fullscreen-cross-origin-multi-steps.sub.html | 132-------------------------------------------------------------------------------
Dtesting/web-platform/mozilla/tests/fullscreen/api/resources/recursive-iframe-fullscreen.html | 87-------------------------------------------------------------------------------
Dtesting/web-platform/mozilla/tests/fullscreen/api/resources/trusted-click.js | 25-------------------------
4 files changed, 5 insertions(+), 285 deletions(-)

diff --git a/dom/base/Document.cpp b/dom/base/Document.cpp @@ -16411,24 +16411,6 @@ const char* Document::GetFullscreenError(CallerType aCallerType) { return nullptr; } -// Informs JSWA Fullscreen implementation to resume via sending -// "MozDOMFullscreen:Entered". -static inline void PropagateFullscreenRequest(Document* aDoc, - Element* aElement) { - nsContentUtils::DispatchEventOnlyToChrome( - aDoc, aElement, u"MozDOMFullscreen:Entered"_ns, CanBubble::eYes, - Cancelable::eNo, /* DefaultAction */ nullptr); -} - -static bool ElementIsRemoteFrame(Element* aElement) { - MOZ_ASSERT(aElement); - RefPtr<nsFrameLoader> loader; - if (RefPtr<nsFrameLoaderOwner> loaderOwner = do_QueryObject(aElement)) { - loader = loaderOwner->GetFrameLoader(); - } - return loader && loader->IsRemoteFrame(); -} - bool Document::FullscreenElementReadyCheck(FullscreenRequest& aRequest) { Element* elem = aRequest.Element(); // Strictly speaking, this isn't part of the fullscreen element ready @@ -16437,19 +16419,7 @@ bool Document::FullscreenElementReadyCheck(FullscreenRequest& aRequest) { // should change and no event should be dispatched, but we still need // to resolve the returned promise. Element* fullscreenElement = GetUnretargetedFullscreenElement(); - if (NS_WARN_IF(elem == fullscreenElement)) { - // But this introduces behavior that we now need to account for; - // because we can have arbitrary depth of OOP-frames, we may hit this check - // for a process that already is fullscreen, e.g. the parent process. - // If the target element is a frame or we're the parent process, just resume - // the JS Window Actor messaging without doing any more work. - // We know for sure, that the document must be fullscreened already, so - // there is no request to the OS for fullscreen that needs to be made, for - // instance. Note: this is just for JSWA not the platform-only fullscreen - // implementation. - if (ElementIsRemoteFrame(elem)) { - PropagateFullscreenRequest(this, elem); - } + if (elem == fullscreenElement) { aRequest.MayResolvePromise(); return false; } @@ -16777,16 +16747,10 @@ bool Document::ApplyFullscreen(UniquePtr<FullscreenRequest> aRequest) { // notifying parent process to enter fullscreen. Note that chrome // code may also want to listen to MozDOMFullscreen:NewOrigin event // to pop up warning UI. - // We also need to propagate the message in the JSWA message chain, - // so that if out of process sub-frames, that has requested fs - // gets notified to resume it's request. We can know, that the request did not - // originate from this process, if the JS promise is null. - if (!aRequest->GetPromise() || !previousFullscreenDoc) { - MOZ_ASSERT( - (previousFullscreenDoc && - ElementIsRemoteFrame(child->GetUnretargetedFullscreenElement())) || - !previousFullscreenDoc); - PropagateFullscreenRequest(this, elem); + if (!previousFullscreenDoc) { + nsContentUtils::DispatchEventOnlyToChrome( + this, elem, u"MozDOMFullscreen:Entered"_ns, CanBubble::eYes, + Cancelable::eNo, /* DefaultAction */ nullptr); } // The origin which is fullscreen gets changed. Trigger an event so diff --git a/testing/web-platform/mozilla/tests/fullscreen/api/element-request-fullscreen-cross-origin-multi-steps.sub.html b/testing/web-platform/mozilla/tests/fullscreen/api/element-request-fullscreen-cross-origin-multi-steps.sub.html @@ -1,132 +0,0 @@ -<!DOCTYPE html> -<title> - Element#requestFullscreen() works properly with a tree of cross-origin iframes, with multiple requests -</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<script src="/resources/testdriver.js"></script> -<script src="/resources/testdriver-vendor.js"></script> - -<body> - <script> - function waitFor(action, frameName) { - return new Promise((resolve) => { - window.addEventListener("message", function listener(e) { - if (e.data.action === action && e.data.name === frameName) { - window.removeEventListener("message", listener); - resolve(event.data); - } - }); - }); - } - - function compare_report(report, frame, expectedIndex) { - assert_array_equals(report.events, frame.expectedEvents[expectedIndex], `compare events for ${frame.name}`); - assert_equals(report.fullscreenElementIsNull, frame.expectedNullFullscreenElement[expectedIndex], `frame ${frame.name} has expected fullscreen element`); - } - - const iframes = [ - { - name: "A", - src: "http://{{hosts[][]}}:{{ports[http][0]}}/_mozilla/fullscreen/api/resources/recursive-iframe-fullscreen.html?a", - allow_fullscreen: true, - expectedEvents: [["fullscreenchange"], []], - expectedNullFullscreenElement: [false, false] - }, - { // first check should see its body go fs, 2nd should see it's <iframe> go fs - name: "B", - src: "http://{{hosts[alt][]}}:{{ports[http][1]}}/_mozilla/fullscreen/api/resources/recursive-iframe-fullscreen.html?b", - allow_fullscreen: true, - expectedEvents: [["fullscreenchange"], ["fullscreenchange"]], - expectedNullFullscreenElement: [false, false] - }, - { - name: "C", - src: "http://{{hosts[][www]}}:{{ports[http][0]}}/_mozilla/fullscreen/api/resources/recursive-iframe-fullscreen.html?c", - allow_fullscreen: true, - expectedEvents: [[], ["fullscreenchange"]], - expectedNullFullscreenElement: [true, false] - }, - { - name: "D", - src: "http://{{hosts[][]}}:{{ports[http][1]}}/_mozilla/fullscreen/api/resources/recursive-iframe-fullscreen.html?d", - allow_fullscreen: true, - expectedEvents: [[],["fullscreenchange"]], - expectedNullFullscreenElement: [true, false] - }, - { - name: "E", - src: "http://{{hosts[][]}}:{{ports[http][0]}}/_mozilla/fullscreen/api/resources/recursive-iframe-fullscreen.html?e", - allow_fullscreen: true, - expectedEvents: [[],[]], - expectedNullFullscreenElement: [true, true] - }, - ]; - - promise_setup(async () => { - // Add the first iframe. - const iframeDetails = iframes[0]; - const childFrame = document.createElement("iframe"); - childFrame.allow = iframeDetails.allow_fullscreen ? "fullscreen" : ""; - childFrame.name = iframeDetails.name; - childFrame.style.width = "100%"; - childFrame.style.height = "100%"; - childFrame.src = iframeDetails.src; - await new Promise((resolve) => { - childFrame.onload = resolve; - document.body.appendChild(childFrame); - }); - - // Create the nested iframes. - for (let i = 1; i < iframes.length; i++) { - const parentName = iframes[i - 1].name; - const details = iframes[i]; - childFrame.contentWindow.postMessage( - { action: "addIframe", iframe: details, name: parentName }, - "*" - ); - await waitFor("load", details.name); - } - }); - - promise_test(async (t) => { - t.add_cleanup(async () => { - if (document.fullscreenElement) { - await new Promise((resolve) => { - document.addEventListener("fullscreenchange", resolve, { once: true }); - document.exitFullscreen(); - }); - } - }); - document.onfullscreenerror = t.unreached_func( - "fullscreenerror event fired" - ); - - const childFrame = document.querySelector("iframe[name=A]"); - - const requestFullscreenIn = (name) => { - const action = "requestFullscreen"; - childFrame.contentWindow.postMessage({ action, name }, "*"); - return waitFor(action, name); - } - - const verifyResult = async (expectedResultIndex) => { - for (const frame of iframes) { - const data = { - action: "requestReport", - name: frame.name, - }; - childFrame.contentWindow.postMessage(data, "*"); - const { report } = await waitFor("report", frame.name); - compare_report(report, frame, expectedResultIndex); - } - } - - await requestFullscreenIn("B"); - await verifyResult(0); - - await requestFullscreenIn("D"); - await verifyResult(1); - }, "Element#requestFullscreen() works properly with a tree of cross-origin iframes"); - </script> -</body> diff --git a/testing/web-platform/mozilla/tests/fullscreen/api/resources/recursive-iframe-fullscreen.html b/testing/web-platform/mozilla/tests/fullscreen/api/resources/recursive-iframe-fullscreen.html @@ -1,87 +0,0 @@ -<!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 = () => { - events.push("fullscreenchange"); - }; - - document.onfullscreenerror = () => { - events.push("fullscreenerror"); - }; - - function send_report() { - window.top.postMessage( - { - name: window.name, - action: "report", - report: { - api: "fullscreen", - 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> diff --git a/testing/web-platform/mozilla/tests/fullscreen/api/resources/trusted-click.js b/testing/web-platform/mozilla/tests/fullscreen/api/resources/trusted-click.js @@ -1,25 +0,0 @@ -/** - * Invokes callback from a trusted click event, avoiding interception by fullscreen element. - * - * @param {Element} container - Element where button will be created and clicked. - */ -function trusted_click(container = document.body) { - var document = container.ownerDocument; - var button = document.createElement("button"); - button.textContent = "click to continue test"; - button.style.display = "block"; - button.style.fontSize = "20px"; - button.style.padding = "10px"; - button.addEventListener("click", () => { - button.remove(); - }); - container.appendChild(button); - if (window.top !== window) test_driver.set_test_context(window.top); - // Race them for manually testing... - return Promise.race([ - test_driver.click(button), - new Promise((resolve) => { - button.addEventListener("click", resolve); - }), - ]); -}