Progress Listeners
Progress listeners allow extensions to be notified of events associated with documents loading in the browser and with tab switching events. Progress listeners implement the nsIWebProgressListener
interface.
Note that if you just want to execute your code each time a page loads, you can use an an easier method, onPageLoad()
. Note that onPageLoad does not fire for back button clicks.
In the examples below the progress listener is attached to the tabbrowser, which means you don't get any notifications for inactive tabs. Firefox 3.5 includes a way to set up a listener for all tabs, selected and not: Listening to events on all tabs.
Example
- Create an object which implements
nsIWebProgressListener
:const STATE_START = Ci.nsIWebProgressListener.STATE_START; const STATE_STOP = Ci.nsIWebProgressListener.STATE_STOP; var myListener = { QueryInterface: XPCOMUtils.generateQI(["nsIWebProgressListener", "nsISupportsWeakReference"]), onStateChange: function(aWebProgress, aRequest, aFlag, aStatus) { // If you use myListener for more than one tab/window, use // aWebProgress.DOMWindow to obtain the tab/window which triggers the state change if (aFlag & STATE_START) { // This fires when the load event is initiated } if (aFlag & STATE_STOP) { // This fires when the load finishes } }, onLocationChange: function(aProgress, aRequest, aURI) { // This fires when the location bar changes; that is load event is confirmed // or when the user switches tabs. If you use myListener for more than one tab/window, // use aProgress.DOMWindow to obtain the tab/window which triggered the change. }, // For definitions of the remaining functions see related documentation onProgressChange: function(aWebProgress, aRequest, curSelf, maxSelf, curTot, maxTot) {}, onStatusChange: function(aWebProgress, aRequest, aStatus, aMessage) {}, onSecurityChange: function(aWebProgress, aRequest, aState) {} }
- Attach the progress listener to a <
browser
> or a <tabbrowser
> element usingAddProgressListener
, for example for Firefox put the following code in aload
listener of a main window:gBrowser.addProgressListener(myListener);
When used with a
browser
, the second argument is amask
which determines the type of events that will be received. Note that thebrowser
uses a weak reference to your listener object, so make sure to keep an external reference to your object to ensure that it stays in memory.When used with a
tabbrowser
, you cannot choose which types of events that will be received. Instead, you receive those events that thetabbrowser
is interested in, except that theonLinkIconAvailable
andonRefreshAttempted
notifications are optional. Thetabbrowser
uses a strong reference to your listener object.
Starting in Gecko 2.0 (Firefox 4 / Thunderbird 3.3 / SeaMonkey 2.1), all events are optional. The tabbrowser
only notifies you of the events for which you provide a callback.
Remember to change myListener
to a unique identifier.
Example: Notification when the value in Address Bar changes
A commonly asked question is how to get notified whenever the URL in the address bar (also known as location bar) changes. Using the following code, you will get notified when user navigates to another page (by clicking a link, using the back/forward button, by typing an address in the Location Bar, etc.) and also when user switches tabs.
var myExtension = { oldURL: null, init: function() { gBrowser.addProgressListener(this); }, uninit: function() { gBrowser.removeProgressListener(this); }, processNewURL: function(aURI) { if (aURI.spec == this.oldURL) return; // now we know the url is new... alert(aURI.spec); this.oldURL = aURI.spec; }, // nsIWebProgressListener QueryInterface: XPCOMUtils.generateQI(["nsIWebProgressListener", "nsISupportsWeakReference"]), onLocationChange: function(aProgress, aRequest, aURI) { this.processNewURL(aURI); }, onStateChange: function() {}, onProgressChange: function() {}, onStatusChange: function() {}, onSecurityChange: function() {} }; window.addEventListener("load", function() { myExtension.init() }, false); window.addEventListener("unload", function() { myExtension.uninit() }, false);
Note: If you use the same listener for more than one tab/window, use aWebProgress.DOMWindow in the callback methods to obtain the tab/window which triggers the state change or event.
Example: Example of listener for anchor change
The above example "Notification when the value in Address Bar changes" fires multiple times, one of which is when the tab is changed. In some cases you want to catch only a location change when the anchor changes. To do this the optional aFlags parameter of the onLocationChange listener is used.
var myExt_urlBarListener = { onLocationChange: function (aProgress, aRequest, aURI, aFlags) { if (aFlags & Ci.nsIWebProgressListener.LOCATION_CHANGE_SAME_DOCUMENT) { //anchor clicked! var domWin = aProgress.DOMWindow; var domDoc = domWin.document; } } };
You can learn about this here: nsIWebProgressListener - Location Change Flags