[Call for feedback] Proposal to gradually skip unload events: already unreliable, top back/forward cache blocker, better alternatives available!

1,060 views
Skip to first unread message

Kenji Baheux

unread,
Mar 23, 2023, 9:16:27 PM3/23/23
to blink-dev, bfcache-dev, fer...@chromium.org

Tl;dr: the presence of unload event listeners is a primary blocker for back/forward cache on Chromium based browsers and for Firefox on desktop platforms. On the other hand, for mobile platforms, almost all browsers prioritize the bfcache by not firing unload events in most cases. To improve the situation, we’ve been working with lots of partners and successfully reduced the use of unload event listeners over the last few years. To further accelerate this migration, we propose to have Chrome for desktop gradually skip unload events. If this call for feedback doesn’t unearth critical showstoppers and if the proposal makes it through the blink process, the behavior change could be starting from M114 at the earliest (note: beforeunload will remain unchanged). We’d like feedback on this plan, in particular use cases that don’t yet have a viable alternative.



Hi,


This is a call for feedback about a tentative plan regarding unload events. Our goal is to identify use cases for which there isn’t any good alternative to unload events, and would therefore prevent this plan from moving forward.


The unload event is extremely unreliable. It is ignored in most cases by all mobile browsers with the exception of Firefox on Android. Furthermore, in Safari, the unload event is ignored on both desktop & mobile platforms. In addition to being unreliable, the presence of unload event listeners on a page is a major back/forward cache blocker on desktop for Chromium browsers and Firefox. Based on Chrome stats, we believe that unload event listeners reduce bfcache’s ability to deliver instant back/forward navigation by ~18 percentage points (hit-rate).


Over the course of 2021~2022, we ran a large collaborative effort to reduce the usage of unload event listeners, in particular across popular third parties. We’ve seen great progress with many sites and third parties having already completed their migration.


Given how unreliable unload events are, the potential user experience upsides, and the great progress achieved by the ecosystem on switching away from unload, we’d like to help accelerate the migration by gradually skipping unload events on Chrome for desktop. 


👉 Please note that beforeunload will remain unchanged as this event doesn’t have reliability issues and doesn’t block BFCache. 👈


We are interested in hearing your feedback about this plan. In particular, please let us know if you are aware of unload event listener use cases that lack a viable alternative. Your feedback will inform the proposal (e.g. behavior and timeline). 


If this call for feedback doesn’t unearth any critical showstoppers, and if the proposal makes it through the blink process, we’d start the plan from M114 at the earliest by having a small likelihood of ignoring unload events while providing access to fine-tuning control (e.g. Permission-Policy: unload API) and Enterprise/Edu carve outs. From there, we’ll continue to monitor the community’s feedback and gradually increase the likelihood over time. We are hoping to make significant progress by the end of this year, and hope to reach a satisfying state sometime in 2024.


See the sections below for more context, our guidance for a post-unload web, an API to exert control over unload event listeners, and our approach to ease-in enterprise/edu products into this change.



Background about bfcache

Back/forward cache is a browser optimization that enables instant back and forward navigation. It’s an in-memory cache that stores a complete snapshot of a page (including the JavaScript heap) as the user is navigating away. With the entire page in memory, the browser can quickly and easily restore it if the user decides to return.


The multiple behaviors of bfcache with unload events

Unfortunately, not all pages can be stored in bfcache. For instance, using certain APIs prevent pages from entering the bfcache. In particular, the presence of unload listeners on a page is the most common bfcache blocker. 


The use of unload listeners is highly discouraged because it’s a fundamentally unreliable event:

  • On desktop, Chrome and Firefox are currently firing unload events at the cost of the user experience, while Safari will attempt to cache some pages with an unload event listener (skipping the event in doing so).

  • On mobile, Chrome and Safari will attempt to cache pages with an unload event listener. On the other hand, Firefox treats pages that use unload event listeners as ineligible for the bfcache, except on iOS, which requires all browsers to use the WebKit rendering engine (i.e. all browsers inherently behave like Safari on this platform).


Alternatives to unload event listener

The recommended alternatives to unload event listeners are to:


In addition, you may be interested in the origin trial for the Pending Beacon API. This bfcache-friendly API allows sending a bundle of data to a backend server, ideally at the ‘end’ of a user’s visit to a page. From our observations, we believe this is the most common use case for unload event listeners. Compared to the methods highlighted above, this API has better ergonomics.


Test driving a web free of unload event listeners!

To understand how the plan might play out, please consider joining the origin trial for the Permissions-Policy: unload API. This API allows any site to:

  • Exert control over unload event listeners (e.g. completely disallow them, or selectively allow them for specific origins).

  • Report the use of unload event listeners to an endpoint for assessment purposes.


Chrome for Enterprise & Education

We also acknowledge that providers of enterprise & education solutions may not always have the flexibility to quickly update existing deployments. To minimize concerns, we’ll offer a group policy to keep the current behavior for unload events. This policy will also be enabled by default if Chrome detects that it is in an enterprise / education environment, as hinted by the presence of one or more existing group policies. For unmanaged Enterprise/Edu environments, a simple Chrome extension could inject the relevant calls to the Permission-Policy:unload API for temporarily opting-out the relevant origin(s).

Jacob “kurtextrem” G

unread,
Mar 24, 2023, 11:15:33 AM3/24/23
to blink-dev, Kenji Baheux, bfcache-dev, fer...@chromium.org
At my company, we've been using the original trial since it has launched and found improved metrics. We've tried pushing one tracking company to remove the unload listener from multiple contact points with no success, leaving us only with the origin trial as option to enable BFCache. We found no impact on our tracking accuracy.
Thus, I support this proposal, as tracking companies only need to switch out the event they're using and could keep the same functionality.

Fergal Daly

unread,
Mar 30, 2023, 2:23:16 AM3/30/23
to Kenji Baheux, sm...@mozilla.com, blink-dev, bfcache-dev

I'm relaying a piece of feedback from Mozilla in this github issue.

It's possible that pages are depending on `unload` handlers in subframes for functionality even without any main frame navigation. E.g a page creates a subframe with an unload handler, when the subframe is destroyed or navigates to somewhere else, that unload handler does something interesting, e.g. notifies the outer frame that this has happened.

This is definitely possible. It's also pretty easy to switch to pagehide for this case but we should try to understand how common this is before breaking it. It should be possible to measure how often subframe unloads fire when the mainframe is not navigating. This will give us an upper bound on the size of the problem,

F

Kenji Baheux

unread,
Apr 7, 2023, 5:03:45 AM4/7/23
to blink-dev, Fergal Daly, blink-dev, bfcache-dev, Kenji Baheux, sm...@mozilla.com
In light of this feedback, we are landing a metric to understand how often subframe unload handlers run without main frame navigation.
We'll use the data to adjust our plans accordingly. 

Since it takes time to get & analyze the data, we are pushing the proposed behavior change to M115.

Adjustments based on feedback received thus far
We'll offer a "deprecation flag" (a flag to temporarily keep unload working as it currently does) which should be more convenient than the Extension suggestion (e.g. unmanaged devices where group policy can't be deployed). 

We are also removing the following aspect "This policy will also be enabled by default if Chrome detects that it is in an enterprise / education environment, as hinted by the presence of one or more existing group policies." from the proposal since we got feedback that it's better to keep group policy free of any automated logic.

I've reached out to a few more communities and have only heard supportive comments so far (touching wood).
Please continue to help us get the word out so that we can further minimize the risk of oversights.
Thanks!

Nic Jansma

unread,
Apr 18, 2023, 10:20:21 AM4/18/23
to blink-dev, Kenji Baheux, Fergal Daly, blink-dev, bfcache-dev, sm...@mozilla.com
Hi Kenji,

Will there be a way to detect whether or not unload will fire from JS?

We (Akamai) have some security products that may hook into unload, only if they detect that another script has hooked into unload.  When this happens, we also shift some "cleanup" work to that unload handler that we need to execute.  Otherwise the cleanup work executes in beforeunload/pagehide/etc.

If we have knowledge that unload won't execute, we would skip hooking unload and keep our cleanup behavior earlier.  (we don't hook unload for any other reason).

For browsers that don't reliably execute unload today (e.g. Safari), we a combination of UA sniffing and feature detection.   But that could be tricky if Chrome transitions from reliably firing it to not over time.

Fergal Daly

unread,
Apr 18, 2023, 7:34:20 PM4/18/23
to Nic Jansma, Ian Clelland, blink-dev, Kenji Baheux, bfcache-dev, sm...@mozilla.com
[+iclelland]

On Tue, 18 Apr 2023 at 23:19, Nic Jansma <nicj...@gmail.com> wrote:
Hi Kenji,

Will there be a way to detect whether or not unload will fire from JS?

I don't believe there is a way to query the policies that currently apply to a document.

Ian, is there? Should there be?

You could attempt to add an unload handler then use

getEventListeners(window).hasOwnProperty("unload")

to see if it worked and then remove it.

That would not detect when the current origin is disallowed but some other origin used in a subframe is allowed, however I don't think that case is relevant to you since you don't have any access to that origin,


We (Akamai) have some security products that may hook into unload, only if they detect that another script has hooked into unload.  When this happens, we also shift some "cleanup" work to that unload handler that we need to execute.  Otherwise the cleanup work executes in beforeunload/pagehide/etc.

If we have knowledge that unload won't execute, we would skip hooking unload and keep our cleanup behavior earlier.  (we don't hook unload for any other reason).

For browsers that don't reliably execute unload today (e.g. Safari), we a combination of UA sniffing and feature detection.   But that could be tricky if Chrome transitions from reliably firing it to not over time.

In the Safari case, what do you do? If an unload handler was installed, you cannot tell whether it will fire since it depends on whether the page is BFCacheable. Do you add it just in case but also do stuff in pagehide?

F

Ian Clelland

unread,
Apr 20, 2023, 1:25:59 PM4/20/23
to Fergal Daly, Nic Jansma, blink-dev, Kenji Baheux, bfcache-dev, sm...@mozilla.com
On Tue, Apr 18, 2023 at 7:34 PM Fergal Daly <fer...@google.com> wrote:
[+iclelland]

On Tue, 18 Apr 2023 at 23:19, Nic Jansma <nicj...@gmail.com> wrote:
Hi Kenji,

Will there be a way to detect whether or not unload will fire from JS?

I don't believe there is a way to query the policies that currently apply to a document.

Ian, is there? Should there be?

You can query permissions policies currently, with document.featurePolicy.allowedFeatures (although I'm working on replacing that with a permissions-API-based interface, it will certainly work right now). So if you're using permissions policy to control unload handlers, then that will tell you whether it is enabled in the current frame.

If you're not using permissions policy, and just want to know whether *this* proposal will cause unload handlers to be skipped, that's not going to work. You'd need to do something like what you indicated below. (And, of course, accept that unload handlers are fundamentally reliable, even if Chrome *is* intending to execute them)

Ian

Fergal Daly

unread,
Oct 10, 2023, 8:46:17 PM10/10/23
to Kevin D., blink-dev, bfcache-dev, Kenji Baheux, sm...@mozilla.com
Thanks Kevin. Replies in-line.

On Wed, 11 Oct 2023 at 09:30, Kevin D. <kevin.de...@gmail.com> wrote:
Does the Permissions-Policy: unload API not support sourceless subframes? (i.e. iframes without src attributes and with content set inline in srcdoc)

My team uses sourceless iframes, and hooks to the unload event for cleaning up resources and such (to avoid potential memory leaks, etc.).

We’ve tried replicating your demo showing how subframes can still use the unload event with Permissions-Policy even after the deprecation, but our repro confirms it does not work for sourceless iframes case.

I have filed https://crbug.com/1491597 for this.

 

Secondly, does the pagehide event serve as an exact replacement for our case? (sourceless iframes needing to clear resources). According to Back/forward cache, pagehide events should be a superset of unload

I think it should work for you. I will add more docs to our explainer but in brief you can listen for `pagehide` events and look at `.persisted` set to `false`.

- If it's set to `false`, then the subframe is being destroyed either as part of a main frame navigation or as a result the parent removing it et
- if it's set to `true`, then the main frame is navigating and potentially entering BFCache. So you I think you wouldn't want to free resources. If it is BFCached, then you may be restored. If it doesn't enter BFCache or is never restored then your resources will be freed anyway as everything is being destroyed.

F
 

Thanks
Kevin

Kevin D.

unread,
Oct 10, 2023, 9:02:41 PM10/10/23
to blink-dev, Fergal Daly, blink-dev, bfcache-dev, Kenji Baheux, sm...@mozilla.com
Does the Permissions-Policy: unload API not support sourceless subframes? (i.e. iframes without src attributes and with content set inline in srcdoc)

My team uses sourceless iframes, and hooks to the unload event for cleaning up resources and such (to avoid potential memory leaks, etc.).

We’ve tried replicating your demo showing how subframes can still use the unload event with Permissions-Policy even after the deprecation, but our repro confirms it does not work for sourceless iframes case.

Secondly, does the pagehide event serve as an exact replacement for our case? (sourceless iframes needing to clear resources). According to Back/forward cache, pagehide events should be a superset of unload

Thanks
Kevin
On Wednesday, March 29, 2023 at 11:23:16 PM UTC-7 Fergal Daly wrote:

Kevin D.

unread,
Oct 24, 2023, 4:48:54 PM10/24/23
to blink-dev, Fergal Daly, blink-dev, bfcache-dev, Kenji Baheux, sm...@mozilla.com
Thanks F

I see origin trial [1] starts soon with 119 and I need clarification:

1. Does this mean starting Chrome 119, `unload` won't be fired?
2. The Permissions Policy alternative does not work with sourceless iframes (iframes using `srcdoc`). You filed a bug [2] earlier for that after I raised it, any updates?
3. My team is experimenting with `pagehide` as an alternative solution, but would like to know the timelines for us to plan and ship accordingly. Will `unload` still fire during the dep. trial?

[1] https://developer.chrome.com/origintrials/#/view_trial/4070128163236085761
[2] https://bugs.chromium.org/p/chromium/issues/detail?id=1491597

Fergal Daly

unread,
Oct 25, 2023, 7:31:38 AM10/25/23
to Kevin D., blink-dev, bfcache-dev, Kenji Baheux, sm...@mozilla.com
On Wed, 25 Oct 2023 at 05:28, Kevin D. <kevin.de...@gmail.com> wrote:
Thanks F

I see origin trial [1] starts soon with 119 and I need clarification:

That origin trial is a little confusing. It ended up not being implemented in 119 and may not even make it into 120. However we not roll this out generally for any version that doesn't have the OT, so hopefully that means you don't need to worry.

 

1. Does this mean starting Chrome 119, `unload` won't be fired?
 
We will experiment with a small fraction of traffic on a restricted set of domains. 119 is the earlier version that supports disabling it but we won't do it in any version that has known issue (e.g. like below).


2. The Permissions Policy alternative does not work with sourceless iframes (iframes using `srcdoc`). You filed a bug [2] earlier for that after I raised it, any updates?

It will also be fixed before any general roll out, but no update yet.


3. My team is experimenting with `pagehide` as an alternative solution, but would like to know the timelines for us to plan and ship accordingly. Will `unload` still fire during the dep. trial?

Joining the dep trial will cause unload to continue to fire as before,

F

Kevin D.

unread,
Oct 25, 2023, 12:19:17 PM10/25/23
to blink-dev, Fergal Daly, blink-dev, bfcache-dev, Kenji Baheux, sm...@mozilla.com, Kevin D.

Understood.

  1. Is there any action required from us until general rollout (when `unload` isn’t fired anymore)?
  2. Is there a list of this restricted set domains with which you’re experimenting? Want to know if ours are included
  3. We should have `pagehide` replacement by Dec, is that too late?
    • Or would we have to join the dep trial to avoid our current workflows being messed up? If so, how do we join?

Fergal Daly

unread,
Nov 8, 2023, 7:08:03 AM11/8/23
to Kevin D., blink-dev, bfcache-dev, Kenji Baheux, sm...@mozilla.com
On Thu, 26 Oct 2023 at 01:11, Kevin D. <kevin.de...@gmail.com> wrote:

Understood.

  1. Is there any action required from us until general rollout (when `unload` isn’t fired anymore)?
No. 
  1. Is there a list of this restricted set domains with which you’re experimenting? Want to know if ours are included
The ls not ready yet, we'll update this thread before going ahead.

  1. We should have `pagehide` replacement by Dec, is that too late?
    • Or would we have to join the dep trial to avoid our current workflows being messed up? If so, how do we join?
The earliest version this will be enabled in is M120 which released in Jan. So that should be safe


F

Fergal Daly

unread,
Feb 6, 2024, 5:42:58 AMFeb 6
to Kevin D., blink-dev, bfcache-dev, Kenji Baheux, sm...@mozilla.com
On Wed, 8 Nov 2023 at 21:07, Fergal Daly <fer...@google.com> wrote:


On Thu, 26 Oct 2023 at 01:11, Kevin D. <kevin.de...@gmail.com> wrote:

Understood.

  1. Is there any action required from us until general rollout (when `unload` isn’t fired anymore)?
No. 
  1. Is there a list of this restricted set domains with which you’re experimenting? Want to know if ours are included
The ls not ready yet, we'll update this thread before going ahead.

 

  1. We should have `pagehide` replacement by Dec, is that too late?
    • Or would we have to join the dep trial to avoid our current workflows being messed up? If so, how do we join?
The earliest version this will be enabled in is M120 which released in Jan. So that should be safe


This is actually going to arrive in M122 and will be visible to canary/dev users right around now,

F

Reply all
Reply to author
Forward
0 new messages