In a Firefox restartless add-on, how do I run code when a new window opens (listen for window open)?

aosdict

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:

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() {}

This code works and I can control things in the existing windows. For example, domWindow.alert("text") successfully creates a standard alert saying "text" on every window that is currently open.

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?

Edit: Using the nsWindowMediator class and the code sample from MDN, I now have this:

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);
}

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 Services.prompt.alert() 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.

Makyen

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?

The correct way to act on each window when it opens is to use addListener() from nsIWindowMediator. The example code below does this. The nsIWindowMediator is included in Services.jsm and is accessed through Services.wm.addListener(WindowListener). In order to use a window listener, you have to pass it an nsIWindowMediatorListener (ref2) object. An nsIWindowMediatorListener contains three keys: onOpenWindow, onCloseWindow, and onWindowTitleChange. Each should be defined as a function which will be called when the appropriate event occurs.

The MDN document How to convert an overlay extension to restartless in "Step 9: bootstrap.js" contains an example of a basic bootstrap.js which will run the code in the function loadIntoWindow(window) for each currently open browser window and any browser window which opens in the future. I have used code modified from this in a couple of different add-ons. The example is substantially similar to the code you are already using. The example is (slightly modified):

const Ci = Components.interfaces;

Components.utils.import("resource://gre/modules/Services.jsm");

function startup(data,reason) {
    // Load this add-ons module(s):
    Components.utils.import("chrome://myAddon/content/myModule.jsm");
    // Do whatever initial startup stuff is needed for this add-on.
    //   Code is in module just loaded.
    myModule.startup();  

    // Make changes to the Firefox UI to hook in this add-on
    forEachOpenWindow(loadIntoWindow);
    // Listen for any windows that open in the future
    Services.wm.addListener(WindowListener);
}

function shutdown(data,reason) {
    if (reason == APP_SHUTDOWN)
        return;

    // Unload the UI from each window
    forEachOpenWindow(unloadFromWindow);
    // Stop listening for new windows to open.
    Services.wm.removeListener(WindowListener);

    // Do whatever shutdown stuff you need to do on add-on disable
    myModule.shutdown();  

    // Unload the module(s) loaded specific to this extension.
    // Use the same URL for your module(s) as when loaded:
    Components.utils.unload("chrome://myAddon/content/myModule.jsm"); 

    // HACK WARNING: The Addon Manager does not properly clear all add-on related caches
    //               on update. In order to fully update images and locales, their
    //               caches need clearing here.
    Services.obs.notifyObservers(null, "chrome-flush-caches", null);
}

function install(data,reason) { }

function uninstall(data,reason) { }

function loadIntoWindow(window) {
    /* call/move your UI construction function here */
}

function unloadFromWindow(window) {
    /* call/move your UI tear down function here */
}

function forEachOpenWindow(todo) {
    // Apply a function to all open browser windows
    var windows = Services.wm.getEnumerator("navigator:browser");
    while (windows.hasMoreElements())
        todo(windows.getNext().QueryInterface(Ci.nsIDOMWindow));
}

var WindowListener = {
    onOpenWindow: function(xulWindow) {
        var window = xulWindow.QueryInterface(Ci.nsIInterfaceRequestor)
                              .getInterface(Ci.nsIDOMWindow);
        function onWindowLoad() {
            window.removeEventListener("load",onWindowLoad);
            // Only add UI changes if this is a browser window
            if (window.document.documentElement.getAttribute("windowtype") 
                                                                == "navigator:browser")
                loadIntoWindow(window);
        }
        window.addEventListener("load",onWindowLoad);
    },
    onCloseWindow: function(xulWindow) { },
    onWindowTitleChange: function(xulWindow, newTitle) { }
};

While there is quite a bit more that your might want to do in your bootstrap.js code, the above is organized reasonably well and keeps all of the code to load into the Firefox UI within loadIntoWindow(window) and unloading the UI within unloadFromWindow(window). However, it should be noted that some UI elements you should only be adding/removing once (e.g. australis widgets, like buttons) and other elements (e.g. direct changes to the Firefox DOM) have to be added once in each window.

Unfortunately, I get an infinite loop of alerts and I have no idea why.

One of the significant differences between this example and what you are currently using is the test for the type of window that has opened. This is done so that we are only acting on newly opened windows which are browser windows instead of all newly opened windows:

if (window.document.documentElement.getAttribute("windowtype") == "navigator:browser")
    loadIntoWindow(window);

The problem you describe of getting an infinite loop of alert() popups is caused by not checking to make sure that you are only acting on browser windows. The alert() popup is a window. Thus, you are calling alert() for every alert() window you open which, of course, just opens another alert() window on which you call alert(). This is your infinite loop.

Additional references:
1. Working with windows in chrome code

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

How can I find Firefox code that opens "Add new Bookmark" window?

From Dev

How do I add a target=_blank to php code to open in new window?

From Dev

How to run a cancellable function when a new Tkinter window opens

From Dev

How can I do SSH to a specific location when I open new tab/window in iterm2?

From Dev

When I run WinSat.exe from the command line, it opens a new terminal window

From Dev

How do I add a link to open a pdf file in a new window from my R shiny app?

From Dev

How do I close a new Firefox window from the Terminal?

From Dev

How do I close a new Firefox window from the Terminal?

From Dev

How do I create an executable from Golang that doesn't open a console window when run?

From Dev

jquery - how do I open a URL in a new tab/window when the user clicks on a div with no associated href?

From Dev

How can I open a new window not a new tab or popup window but a new fresh window in c# on button click from code behind

From Dev

How do I control where CKEditor API opens a new new window for the filebrowserBrowseUrl?

From Dev

How do I control where CKEditor API opens a new new window for the filebrowserBrowseUrl?

From Dev

How do I make a Jbutton in a GUI open a new GUI window?

From Dev

Firefox opens new window instead of link

From Dev

How do I resize the window in Chrome and Firefox when testing with Selenium?

From Dev

Yahoo Search opens when I open a new tab in Firefox

From Dev

How can I customize the window that opens when starting a command from the Windows "Run" command?

From Dev

I want the Firefox icon on the launcher to open a new window if there is no Firefox window open on the current workspace

From Dev

I want the Firefox icon on the launcher to open a new window if there is no Firefox window open on the current workspace

From Dev

how to open a new window and close the current window when I click the button on java GUI?

From Dev

How can I get a new browser session when opening a new tab or window on Firefox/Chrome?

From Dev

How do I open window inside another window after

From Dev

How to close current window (in Code) when launching new Window

From Dev

Fancybox opens new window

From Dev

New window opens incorrectly

From Dev

How to code for a new window

From Dev

How Do I Open Fixed Window In Firefox (like Chrome app mode)?

From Dev

How Do I Open Fixed Window In Firefox (like Chrome app mode)?

Related Related

  1. 1

    How can I find Firefox code that opens "Add new Bookmark" window?

  2. 2

    How do I add a target=_blank to php code to open in new window?

  3. 3

    How to run a cancellable function when a new Tkinter window opens

  4. 4

    How can I do SSH to a specific location when I open new tab/window in iterm2?

  5. 5

    When I run WinSat.exe from the command line, it opens a new terminal window

  6. 6

    How do I add a link to open a pdf file in a new window from my R shiny app?

  7. 7

    How do I close a new Firefox window from the Terminal?

  8. 8

    How do I close a new Firefox window from the Terminal?

  9. 9

    How do I create an executable from Golang that doesn't open a console window when run?

  10. 10

    jquery - how do I open a URL in a new tab/window when the user clicks on a div with no associated href?

  11. 11

    How can I open a new window not a new tab or popup window but a new fresh window in c# on button click from code behind

  12. 12

    How do I control where CKEditor API opens a new new window for the filebrowserBrowseUrl?

  13. 13

    How do I control where CKEditor API opens a new new window for the filebrowserBrowseUrl?

  14. 14

    How do I make a Jbutton in a GUI open a new GUI window?

  15. 15

    Firefox opens new window instead of link

  16. 16

    How do I resize the window in Chrome and Firefox when testing with Selenium?

  17. 17

    Yahoo Search opens when I open a new tab in Firefox

  18. 18

    How can I customize the window that opens when starting a command from the Windows "Run" command?

  19. 19

    I want the Firefox icon on the launcher to open a new window if there is no Firefox window open on the current workspace

  20. 20

    I want the Firefox icon on the launcher to open a new window if there is no Firefox window open on the current workspace

  21. 21

    how to open a new window and close the current window when I click the button on java GUI?

  22. 22

    How can I get a new browser session when opening a new tab or window on Firefox/Chrome?

  23. 23

    How do I open window inside another window after

  24. 24

    How to close current window (in Code) when launching new Window

  25. 25

    Fancybox opens new window

  26. 26

    New window opens incorrectly

  27. 27

    How to code for a new window

  28. 28

    How Do I Open Fixed Window In Firefox (like Chrome app mode)?

  29. 29

    How Do I Open Fixed Window In Firefox (like Chrome app mode)?

HotTag

Archive