Event Pages
Event pages are very similar to background pages, with one important difference: event pages are loaded only when they are needed. When the event page is not actively doing something, it is unloaded, freeing memory and other system resources.
Event pages are available in the stable channel as of Chrome 22, and the performance advantages are significant, especially on low-power devices. Please prefer them to persistent background pages whenever possible for new development and begin migrating existing background pages to this new model.
Manifest
Register your event page in the extension manifest:
{ "name": "My extension", ... "background": { "scripts": ["eventPage.js"], "persistent": false }, ... }
Notice that without the "persistent" key, you have a regular background page. Persistence is what differentiates an event page from a background page.
Lifetime
The event page is loaded when it is "needed", and unloaded when it goes idle again. Here are some examples of things that will cause the event page to load:
- The app or extension is first installed or is updated to a new version (in order to register for events).
- The event page was listening for an event, and the event is dispatched.
- A content script or other extension sends a message.
- Another view in the extension (for example, a popup) calls
runtime.getBackgroundPage
.
Once it has been loaded, the event page will stay running as long as it is active (for example, calling an extension API or issuing a network request). Additionally, the event page will not unload until all visible views (for example, popup windows) are closed and all message ports are closed. Note that opening a view does not cause the event page to load, but only prevents it from closing once loaded.
Make sure your event page closes as soon as the event that opened it is processed. You can observe the lifetime of your event page by opening Chrome's task manager. You can see when your event page loads and unloads by observing when an entry for your extension appears in the list of processes.
Once the event page has been idle a short time
(a few seconds), the
runtime.onSuspend
event is dispatched. The event page has a few more seconds to handle this
event before it is forcibly unloaded. If during this time an event occurs which
would normally cause the event page to be loaded, the suspend is canceled
and the runtime.onSuspendCanceled
event is dispatched.
Event registration
Chrome keeps track of events that an app or extension has added listeners
for. When it dispatches such an event, the event page is
loaded. Conversely, if the app or extension removes all of its listeners for
an event by calling removeListener
, Chrome will no longer
load its event page for that event.
Because the listeners themselves only exist in the context of the
event page, you must use addListener
each time the event
page loads; only doing so at
runtime.onInstalled
by itself is insufficient.
For an example of event registration in action, you can view the Google Mail Checker extension.
Convert background page to event page
Follow this checklist to convert your extension's (persistent) background page to an event page.
- Add
"persistent": false
to your manifest as shown above. - If your extension uses
window.setTimeout()
orwindow.setInterval()
, switch to using the alarms API instead. DOM-based timers won't be honored if the event page shuts down. - Similarly, other asynchronous HTML5 APIs like notifications and geolocation will not complete if the event page shuts down. Instead, use equivalent extension APIs, like notifications.
- If your extension uses,
extension.getBackgroundPage
, switch toruntime.getBackgroundPage
instead. The newer method is asynchronous so that it can start the event page if necessary before returning it.
Best practices when using event pages
Keep these tips in mind when using event pages to avoid common subtle pitfalls.
- Register to receive any events your extension is interested in each time the event page is loaded. The event page will be loaded once for each new version of your extension. After that it will only be loaded to deliver events you have registered for. This generally means that your event listeners should be added at the top level scope of the event page, otherwise they may not be available when the event page reloads.
- If you need to do some initialization when your extension is
installed or upgraded, listen to the
runtime.onInstalled
event. This is a good place to register for declarativeWebRequest rules, contextMenu entries, and other such one-time initialization. - If you need to keep runtime state in memory throughout a browser session, use the storage API or IndexedDB. Since the event page does not stay loaded for long, you can no longer rely on global variables for runtime state.
- Use event filters to restrict
your event notifications to the cases you care about. For example, if
you listen to the
tabs.onUpdated
event, try using thewebNavigation.onCompleted
event with filters instead (the tabs API does not support filters). That way, your event page will only be loaded for events that interest you. - Listen to the
runtime.onSuspend
event if you need to do last second cleanup before your event page is shut down. However, we recommend persisting periodically instead. That way if your extension crashes without receivingonSuspend
, no data will typically be lost. - If you're using message passing, be sure to close unused message ports. The event page will not shut down until all message ports are closed.
- If you're using the context menus API,
pass a string
id
parameter tocontextMenus.create
, and use thecontextMenus.onClicked
callback instead of anonclick
parameter tocontextMenus.create
. - Remember to test that your event page works properly when it is unloaded and then reloaded, which only happens after several seconds of inactivity. Common mistakes include doing unnecessary work at page load time (when it should only be done when the extension is installed); setting an alarm at page load time (which resets any previous alarm); or not adding event listeners at page load time.