title: In a Firefox restartless add-on, how do I run code when a new window opens (listen for window open)?
body: <p>I am starting to build a restartless Firefox add-on and I am having trouble setting up the bootstrap.js. Everyone seems to agree that the core of a bootstrap.js is pretty much boilerplate code, along these lines:</p>
  
  <pre><code>const Cc = Components.classes;
  const Ci = Components.interfaces;
  
  function startup() {
    let wm = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator);
    let windows = wm.getEnumerator("navigator:browser");
    while (windows.hasMoreElements()) {
      let domWindow = windows.getNext().QueryInterface(Ci.nsIDOMWindow); 
      // then can control what happens with domWindow.document
    } 
  }
  function shutdown() {}
  function install() {}
  function uninstall() {}
  </code></pre>
  
  <p>This code works and I can control things in the existing windows. For example, <code>domWindow.alert("text")</code> successfully creates a standard alert saying "text" on every window that is currently open.</p>
  
  <p>However, I can't find any code that will allow me to do things in new windows; i.e. those created after the script runs. What is the correct way to handle the creation of new windows and gain control over them, to the point where I could get another "text" alert from one when it is created?</p>
  
  <p><strong>Edit:</strong> Using the nsWindowMediator class and the code sample from MDN, I now have this:</p>
  
  <pre><code>var windowListener = {
  onOpenWindow: function (aWindow) {
    try {
      let domWindow = aWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
      domWindow.addEventListener("load", function () {
        domWindow.removeEventListener("load", arguments.callee, false);
        //window has now loaded now do stuff to it
        domWindow.alert("text");
      }, false);
    } catch (err) {
      Services.prompt.alert(null, "Error", err);
    }
  },
  onCloseWindow: function (aWindow) {},
  onWindowTitleChange: function (aWindow, aTitle) {}
  };
  
  function startup(aData, aReason) {
    // Load into any existing windows
    try {
      let wm = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator);
      let windows = wm.getEnumerator("navigator:browser");
      while (windows.hasMoreElements()) {
        let domWindow = windows.getNext().QueryInterface(Ci.nsIDOMWindow);
        loadIntoWindow(domWindow);
      }
    } catch (err) {
      Services.prompt.alert(null, "Error", err);
    }
  
    Services.wm.addListener(windowListener);
  }
  </code></pre>
  
  <p>However, there is still no output from the onOpenWindow call - the "text" alert does not appear, nor does the error alert in the catch block. I can confirm that onOpenWindow is actually being entered; if I put a <code>Services.prompt.alert()</code> at the beginning of onOpenWindow, I get the alert when I create a new window. Unfortunately, I get an infinite loop of alerts and I have no idea why. </p>