Reputation: 119
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).
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.contentWindow.addEventListener
and look for unload
event, the results are quite unpredictable. Some times, I don't get the events at all. 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.
Upvotes: 1
Views: 1168
Reputation: 119
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
}
}
Upvotes: 2
Reputation: 37328
I say hold a reference to the tab. This is how i do it in addons MouseControl and WorkspaceHopper.
so like check:
if (tab.parentNode) {
}
do a try catch too, if it catches then tab obviously doesnt exist.
but for tabClose you might as well use the tabclose event and for window popup, use the windowsMediator listner and listen to onWindowClose
var windowListener = {
//DO NOT EDIT HERE
onOpenWindow: function (aXULWindow) {
// Wait for the window to finish loading
let aDOMWindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
aDOMWindow.addEventListener('load', function () {
aDOMWindow.removeEventListener('load', arguments.callee, false);
windowListener.loadIntoWindow(aDOMWindow);
}, false);
},
onCloseWindow: function (aXULWindow) {},
onWindowTitleChange: function (aXULWindow, aNewTitle) {},
register: function () {
// Load into any existing windows
let DOMWindows = Services.wm.getEnumerator(null);
while (DOMWindows.hasMoreElements()) {
let aDOMWindow = DOMWindows.getNext();
windowListener.loadIntoWindow(aDOMWindow);
}
// Listen to new windows
Services.wm.addListener(windowListener);
},
unregister: function () {
// Unload from any existing windows
let DOMWindows = Services.wm.getEnumerator(null);
while (DOMWindows.hasMoreElements()) {
let aDOMWindow = DOMWindows.getNext();
windowListener.unloadFromWindow(aDOMWindow);
}
//Stop listening so future added windows dont get this attached
Services.wm.removeListener(windowListener);
},
//END - DO NOT EDIT HERE
loadIntoWindow: function (aDOMWindow) {
if (!aDOMWindow) {
return;
}
//do stuff here
},
unloadFromWindow: function (aDOMWindow) {
if (!aDOMWindow) {
return;
}
//do stuff here
}
};
Upvotes: 2
Reputation: 169
For a one solution fits tab and window you can try window observers: https://developer.mozilla.org/en-US/docs/Observer_Notifications#Windows
Probably want to use the outer-window-destroyed
observer, I think each browser element within tab is an outer window. I'm not sure. It might trigger everytime the document changes though, so you would have to QI and get the tab and check if its closed/closing or still open.
Try it out, share with us what you learn, I'm very interested. On close i think it gets destroyed.
Upvotes: 1