Skip to content
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

Semantics of initial "about:blank" elision are unclear; every browser disagrees #546

Open
avidrissman opened this issue Jan 20, 2016 · 24 comments
Labels
compat Standard is not web compatible or proprietary feature needs standardizing interop Implementations are not interoperable with each other topic: history topic: navigation

Comments

@avidrissman
Copy link

If you create a frame without specifying a src attribute, the spec says that the frame is created with a URL of about:blank:

If, when the element is created, the srcdoc attribute is not set, and the src attribute is either also not set or set but its value cannot be resolved, the browsing context will remain at the initial about:blank page.

The spec doesn't seem to say that that about:blank is special in any way, but it seems like no two browsers treat it alike. Here's an experiment.

I've provided a test page at http://avidrissman.github.io/htmltests/aboutblank.html. It has an iframe with no specified src, and two buttons. One button loads a page into the frame, and one button adds an entry to the session history with pushState.

Scenarios:

  1. Go to the test page. Click the "Load the frame" button. When the frame is loaded, is a new entry added to the session history?
  2. Go to the test page. Click the "Push a history entry" button, then click the "Load the frame" button. When the frame is loaded, is a new entry added to the session history?
  3. Set up as in scenario 2. If the browser created a new entry, what happens to the iframe when you go back once?
  4. Set up as in scenario 2. What happens to the iframe when you go back to the initial test page (in one jump)?

The results that I'm seeing vary wildly:

  Chrome Edge Safari Firefox
Scenario 1 No entry is added. No entry is added. No entry is added. Yes, an entry is added.
Scenario 2 No entry is added. No entry is added. Yes, an entry is added. Yes, an entry is added.
Scenario 3 n/a n/a The iframe clears. The iframe clears.
Scenario 4 The iframe keeps its content. The iframe keeps its content. The iframe clears. The iframe keeps its content.

(As a note, I don't have access to Edge myself, so I asked a colleague to perform this test. Apologies if I got the results wrong.)

Chrome/Edge: These browsers seem to have the rule that if an iframe starts with no src, and gets one later, then the initial about:blank goes away. This might be good in terms of not creating confusing extra entries in the session history. However, this creates a situation where going back over a pushState doesn't return you to the page you saw. Before the pushState, you were looking at an empty frame. Shouldn't going back return you to that empty frame?

Safari: This browser sometimes creates a new session history entry when loading a blank iframe. I'm not sure what rule it's following; this behavior might be accidental.

Firefox: This browser seems to have the rule that loading an iframe always creates a new session history entry. It is consistent with that, though its failure to clear the iframe when jumping back two page appears to be a bug.

In any case, though, it looks like this is a case where no two browsers agree on what should be done. Can we decide what the rule for about:blank elision is?

@jdm
Copy link
Member

jdm commented Jan 20, 2016

This sounds very similar to #490!

@jdm
Copy link
Member

jdm commented Jan 20, 2016

cc @hsivonen

@zcorpan zcorpan added the compat Standard is not web compatible or proprietary feature needs standardizing label Jan 21, 2016
@zcorpan
Copy link
Member

zcorpan commented Jan 21, 2016

I think the main problem here is that this involves document loading/navigation, and changing how that works in browsers is high-investment, high-risk, and low value. So it hasn't really happened yet.

We did rewrite document loading/navigation in Presto, but that never ended up shipping before we switched to Chromium. But most tests that @jgraham wrote are now in web-platform-tests: web-platform-tests/wpt#304

So the fact that browsers still disagree doesn't necessarily mean that the spec has a bug. It's more convincing if a browser tries to implement the spec and finds that Web content regresses because of something specific in the spec. I hope that makes sense. :-)

@avidrissman
Copy link
Author

changing how [document loading/navigation] works in browsers is high-investment, high-risk, and low value

I've been working on Chromium's navigation code now for over a year, so I know how high-risk it can be. (I see the value in cleaning it up, though I know what you mean by "low value" in relation to the rest of the code.)

I ran into this behavior while investigating a navigation crash, and since it was surprising and disturbing how we behaved in this case, I wanted to see how other browsers behaved. When I found that no one agreed on what should be done, I wanted to ask the standards peeps what they thought.

If the standards peeps aren't interested in specifying this behavior, then I'll go ahead and fix it for Chromium in a way that makes sense for us. (I'll probably keep our elision behavior but fix the bug that was causing the iframes to not go back to being blank on the history navigation.) But I thought it would be nice to check here first.

@domenic
Copy link
Member

domenic commented Jan 21, 2016

I think we should fix this in the standard. @avidrissman has made a case that the standard's current behavior is pretty surprising to users and authors, IMO.

I'll probably keep our elision behavior but fix the bug that was causing the iframes to not go back to being blank on the history navigation.

Can you spell this out in terms of the scenario 1/2/3/4 behaviors?

@avidrissman
Copy link
Author

This would be a slight alteration of Chromium's behavior; we would keep eliding initial about:blank URLs, but would be sure to restore it as part of a history navigation.

Or framed in terms of the scenarios:

  1. No entry is added. (no change)
  2. No entry is added. (no change)
  3. n/a (no change)
  4. The iframe clears. (change)

@domenic
Copy link
Member

domenic commented Jan 21, 2016

Thanks. I'm willing to write up the spec patch to match that behavior, which seems more user-friendly than either the current spec (which includes about:blank history entries, which is not generally expected and doesn't occur in other cases e.g. the initial loading transition) or the current Chrome/Edge behavior (which has the surprising impact of going forward then back taking you to a non-blank iframe). I'd really like to get some involvement from another vendor on this interop issue though before we call it case-closed.

@jdm and @hsivonen from Gecko are already CCed; what do you guys think about converging on the behavior proposed in #546 (comment)? Also tagging in @bzbarsky...

@travisleithead, @DigiTec from Edge, any thoughts? You are pretty close to the proposed behavior already but as @avidrissman points out it would be better to converge on something more user-friendly that actually navigates back to a blank page, as the user might expect since that is what they saw before going forward then back.

@hober, any ideas on Safari's behavior here?

@bzbarsky
Copy link
Contributor

So a few thoughts off the top of my head:

  1. Yes, this is all a bloody mess.
  2. Who said an about:blank page is always empty? It can be nonempty due to javascript: URIs being loaded in it, or due to document.open/write/close (which, btw, may change its URI from about:blank to something else, but keep the same document; this may matter in terms of how the spec is written). Note that many of these situations are totally broken in Blink/WebKit right now in that the user does something that looks like a navigation but doesn't get a corresponding history entry.
  3. Gecko's behavior is largely due to it creating an initial about:blank document and also doing an async about:blank load in the no-src situation. I'm not sure what things would look like if we skipped doing the latter and just synthesized some load events and whatnot; we've talked about doing that already...
  4. A consequence of item 2 is that deciding on what's most user-friendly here is pretty hard. :(

@zcorpan
Copy link
Member

zcorpan commented Jan 22, 2016

I've been working on Chromium's navigation code now for over a year, so I know how high-risk it can be.

Sorry, I didn't know about that! To be clear, I am interested in fixing spec bugs and tests in web-platform-tests in this area, and would love to see interop, so I'm glad you're working on it. :-)

@annevk
Copy link
Member

annevk commented Jun 10, 2016

@avidrissman did you look at the comment from @hsivonen here #490 (comment)? That looks pretty ideal...

@avidrissman
Copy link
Author

I'm not quite up to speed with those mechanisms. @csreis, thoughts?

@avidrissman
Copy link
Author

I'm going to refer a few colleagues to this as well. A question, though, @annevk. Does the proposal there address the elision of the "about:blank" history entries? It's Chrome's history entry code that I'm familiar with, but it's not clear to me how the discussion of events affects that behavior.

@csreis
Copy link

csreis commented Jun 10, 2016

Right. I would defer to [email protected] or [email protected] on the synchronous loading question from #490, but I'm more concerned about whether you can go back to the initial about:blank page in an earlier history entry. (The race in #1191 is what concerns me.)

I'm curious if all previous history entries referencing the initial about:blank page are expected to be updated when the frame commits a real page, such that scenario 4 above (going back) has the frame keep its content. (The way Chrome does it is unfortunate and inconsistent: it skips navigating the subframe if the parent frame goes back in-page, even though the history entry says the iframe should go back to about:blank.)

@annevk
Copy link
Member

annevk commented Jun 21, 2016

This also relates to #1377 it seems.

I think in general replacing "initial about:blank" if it indeed stays empty is nice. Perhaps a solution here would be to stop flagging "initial about:blank" if pushState() or document.write(), or a javascript URL happens? Meaning that any replacement would no longer happen.

@bzbarsky
Copy link
Contributor

if pushState() or document.write(), or a javascript URL happens?

Or document.body.appendChild? This quickly gets messy...

@annevk
Copy link
Member

annevk commented May 4, 2017

Who said an about:blank page is always empty? It can be nonempty due to javascript: URIs being loaded in it, or due to document.open/write/close (which, btw, may change its URI from about:blank to something else, but keep the same document; this may matter in terms of how the spec is written). Note that many of these situations are totally broken in Blink/WebKit right now in that the user does something that looks like a navigation but doesn't get a corresponding history entry.

So how is this implemented? Do you keep track of DOM mutations, something else?

Gecko's behavior is largely due to it creating an initial about:blank document and also doing an async about:blank load in the no-src situation.

How does this interact with the modifications? Would they just get overwritten?


Aside: any differences between <iframe></iframe>, <iframe src></iframe>, and <iframe src=about:blank></iframe>?

@annevk annevk added the interop Implementations are not interoperable with each other label May 4, 2017
@bzbarsky
Copy link
Contributor

bzbarsky commented May 4, 2017

So how is this implemented? Do you keep track of DOM mutations, something else?

In Gecko, document.open/close creates a new history entry. In Blink/WebKit it does not.

Other mutations I described do not cause history entry creation.

How does this interact with the modifications? Would they just get overwritten?

Yes, they do. We consider this a bug, by the way; it's just hard to fix, which is why it's not fixed yet.

@annevk
Copy link
Member

annevk commented May 4, 2017

@bzbarsky I see, but Chromium/WebKit probably don't want to due to #1698. Or can we do this while not creating a new global object?

@bzbarsky
Copy link
Contributor

bzbarsky commented May 4, 2017

Or can we do this while not creating a new global object?

If you don't create a new global, then your post-write document can have scripts that depend on the state set up by scripts in the pre-write document in ways that make it hard to "load the post-write document" in any meaningful sense. But if there are no such scripts, then there is no hard dependency on the new global bit.

@annevk
Copy link
Member

annevk commented May 4, 2017

also doing an async about:blank load in the no-src situation

One thing is still unclear here. Does this race with a document.open() call somehow?

@bzbarsky
Copy link
Contributor

bzbarsky commented May 4, 2017

Does this race with a document.open() call somehow

In Gecko a document.open as in this testcase here:

<iframe src="about:blank"></iframe>
<script>
  frames[0].document.write("hey");
</script>

cancels the async load of "about:blank". That's in the spec too: https://html.spec.whatwg.org/multipage/webappapis.html#dom-document-open step 12, if you assume that the async load is in the context of the initial about:blank.

@avidrissman
Copy link
Author

avidrissman commented Dec 5, 2017

FYI I had to revert the change that I made to Chrome; the current state of Chrome is what I mentioned in the OP. The revert was due to the discovery of a race, #1191.

@annevk
Copy link
Member

annevk commented Feb 14, 2023

@domenic was this "resolved" perhaps by the navigation and history rewrite?

@domenic
Copy link
Member

domenic commented Feb 14, 2023

No, this area was not really touched. I am hopeful that given #3267 (comment) we can make progress here though, we just need to make some time for it...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compat Standard is not web compatible or proprietary feature needs standardizing interop Implementations are not interoperable with each other topic: history topic: navigation
Development

No branches or pull requests

7 participants