Specify back button history-entry skipping? · Issue #7832 · whatwg/html (original) (raw)
Per WICG/interventions#21, some browsers have implemented a heuristic where pressing the back button skips certain entries in the joint session history. Generally, these are entries where there is no user interaction. The intent is to avoid "back trapping", e.g. if you arrive on a malicious site which does history.pushState()
10 times, this makes it hard to escape the site by pressing the back button.
Notably, this is different than ignoring the history.pushState()
calls entirely (which is explicitly allowed). The joint session history entries still exist from the page's point of view: e.g., history.length
still increases, and history.back()
still goes back to them. But the user pressing the back button will do the equivalent of history.go(-11)
or similar, instead of history.go(-1)
.
The current HTML Standard sort of allows this:
The History interface is not meant to place restrictions on how implementations represent the session history to the user.
For example, session history could be implemented in a tree-like manner, with each page having multiple "forward" pages. This specification doesn't define how the linear list of pages in the history object are derived from the actual session history as seen from the user's perspective.
... but sort of doesn't:
When the user navigates through a browsing context, e.g. using a browser's back and forward buttons, the user agent must traverse the history by a delta with a delta equivalent to the action specified by the user and the browsing context being operated on.
So at a minimum we should make it clearer that mapping the user expression to the delta might involve such considerations.
But we should probably go further than that. We should probably give more detail on which entries, exactly, will be skipped. Otherwise there are problematic interop problems, where e.g. pressing back will skip a history entry in one browser, and sites depend on it, but in other browsers that entry will not be skipped, leading to an inadvertent bad user experience.
@johannhof has mentioned that reverse-engineering Chromium's logic was a pain for Firefox (and still not shipped). And @miketaylr points out that there are many cases of "back button works in Chrome but not Firefox" bugs; my suspicion is that many of these are due to this issue (although others may be due to other history interop problems).
So even though this part of the web platform, dealing with how you translate user gestures on browser UI into web page actions, is traditionally outside the bounds of specs, in this case I think working on a specification for interoperable behavior would be appreciated. (As a compromise, I think the end result would be mostly "should"s, not "must"s.)
The bad news is that the heuristics here are still evolving. E.g. Chromium has some known bugs in our back-trapping prevention, which @shivanigithub and @creis have been looking at. So it's not even clear whether any browser has an implementation stable enough to spec. Maybe we can try to spec what we have, with the understanding that it will probably continue evolving? I just want to make sure we don't freeze this mapping in stone too early, by specifying it.
As part of this work we may also want to try coming up with more interoperable heuristics for ignoring pushState()
/replaceState()
calls, since that has similar user-facing effects. As introduced in #999, the spec just says "Optionally, return" with no guidance.