Load multiple pages in a hidden iframe from a xul-based firefox extension

469 views Asked by At

From a xul-based firefox addon, I need to:

  1. programmatically create an invisible iframe (once)
  2. reuse it to load multiple URLs as the addon runs
  3. access the returned HTML after each URL loads

Problem: I can only get the first page-load for any created iframe to trigger an 'onload' or 'DOMContentLoaded' event. For subsequent URLs, there is no event triggered.

Note: I'm also fine with using the hiddenDOMWindow itself if this is possible...

Code:

var urls = ['http://en.wikipedia.org/wiki/Internet', 'http://en.wikipedia.org/wiki/IPv4', 'http://en.wikipedia.org/wiki/Multicast' ];

visitPage(urls.pop());

function visitPage(url) {

    var XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";

    var hiddenWindow = Components.classes["@mozilla.org/appshell/appShellService;1"].getService
        (Components.interfaces.nsIAppShellService).hiddenDOMWindow;

    var doc = hiddenWindow.document, iframe = doc.getElementById("my-iframe");

    if (!iframe) 
    {
        iframe = doc.createElement("iframe");
        //OR: iframe = doc.createElementNS(XUL_NS,"iframe");

        iframe.setAttribute("id", "my-iframe");
        iframe.setAttribute('style', 'display: none');

        iframe.addEventListener("DOMContentLoaded", function (e) { 
            dump('DOMContentLoaded: '+e.originalTarget.location.href);
            visitPage(urls.pop()); 
        });

        doc.documentElement.appendChild(iframe);
    }

    iframe.src = url;    
}
1

There are 1 answers

0
nmaier On BEST ANSWER

There are some traps:

  • The hiddenWindow differs between platforms. It is XUL on Mac, and HTML else.
  • You should use .setAttribute("src", url); to reliably navigate.

The following works for me (Mac, Win7):

var urls = [
    'http://en.wikipedia.org/wiki/Internet',
    'http://en.wikipedia.org/wiki/IPv4',
    'http://en.wikipedia.org/wiki/Multicast'
];

var hiddenWindow = Components.classes["@mozilla.org/appshell/appShellService;1"].
                   getService(Components.interfaces.nsIAppShellService).
                   hiddenDOMWindow;

function visitPage(url) {
    var iframe = hiddenWindow.document.getElementById("my-iframe");
    if (!iframe) {
        // Always use html. The hidden window might be XUL (Mac)
        // or just html (other platforms).
        iframe = hiddenWindow.document.
                 createElementNS("http://www.w3.org/1999/xhtml", "iframe");
        iframe.setAttribute("id", "my-iframe");
        iframe.addEventListener("DOMContentLoaded", function (e) {
            console.log("DOMContentLoaded: " +
                        e.originalTarget.location);
            var u = urls.pop();
            // Make sure there actually was something left to load.
            if (u) {
                visitPage(u);
            }
        });
        hiddenWindow.document.documentElement.appendChild(iframe);
    }
    // Use .setAttribute() to reliably navigate the iframe.
    iframe.setAttribute("src", url);
}

visitPage(urls.pop());

Don't reload the hiddenWindow itself, or you will break lots of other code.