Description: fix denial of service and possible code execution
Author: Chris Coulson <chris.coulson@canonical.com>
Origin: other, http://bazaar.launchpad.net/~chrisccoulson/unity-firefox-extension/lp1076350/revision/350
Origin: other, http://bazaar.launchpad.net/~chrisccoulson/unity-firefox-extension/lp1076350/revision/351
Bug: https://bugs.launchpad.net/unity-firefox-extension/+bug/1076350

Index: unity-firefox-extension-2.4.1/unity-firefox-extension/content/unity-global-property-initializer.js
===================================================================
--- unity-firefox-extension-2.4.1.orig/unity-firefox-extension/content/unity-global-property-initializer.js	2012-10-10 12:25:22.000000000 -0400
+++ unity-firefox-extension-2.4.1/unity-firefox-extension/content/unity-global-property-initializer.js	2012-11-22 10:12:41.575592356 -0500
@@ -328,6 +328,7 @@
 	    .QueryInterface(Components.interfaces.nsIInterfaceRequestor)
             .getInterface(Components.interfaces.nsIDOMWindow);
 
+        Services.obs.addObserver(this, "dom-window-destroyed", false);
         this._listenEvent(aWindow, "pagehide", function (event) {
             this._loseInterest(true);
         });
@@ -362,14 +363,23 @@
         this._active = value;
     },
 
+    observe: function (aWindow, aTopic, aData) {
+        // This can be dispatched from either the inner or outer window
+        if (aWindow.window == this._aWindow && aTopic == "dom-window-destroyed") {
+            Services.obs.removeObserver(this, "dom-window-destroyed");
+            this._loseInterest(true);
+
+            this._removeAllListeners();
+            this._callbackManager.releaseAll();
+        }
+    },
+
     _loseInterest: function (abandoned) {
-        if (this._contextManager.removeContext(this._unity.context)) {
+        if (this._unity.context && this._contextManager.removeContext(this._unity.context)) {
             this.uwa.context_destroy(this._unity.context, abandoned);
         }
 
         this._unity.context = null;
-        this._removeAllListeners();
-        this._callbackManager.releaseAll();
     }
 }
 
@@ -486,11 +496,11 @@
     _get: function(aWindow) {
         aWindow = FindToplevelContentWindow(aWindow);
 
-        if (!this._windows.has(aWindow)) {
-            this._windows.set(aWindow, { unity: new UnityObject(this.uwa, this.service, this.contextManager, aWindow),
-                                         webkitNotifications: new WebkitNotifications(this.uwa, this.libnotify, aWindow) });
+        if (!this._windows.has(aWindow.navigator)) {
+            this._windows.set(aWindow.navigator, { unity: new UnityObject(this.uwa, this.service, this.contextManager, aWindow),
+                                                   webkitNotifications: new WebkitNotifications(this.uwa, this.libnotify, aWindow) });
         }
-        return this._windows.get(aWindow);
+        return this._windows.get(aWindow.navigator);
     },
 
     getForWindow: function(aWindow) {
