-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Disowning owner should perhaps affect link targeting #313
Comments
I prefer Gecko and Blink's current behavior, FWIW. That is, I agree that the spec should change. |
Otherwise window names would still leak across.
I also get two windows for
and if I remove When I do Anyway, it seems pretty clear that not having an opener should affect link targeting. I do get the same set of cookies if open
|
So @bzbarsky points out that an important factor here is same-origin vs cross-origin. E.g., in Gecko today
would likely let the javascript URL read all the inherited stuff from the |
In an ideal world, I'd like to get to a place where
This seems like correct behavior to me. We want to decouple these windows, so they shouldn't be familiar with each other. If y'all agree, we'll need to change the "familiar with" definition to adjust the same-origin bit to exclude this case.
Chrome throws an error because we treat
It would be good to prevent this, as it would enable the opened window to gain access to a cooperative opener. I'd like to prevent this in the same way we'd prevent targeting the one window from the other.
Wouldn't the targeting change fix this? That is, |
I talked with @bzbarsky and we would be okay with changing our behavior for the same-origin case, to also not allow targeting by name there. That would mean that the "familiar with" clause needs to change to "Either A is same-origin with B and neither A nor B is disowned, or", correct? What is the reason for not setting |
In blink, we only do the lookup by frame name in the local process. So in all cases where we host the navigation in a different process, the lookup by name just never works. Ideally, that would be spec'd somewhere :) |
Agreed and that is what this issue is about. However, that does not mean that the browsing context name cannot be set for (what will be) a different process. |
right |
Specifically, I would be OK with changing to a behavior that is (1) unambiguously specified (which I don't think the current spec is, nor is Chrome's "local process" thing, since nothing defines what does and doesn't share processes in Chrome, and in fact it depends on various runtime things like how many processes are live already, last I checked) and (2) very likely to actually be web-compatible (because I don't want to change this behavior more than once). |
Put another way, we need to prevent targeting by name in the same process for same-origin stuff in some cases to have a well-defined spec here that doesn't depend on arbitrary implementation details. |
Otherwise window names would still leak across.
With this change, whenever an auxiliary browsing context is disowned, whether through setting window.opener to null, through using the rel=noreferrer and rel=noopener keywords, or through using the window.open() noopener /features/ argument, it isolates that browsing context from its opener. It will no longer be "familiar with" it, even same-origin, and its opener browsing context is explicitly set to null. It will still get its assigned name (e.g., from the target="" attribute) and will still be script closable.
I updated the patch in #313 to do that. I also posted an update there on the test front: #323 (comment). Input appreciated. |
This change attempts to make it so that when using rel=noopener, rel=noreferrer, and when setting window.opener to null, the browsing contexts involve can no longer directly reach each other. They end up in their own unit of related browsing contexts. (This is what some in the ECMAScript community refer to as a vat or continent.) We do this by making directly reachable account for disowning, by making familiar with account for directly reachable, and by changing the rules for choosing a browsing context given a browsing context name to no longer say "related enough", but instead clearly say that the browsing contexts have to be familiar with each other, and by extension, have to be directly reachable.
This change attempts to make it so that when using rel=noopener, rel=noreferrer, and when setting window.opener to null, the browsing contexts involve can no longer directly reach each other. They end up in their own unit of related browsing contexts. (This is what some in the ECMAScript community refer to as a vat or continent.) We do this by making directly reachable account for disowning, by making familiar with account for directly reachable, and by changing the rules for choosing a browsing context given a browsing context name to no longer say "related enough", but instead clearly say that the browsing contexts have to be familiar with each other, and by extension, have to be directly reachable.
This change attempts to make it so that when using rel=noopener, rel=noreferrer, and when setting window.opener to null, the browsing contexts involve can no longer directly reach each other. They end up in their own unit of related browsing contexts. (This is what some in the ECMAScript community refer to as a vat or continent.) We do this by making directly reachable account for disowning, by making familiar with account for directly reachable, and by changing the rules for choosing a browsing context given a browsing context name to no longer say "related enough", but instead clearly say that the browsing contexts have to be familiar with each other, and by extension, have to be directly reachable.
Instead of adjusting "familiar with", how about noopener effectively ends up creating a new "unit of related browsing contexts" and name targeting only searches within that unit (per #1440)? As long as we then restrict "familiar with" to play within a "unit of related browsing contexts" I think we're good and don't run into the numerous complications I ran into with my PR. @bzbarsky does that make sense? |
This issue is explicitly about disowning openers via setting I'm happy to discuss noopener behavior in #1826 if you would like. |
Sorry. For this issue, if I refactored the specification sufficiently such that I can allocate "unit of related browsing contexts" and I refactored that so it actually consists of a set of browsing context trees (which I think is what implementations do), I could allocate a new unit of related browsing contexts and just move one item of the set (whose top-level browsing context's window's Or would we then end up with more separation than we'd like? (Reading through #323 it seems like this might be okay, but maybe things have changed.) |
I guess that setup doesn't quite work when A creates auxiliary B and B creates auxiliary C and then B sets opener to null. You'd then want (A), (B, C) I think, although it gets weird if A already accessed (nested) bits of B or C. |
Anyway, if we can figure out the actual structure of a "unit of related browsing contexts" (tab group in Firefox, dunno about Chrome), we can then debate how to divide it and whether that works or whether we'll need some access restrictions on top of that structure for a couple special cases (such as link targeting). Hopefully that makes sense. |
I think there are two separate concepts here:
|
I think the event loop, if Chrome's out-of-process-iframe experiments continue well, ends up being scoped to similar-origin window agent, which is a "subset" of "unit related browsing contexts" (currently called "unit of related similar-origin browsing contexts" though that is a bit of a misnomer as it's really documents/windows, not browsing contexts). So splitting "unit of related browsing contexts" could work out and my main goal there was mostly that it would be a little cleaner and potentially have benefits beyond link targeting (although I'm not sure which, granted). Anyway, even if that cannot work, defining the layout of a "unit of related browsing contexts" would help a lot. In particular if it's a collection of browsing context trees (root of which is auxiliary or top-level browsing context) we could give each item in that collection a flag and make it very clear how accessing between them goes. |
A browsing context tree is the wrong model as child browsing contexts are tied to a document (or element, really), not a browsing context. |
…o one another https://bugs.webkit.org/show_bug.cgi?id=190475 Reviewed by Alex Christensen. Source/WebCore: Update our frame lookup by name logic to take in the active / requesting frame and only a return a frame that is related to it. By related to it, I mean: - Ancestor <-> Descendant relationship - Opener <-> Openee relationship Being able to look up unrelated frames makes process swapping difficult so we need to be stricter. This change is being discussed at: - whatwg/html#313 Tests: http/tests/dom/new-window-can-target-opener.html http/tests/dom/noopener-window-cannot-target-opener.html http/tests/dom/noopener-window-not-targetable.html http/tests/dom/noopener-window-not-targetable2.html http/tests/dom/noreferrer-window-not-targetable.html http/tests/dom/opened-window-not-targetable-after-disowning-opener.html * loader/FrameLoader.cpp: (WebCore::FrameLoader::findFrameForNavigation): * page/FrameTree.cpp: (WebCore::isFrameFamiliarWith): (WebCore::FrameTree::find const): * page/FrameTree.h: * rendering/HitTestResult.cpp: (WebCore::HitTestResult::targetFrame const): Source/WebKit: * WebProcess/Plugins/PluginView.cpp: (WebKit::PluginView::performJavaScriptURLRequest): Source/WebKitLegacy/mac: * WebView/WebFrame.mm: (-[WebFrame findFrameNamed:]): LayoutTests: * http/tests/dom/new-window-can-target-opener-expected.txt: Added. * http/tests/dom/new-window-can-target-opener.html: Added. * http/tests/dom/noopener-window-cannot-target-opener-expected.txt: Added. * http/tests/dom/noopener-window-cannot-target-opener.html: Added. * http/tests/dom/noopener-window-not-targetable-expected.txt: Added. * http/tests/dom/noopener-window-not-targetable.html: Added. * http/tests/dom/noopener-window-not-targetable2-expected.txt: Added. * http/tests/dom/noopener-window-not-targetable2.html: Added. * http/tests/dom/noreferrer-window-not-targetable-expected.txt: Added. * http/tests/dom/noreferrer-window-not-targetable.html: Added. * http/tests/dom/opened-window-not-targetable-after-disowning-opener-expected.txt: Added. * http/tests/dom/opened-window-not-targetable-after-disowning-opener.html: Added. * http/tests/dom/resources/new-window-can-target-opener-win.html: Added. * http/tests/dom/resources/noopener-window-cannot-target-opener-win.html: Added. Add layout test coverage. * fast/dom/Window/a-rel-noopener-expected.txt: * fast/dom/Window/area-rel-noopener-expected.txt: * fast/dom/Window/resources/rel-noopener.js: * http/tests/navigation/no-referrer-target-blank-expected.txt: * http/tests/navigation/resources/no-referrer-helper.php: * platform/mac-wk1/imported/w3c/web-platform-tests/html/browsers/windows/noreferrer-window-name-expected.txt: * platform/wk2/imported/w3c/web-platform-tests/html/browsers/windows/noreferrer-window-name-expected.txt: Update / rebaseline existing tests to reflect behavior change. git-svn-id: http://svn.webkit.org/repository/webkit/trunk@237112 268f45cc-cd09-0410-ab3c-d52691b4dbfc
Gecko's current behavior is as follows, ignoring the special First, we define a
Note that I can't claim that this Armed with this
the named target search for a string "name" now works like this:
|
Thanks for writing this up! It's good to know that my understanding of our algorithm wasn't too far off :-)
For inactive documents here, are your referring to documents in the BFCache? IIRC currently we consider documents framed by a cached document to not have a parent, meaning that they wouldn't be able to target their |
Yes, or just unloaded in general. |
The above algorithm also needs to be influenced by |
…o one another https://bugs.webkit.org/show_bug.cgi?id=190475 Reviewed by Alex Christensen. Source/WebCore: Update our frame lookup by name logic to take in the active / requesting frame and only a return a frame that is related to it. By related to it, I mean: - Ancestor <-> Descendant relationship - Opener <-> Openee relationship Being able to look up unrelated frames makes process swapping difficult so we need to be stricter. This change is being discussed at: - whatwg/html#313 Tests: http/tests/dom/new-window-can-target-opener.html http/tests/dom/noopener-window-cannot-target-opener.html http/tests/dom/noopener-window-not-targetable.html http/tests/dom/noopener-window-not-targetable2.html http/tests/dom/noreferrer-window-not-targetable.html http/tests/dom/opened-window-not-targetable-after-disowning-opener.html * loader/FrameLoader.cpp: (WebCore::FrameLoader::findFrameForNavigation): * page/FrameTree.cpp: (WebCore::isFrameFamiliarWith): (WebCore::FrameTree::find const): * page/FrameTree.h: * rendering/HitTestResult.cpp: (WebCore::HitTestResult::targetFrame const): Source/WebKit: * WebProcess/Plugins/PluginView.cpp: (WebKit::PluginView::performJavaScriptURLRequest): Source/WebKitLegacy/mac: * WebView/WebFrame.mm: (-[WebFrame findFrameNamed:]): LayoutTests: * http/tests/dom/new-window-can-target-opener-expected.txt: Added. * http/tests/dom/new-window-can-target-opener.html: Added. * http/tests/dom/noopener-window-cannot-target-opener-expected.txt: Added. * http/tests/dom/noopener-window-cannot-target-opener.html: Added. * http/tests/dom/noopener-window-not-targetable-expected.txt: Added. * http/tests/dom/noopener-window-not-targetable.html: Added. * http/tests/dom/noopener-window-not-targetable2-expected.txt: Added. * http/tests/dom/noopener-window-not-targetable2.html: Added. * http/tests/dom/noreferrer-window-not-targetable-expected.txt: Added. * http/tests/dom/noreferrer-window-not-targetable.html: Added. * http/tests/dom/opened-window-not-targetable-after-disowning-opener-expected.txt: Added. * http/tests/dom/opened-window-not-targetable-after-disowning-opener.html: Added. * http/tests/dom/resources/new-window-can-target-opener-win.html: Added. * http/tests/dom/resources/noopener-window-cannot-target-opener-win.html: Added. Add layout test coverage. * fast/dom/Window/a-rel-noopener-expected.txt: * fast/dom/Window/area-rel-noopener-expected.txt: * fast/dom/Window/resources/rel-noopener.js: * http/tests/navigation/no-referrer-target-blank-expected.txt: * http/tests/navigation/resources/no-referrer-helper.php: * platform/mac-wk1/imported/w3c/web-platform-tests/html/browsers/windows/noreferrer-window-name-expected.txt: * platform/wk2/imported/w3c/web-platform-tests/html/browsers/windows/noreferrer-window-name-expected.txt: Update / rebaseline existing tests to reflect behavior change. Canonical link: https://commits.webkit.org/205486@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@237112 268f45cc-cd09-0410-ab3c-d52691b4dbfc
This monster completely rewrites everything to do with navigation and traversal. It introduces the "navigable" and "traversable navigable" concepts, which take on many of the roles that browsing contexts previously did, but better. A navigable can present a sequence of browsing contexts, which to the user seem to all be the same, but due to browsing context group switches, have different WindowProxys and are allocated in different agent clusters. A traversable navigable manages the session history for itself and all its descendant navigables, providing a synchronization point and source of truth. The general flow of navigation and traversal is now geared toward creating a session history entry, populated with the appropriate document, before finally applying the history "step". The step concept for session history, managed by the traversable, replaces the previous idea of joint session history, which was a sort of deduplicated union of individual session histories for each browsing context within a top-level browsing context. Notable things we won't tackle this round, but are much easier to tackle in the future: - Iframe restoration on (non-bfcache) history traversal is not yet specified. - Overlapping navigations and traversals (see #6927) are not perfect yet, although this makes them better. - Browsing context names (see #313) are not perfect yet, although this makes them better. - Base URL inheritance and storage in session history (see #421, #2883, and #3989) is not yet specified. - Sandbox flag storage in session history (see #6809) is not yet specified. - Task queuing when creating agents/realms/windows/documents (see #8443) remains sketchy. - Window object reuse is not yet rationalized (see #3267). Closes #854 by clarifying the javascript: URL origin and origin-checking setup. Closes #1073 by properly resetting active-ness of documents when they are removed. Closes #1130 by removing the source browsing context concept, using a sourceDocument argument instead, and taking source snapshot params at the appropriate early time. Closes #1191 by properly sharing document state across documents, as well as overlapping same-document navigations plus cross-document traversals. Closes #1336 by properly handling child browsing contexts. Closes #1382 by only unloading after we are sure we have a new document (i.e., not a 204 or download). Closes #1454 by rewriting session history closer to what implementations do, with the nested history concept in particular taking care of the issues discussed there. Closes #1524 by introducing the POST data concept and storing it in the document state. Closes #2436 by rewriting the spec for history.go() to be clear about the results. Tests: web-platform-tests/wpt#36366. Closes #2566 by introducing an explicit "history object" definition. Tests: web-platform-tests/wpt#36367. Closes #2649 through clear creation of srcdoc documents, including during history traversal. Closes #3215 by preserving POST data and reusing it on reloads. Closes #3447 by specifying a precise mechanism (the ongoing navigation) for canceling navigations, and the points at which that mechanism is consulted. It also stops queuing a task for hyperlink navigations. Closes #3497 by posting appropriate tasks for cross-event-loop navigations. Closes #3615 by rewriting traverse a history by a delta, which eventually calls into apply the history step, to navigate all relevant navigables. Closes #3625 by storing information in the document state (not just the URL), so that future traversals can reconstruct the request appropriately. Closes #3730 by doing proper task queuing for navigation, including one for javascript: URLs but not including one for normal same-frame navigations. Tests: web-platform-tests/wpt#36358. Closes #3734 by rewriting the definition of script-closable to use well-defined concepts. Closes #3812 by removing all uses of "active document" as a predicate instead of a property. Closes #4054 by introducing the session history traversal queue and renaming the previous "history traversal task source" to "navigation and traversal task source". Closes #4121 by doing the "allowed to navigate" check at the top of apply the history step. Closes #4428 by keeping a strong reference from documents (including bfcached documents) to their containing browsing context. Closes #4782 by introducing the top-level traversable and navigable concepts. Closes #4838 by doing sandbox checking in a much more precise manner, in particular snapshotting the relevant flags early in any traversals. Closes #4852 by using document state (in particular history policy container, request referrer, and request referrer policy) in reloads. Closes #5103 by properly restoring scroll positions for everything that is traversed, as part of properly traversing more than one navigable. Closes #5350 by properly restoring window names across browsing context group switches, and going back to the same browsing context as was previously there when traversing back across a BCG switch boundary. (Implementations could create new browsing contexts, as long as they restore the WindowProxy scripting relationships and other browsing context features; the result is observably equivalent.) Closes #5597 by rewriting "allowed to download" to just take booleans, derived from the appropriate snapshotted or computed sandboxing flags. Closes #5767, modulo bugs and oversights we made, by rewriting everything :). Closes #5877 by re-specifying "fully active" in terms of navigables, instead of browsing contexts. Closes #6446 by properly firing beforeunload to all descendant navigables, although whether or not they actually prompt still allows implementation leeway. Closes #6483 by introducing the distinction between current session history entry and active session history entry. Closes #6514 by settling on using a single origin for these checks. Closes #6628 by storing window.name values in the document state, so even in strange splitting situations like described there, they remain. Closes #6652 by no longer changing history.state when reactivating a document from bfcache ("restore the history object state" is called only when documentsEntryChanged is true). Tests: web-platform-tests/wpt#36368. Closes #6773 by having careful handling of synchronous navigations during traversals. Test updates: web-platform-tests/wpt#36364. Closes #6798 by treating javascript: URL navigations as replacements. Works towards #6809 by storing srcdoc resources in the document state. Closes #6813 by storing referrer in the document state. Tests for the repopulation case: web-platform-tests/wpt#36352. (No tests yet for the reload case.) Closes #6947 by rolling its contents into this change: PDF documents are put in the same category as other inaccessible, no-DOM documents. Closes #7107 by clearing history state on redirects and when origin changes by other means, such as CSP. Closes #7441 by making window.blur() a no-op because that was simpler than updating it to operate on navigables. Closes #7722 by incorporating its contents into the rewritten version. Closes #8295 by refactoring the iframe/frame load event specs to avoid the bug. Helps with #8395 by at least ensuring the javascript: case does not fire beforeunload. Tests: web-platform-tests/wpt#36488. (The other cases remain open for investigation and testing.) Closes #8449 by exporting "create a fresh top-level traversable" which is designed for the use case in question. Co-authored-by: Domenic Denicola <[email protected]> Co-authored-by: Dominic Farolino <[email protected]>
Consider this document:
I believe per spec clicking the first link then the second one should only open one window, since disowning the owner doesn't affect link targeting as far as I can tell.
In both Gecko and Blink, two windows are opened instead.
In Edge only one window is opened and the second click doesn't navigate it (no matter what I do with the opener) which seems a bit odd.
The text was updated successfully, but these errors were encountered: