it uses the onbeforeunload thing and attaches it to all top windows on load of tabs, and also on open of tabs with event listener of TabOpen
when you want to undo the changes this made, run windowListener.unregister() i gave commented out example at bottom of window. but if you run unregister from scratchpad make sure you blank out the stuff at top first otherwise it wont unregister what was registered on the PREVIOUS run, it will just unregister what it registerd on the current run.
not tailored for addon-sdk, but you can drop this into your addon sdk but at top you have to add like var {Cu, Ci} = require('chrome'); Cu.import('resource://gre/modules/Services.jsm');
this code does modify the text of the warning modal.
it doesnt check if some other onbeforeunload is already registered, its an ez check you should add that in. if need help let me know.
try {
windowListener.unregister();
} catch (ignore) {}
var ignoreFrames = true;
function beforeUnloader(e) {
//console.log('beforeUnload e:', e); //http://i.imgur.com/AbUn20J.png
var DOMWindow = e.target.defaultView.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShellTreeItem)
.rootTreeItem
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindow);
DOMWindow.setTimeout(function() {
try {
if (DOMWindow.gBrowser) {
var linkedBrowser = DOMWindow.gBrowser.getBrowserForDocument(e.target);
} else {
var linkedBrowser = DOMWindow.document;
}
var modal = linkedBrowser.parentNode.querySelector('tabmodalprompt');
var warnTxtNode = modal.ownerDocument.getAnonymousElementByAttribute(modal, 'anonid', 'info.body').firstChild;
warnTxtNode.textContent = 'rawr';
} catch (ex) {
console.warn('excpetion occured when trying to modify warn text, ex:', ex);
}
}, 10);
return 'dummy text so it shows unloader'; //see third bullet here: https://developer.mozilla.org/en-US/docs/WindowEventHandlers.onbeforeunload it says "Note that in Firefox 4 and later the returned string is not displayed to the user. Instead, Firefox displays the string "This page is asking you to confirm that you want to leave - data you have entered may not be saved." See bug 588292."
};
function addInjections(theDoc) {
theDoc.defaultView.onbeforeunload = beforeUnloader;
}
function removeInjections(theDoc, skipChecks) {
theDoc.defaultView.onbeforeunload = null;
}
function tabopened(e) {
//console.info('tabopened: e:', e); //http://i.imgur.com/Re0Wmfn.png
addInjections(e.target.linkedBrowser.contentDocument);
}
function listenPageLoad(event) {
var win = event.originalTarget.defaultView;
var doc = win.document;
Cu.reportError('page loaded loc = ' + doc.location);
if (win.frameElement) {
//its a frame
Cu.reportError('its a frame');
if (ignoreFrames) {
return;//dont want to watch frames
}
}
addInjections(doc);
}
/*start - windowlistener*/
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, aXULWindow);
}, false);
},
onCloseWindow: function (aXULWindow) {},
onWindowTitleChange: function (aXULWindow, aNewTitle) {},
register: function () {
// Load into any existing windows
let XULWindows = Services.wm.getXULWindowEnumerator(null);
while (XULWindows.hasMoreElements()) {
let aXULWindow = XULWindows.getNext();
let aDOMWindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
windowListener.loadIntoWindow(aDOMWindow, aXULWindow);
}
// Listen to new windows
Services.wm.addListener(windowListener);
},
unregister: function () {
// Unload from any existing windows
let XULWindows = Services.wm.getXULWindowEnumerator(null);
while (XULWindows.hasMoreElements()) {
let aXULWindow = XULWindows.getNext();
let aDOMWindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
windowListener.unloadFromWindow(aDOMWindow, aXULWindow);
}
//Stop listening so future added windows dont get this attached
Services.wm.removeListener(windowListener);
},
//END - DO NOT EDIT HERE
loadIntoWindow: function (aDOMWindow, aXULWindow) {
if (!aDOMWindow) {
return;
}
if (aDOMWindow.gBrowser) {
aDOMWindow.gBrowser.addEventListener('DOMContentLoaded', listenPageLoad, false);
if (aDOMWindow.gBrowser.tabContainer) {
//has tabContainer
aDOMWindow.gBrowser.tabContainer.addEventListener("TabOpen", tabopened, false);
//start - go through all tabs in this window we just added to
var tabs = aDOMWindow.gBrowser.tabContainer.childNodes;
for (var i = 0; i < tabs.length; i++) {
Cu.reportError('DOING tab: ' + i);
var tabBrowser = tabs[i].linkedBrowser;
var win = tabBrowser.contentWindow;
loadIntoContentWindowAndItsFrames(win);
}
//end - go through all tabs in this window we just added to
} else {
//does not have tabContainer
var win = aDOMWindow.gBrowser.contentWindow;
loadIntoContentWindowAndItsFrames(win);
}
} else {
//window does not have gBrowser
}
},
unloadFromWindow: function (aDOMWindow, aXULWindow) {
if (!aDOMWindow) {
return;
}
if (aDOMWindow.gBrowser) {
aDOMWindow.gBrowser.removeEventListener('DOMContentLoaded', listenPageLoad, false);
if (aDOMWindow.gBrowser.tabContainer) {
//has tabContainer
aDOMWindow.gBrowser.tabContainer.removeEventListener("TabOpen", tabopened, false);
//start - go through all tabs in this window we just added to
var tabs = aDOMWindow.gBrowser.tabContainer.childNodes;
for (var i = 0; i < tabs.length; i++) {
Cu.reportError('DOING tab: ' + i);
var tabBrowser = tabs[i].linkedBrowser;
var win = tabBrowser.contentWindow;
unloadFromContentWindowAndItsFrames(win);
}
//end - go through all tabs in this window we just added to
} else {
//does not have tabContainer
var win = aDOMWindow.gBrowser.contentWindow;
unloadFromContentWindowAndItsFrames(win);
}
} else {
//window does not have gBrowser
}
}
};
/*end - windowlistener*/
function loadIntoContentWindowAndItsFrames(theWin) {
var frames = theWin.frames;
var winArr = [theWin];
for (var j = 0; j < frames.length; j++) {
winArr.push(frames[j].window);
}
Cu.reportError('# of frames in tab: ' + frames.length);
for (var j = 0; j < winArr.length; j++) {
if (j == 0) {
Cu.reportError('**checking win: ' + j + ' location = ' + winArr[j].document.location);
} else {
Cu.reportError('**checking frame win: ' + j + ' location = ' + winArr[j].document.location);
}
var doc = winArr[j].document;
//START - edit below here
addInjections(doc);
if (ignoreFrames) {
break;
}
//END - edit above here
}
}
function unloadFromContentWindowAndItsFrames(theWin) {
var frames = theWin.frames;
var winArr = [theWin];
for (var j = 0; j < frames.length; j++) {
winArr.push(frames[j].window);
}
Cu.reportError('# of frames in tab: ' + frames.length);
for (var j = 0; j < winArr.length; j++) {
if (j == 0) {
Cu.reportError('**checking win: ' + j + ' location = ' + winArr[j].document.location);
} else {
Cu.reportError('**checking frame win: ' + j + ' location = ' + winArr[j].document.location);
}
var doc = winArr[j].document;
//START - edit below here
removeInjections(doc);
if (ignoreFrames) {
break;
}
//END - edit above here
}
}
windowListener.register();
Ok man here is what you want. The previous version was to see if i could get onbeforeunload to trigger only when tab closed, but i couldnt figure that out.
// Keep a reference to the original function.
var _original = gBrowser.removeTab;
// Override a function.
gBrowser.removeTab = function() {
// Execute some action before the original function call.
if (window.myAddonIsInstalled = true) {
var closeit = confirm('are you sure you want to close the tab?')
// Execute original function.
if (closeit) {
var rv = _original.apply(gBrowser, arguments);
}
// return the original result
return rv;
} else {
var rv = _original.apply(gBrowser, arguments);
// return the original result
return rv;
}
};
on uninstall of your addon make sure to set the global property of window.myAddonIsInstalled to false. As that is the recommended way to disable your functionality per that article.
This does the trick. Can copy paste this to scratchpad and run (with environment > browser of course)
adapted from here: https://gist.github.com/Noitidart/9406437 which is from: https://gist.github.com/Noitidart/51b62b356b3a21010a4d
it uses the
onbeforeunload
thing and attaches it to all top windows on load of tabs, and also on open of tabs with event listener ofTabOpen
when you want to undo the changes this made, run
windowListener.unregister()
i gave commented out example at bottom of window. but if you run unregister from scratchpad make sure you blank out the stuff at top first otherwise it wont unregister what was registered on the PREVIOUS run, it will just unregister what it registerd on the current run.not tailored for addon-sdk, but you can drop this into your addon sdk but at top you have to add like
var {Cu, Ci} = require('chrome'); Cu.import('resource://gre/modules/Services.jsm');
this code does modify the text of the warning modal.
it doesnt check if some other onbeforeunload is already registered, its an ez check you should add that in. if need help let me know.
Ok man here is what you want. The previous version was to see if i could get onbeforeunload to trigger only when tab closed, but i couldnt figure that out.
Here's how to do it: We override the removeTab function. Following the guidlines here: MDN :: Overriding/Extending/Amending existing functions - Alternative: Replace + Function.apply()
on uninstall of your addon make sure to set the global property of window.myAddonIsInstalled to false. As that is the recommended way to disable your functionality per that article.