-
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
A new mode for iframes where they don't add to the joint session history? #6501
Comments
I figured we might need to solve this problem so I've been designing for it in #6315, but it's a little different to what you're proposing here. I have:
Currently, browsers only treat the top-level as traversable, but the model will allow for traversables to be nested. However, in this model, nested traversables would have their own session history of multiple entries, rather than have everything turned into "replace" navigations. These history entries wouldn't be traversable via the back/forward buttons, but could be traversed using Since the top-level doesn't store the session history of nested traversables, their session history wouldn't be repopulated after going back to the page (unless of course the previous page was kept alive in bfcache). The benefit of this is you wouldn't need to remove The downside is it might be more complicated to implement, but I'm not sure. |
I think what @jakearchibald outlines matches what we wanted for #763 (see also the very long discussion at WICG/webcomponents#184). A good initial test for this feature might be deploying it for shadow cc @rniwa |
What is the appropriate model for how to impose this? I can think of a few options:
Of these permissions policy seems pretty good... |
Yeah, although I'm not a big fan of opt-in for third parties, I agree it fits here. (And perhaps we can switch the default over time.) cc @clelland |
Some implementation discussions among the Chrome team revealed that implementing the variant of this that @jakearchibald proposes, with independent session histories for the iframes, would be quite difficult. Also, it could be confusing for users in cases involving iframe restoration. The proposal we're favoring now is to have this make every navigation in the iframe a "replace" navigation. This still meets the use cases I'm most concerned with, which is letting pages ensure that iframes don't add entries to the joint session history. Does that still sound reasonable to Mozilla folks? /cc @smaug---- |
What happens with a nested I'm also still wondering if we could make this the default for shadow tree nested documents to solve the leakage problem there. |
Yeah, it could indeed have that impact. I think that's OK? I remain doubtful that it would be web-compatible to change how shadow trees work, but we'd welcome anyone running an experiment to prove us wrong. |
In the case where this is a policy you force upon descendants you probably would not want any descendant to be able to navigate away from you again. It seems quite easy for a descendant to have some |
Oh, I see, because Were you thinking we would just make |
I was wondering what you all were thinking since @jakearchibald hinted at this being a problem in #6501 (comment), but no-op would work I think. |
In what way? |
I think I was making a few logic jumps there that are not, in retrospect, justified. In particular I was thinking "having to save/restore/sync for these independent session history lists would be a lot of work to spec/implement, so, we should probably just not do so and restore from the So this is mostly a question as to whether the web developer experience gains of allowing non-replace navigations/nontrivial session history in these scenarios is worth the implementation cost. I think the Chrome history engineers' position is that it is not worth it, and I tend to agree. |
Expanding on the Chrome implementation position, I think what's really hard to implement is actually full separation of top-level and iframe session history in general. So even if we had replacement-only session history model in iframes, I think what would be really challenging is (a) the back button restoration stuff mentioned earlier, (b) Divorcing the history entirely (i.e., not sharing history.length, having history.back() in an iframe not influence the top-level page). I think that's the tricky part. That is, the implementation complexity is agnostic to the triviality of the session history model in the iframe, but is related to the completeness of the separation in general. I'd like @csreis to correct me though if I am wrong. |
Hmm, my impression was different. (a) restoration gets pretty easy if we only have to serialize "current URL" for the iframe, and not an entire history list? Maybe? (b) history.length never changes due to replacement, only due to push. And we can just add a check (e.g. in the renderer process) to bail out for history.back(), etc. in these iframes. |
But it is still shared. If A.com embeds B.com and C.com where both B and C are sibling iframes, and C.com navigates a million times, I think all of these are observable by A.com and B.com via history.length. Maybe this is too implementation-specific or "deep" but the question seems to be which one do we want:
The distinction between the two might be overly-pedantic from a spec perspective; if that's the case then sorry.
That's quite possible! I'm not totally sure so I delegate to Charlie. From an impl POV it does seem like if we don't actually require fully separated iframe history but still have it operate on the same underlying objects (just in a replacement-only manner and with manually patched i.e., |
What I was getting at was if the million C.com navigations are with replacement, then history.length will not change. But I agree it provides a communications channel. E.g. if B is in replace-only mode and C is not, then B and C can communicate by B observing history.length and C modifying it. We could manually patch this out by making history.length return 1 in such replace-only iframes. Probably that's a good idea anyway since we're saying history.back() will no-op; it seems like those two should stay in sync, generally. If we do such patching, then I hope the two are equivalent. But I agree they're conceptually different, and there might be things we miss patching which could make them diverge :-/. |
Yeah, that is the only thing I am worried about, basically a slightly incomplete audit and therefore incomplete manual patches. Side-question:
Do we think that we could ever actually make this the default behavior without requiring all content to opt-in to being framed? Right now content can opt-out of being framed and we're discussing the possibility of making all framed content have this replacement-only model in the future. This is a big pretty big behavior difference between a given site operating in a top-level context and the same site operating in a framed context, so I feel like this would just require turning the opt-in for this new replacement-only model into an opt-in for "You're being placed in an iframe". |
To clarify, it's impractical in Chrome to restore a nested joint session history (e.g., if "nested traversables would have their own session history of multiple entries"), even if that nested history is limited to a single item. In the single item case, we would still need to store more than just the URL: also scroll position, form state, and many other things that get serialized. However, I agree with @domfarolino that the replace-only + manual-patch suggestion seems to avoid the need for a nested joint session history. If an iframe in this mode is limited to a single session history item and can't otherwise affect the top-level joint session history, then it seems reasonable to store it as a single session history item within the top-level joint session history. That does seem like it would make restoration possible. |
Surely this should be a property of a frame, and not of a specific document / navigation? At least that's what we were discussing for the shadow DOM. |
Yep, this would be a property of the iframe (browsing context); that's how permissions policy works. |
Background: Fenced frames can navigate themselves but their history is not part of the browser back/forward list as that could be a communication channel from the fenced frame to the embedding page. This aligns with MPArch's disjoint back/forward list for nested frame trees. (For shadowDOM, this would be achieved with additional API level restrictions like history.length always returning 1 etc.) Current Change: This CL focuses on fenced frames to always have a replacement-only navigation which was decided due to being a simpler model since it doesn't imply that there's a hidden list of back/forward entries for the nested page, only accessible via history APIs and not via the back/forward buttons. This is also consistent with the iframes new opt-in mode for disjoint session history as discussed in whatwg/html#6501. This change affects both shadowDOM and MPArch versions. Design: https://docs.google.com/document/d/17rtX55WkxMcfh6ipuhP4mNULIVxUApvYt4ZYXfX2x-s/edit#heading=h.af2cik2j1rbs This CL includes browser tests to check the NavigationController's entry count and https://chromium-review.googlesource.com/c/chromium/src/+/3227344 added WPTs for all the history API surface. Bug: 1242533 Change-Id: Ic574ee1bf87ce3a53dde7d280abaa46233d85b0d Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3216452 Reviewed-by: Reilly Grant <[email protected]> Reviewed-by: Dave Tapuska <[email protected]> Reviewed-by: Rakina Zata Amni <[email protected]> Reviewed-by: Jeremy Roman <[email protected]> Reviewed-by: Lei Zhang <[email protected]> Reviewed-by: Alex Moshchuk <[email protected]> Commit-Queue: Dave Tapuska <[email protected]> Commit-Queue: Shivani Sharma <[email protected]> Cr-Commit-Position: refs/heads/main@{#938761}
This reverts commit 5e37873. Reason for revert: Appears to be breaking the tree https://ci.chromium.org/ui/p/chromium/builders/ci/Mac%20Builder%20(dbg)/202959/blamelist Original change's description: > Fenced Frames: Navigations always replace the current entry > > Background: > Fenced frames can navigate themselves but their history is not part of > the browser back/forward list as that could be a communication channel > from the fenced frame to the embedding page. This aligns with MPArch's > disjoint back/forward list for nested frame trees. (For shadowDOM, this > would be achieved with additional API level restrictions like > history.length always returning 1 etc.) > > Current Change: > This CL focuses on fenced frames to always have a replacement-only > navigation which was decided due to being a simpler model since it > doesn't imply that there's a hidden list of back/forward entries for > the nested page, only accessible via history APIs and not via the > back/forward buttons. This is also consistent with the iframes new > opt-in mode for disjoint session history as discussed in > whatwg/html#6501. > This change affects both shadowDOM and MPArch versions. > > Design: > https://docs.google.com/document/d/17rtX55WkxMcfh6ipuhP4mNULIVxUApvYt4ZYXfX2x-s/edit#heading=h.af2cik2j1rbs > > This CL includes browser tests to check the NavigationController's entry > count and > https://chromium-review.googlesource.com/c/chromium/src/+/3227344 > added WPTs for all the history API surface. > > > Bug: 1242533 > Change-Id: Ic574ee1bf87ce3a53dde7d280abaa46233d85b0d > Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3216452 > Reviewed-by: Reilly Grant <[email protected]> > Reviewed-by: Dave Tapuska <[email protected]> > Reviewed-by: Rakina Zata Amni <[email protected]> > Reviewed-by: Jeremy Roman <[email protected]> > Reviewed-by: Lei Zhang <[email protected]> > Reviewed-by: Alex Moshchuk <[email protected]> > Commit-Queue: Dave Tapuska <[email protected]> > Commit-Queue: Shivani Sharma <[email protected]> > Cr-Commit-Position: refs/heads/main@{#938761} Bug: 1242533 Change-Id: Ib946f629447de53164e1d335cf4b983e1fbdaa35 No-Presubmit: true No-Tree-Checks: true No-Try: true Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3260236 Auto-Submit: anthonyvd <[email protected]> Owners-Override: anthonyvd <[email protected]> Commit-Queue: Rubber Stamper <[email protected]> Bot-Commit: Rubber Stamper <[email protected]> Cr-Commit-Position: refs/heads/main@{#938770}
[Catching up] Breaking |
Background: Fenced frames can navigate themselves but their history is not part of the browser back/forward list as that could be a communication channel from the fenced frame to the embedding page. This aligns with MPArch's disjoint back/forward list for nested frame trees. (For shadowDOM, this would be achieved with additional API level restrictions like history.length always returning 1 etc.) Current Change: This CL focuses on fenced frames to always have a replacement-only navigation which was decided due to being a simpler model since it doesn't imply that there's a hidden list of back/forward entries for the nested page, only accessible via history APIs and not via the back/forward buttons. This is also consistent with the iframes new opt-in mode for disjoint session history as discussed in whatwg/html#6501. This change affects both shadowDOM and MPArch versions. Design: https://docs.google.com/document/d/17rtX55WkxMcfh6ipuhP4mNULIVxUApvYt4ZYXfX2x-s/edit#heading=h.af2cik2j1rbs This CL includes browser tests to check the NavigationController's entry count and https://chromium-review.googlesource.com/c/chromium/src/+/3227344 added WPTs for all the history API surface. Bug: 1242533 Change-Id: Ic574ee1bf87ce3a53dde7d280abaa46233d85b0d Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3216452 Reviewed-by: Reilly Grant <[email protected]> Reviewed-by: Dave Tapuska <[email protected]> Reviewed-by: Rakina Zata Amni <[email protected]> Reviewed-by: Jeremy Roman <[email protected]> Reviewed-by: Lei Zhang <[email protected]> Reviewed-by: Alex Moshchuk <[email protected]> Commit-Queue: Dave Tapuska <[email protected]> Commit-Queue: Shivani Sharma <[email protected]> Cr-Commit-Position: refs/heads/main@{#938761} NOKEYCHECK=True GitOrigin-RevId: 5e37873045b5e4c8cd4244480476a2b0c23b8114
This reverts commit 5e37873045b5e4c8cd4244480476a2b0c23b8114. Reason for revert: Appears to be breaking the tree https://ci.chromium.org/ui/p/chromium/builders/ci/Mac%20Builder%20(dbg)/202959/blamelist Original change's description: > Fenced Frames: Navigations always replace the current entry > > Background: > Fenced frames can navigate themselves but their history is not part of > the browser back/forward list as that could be a communication channel > from the fenced frame to the embedding page. This aligns with MPArch's > disjoint back/forward list for nested frame trees. (For shadowDOM, this > would be achieved with additional API level restrictions like > history.length always returning 1 etc.) > > Current Change: > This CL focuses on fenced frames to always have a replacement-only > navigation which was decided due to being a simpler model since it > doesn't imply that there's a hidden list of back/forward entries for > the nested page, only accessible via history APIs and not via the > back/forward buttons. This is also consistent with the iframes new > opt-in mode for disjoint session history as discussed in > whatwg/html#6501. > This change affects both shadowDOM and MPArch versions. > > Design: > https://docs.google.com/document/d/17rtX55WkxMcfh6ipuhP4mNULIVxUApvYt4ZYXfX2x-s/edit#heading=h.af2cik2j1rbs > > This CL includes browser tests to check the NavigationController's entry > count and > https://chromium-review.googlesource.com/c/chromium/src/+/3227344 > added WPTs for all the history API surface. > > > Bug: 1242533 > Change-Id: Ic574ee1bf87ce3a53dde7d280abaa46233d85b0d > Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3216452 > Reviewed-by: Reilly Grant <[email protected]> > Reviewed-by: Dave Tapuska <[email protected]> > Reviewed-by: Rakina Zata Amni <[email protected]> > Reviewed-by: Jeremy Roman <[email protected]> > Reviewed-by: Lei Zhang <[email protected]> > Reviewed-by: Alex Moshchuk <[email protected]> > Commit-Queue: Dave Tapuska <[email protected]> > Commit-Queue: Shivani Sharma <[email protected]> > Cr-Commit-Position: refs/heads/main@{#938761} Bug: 1242533 Change-Id: Ib946f629447de53164e1d335cf4b983e1fbdaa35 No-Presubmit: true No-Tree-Checks: true No-Try: true Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3260236 Auto-Submit: anthonyvd <[email protected]> Owners-Override: anthonyvd <[email protected]> Commit-Queue: Rubber Stamper <[email protected]> Bot-Commit: Rubber Stamper <[email protected]> Cr-Commit-Position: refs/heads/main@{#938770} NOKEYCHECK=True GitOrigin-RevId: 367479e4b169662f146b1053e9deaeedee035208
This is a reland of 5e37873045b5e4c8cd4244480476a2b0c23b8114 The change here is that the new tests should call GetPrimaryFrameTree instead of GetFrameTree. Original change's description: > Fenced Frames: Navigations always replace the current entry > > Background: > Fenced frames can navigate themselves but their history is not part of > the browser back/forward list as that could be a communication channel > from the fenced frame to the embedding page. This aligns with MPArch's > disjoint back/forward list for nested frame trees. (For shadowDOM, this > would be achieved with additional API level restrictions like > history.length always returning 1 etc.) > > Current Change: > This CL focuses on fenced frames to always have a replacement-only > navigation which was decided due to being a simpler model since it > doesn't imply that there's a hidden list of back/forward entries for > the nested page, only accessible via history APIs and not via the > back/forward buttons. This is also consistent with the iframes new > opt-in mode for disjoint session history as discussed in > whatwg/html#6501. > This change affects both shadowDOM and MPArch versions. > > Design: > https://docs.google.com/document/d/17rtX55WkxMcfh6ipuhP4mNULIVxUApvYt4ZYXfX2x-s/edit#heading=h.af2cik2j1rbs > > This CL includes browser tests to check the NavigationController's entry > count and > https://chromium-review.googlesource.com/c/chromium/src/+/3227344 > added WPTs for all the history API surface. > > > Bug: 1242533 > Change-Id: Ic574ee1bf87ce3a53dde7d280abaa46233d85b0d > Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3216452 > Reviewed-by: Reilly Grant <[email protected]> > Reviewed-by: Dave Tapuska <[email protected]> > Reviewed-by: Rakina Zata Amni <[email protected]> > Reviewed-by: Jeremy Roman <[email protected]> > Reviewed-by: Lei Zhang <[email protected]> > Reviewed-by: Alex Moshchuk <[email protected]> > Commit-Queue: Dave Tapuska <[email protected]> > Commit-Queue: Shivani Sharma <[email protected]> > Cr-Commit-Position: refs/heads/main@{#938761} Bug: 1242533 Change-Id: Ifc03b2021f8734b4b09cb1f5b647432d654bf8e7 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3260313 Reviewed-by: Dave Tapuska <[email protected]> Reviewed-by: Jeremy Roman <[email protected]> Reviewed-by: Alex Moshchuk <[email protected]> Reviewed-by: Lei Zhang <[email protected]> Owners-Override: Dave Tapuska <[email protected]> Commit-Queue: Shivani Sharma <[email protected]> Cr-Commit-Position: refs/heads/main@{#938856} NOKEYCHECK=True GitOrigin-RevId: f405bf0de9c265c35b4570dbe16aa4b60483dc27
Having opened a related issue here: #8773, I wanted to contribute some thoughts here re iframe's maintaining their own history. I side most closely with @jakearchibald's proposed spec. Firstly, I think it's essential that iframes have their own maintained history, and as far as I understand, using I think its imperative that iframes can manage their own history, and that the history for an iframe can be traversed fwd/bwd from the parent frame, at least so that the parent frame can present backward/forward/refresh navigation options. I don't think we need to worry about restoring nested joint session histories, only the top-level. As for nested iframes-in-iframes, I think it's perfectly suitable for a nested iframe-in-iframe to also self maintain its own history, and how that works would be dictated by the setting of those nested iframes For example:
In the above example, without using With this in mind…
Note, rather than
|
When the URL of an iframe changes, an entry is pushed onto the history stack: whatwg/html#6501 We get two history entries if we change gene page. Then we need to oush the back button twice to go back to the previous gene page. And the first click shows the wrong iframe contents. This hack recreate the iframe component on page change so it's not added to the history. Sort of like this: https://stackoverflow.com/a/79096750 Refs #2284
This has come up several times in discussions with @annevk, @csreis, @natechapin, @smaug----, @jakearchibald, and others.
Basically, iframes participating in the joint session history can be problematic for web developers and for users. It means iframes can change the meaning of
history.back()
and the back button. Although this is sometimes a good thing, in terms of allowing the user to transition between multiple states, in other cases it's not desired, such as when iframing ads or other untrusted third-party code.Even the app history proposal cannot tame this fully, because it wants to stay based on top of joint session history so as to avoid creating a whole parallel incompatible model. It tries to make things better, by saying that
appHistory.back()
is guaranteed to move your own frame back (and not just some subframe or parent frame), but that leads to a problem (WICG/navigation-api#73) whereappHistory.back(); appHistory.forward()
can take you to a different joint session history entry than the one you started, in a way that is visible in terms of what subframes are showing.So I'm wondering if we can approach this from a different angle, of allowing web developers to say that a given frame cannot impact joint session history. In particular, I'd propose that this makes all navigations within the frame "replace" navigations. (This is what is currently planned for prerendering and portals, although those are early-stage.) We could also contemplate removing the
history.back/forward/go()
APIs in such frames since they would only be able to mess with the parent, and maybe we don't want to allow such parent-messing.If people think this is a good idea, the biggest question is whether the embedded content would need to opt-in (e.g., in the style that document policy requires) or whether we could allow the embedder page to impose this on the embeddee without consent (like
sandbox=""
does).The text was updated successfully, but these errors were encountered: