Bug 1007520 - Part 3: Avoid leaking SpecialPowers to nsInProcessTabChildGlobal.mMessageManager. r=ted
authorTing-Yu Chou <janus926@gmail.com>
Thu, 05 Jun 2014 22:17:23 +0800
changeset 187851 b1d4ab072fc255cd9df2aa713bd69f7a9df1740a
parent 187850 0522e007a3aaf1059fe0b5307e341a8711e5c50a
child 187852 a4859b482f4474e01eaa617dc1d8f33f5109bb7e
push id26936
push useremorley@mozilla.com
push dateTue, 10 Jun 2014 15:01:30 +0000
treeherdermozilla-central@bb7ae9b80274 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersted
bugs1007520
milestone33.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1007520 - Part 3: Avoid leaking SpecialPowers to nsInProcessTabChildGlobal.mMessageManager. r=ted
testing/specialpowers/content/specialpowers.js
--- a/testing/specialpowers/content/specialpowers.js
+++ b/testing/specialpowers/content/specialpowers.js
@@ -2,30 +2,47 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 /* This code is loaded in every child process that is started by mochitest in
  * order to be used as a replacement for UniversalXPConnect
  */
 
 function SpecialPowers(window) {
   this.window = Components.utils.getWeakReference(window);
+  this._windowID = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+                         .getInterface(Components.interfaces.nsIDOMWindowUtils)
+                         .currentInnerWindowID;
   this._encounteredCrashDumpFiles = [];
   this._unexpectedCrashDumpFiles = { };
   this._crashDumpDir = null;
   this.DOMWindowUtils = bindDOMWindowUtils(window);
   Object.defineProperty(this, 'Components', {
       configurable: true, enumerable: true, get: function() {
           var win = this.window.get();
           if (!win)
               return null;
           return getRawComponents(win);
       }});
   this._pongHandlers = [];
   this._messageListener = this._messageReceived.bind(this);
   addMessageListener("SPPingService", this._messageListener);
+  let (self = this) {
+    Services.obs.addObserver(function onInnerWindowDestroyed(subject, topic, data) {
+      var id = subject.QueryInterface(Components.interfaces.nsISupportsPRUint64).data;
+      if (self._windowID === id) {
+        Services.obs.removeObserver(onInnerWindowDestroyed, "inner-window-destroyed");
+        try {
+          removeMessageListener("SPPingService", self._messageListener);
+        } catch (e if e.result == Components.results.NS_ERROR_ILLEGAL_VALUE) {
+          // Ignore the exception which the message manager has been destroyed.
+          ;
+        }
+      }
+    }, "inner-window-destroyed", false);
+  }
 }
 
 SpecialPowers.prototype = new SpecialPowersAPI();
 
 SpecialPowers.prototype.toString = function() { return "[SpecialPowers]"; };
 SpecialPowers.prototype.sanityCheck = function() { return "foo"; };
 
 // This gets filled in in the constructor.