Skip to content

Handle unreliable in-memory storage for Manifest v3

Background / User story

Manifest v3 forces us to run our background scripts in a service worker, which can be suspended/terminated at any time. Therefore we need to make sure that we can handle unreliable in-memory storage to avoid regressions.

Potential breakage:

  • Incorrect allowlisting state shown in icon
  • Blocked counter shown/hidden in icon when it shouldn't be.
  • Incorrect blocked counter shown in icon.
  • Developer tools panel content not reset on page load (incl. on reload).
  • Notification no longer shown (i.e. is dismissed).
  • Nothing happens when interacting with desktop notification.
  • Language filter list recommendation notification not shown.
  • Changes to preferences for total blocked counter aren't saved.
  • Error message not shown in settings page when downloadable filter lists contains disabled filters.
  • Unable to determine meta data about current session (i.e. is first-run, encountered data corruption, settings were reinitialized).
  • Block element context menu item and icon popup button shown as expected (e.g. not shown for allowlisted pages; not shown for non-HTML pages).
  • Extension tries to recover from data corruption (e.g. reset filter settings; show "problem" notification) each time the service worker wakes up, instead of only each time the extension is loaded.
  • Incorrect "corrupted" query string parameter value is passed to uninstall page.

What to change

  • Design: N/A
  • Research: N/A
  • Spec: N/A
  • Legal: N/A
  • Development:
    • Deterministic states: Reevaluate the values of the following variables whenever the service worker activates:
      • lib/icon: allowlistedState (values already being restored when service worker wakes up)
      • lib/stats: (values already being restored when service worker wakes up)
        • activeTabIds
        • activeTabIdByWindowId
    • Non-deterministic states: Store and retrieve the values of the following variables using browser.storage.session when in a service worker:
      • lib/browserAction: badgeStateByPage
      • lib/devtools:
      • lib/filterComposer: readyActivePages
      • lib/filterConfiguration: disabledFilterCounters (values already being restored when service worker wakes up)
      • lib/icon: allowlistedState
      • lib/notificationHelper:
        • activeNotification
        • buttonsByNotificationId
      • lib/prefs: overrides (values already being restored when service worker wakes up; only a problem on Firefox <66 due to write-throttling of "blocked_total")
      • lib/recommendLanguage: lastVisits
      • lib/stats: blockedPerPage
      • lib/subscriptionInit:
        • dataCorrupted (values already being restored when service worker wakes up; value may change when service worker wakes up)
        • firstRun (value of FirstRunInfo.foundSubscriptions may change after recovery from data corruption; only used during first initialization)
        • reinitialized (value of FirstRunInfo.foundStorage may change after recovery from data corruption; only used during first initialization)
        • userNotificationCallback (values already being restored when service worker wakes up)

Hints for testers

See list of potential breakage under "Background".

The above data used to be stored in memory, but now has to make use of browser.storage.session, which currently has a 1MB quota. Therefore we should verify that we don't hit this quota (even with lots of tabs open) or that the extension at least degrades gracefully.

Hints for translators

N/A

Further information

Initialization code runs again on service worker activation in the following scenarios:

// yes

{
  // yes
}

(() =>
{
  // yes
})();

(async () =>
{
  // yes
  await syncFunc(); // function is executed synchronously (even as an `async` function)
  // yes
  await asyncFunc(); // function is executed asynchronously
  // no
})();

setTimeout(() =>
{
  // no
}, 0);

function foo()
{
  // yes
}
foo();

new Promise((resolve) =>
{
  // yes
  resolve();
})
.then(() =>
{
  // yes
});

Therefore any data that is added to memory in the places marked with "no" is not persisted across service worker activations.

Edited by Thomas Greiner
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information