Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Finding the tab associated with a DOM window

I'm adding some new functionality in a Firefox extension, TryAgain, that traps HTTP error codes (e.g. 500) and automatically retries loading the page after some interval.

Trapping the codes works excellently, and I'm trying to tally the total number of retries and store this in the tab using Session Store. Unfortunately, right now I'm getting a reference to a DOM window (through interfaceRequestor.getInterface(Components.interfaces.nsIDOMWindow)), but I need a reference to a tab, which is a nsIDOMNode as per nsISessionStore docs on setTabValue().

What I have so far (I've snipped the actual retrying out of this example):

// This function implements the nsIObserverService interface and observes
// the status of all HTTP channels
observe : function(aSubject, aTopic, aData) {
    var httpChannel = aSubject
            .QueryInterface(Components.interfaces.nsIHttpChannel);
    if (httpChannel.responseStatus == 500) {
        var domWindow;
        try {
            var notificationCallbacks;
            if (httpChannel.notificationCallbacks) {
                notificationCallbacks = httpChannel.notificationCallbacks;
            } else {
                notificationCallbacks = aSubject.loadGroup
                        .notificationCallbacks;
            }
            var interfaceRequestor = notificationCallbacks
                    .QueryInterface(Components.interfaces
                        .nsIInterfaceRequestor);
            domWindow = interfaceRequestor
                    .getInterface(Components.interfaces.nsIDOMWindow);
        } catch (e) {
            // No window associated with this channel
            return;
        }
        var ss = Components.classes["@mozilla.org/browser/sessionstore;1"]
                .getService(Components.interfaces.nsISessionStore);
        ss.setTabValue(domWindow, "foo", "bar");
    }
},

This of course fails on setTabValue with an invalid parameter. How can I get the tab associated with the DOM window?

As an alternative solution, can I store variables associated with a DOM window in some way such that I don't have to clean up the memory myself?

like image 709
Paul Lammertsma Avatar asked Jun 26 '11 15:06

Paul Lammertsma


People also ask

What is window in DOM?

The Window interface represents a window containing a DOM document; the document property points to the DOM document loaded in that window. A window for a given document can be obtained using the document. defaultView property.

Is window part of the DOM?

The window object is not part of the DOM.

What is the window object?

The window object represents an open window in a browser. If a document contain frames (<iframe> tags), the browser creates one window object for the HTML document, and one additional window object for each frame.


2 Answers

domWindow is a content window, first you need to get the chrome window containing it. That's done by this rather ugly code:

var chromeWindow = window.QueryInterface(Ci.nsIInterfaceRequestor)
                         .getInterface(Ci.nsIWebNavigation)
                         .QueryInterface(Ci.nsIDocShellTreeItem)
                         .rootTreeItem
                         .QueryInterface(Ci.nsIInterfaceRequestor)
                         .getInterface(Ci.nsIDOMWindow);

Then you want to ask the <tabbrowser> element about the tab (note that you should pass in domWindow.top because domWindow might not be the top frame):

var browser = chromeWindow.gBrowser.getBrowserForDocument(domWindow.top.document);

Note that this is the <browser> element, not the associated <tab> (for the latter you would need getBrowserIndexForDocument and then look at gBrowser.tabs[index]). But I think you simply want to store a property for this tab, not have this property persist across sessions? Then you can use an expando property:

if (!("_myExtensionErrorCount" in browser))
  browser._myExtensionErrorCount = 0;
browser._myExtensionErrorCount++;

Here _myExtensionErrorCount should be a name that is unique enough to avoid conflicts with other extensions that might want to use expando properties as well.

like image 167
Wladimir Palant Avatar answered Sep 27 '22 19:09

Wladimir Palant


The nsISessionStore APIs referencing nsIDOMNode aTab require you to get hold of the tab node storing the data. If you you are working in a browser.xul overlay and want the currently selected tab, it's as simple as gBrowser.selectedTab. If you just hold a reference to some content document in the overlay's chrome window, here is how you find its corresponding tab:

function tabFromDoc(doc) {
    var no = gBrowser.getBrowserIndexForDocument(doc);
    return gBrowser.tabContainer.childNodes[no];
}

// example use:
Cc['@mozilla.org/browser/sessionstore;1']
    .getService(Ci.nsISessionStore)
    .setTabValue(tabFromDoc(myContentDoc), 'myKey', 'myValue');
like image 29
winterTTr Avatar answered Sep 27 '22 21:09

winterTTr