Open Bug 1771203 Opened 2 years ago Updated 1 month ago

Tweak the lifetime and termination triggers of event pages / extension service workers

Categories

(WebExtensions :: General, enhancement, P3)

enhancement

Tracking

(Not tracked)

People

(Reporter: robwu, Unassigned)

References

(Depends on 4 open bugs, Blocks 2 open bugs)

Details

(Whiteboard: [addons-jira])

Event pages should be designed to account for sudden shutdown, to improve the user experience in cases where that's inevitable, e.g. process crashes by out-of-memory, the OS (Android), etc. (bug 1355239).

A time-bound lifetime forces the development of extensions that are resilient against terminations (which is positive), but being overly aggressive in terminating them degrades the user experience of extensions that lack alternatives, and of those where the startup is expensive. On the other hand, having an indefinite lifetime (or being able to extent the lifetime to that effect - bug 1748533) discourages the design of a resilient background script.

The current termination policy is (too) aggressive. We should tweak the lifetime and termination triggers/blockers.

As of writing, the termination of event pages/extension service workers in Firefox is as follows (with state transitions documented here):

  • After background startup, a timer is registered (default 30s, min 0.1s, max 300s)
    • This timer is reset when an extension event is received (source).
  • When the timer is reached, termination is requested (terminateBackground logic here)
    • If the devtools is open, the background is not suspended (source).
    • If there is an active StreamFilter, the background is not suspended (source).
  • runtime.onStartup is triggered, which may delay the shutdown by 5 seconds (source).
  • The background is terminated, and is reset for start up (when an extension event is triggered).

"This timer is reset when an extension event is received."

Are you planning to keep it this way? Chrome doesn't reset the timer when an event is received.

An extension can make Firefox generate events to stay alive indefinitely, for example:

browser.storage.onChanged.addListener((storage) => {});
function keepAlive() {
	browser.storage.local.set({keepAlive: true});
	setTimeout(() => keepAlive(), 15000);
}
keepAlive();

Chrome methods to keep a service worker alive indefinitely are far more inconvenient, like making a connection to a native application.

Many extensions need to have persistent background pages, event pages, or service workers because of performance and/or memory issues.
Allowing received events to reset the timer is very useful for extensions that aren't intended for Android. They can also still be
designed to be restarted (if there is a rare crash), even if they are never terminated.

Severity: -- → N/A
Priority: -- → P3

Last Friday, we discussed this bug.

Our primary objective behind suspensible/restartable background contexts (event pages / service workers) is to have extensions that are resilient against sudden termination. This is needed on Android, and to a lesser extent on desktop.

In Firefox's current implementation, the lifetime can easily be extended indefinitely (bug 1748533), which may interfere with the goal of having extensions that are resilient by design. I'm not against supporting extensions that really have these needs, but would like that to be more explicit, rather than through some wasteful work-arounds. For example, having stricter lifetime limits by default, plus an opt-in advisory entry in the manifest file (e.g. a permission as suggested at https://github.com/w3c/webextensions/issues/44).

Luca suggested to evaluate the possibility of moving the event page to the bfcache (instead of a full shutdown) to reduce the initialization overhead of event pages. While that doesn't help against sudden termination, it could reduce the cost/overhead of suspending/resuming event pages.

The next step here is for Luca to draft a document about the background's lifecycle / lifetime from where we can continue the discussion.

Depends on: 1800914

FYI: Chromium is working on the task to "Identify additional APIs that require "strong" service worker keepalives" at https://bugs.chromium.org/p/chromium/issues/detail?id=1418780 following the relaxation of the 5 minute limit at https://developer.chrome.com/blog/longer-esw-lifetimes/

(In reply to Rob Wu [:robwu] from comment #3)

FYI: Chromium is working on the task to "Identify additional APIs that require "strong" service worker keepalives" at https://bugs.chromium.org/p/chromium/issues/detail?id=1418780

Per https://bugs.chromium.org/p/chromium/issues/detail?id=1418780#c5, the following APIs will also trigger strong keepalive semantics, justified by them depending on user interaction:

  • permissions.request()
  • management.uninstall() (not supported in Firefox)
  • desktopCapture.chooseDesktopMedia (not supported in Firefox)

Following the same reasoning, I would also expect the following APIs to have the same semantics:

  • identity.launchWebAuthFlow
  • omnibox.onInputChanged and possibly more of the API (e.g. onInputStarted). While the events are not really blocking, the API events are only activated when a user is actively engaging with the address bar, and specifically targeting the extension. It would be quite cumbersome and user-unfriendly if the extension were to be terminated in the middle of a search query from the user.

(In reply to Rob Wu [:robwu] from comment #4)

(In reply to Rob Wu [:robwu] from comment #3)

FYI: Chromium is working on the task to "Identify additional APIs that require "strong" service worker keepalives" at https://bugs.chromium.org/p/chromium/issues/detail?id=1418780

Per https://bugs.chromium.org/p/chromium/issues/detail?id=1418780#c5, the following APIs will also trigger strong keepalive semantics, justified by them depending on user interaction:

  • permissions.request()
  • management.uninstall() (not supported in Firefox)
  • desktopCapture.chooseDesktopMedia (not supported in Firefox)

Following the same reasoning, I would also expect the following APIs to have the same semantics:

  • identity.launchWebAuthFlow
  • omnibox.onInputChanged and possibly more of the API (e.g. onInputStarted). While the events are not really blocking, the API events are only activated when a user is actively engaging with the address bar, and specifically targeting the extension. It would be quite cumbersome and user-unfriendly if the extension were to be terminated in the middle of a search query from the user.

Thanks for capturing the context of those changes, let's file separate focused bugs for permissions.request(), identity.launchWebAuthFlow and one for both omnibox.onInputChanged and omnibox.onInputStarted.

As part of the first one we would be working on it may be reasonable to consider allowing to mark certain API methods or API events for strong keepalive semantic, that would then also allow Thunderbird developers to cover similar needs in their Thunderbird-specific WebExtensions APIs.

The 30 second service worker lifespan in Chrome can now be reset with an extension api call: https://developer.chrome.com/docs/extensions/mv3/service_workers/service-worker-lifecycle/#idle-shutdown

Are there any plans on adding this behavior to Firefox?

Depends on: 1844041
Depends on: 1844044
Depends on: 1874406
You need to log in before you can comment on or make changes to this bug.