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

What should happen when traversing to a history entry results in nothing displayable #6483

Closed
jakearchibald opened this issue Mar 12, 2021 · 2 comments · Fixed by #6315
Closed
Labels
interop Implementations are not interoperable with each other topic: history

Comments

@jakearchibald
Copy link
Contributor

jakearchibald commented Mar 12, 2021

…but also not an error? Things like HTTP 204 and responses with Content-Disposition.

Top level Content-Disposition

Traversing back to a page that, different to last time, serves a file via Content-Disposition.

  1. https://iframe-session-history.glitch.me/
  2. Click "unset all" (just to clear any existing cookies)
  3. Click "Set cookie: Give all responses noStore"
  4. Reload https://iframe-session-history.glitch.me/ (you may want to do this in a new tab so you can "unset all" later)
  5. Click "Set cookie: Make top-level page response trigger download"
  6. Click "Navigate to same origin page"
  7. Click back

Chrome: Download starts. The traversal is cancelled, meaning you're stuck on the history entry. Clicking back again starts another download. If you hammer the back button fast enough you can get past the history entry.

Firefox: Download prompt. The traversal is cancelled, meaning you're stuck on the history entry. Clicking back again starts another download. Hammering the back button doesn't seem to help, but it might be a race.

Safari: As Chrome. Download starts. The traversal is cancelled, meaning you're stuck on the history entry. Clicking back again starts another download. If you hammer the back button fast enough you can get past the history entry.

Top level 204

Traversing back to a page that, different to last time, serves a 204.

  1. https://iframe-session-history.glitch.me/
  2. Click "unset all" (just to clear any existing cookies)
  3. Click "Set cookie: Give all responses noStore"
  4. Reload https://iframe-session-history.glitch.me/ (you may want to do this in a new tab so you can "unset all" later)
  5. Click "Set cookie: Make top-level page response 204"
  6. Click "Navigate to same origin page"
  7. Click back

Chrome: Similar to the download case. The traversal is cancelled, meaning you're stuck on the history entry. If you hammer the download button fast enough you can get past the history entry.

Firefox: Similar to the download case. The traversal is cancelled, meaning you're stuck on the history entry. Hammering the back button doesn't seem to help, but it might be a race.

Safari: Traversal happens, but the active document doesn't change. So, clicking back again returns to the new tab page. Clicking forward also traverses, but you stay visually on the new tab page.

Iframe Content-Disposition

Traversing back to an iframe page that, different to last time, serves a file via Content-Disposition.

  1. https://iframe-session-history.glitch.me/
  2. Click "unset all" (just to clear any existing cookies)
  3. Click "Set cookie: Give all responses noStore"
  4. Reload https://iframe-session-history.glitch.me/
  5. Click "Set cookie: Make iframe initial response trigger download"
  6. Click iframe-1 "add unload listener" (to prevent bfcache)
  7. Click iframe-1 "Navigate to 'one'"
  8. Click back

Chrome: Download starts. The traversal is cancelled, meaning you're stuck on the history entry. Clicking back again starts another download. Hammering the back button doesn't seem to help, but it might be a race.

Firefox: Download prompt. The traversal is cancelled, meaning you're stuck on the history entry. Clicking back again starts another download. Hammering the back button doesn't seem to help, but it might be a race.

Safari: Download starts. Traversal happens, but the active document doesn't change. So, clicking back again returns to the new tab page.

Iframe 204

Traversing back to an iframe page that, different to last time, serves a 204.

  1. https://iframe-session-history.glitch.me/
  2. Click "unset all" (just to clear any existing cookies)
  3. Click "Set cookie: Give all responses noStore"
  4. Reload https://iframe-session-history.glitch.me/
  5. Click "Set cookie: Make iframe initial response 204"
  6. Click iframe-1 "add unload listener" (to prevent bfcache)
  7. Click iframe-1 "Navigate to 'one'"
  8. Click back

Chrome: The traversal is cancelled, meaning you're stuck on the history entry. Hammering the back button doesn't seem to help, but it might be a race.

Firefox: As Chrome. The traversal is cancelled, meaning you're stuck on the history entry. Hammering the back button doesn't seem to help, but it might be a race.

Safari: Traversal happens, but the active document doesn't change. So, clicking back again returns to the new tab page.

Recommendation

The patterns that break the back button seem bad, and potentially abusable.

I like what Safari sometimes does, and I think I can spec it:

Right now, a navigable has a "current session history entry", but I could split this into a "current session history entry" and a "displayed session history entry". These will usually be the same thing, except in cases where you traverse to something that cannot display, such as the cases above.

Take this history:

Screenshot 2021-03-12 at 13 00 16

Where the top row is a top level page and the second row is an iframe in that page.

  1. We're on step 2. The iframe has the /one entry as both its current and displayed entry.
  2. Back clicked, but /frame-start returns a 203. As a result, the iframe has the /frame-start entry as its current entry, but stays with /one as its displayed entry.
  3. Back clicked, traversing the top level page. However, the iframe knows the /frame-start entry is its current entry, so nothing happens to the iframe, even though it's still displaying the document from /one.
  4. Forward clicked, traversing the top level page. However, the iframe knows the /frame-start entry is its current entry, so nothing happens to the iframe, even though it's still displaying the document from /one.
  5. Forward clicked. The iframe now changes its current entry to /one, but since its rendered entry is already /one, it doesn't reload or refresh.

cc @smaug---- @csreis @natechapin @cdumez @domenic

@jakearchibald jakearchibald added topic: history interop Implementations are not interoperable with each other labels Mar 12, 2021
@domenic
Copy link
Member

domenic commented Mar 12, 2021

Another great catch! Your recommendation makes sense to me, although the simplicity and (sort of) 2/3 behavior of just not allowing the traversal is somewhat attractive.

I hope we can get folks like @smaug---- and @csreis / @rakina to chime in on whether they think it's OK to change their implementation in such a fashion.

@jakearchibald
Copy link
Contributor Author

I think "cancel traversal" might be a vector for keeping someone trapped in the site. Also, it gets a lot more complicated if you're stepping back multiple history items at once, and 3 iframes navigate, and one 204s. That would require synchronising all the fetch parts of a traversal before swapping any active documents.

This is pretty similar to #6446, except with beforeunload it's ok to cancel the traversal since it's the user's choice.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
interop Implementations are not interoperable with each other topic: history
Development

Successfully merging a pull request may close this issue.

2 participants