bug 1523104: remote: destruct domain instances on closing session; r=ochameau
authorAndreas Tolfsen <ato@sny.no>
Sat, 23 Feb 2019 16:12:03 +0000
changeset 521109 5ce6f3fcc572
parent 521108 9ffed583c0e4
child 521110 a1a5fdbf9bc8
push id10862
push userffxbld-merge
push dateMon, 11 Mar 2019 13:01:11 +0000
treeherdermozilla-beta@a2e7f5c935da [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersochameau
bugs1523104
milestone67.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 1523104: remote: destruct domain instances on closing session; r=ochameau
remote/Session.jsm
remote/test/unit/test_Session.js
--- a/remote/Session.jsm
+++ b/remote/Session.jsm
@@ -8,39 +8,39 @@ var EXPORTED_SYMBOLS = ["Session"];
 
 const {ParentProcessDomains} = ChromeUtils.import("chrome://remote/content/domains/ParentProcessDomains.jsm");
 const {Domains} = ChromeUtils.import("chrome://remote/content/domains/Domains.jsm");
 const {formatError} = ChromeUtils.import("chrome://remote/content/Error.jsm");
 
 class Session {
   constructor(connection, target) {
     this.connection = connection;
-    this.connection.onmessage = this.dispatch.bind(this);
+    this.target = target;
 
-    this.browsingContext = target.browser.browsingContext;
-    this.messageManager = target.browser.messageManager;
+    this.connection.onmessage = this.dispatch.bind(this);
 
     this.domains = new Domains(this, ParentProcessDomains);
-    this.messageManager.addMessageListener("remote:event", this);
-    this.messageManager.addMessageListener("remote:result", this);
-    this.messageManager.addMessageListener("remote:error", this);
+    this.mm.addMessageListener("remote:event", this);
+    this.mm.addMessageListener("remote:result", this);
+    this.mm.addMessageListener("remote:error", this);
 
-    this.messageManager.loadFrameScript("chrome://remote/content/frame-script.js", false);
+    this.mm.loadFrameScript("chrome://remote/content/frame-script.js", false);
   }
 
   destructor() {
+    this.domains.clear();
     this.connection.onmessage = null;
 
-    this.messageManager.sendAsyncMessage("remote:destroy", {
+    this.mm.sendAsyncMessage("remote:destroy", {
       browsingContextId: this.browsingContext.id,
     });
 
-    this.messageManager.removeMessageListener("remote:event", this);
-    this.messageManager.removeMessageListener("remote:result", this);
-    this.messageManager.removeMessageListener("remote:error", this);
+    this.mm.removeMessageListener("remote:event", this);
+    this.mm.removeMessageListener("remote:result", this);
+    this.mm.removeMessageListener("remote:error", this);
   }
 
   async dispatch({id, method, params}) {
     try {
       if (typeof id == "undefined") {
         throw new TypeError("Message missing 'id' field");
       }
       if (typeof method == "undefined") {
@@ -53,27 +53,37 @@ class Session {
         const methodFn = inst[methodName];
         if (!methodFn || typeof methodFn != "function") {
           throw new Error(`Method implementation of ${methodName} missing`);
         }
 
         const result = await methodFn.call(inst, params);
         this.connection.send({id, result});
       } else {
-        this.messageManager.sendAsyncMessage("remote:request", {
+        this.mm.sendAsyncMessage("remote:request", {
           browsingContextId: this.browsingContext.id,
           request: {id, domainName, methodName, params},
         });
       }
     } catch (e) {
       const error = formatError(e, {stack: true});
       this.connection.send({id, error});
     }
   }
 
+  get mm() {
+    return this.target.mm;
+  }
+
+  get browsingContext() {
+    return this.target.browsingContext;
+  }
+
+  // nsIMessageListener
+
   receiveMessage({name, data}) {
     const {id, result, event, error} = data;
 
     switch (name) {
     case "remote:result":
       this.connection.send({id, result});
       break;
 
@@ -82,16 +92,18 @@ class Session {
       break;
 
     case "remote:error":
       this.connection.send({id, error: formatError(error, {stack: true})});
       break;
     }
   }
 
+  // EventEmitter
+
   onevent(eventName, params) {
     this.connection.send({
       method: eventName,
       params,
     });
   }
 }
 
--- a/remote/test/unit/test_Session.js
+++ b/remote/test/unit/test_Session.js
@@ -1,18 +1,38 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
+const {EventEmitter} = ChromeUtils.import("chrome://remote/content/EventEmitter.jsm");
 const {Session} = ChromeUtils.import("chrome://remote/content/Session.jsm");
 
 const connection = {onmessage: () => {}};
 
+class MockTarget {
+  constructor() {
+    EventEmitter.decorate(this);
+  }
+
+  get browsingContext() {
+    return {id: 42};
+  }
+
+  get mm() {
+    return {
+      addMessageListener() {},
+      removeMessageListener() {},
+      loadFrameScript() {},
+      sendAsyncMessage() {},
+    };
+  }
+}
+
 add_test(function test_Session_destructor() {
-  const session = new Session(connection);
-  session.domains.get("Log");
+  const session = new Session(connection, new MockTarget());
+  session.domains.get("Browser");
   equal(session.domains.size, 1);
   session.destructor();
   equal(session.domains.size, 0);
 
   run_next_test();
 });