Bug 1533682 - Implement sessions. r=ato
authorAlexandre Poirot <poirot.alex@gmail.com>
Mon, 11 Mar 2019 12:48:05 +0000
changeset 521340 fde0fa0c16da
parent 521339 bfd5f1e9223e
child 521341 c5edac4ccac9
push id10866
push usernerli@mozilla.com
push dateTue, 12 Mar 2019 18:59:09 +0000
treeherdermozilla-beta@445c24a51727 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersato
bugs1533682
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 1533682 - Implement sessions. r=ato In order to be able to query/instantiate sub targets like remote frames, or tab targets from the MainProcessTarget, we have to support session at the protocol layer. This is all based on a `sessionId` attribute put on all inbound/outbound messages. This patch will be later used, once we start instantiating sub targets. Differential Revision: https://phabricator.services.mozilla.com/D22694
remote/Connection.jsm
remote/sessions/Session.jsm
remote/test/unit/test_Session.js
--- a/remote/Connection.jsm
+++ b/remote/Connection.jsm
@@ -13,19 +13,39 @@ XPCOMUtils.defineLazyGetter(this, "log",
 XPCOMUtils.defineLazyServiceGetter(this, "UUIDGen", "@mozilla.org/uuid-generator;1", "nsIUUIDGenerator");
 
 class Connection {
   constructor(transport) {
     this.id = UUIDGen.generateUUID().toString();
     this.transport = transport;
 
     this.transport.hooks = this;
-    this.onmessage = () => {};
+    this.transport.ready();
+
+    this.defaultSession = null;
+    this.sessions = new Map();
+  }
 
-    this.transport.ready();
+  /**
+   * Register a new Session to forward the messages to.
+   * Session without any `id` attribute will be considered to be the
+   * default one, to which messages without `sessionId` attribute are
+   * forwarded to. Only one such session can be registered.
+   *
+   * @param Session session
+   */
+  registerSession(session) {
+    if (!session.id) {
+      if (this.defaultSession) {
+        throw new Error("Default session is already set on Connection," +
+                        "can't register another one.");
+      }
+      this.defaultSession = session;
+    }
+    this.sessions.set(session.id, session);
   }
 
   send(message) {
     log.trace(`<-(connection ${this.id}) ${JSON.stringify(message)}`);
     this.transport.send(message);
   }
 
   error(id, e) {
@@ -46,25 +66,38 @@ class Connection {
   // transport hooks
 
   onPacket(packet) {
     log.trace(`(connection ${this.id})-> ${JSON.stringify(packet)}`);
 
     let message = {id: null};
     try {
       message = this.deserialize(packet);
-      this.onmessage.call(null, message);
+      const { sessionId } = packet;
+      if (!sessionId) {
+        if (!this.defaultSession) {
+          throw new Error(`Connection is missing a default Session.`);
+        }
+        this.defaultSession.onMessage(message);
+      } else {
+        const session = this.sessions.get(sessionId);
+        if (!session) {
+          throw new Error(`Session '${sessionId}' doesn't exists.`);
+        }
+        session.onMessage(message);
+      }
     } catch (e) {
       log.warn(e);
       this.error(message.id, e);
     }
   }
 
   close() {
     this.transport.close();
+    this.sessions.clear();
   }
 
   onClosed(status) {}
 
   toString() {
     return `[object Connection ${this.id}]`;
   }
 }
--- a/remote/sessions/Session.jsm
+++ b/remote/sessions/Session.jsm
@@ -21,17 +21,17 @@ const {formatError} = ChromeUtils.import
 class Session {
   constructor(connection, target, id) {
     this.connection = connection;
     this.target = target;
     this.id = id;
 
     this.destructor = this.destructor.bind(this);
 
-    this.connection.onmessage = this.onMessage.bind(this);
+    this.connection.registerSession(this);
     this.connection.transport.on("close", this.destructor);
 
     this.domains = new Domains(this, ParentProcessDomains);
   }
 
   destructor() {
     this.domains.clear();
   }
--- a/remote/test/unit/test_Session.js
+++ b/remote/test/unit/test_Session.js
@@ -1,16 +1,21 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 const {Session} = ChromeUtils.import("chrome://remote/content/sessions/Session.jsm");
 
-const connection = {onmessage: () => {}};
+const connection = {
+  registerSession: () => {},
+  transport: {
+    on: () => {},
+  },
+};
 
 class MockTarget {
   constructor() {
   }
 
   get browsingContext() {
     return {id: 42};
   }