Events in service workers

Extension service workers support both standard service worker events and many events in the extension APIs. This section describes what's available and provides tips for using them.

Declare extension events

Event handlers in service workers need to be declared in the global scope, meaning they should be at the top level of the script and not be nested inside functions. This ensures that they are registered synchronously on initial script execution, which enables Chrome to dispatch events to the service worker as soon as it starts. For example:

Not advised
chrome.storage.local.get(["badgeText"], ({ badgeText }) => {
  chrome.action.setBadgeText({ text: badgeText });
  chrome.action.onClicked.addListener(handleActionClick);
});
Better
chrome.action.onClicked.addListener(handleActionClick);

chrome.storage.local.get(["badgeText"], ({ badgeText }) => {
  chrome.action.setBadgeText({ text: badgeText });
});

Common events

Extension service workers support events in specific APIs. A few common ones are described in what follows. Note that some of these APIs require permissions to use and others may have events, methods, or properties that are not available in all versions of Chrome. For details, see the linked API documentation, particularly the events, methods, or properties you want to use.

chrome.action
Fired in response to a user interaction with your extension's toolbar icon, whether that action be for a specific page (tab) or for the whole extension.
chrome.management
Provides events related to the installation, uninstallation, enabling, and disabling extensions.
chrome.notifications
Provides events related to the user's interaction with system notifications generated by the extension.
chrome.permissions
Indicates when extension permissions are granted or revoked by the user.
chrome.runtime
Provides events related to the extension lifecycle, messages sent from other parts of the extension, and notification of an available extension or Chrome update.
chrome.storage.onChanged
Fired whenever any StorageArea object is cleared or when the value of a key is changed or set. Note that the each StorageArea instance has its own onChanged event.
chrome.webNavigation
Provides information about the status of in-flight navigation requests.

Filters

To restrict events to specific use case, or eliminate unnecessary event calls, use APIs that support event filters. For example, consider an extension listening for the tabs.onUpdated event to detect when a user navigates to a specific website. This event will be called on every navigation on every tab. Instead, use webNavigation.onCompleted with a filter. For example:

const filter = {
  url: [
    {
      urlMatches: 'https://www.google.com/',
    },
  ],
};

chrome.webNavigation.onCompleted.addListener(() => {
  console.info("The user has loaded my favorite website!");
}, filter);

Web service worker events

Extension service workers support more than the lifecycle events described elsewhere.

ServiceWorkerGlobal.fetch

Fired when anything is retrieved from the extension package or when fetch() and XMLHttpRequest() are called from an extension or popup script. (Calls from content scripts are not intercepted by the service worker fetch handler.) In the latter cases, you will need to add the URLs of the pages you want to fetch to the "host_permissions" key in the manifest.json.

ServiceWorkerGlobal.message

Service worker message passing is available in addition to extension messaging passing, but the two systems are not interoperable. That means that messages sent using sendMessage() (which is available from several extension APIs) aren't intercepted by service worker message handlers. Likewise, messages sent using postMessage() aren't intercepted by extension message handlers. Both types of message handlers—meaning both ServiceWorkerGlobal.message and chrome.runtime.onMessage—are supported in extension service workers.

You should prefer extension messaging unless you have a specific reason for using service worker messaging.