Listening to events in Firefox extensions

Gecko uses events to pass information about interesting things that have occurred along to the parties that may wish to know about them. There are several different categories of events; this article will help you learn about them and direct you to more specific documentation covering each of them. It also provides some use cases that may be of specific interest.

Types of events

There are multiple types of events that application and extension authors can use to receive notifications from <xul:browser> and <xul:tabbrowser> elements to hear about changes relating to loads of the content contained within them.

Simple DOM events

Registering for a DOM event is done using with code such as the following:

function callback(evt) {
  // Do your processing here. Check evt.target for the target of the event.
}

b.addEventListener("event", callback, false)

Where b is the browser or tabbrowser you wish to watch for events from. Keep in mind that the events may come from any frame within the browser or, for a tabbrowser, any of the browsers within it.

Some of the more interesting DOM events you may wish to monitor are listed here:

Event Description
DOMLinkAdded Dispatched when a new HTML <link> element is detected in the document.
DOMTitleChanged Dispatched when the title of the page changes.
DOMContentLoaded Dispatched when the initial DOM for the page is completely loaded.
load Dispatched after the page—including images—has first finished loading.
unload Dispatched when the user has navigated away from the page.
pageshow Dispatched when a page is newly displayed.
pagehide Dispatched when a page is hidden.

Standard behavior for Web pages is:

  1. User navigates to a page.
  2. As the page loads, inline scripts run.
  3. Once the page is loaded, the onload handler fires.

Some pages include a fourth step. If a page uses an unload or beforeunload handler, it fires when the user navigates away from the page. If an unload handler is present, the page will not be cached.

When a user navigates to a cached page, inline scripts and the onload handler do not run (steps 2 and 3), since in most cases, the effects of these scripts have been preserved.

If the page contains scripts or other behaviors that fire during loading that you want to continue to execute every time the user navigates to the page, or if you want to know when a user has navigated to a cached page, use the new pageshow event.

If you have behaviors that fire when a user navigates away from the page, but you want to take advantage of this new caching feature, and therefore don't want to use the unload handler, use the new pagehide event.

pageshow event

This event works the same as the load event, except that it fires every time the page is loaded (whereas the load event doesn't fire in Firefox 1.5 when the page is loaded from cache). The first time the page loads, the pageshow event fires just after the firing of the load event. The pageshow event uses a boolean property called persisted that is set to false on the initial load. It is set to true if it is not the initial load (in other words, it is set to true when the page is cached).

Set any JavaScript that you want to run every time a page loads to run when the pageshow event fires.

If you call JavaScript functions as part of the pageshow event, you can ensure these functions are called when the page is loaded in browsers other than Firefox 1.5 by calling the pageshow event as part of the load event, as shown in the sample later in this article.

pagehide event

If you want to define behavior that occurs when the user navigates away from the page, but you don't want to use the unload event (which would cause the page to not be cached), you can use the new pagehide event. Like pageshow, the pagehide event uses a boolean property called persisted. This property is set to false if the page is not cached by the browser and set to true if the page is cached by the browser. When this property is set to false, the unload handler, if present, fires immediately after the pagehide event.

Firefox 1.5 tries to simulate load events in the same order they would occur when the page is initially loaded. Frames are treated the same way as the top-level document. If the page contains frames, then when the cached page is loaded:

  • pageshow events from each frame fire before the pageshow event in the main document fires.
  • When the user navigates away from the cached page, the pagehide event from each frame fires before the pagehide event in the main document.
  • For navigation that occurs inside a single frame, events fire only in the affected frame.

Web progress listeners

For more information about web loads a web progress listener can be used; these provide more details about the progress of loading data from the web. Both browser and tabbrowser elements support the following:

var progressListener = {
  // add nsIWebProgressImplementation here
}

b.addProgressListener(progressListener);

Where b is the browser or tabbrowser you want to listen to events for. There are code snippets available that give more detail on using web progress listeners.

For a tabbrowser, the above code will only get events from the browser that is currently displayed at the time the event occurs. In order to listen to events from all browsers, including those not currently being displayed, the following example can be used:

var tabsProgressListener = {
  // add tabs progress listener implementation here
}

gBrowser.addTabsProgressListener(tabsProgressListener);

This lets you receive events related to all tabs. More information about listening to events from all tabs is available.

How events are used by Firefox

The Firefox frontend already listens for a number of these progress events from web pages. Most of this goes on in browser.js.

DOMLinkHandler

The DOMLinkHandler object is called by the DOMLinkAdded event in order to detect any RSS feeds, site icons, or OpenSearch plugins for the web site.

pageShowEventHandlers

The pageShowEventHandlers() function is called by the pageshow event and is used to populate the character set menu and update the UI elements associated with any detected feeds or OpenSearch plugins for the website.

XULBrowserWindow

XULBrowserWindow is an nsIWebProgressListener used to get progress events for the currently visible browser. It is used to update the UI for many different reasons:

  • Update the progress bar and status messages as pages load
  • Turn on and off the throbber as pages load
  • Set the site icon when available
  • Update the address bar as the user navigates
  • Hide notification bars when appropriate as the user navigates
  • Apply the site zoom preferences to newly loading pages
  • Update the bookmarking star button UI
  • Update the identity display as the site's security changes

TabsProgressListener

This object is a tabs progress listener and receives events for all browsers in the window. It is used to detect when a webpage attempts to refresh itself and allow the user to block the attempt.

How events are used by the tabbrowser

tabbrowser maintains a set of objects relating to progress listening for each browser. First it creates a browser-status-filter and adds it as a web progress listener for the browser. Next it creates an internal object to receive all web progress events from the browser. This is created by the method mTabProgressListener(). This receives events from the browser-status-filter. The filter acts to reduce the number of status and progress events to improve performance. The filters are held in the array mFilters, the internal listeners in the array mTabListeners.

The internal listeners are used to send out progress events to listeners registered with addProgressListener() (which receives events from the browser that is currently visible) and addTabsProgressListener() (which receives events from all browsers).

See also