Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.onload called multiple times from Firefox extension

I'm developing a Firefox extension and have the following code:

function initialize() { 
    // For accessing browser window from sidebar code.
    var mainWindow = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
               .getInterface(Components.interfaces.nsIWebNavigation)
               .QueryInterface(Components.interfaces.nsIDocShellTreeItem)
               .rootTreeItem
               .QueryInterface(Components.interfaces.nsIInterfaceRequestor)
               .getInterface(Components.interfaces.nsIDOMWindow);
    var gBrowser = mainWindow.gBrowser;
    gBrowser.onload = function() {
        alert('loaded');
    };
}
  1. When I open the extension (a sidebar) and proceed to open a new tab within the Firefox window, there are three alert boxes.
  2. When I refresh a page, there are two alert boxes.
  3. When a page finishes loading, there is only one alert box.
  4. When I change tabs, an alert is fired.

I use .onload rather than DOMContentLoaded or readystatechange as I need to wait until all other javascript has finished loading on a page before I run mine.

Any ideas as to why multiple events are being triggered (and for things that the event shouldn't be triggered for)?

SOLUTION

Following from MatrixFrog's suggestion, here is the solution I came to:

function initialize() { 
    // For accessing browser window from sidebar code.
    var mainWindow = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
               .getInterface(Components.interfaces.nsIWebNavigation)
               .QueryInterface(Components.interfaces.nsIDocShellTreeItem)
               .rootTreeItem
               .QueryInterface(Components.interfaces.nsIInterfaceRequestor)
               .getInterface(Components.interfaces.nsIDOMWindow);
    var gBrowser = mainWindow.gBrowser;
    if (gBrowser.addEventListener) {
        gBrowser.addEventListener("load",pageLoaded,true);
    }    
}

function pageLoaded(aEvent) {
    if ((aEvent.originalTarget.nodeName == '#document') && 
       (aEvent.originalTarget.defaultView.location.href == gBrowser.currentURI.spec)) 
    {
        alert('loaded');
    }
}
  1. aEvent.originalTarget.nodeName == '#document' checks that the page is loaded and not favicons.
  2. (aEvent.originalTarget.defaultView.location.href == gBrowser.currentURI.spec)) checks that the element that fired the event is the page in the tab, and not one of its IFRAMEs
  3. gBrowser.onload would only fire for xul-image and not for #document so it was replaced with gBrowser.addEventListener("load",pageLoaded,true);
  4. If you want to avoid firing the event for new blank tabs, make sure gBrowser.currentURI.spec != "about:blank"
like image 462
Ivan Avatar asked Aug 12 '10 18:08

Ivan


1 Answers

From https://developer.mozilla.org/en/Code_snippets/On_page_load

Current Firefox trunk nightlies will fire the onPageLoad function for not only documents, but xul:images (favicons in tabbrowser). If you only want to handle documents, ensure aEvent.originalTarget.nodeName == "#document"

If you're still seeing extraneous 'load' events firing, you may want to inspect the event target to figure out what's being loaded, and use similar logic to avoid calling your extension's logic in certain specific cases.

like image 172
Tyler Avatar answered Oct 30 '22 16:10

Tyler