Permalink
Browse files

Check if the window is closed before trying to use it.

In the GM_xhr callback.

Fixes #1599
  • Loading branch information...
1 parent 007c4c4 commit b9a071376b4f603496b99ed103788d087ad2b751 @arantius committed Aug 30, 2012
Showing with 41 additions and 32 deletions.
  1. +5 −32 components/greasemonkey.js
  2. +4 −0 content/xmlhttprequester.js
  3. +32 −0 modules/util/windowIsClosed.js
View
@@ -436,38 +436,11 @@ service.prototype.__defineGetter__('config', function() {
service.prototype.contentDestroyed = function(aContentWindowId) {
this.withAllMenuCommandsForWindowId(null, function(index, command) {
- var closed = false;
-
- try {
- // If this content destroyed message matches the command's window id.
- if (aContentWindowId && (command.contentWindowId == aContentWindowId)) {
- closed = true;
- }
-
- // If isDeadWrapper (Firefox 15+ only) tells us the window is dead.
- if (!closed &&
- Cu.isDeadWrapper && Cu.isDeadWrapper(command.contentWindow)) {
- closed = true;
- }
-
- // If we can access the .closed property and it is true, or there is any
- // problem accessing that property.
- try {
- if (!closed && command.contentWindow.closed) {
- closed = true;
- }
- } catch (e) {
- closed = true;
- }
- } catch (e) {
- Cu.reportError(e);
- // Failsafe. In case of any failure, destroy the command to avoid leaks.
- closed = true;
- }
-
- if (closed) {
- // If anything above decided the window is closed, remove the command
- // that holds a reference to it.
+ if (GM_util.windowIsClosed(command.contentWindow)
+ // This content destroyed message matches the command's window id.
+ || (aContentWindowId && (command.contentWindowId == aContentWindowId))
+ ) {
+ // If the window is closed, remove the reference to it.
gMenuCommands.splice(index, 1);
}
}, true); // Don't forget the aForced=true passed here!
@@ -164,6 +164,10 @@ function(wrappedContentWin, req, event, details) {
break;
}
+ if (GM_util.windowIsClosed(wrappedContentWin)) {
+ return;
+ }
+
// Pop back onto browser thread and call event handler.
// Have to use nested function here instead of GM_util.hitch because
// otherwise details[event].apply can point to window.setTimeout, which
@@ -0,0 +1,32 @@
+Components.utils.import('resource://greasemonkey/util.js');
+
+const EXPORTED_SYMBOLS = ['windowIsClosed'];
+
+var Cu = Components.utils;
+
+/*
+Accessing windows that are closed can be dangerous after
+http://bugzil.la/695480 . This routine takes care of being careful to not
+trigger any of those broken edge cases.
+*/
+function windowIsClosed(aWin) {
+ try {
+ // If isDeadWrapper (Firefox 15+ only) tells us the window is dead.
+ if (Cu.isDeadWrapper && Cu.isDeadWrapper(aWin)) {
+ return true;
+ }
+
+ // If we can access the .closed property and it is true, or there is any
+ // problem accessing that property.
+ try {
+ if (aWin.closed) return true;
+ } catch (e) {
+ return true;
+ }
+ } catch (e) {
+ Cu.reportError(e);
+ // Failsafe. In case of any failure, destroy the command to avoid leaks.
+ return true;
+ }
+ return false;
+}

0 comments on commit b9a0713

Please sign in to comment.