Nested browsing context with identical URLs
The current spec states the following about nested browsing contexts with identical URLs (for example, foo.html containing an iframe which loads foo.html).
https://html.spec.whatwg.org/#the-iframe-element
If there exists an ancestor browsing context whose active document's URL, ignoring fragments, is equal to url, then abort these steps.
This behavior is followed by firefox and internet explorer, but is not followed by safari, chrome or edge. These browsers instead allow 1 level of nesting, and reject nested browsing contexts past that point. So, for example, the file
<!-- foo.html -->
<p>Some Text</p>
<iframe src="http://example.com/foo.html"></iframe>
Firefox and IE will render the root page, and an empty iframe, Edge will render the root page, the first iframe, and an empty iframe within that first iframe. Chrome will render the root page and the first iframe, but the iframe within the first iframe will not be rendered at all.
Should the behavior in the spec be changed to allow one level of nested browsing contexts with identical URLs?
(bugzilla bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1279728) cc @annevk @bzbarsky
Paging @rbyers, @cdumez, and @travisleithead. Edge's behavior seems most reasonable if we are going to change something here. Not quite sure how you can end up with the <iframe> not rendered.
Has there been any off-issue discussion about this?
Not aware of any discussion. @foolip can you help out perhaps?
I haven't heard of this issue before. That this changed between IE and Edge could mean that there's some content that depends on it, or a bunch of code was just rewritten and this happened to change.
I tested the foo.html in https://github.com/whatwg/html/issues/1518#issue-164404944 and AFAICT Chrome and Firefox have the same behavior. More detailed tests and reports including browser version numbers might be helpful.
Not sure who might know how this works in Blink, maybe @zetafunction?
In Blink, this check is enforced in https://chromium.googlesource.com/chromium/src/+/adba2165f4c6e1c7d4a78179d6e066aa8e37f938/third_party/WebKit/Source/core/frame/LocalFrame.cpp#740.
The comment claims that some sites that depend on this behavior, but if IE and Firefox didn't support this...
(Incidentally, it looks like the Blink check is probably broken with out-of-process iframes. Oops. ~~Edit: just kidding~~ Edit 2: nope, totally broken.)
Trying the test again, screenshots from Chrome, Edge, Firefox and Safari:
![]()
![]()
![]()
![]()
So it's only Firefox that allows no nesting at all, while the rest have some weird stuff going on. Whether or not it's still required for web compat, spec'ing something like what Edge does seems reasonable.
The code in https://github.com/whatwg/html/issues/1518#issuecomment-249526213 goes way back to 2002: https://trac.webkit.org/changeset/3209
I don't know what the bug numbers 3103287 and 3083732 refer to, but it's a good guess that those sites in particular are gone.
@mystor are there web platform tests for this?
Also, am I right I thinking that the fix here would be changing the requirement to:
If there exist[ two] ancestor browsing context[s] whose active document's URL, ignoring fragments, is equal to url, then abort these steps.
(We should maybe also change how we compare the URL to make use of https://url.spec.whatwg.org/#concept-url-equals instead.)
Having written that down, I guess the question is what happens when the nesting is A loading B and B loading A. Does that result in A > B > A > B > about:blank? Same for A loading B, B loading C, and C loading A. Does that result in A > B > C > A > B > C > about:blank?
That sounds about right. The only alternative that comes to mind is to allow only one hop after detecting a loop, but it probably doesn't matter. Needs tests though.
Firefox fires an "error" event under these conditions. @bzbarsky wrote about this while helping out with a web-platform-test:
When Firefox does the blocking, we fire an error event on the
<iframe>. The spec doesn't say to fire any events, whether load or error, but that seems like a pretty weird behavior to me; the load is not being done as requested, and firing error seems appropriate.
What do you folks think about adding that to the set of changes that you've already agreed on?
Separately, I've filed a patch for the behavior as currently specified. Even though we're considering changes to the spec, it's a little tricky to test without race conditions, so the methodology can be worked out in parallel.
I think it's a good idea, assuming no load event is dispatched. Ideally we make iframe elements more similar to other network APIs over time.