whatwg / html

HTML Standard
https://html.spec.whatwg.org/multipage/
Other
7.86k stars 2.58k forks source link

Should COOP-related browsing context switch result in nullification of a popup's WindowProxy's `window`? #10457

Open yoavweiss opened 4 days ago

yoavweiss commented 4 days ago

What is the issue with the HTML Standard?

When a document opens a popup (using something like const popup = window.open(url)), and that popup requires a browsing context group switch due to COOP enforcement, it's not immediately obvious (to me) what the value of popup.window should be.

When adding an assertion on that front to popup-test.js#89, Chromium and WebKit seem to disagree on what that value should be. The value is asynchronously being set to null in Chromium (once the response is received), while remaining a global object in WebKit. This might be a bug in one of them, but it'd be good to clarify the behavior, so that we'd know which needs to be aligned.

Update: clarified that the value is being set async.

/cc @domfarolino @ArthurSonzogni @cdumez

annevk commented 4 days ago

This should follow from https://html.spec.whatwg.org/multipage/nav-history-apis.html#window-open-steps. If the document associated with the window.open() call is enforcing policy it will typically be null. If it's the document associated with url it can't be null, since we don't know that synchronously.

domfarolino commented 4 days ago

If it's the document associated with url it can't be null, since we don't know that synchronously.

Right, but I think the question is: is there any mechanism that should set popup.window to null asynchronously (as Chromium does at least) after the browsing context group switch is performed, to ensure that the opener doesn't continue to hold a handle to the new Window loaded in the popup, which now lives in another BCG.

yoavweiss commented 4 days ago

Exactly, the value in Chromium is asynchronously being set to null, once the response is received. I'll clarify that in the OP.

ArthurSonzogni commented 4 days ago

Exactly, the value in Chromium is asynchronously being set to null, once the response is received. I'll clarify that in the OP.

The opener (original window), the popup's old document (initial content), and the popup's new document (updated content) can run in 3 separate processes. As a result, updating the WindowProxy in the opener must be asynchronous, relative to the two other, no matter the implementation.

An interesting observation made while writing tests is that it's possible for the opener to detect (through external channels) an event triggered by running JS in popup's new document before receiving the .closed event, which signals the removal of the old document. This might seem counterintuitive at first, but it's logical when you consider that the new document starts executing before the opener explicitly acknowledges that the WindowProxy has been updated.

So either WebKit as a different chain of causality (e.g. Waiting for WindowProxy update before creating the new document) or this a difference of degree (WebKit IPCs winning the race ften)

annevk commented 3 days ago

Wait what? popup.window should always be the same as just popup (assuming popup is a WindowProxy).

And once something is a WindowProxy, you can't just nullify it.

Or maybe you are talking about popup.opener and whether that is equal to window? I guess once url is loaded popup would be closed and that might severe that relationship, although I'm not entirely sure.

ArthurSonzogni commented 1 day ago

Wait what? popup.window should always be the same as just popup (assuming popup is a WindowProxy).

Chrome implementation for the 3 self referencial attributes (window, self, frames) appears to check the WindowProxy's window still exist before returning itself. code search

WebKit seems to do the same as Chrome fo self(). (I did not found ::window() and ::frame()) code search code search 2

Firefox: I did not find information.