If a page modifies the DOM tree, the user navigates away from it, and then hits Back, Firefox will not consistently restore the DOM state in all cases.
I don’t know whether there is a spec defining whether the DOM tree *should* be restored into its modified state (I sure wish this were the case). But regardless of that, what Firefox does currently is inconsistent: in some cases the modified DOM is restored, and in others it isn’t.
Here’s a micro-website for demonstrating this issue: http://bbb.akshell.com
Observe the following scenarios:
- Modify the DOM, go away, go Back: the modified DOM is **restored**.
- Modify the DOM, close the tab, undo close: the modified DOM is **discarded**.
- Switch to the "broken" variant, which is the same except for also including a Google Map. Modify the DOM, go away, go Back: the modified DOM is also **discarded**.
My personal preference would be to make all scenarios restore the modified DOM. However, a consistent behaviour is preferable to the current situation.
Tested on Nightly 14.0a1 (2012-03-22).
If anyone knows whether there are any plans to make the Back button always restore the latest DOM, please say so.
I answered this at http://stackoverflow.com/a/10466698/1026 : Embedding Google Maps into the page disables the bfcache because the Maps page loaded in an <iframe> uses an unload listener. This is by design: https://developer.mozilla.org/En/Using_Firefox_1.5_caching
But I'm unsure why the iframe rule was needed. I understand why we don't cache the parent page with an uncacheable same-origin iframe, but not in the Google Maps case.
This was part of the initial landing, and the only comment I could find about this in the original bug is bug 274784 comment 73:
> What if there's an unload or beforeunload listener on a subframe of this
> window?In general, it seems to me that we want to save only if we can save the
> presentation for this docshell _and_ all its descendants.
bz, care to clarify and resolve this if needed?
Of course it's needed. Consider a user navigating away from a page that has a subframe that has an unload handler. Say we just put the page into bfcache. That means not firing the unload handler (because if we fire it, the page is likely to do things that would make it broken if we restore it). But once a page is in bfcache, we can't run script on it, so when we evict it we can't fire the unload handler. Result: page has unloaded, but the unload handler has not run. That's broken, both in terms of being web-detectable and in terms of breaking pages.
The real solution is to get more pages to move to pagehide handlers if that's what they really mean.
bz: Just so I understand you correctly: Consider the original bugreport:
If a page modifies the DOM tree, the user navigates away from it, and then
hits Back, Firefox will not consistently restore the DOM state in all cases.
So you are saying that Firefox will deliberately keep this bug because many websites themselves have a bug (namely, doing things on unload that render the page broken)?
The "restore the DOM on back" behavior is opportunistic: it won't happen if the page has an unload handler, it won't happen if the page is not done loading when you navigate away, it won't happen if you navigate enough other pages before you go back, and it won't happen if we get a memory pressure notification before you go back. It's just there to make a common case fast, not to try to cover all edge cases.
So I'm saying Firefox won't change this behavior for a number of reasons, not least because the behavior you're asking for ("always keep all DOM's in memory after navigating away") is impossible anyway. But yes, also because it would cause more sites to be broken for users in practice _and/or_ violate standards (which require us to fire unload when unloading a page).
bz, thanks, I understand why pages/subframes with unload listeners can't be cached. What I intended to ask was this:
Suppose we have an uncacheable iframe in an otherwise cacheable top-level page, and the iframe has different origin from the top-level page (meaning they can't hold references to each other's objects).
Wouldn't it be worth saving the top-level page's presentation, while not saving the iframe's? I.e. when navigating back to the page, the top-level page would be restored from the bfcache, while the iframe would be re-loaded from the necko cache or from the network.
(The only case, I could think of, that would break with this implementation was when the top-level page and the iframe communicate via postMessage. Perhaps we could provide an opt-out mechanism for this case.)
The reason I was wondering about this is the original reporter's case. An author would like his site to be fast with back/forward navigation, but he'd like to include 3rd-party content (google map, a "like" button, an ad) in it. If the 3rd-party decides to use 'unload', the author can't get his page to use bfcache without convincing the 3rd party to change their code.
> Wouldn't it be worth saving the top-level page's presentation, while not saving the
Ah. Yes, perhaps. It'd add significant complexity to the implementation, but it's doable. Modulo the issue you point out of course.
Maybe file a bug specifically about that issue that makes it clear what the proposal is?
If the page was served with Cache-Control: no-store, the Back action reloads the page from the server. Good. With "no-cache", however, the page gets displayed without revalidation while also discarding all DOM changes (hence not coming from bfcache?).
Is this expected behaviour or a bug to be filed separately? If this is expected behaviour, what is the logic I'm missing that makes this valid - surely the only two valid choices are revalidate/refetch and display with all DOM changes intact?
This behaviour can be seen at http://bbb.akshell.com/nocache
The no-cache issue should be filed separately. Please cc me. It shouldn't be affecting non-SSL pages at all.
Bug 752859 posted, with Boris cc'd.