Make notifications module continue working when service workers are suspended
Background
One of the major challenges introduced by MV3 is that service workers (unlike MV2 background pages) may be suspended and restarted at any time. Our existing codebase has all been written assuming we have a long living background page, and so we can do things like hold information that's relevant between events in local variables, or register events asynchronously.
In an MV3 context, our assumptions about how our code will be run are broken. Our extension will break in all sorts of weird ways. We need to identify what those ways are and fix them.
To simplify the process of keeping our code working, making these changes has been broken down by functional area. In this issue, the notifications module should be made to continue working even if the MV3 service worker is suspended.
In https://gitlab.com/eyeo/adblockplus/abc/webext-sdk/-/merge_requests/404, we added a broad method of testing our normal functionality when the service worker is suspended frequently. This is currently skipped for the reporting tests, so as part of this issue those tests should be enabled and they should pass.
Use case
Notifications continue to work in MV3, even though in MV3 the browser may suspend the service worker at any time. This appears to be used for managing showing things like a first run welcome page, and other popup notifications.
What to change
- Enable fuzz tests for notifications.
- Review the code in notifications and fix anything that would stop working if the service worker is suspended (fuzz tests should help to discover these).
- All event listeners that can wake up the service worker must be attached in the first turn of the event loop.
- Events that we emit must be able to have listeners attached in the first turn of the event loop.
- Functionality that currently requires state shared between events must keep working, for example by using a storage API for the state.
Integrator Notes
The following functions are now asynchronous and return promises:
EWE.notifications.start
EWE.notifications.shouldIgnoreNotifications
EWE.notifications.showNotification
EWE.notifications.showNext
EWE.notifications.markAsShown
EWE.notifications.toggleIgnoreCategory
EWE.notifications.getDownloadCount
EWE.notifications.getIgnoredCategories