Skip to content

Implicit race with frame loading vs pushState/hash change #1191

@avidrissman

Description

@avidrissman

Suppose we have this scenario:

  1. Be at a site A with a new iframe in it, still at the initial about:blank URL.
  2. A loads the iframe by setting the url attribute of the frame.
  3. A does a pushState or document.location.hash change to make a new history entry.
  4. The user returns to the original history entry via the back button.

From what I can tell, the spec considers steps 2 and 3 to be a race. pushState gets the URLs of the iframes from their Documents, but switching the iframe's Document is the very last step of an iframe load. Therefore, when the user returns to the original history entry in step 4, one of two things can happen. If the load from step 2 completed before the pushState snapshotted the state of the page in step 3, then the user will see the iframe loaded. Otherwise (and more likely), the pushState completed before the iframe load completed, and the navigation in step 4 will leave a blank iframe.

The race doesn't need to be this explicit; a simple page load can encounter this.

I bring this up because I made a change to Chromium that fixed a bug that was masking this issue. This caused major issues with several big Google apps. I bring up a bug in Gmail chat as an example, and quote from the repro:

  1. switch to another label (like "starred")
  2. open a second chat to someone
  3. switch to another label (like "drafts")
  4. open a third chat to someone
  5. hit back twice, then forward twice

It's obvious what's going on here: opening a chat opens iframes, but switching labels triggers a document.location.hash change. And if the chat iframe hasn't fully loaded, then the iframe's location is captured as about:blank and things break.

The obvious solution according to the spec is to wait until all the onload events fire for the loading iframes. The problems with that solution are 1) that means that every part of the page has to know about all loading iframes, to make sure that they are all loaded before moving on, and 2) if the pushState or hash change is user-initiated, the web page can't wait.

And finally, in discussions with web page authors, when I mention this race to them, it is a surprise. None are expecting this to be the case.

This is a problem today in Chromium because I removed a bug that was masking this race. What is surprising to me is Firefox did not have this bug (see my analysis of Firefox in #546), but Firefox does not appear to have this race. Perhaps they're capturing loads in progress? I'm familiar with Chromium navigation code, so I can state why we're hitting this issue, but I am not familiar with Firefox code.

tl;dr:
The fact that [load iframe; pushState] is a race is surprising to users and has no easy workarounds. Chromium is being bitten by this. What do other browsers do? Should we fix the spec so that this is not a race?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions