title: .onload called multiple times from Firefox extension
body: <p>I'm developing a Firefox extension and have the following code:</p>
  
  <pre><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');
      };
  }
  </code></pre>
  
  <ol>
  <li>When I open the extension (a sidebar) and proceed to open a new tab within the Firefox window, there are <strong>three</strong> alert boxes. </li>
  <li>When I refresh a page, there are <strong>two</strong> alert boxes.</li>
  <li>When a page finishes loading, there is only one alert box.</li>
  <li>When I change tabs, an alert is fired. </li>
  </ol>
  
  <p>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.</p>
  
  <p>Any ideas as to why multiple events are being triggered (and for things that the event shouldn't be triggered for)?</p>
  
  <p><strong>SOLUTION</strong></p>
  
  <p>Following from MatrixFrog's suggestion, here is the solution I came to:</p>
  
  <pre><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;
      if (gBrowser.addEventListener) {
          gBrowser.addEventListener("load",pageLoaded,true);
      }    
  }
  
  function pageLoaded(aEvent) {
      if ((aEvent.originalTarget.nodeName == '#document') &amp;&amp; 
         (aEvent.originalTarget.defaultView.location.href == gBrowser.currentURI.spec)) 
      {
          alert('loaded');
      }
  }
  </code></pre>
  
  <ol>
  <li>aEvent.originalTarget.nodeName == '#document' checks that the page is loaded and not favicons.</li>
  <li>(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 </li>
  <li>gBrowser.onload would only fire for xul-image and not for #document so it was replaced with gBrowser.addEventListener("load",pageLoaded,true);</li>
  <li>If you want to avoid firing the event for new blank tabs, make sure gBrowser.currentURI.spec != "about:blank"</li>
  </ol>