Search code examples
javascriptdomfirefox-addonxulxpcom

How to identify tab close event for browser element [XUL/firefox]


I work on an addon that observes all the http requests and populate some info corresponding to each tab. I want to clear the data for the tab which I close. However, I can't get to identiy tab close event in a cleaner/saner way. So I have the contentWindow (LoadContext -> associatedWindow) for which the request was made, and the browser for that content window (which is for the tab).

  1. I realized that to do a browser.addEventListener, I will have to listen for DOMNodeRemoved event - which is deprecated as per MDN (and should rather use mutation observers). Moreover, I won't get the events when a popup window is closed.
  2. If I do a contentWindow.addEventListener and look for unload event, the results are quite unpredictable. Some times, I don't get the events at all.
  3. If I get this tab element from gBrowser.tabs and listen for TabClose event, I can get all close events for the tab. But then again, it won't inform of any popup-window closes (although I do get a tab element for the popup-window)

So what is the easiest/cleanest way to know any tab/popup-window close ? I don't use the addon SDK, btw.

EDIT : Looking for a simpler, valid-for-all-cases solution. ie. I get notified of close event be it a tab or a popup-window (or any other types of windows if they exist!). I believe that might be possible given that I hold a browser element which contains the DOM window, and the DOM get removed (unloaded) upon a close.

EDIT-2 : Realized that all the problem was due to one thing : there is no TabClose event from Firefox when the last tab closes (which is a window close). Life would have been much easier if we were notified of the tabs that get closed when a window closes. Any ways, I will go with a modified version of @Noitidart's solution - to have a separate window listener, in addition to the TabClose listener. And find the tab elements in it and do my clean up. Sigh! Will do a bit more search in this, and see if this qualifies for a bug/enhancement. Thanks to @Noitidart and @Blargh for their suggestions.


Solution

  • Here's my modified version of @Noitidart's answer. I use an expando property on browser (eg: _myextensionTabId ) to index my cached array.

    var WindowListener = {
    /* Same as @Noitidart's listener */
      onOpenWindow : function(xulWindow) {
        /* Get DOM window, call other window specific modules init */
        myExtension.initWindow(domWindow);
        myHttpObserver.initWindow(domWindow);
      },
      onCloseWindow: function(xulWindow) {
        /* Get DOM window, call other window specific modules uninit */
        myExtension.uninitWindow(domWindow);
        myHttpObserver.uninitWindow(domWindow);
      },
    };
    
    var myHttpObserver = {
        ..  
        initWindow: function(window) {
          window.gBrowser.tabContainer
                  .addEventListener('TabClose', tabClosed, false);
        }, 
    
        uninitWindow: function(window) {
          dump ("Uninit window http observer\n");
          window.gBrowser.tabContainer
                    .removeEventListener('TabClose', tabClosed);
          for (var browser of window.gBrowser.browsers) {
            if (browser._myextensionTabId) {
              // Do any cleanup.
            }
          }
        },
      .. 
        /* Other http observer stuff, methods that sets the expando property etc. */
    };
    
    function tabClosed(e) {
      var browser = Services.wm.getMostRecentWindow("navigator:browser")
                               .gBrowser.getBrowserForTab(e.target);
      dump("Tab closed. \n");
      if (browser._myextensionTabId) {
        dump("My extension tab id : " + browser._myextensionTabId);
        // Do any cleanup
      }
    }