2019-01-29 18:18:42 +03:00
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* 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/. */
|
|
|
|
|
|
|
|
"use strict";
|
|
|
|
|
|
|
|
var EXPORTED_SYMBOLS = ["Connection"];
|
|
|
|
|
|
|
|
const { Log } = ChromeUtils.import("chrome://remote/content/Log.jsm");
|
|
|
|
const { XPCOMUtils } = ChromeUtils.import(
|
|
|
|
"resource://gre/modules/XPCOMUtils.jsm"
|
|
|
|
);
|
|
|
|
|
|
|
|
XPCOMUtils.defineLazyGetter(this, "log", Log.get);
|
2019-03-08 01:14:59 +03:00
|
|
|
XPCOMUtils.defineLazyServiceGetter(
|
|
|
|
this,
|
|
|
|
"UUIDGen",
|
|
|
|
"@mozilla.org/uuid-generator;1",
|
|
|
|
"nsIUUIDGenerator"
|
|
|
|
);
|
2019-01-29 18:18:42 +03:00
|
|
|
|
2019-02-12 16:58:23 +03:00
|
|
|
class Connection {
|
2019-03-21 17:17:36 +03:00
|
|
|
/**
|
2019-07-09 12:36:16 +03:00
|
|
|
* @param WebSocketTransport transport
|
2019-03-21 17:17:36 +03:00
|
|
|
* @param httpd.js's Connection httpdConnection
|
|
|
|
*/
|
|
|
|
constructor(transport, httpdConnection) {
|
2019-03-08 01:14:59 +03:00
|
|
|
this.id = UUIDGen.generateUUID().toString();
|
2019-01-29 18:18:42 +03:00
|
|
|
this.transport = transport;
|
2019-03-21 17:17:36 +03:00
|
|
|
this.httpdConnection = httpdConnection;
|
2019-01-29 18:18:42 +03:00
|
|
|
|
|
|
|
this.transport.hooks = this;
|
2019-03-08 01:15:35 +03:00
|
|
|
this.transport.ready();
|
2019-03-11 15:48:05 +03:00
|
|
|
|
|
|
|
this.defaultSession = null;
|
|
|
|
this.sessions = new Map();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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);
|
2019-01-29 18:18:42 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
send(message) {
|
|
|
|
log.trace(`<-(connection ${this.id}) ${JSON.stringify(message)}`);
|
|
|
|
this.transport.send(message);
|
|
|
|
}
|
|
|
|
|
|
|
|
error(id, e) {
|
|
|
|
const error = {
|
|
|
|
message: e.message,
|
|
|
|
data: e.stack,
|
|
|
|
};
|
|
|
|
this.send({ id, error });
|
|
|
|
}
|
|
|
|
|
|
|
|
deserialize(data) {
|
|
|
|
const id = data.id;
|
|
|
|
const method = data.method;
|
|
|
|
const params = data.params || {};
|
|
|
|
return { id, method, params };
|
|
|
|
}
|
|
|
|
|
|
|
|
// transport hooks
|
|
|
|
|
|
|
|
onPacket(packet) {
|
|
|
|
log.trace(`(connection ${this.id})-> ${JSON.stringify(packet)}`);
|
|
|
|
|
|
|
|
let message = { id: null };
|
|
|
|
try {
|
|
|
|
message = this.deserialize(packet);
|
2019-03-11 15:48:05 +03:00
|
|
|
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);
|
|
|
|
}
|
2019-01-29 18:18:42 +03:00
|
|
|
} catch (e) {
|
|
|
|
log.warn(e);
|
|
|
|
this.error(message.id, e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-14 12:20:20 +03:00
|
|
|
close() {
|
|
|
|
this.transport.close();
|
2019-03-11 15:48:05 +03:00
|
|
|
this.sessions.clear();
|
2019-03-21 17:17:36 +03:00
|
|
|
|
|
|
|
// In addition to the WebSocket transport, we also have to close the Connection
|
|
|
|
// used internaly within httpd.js. Otherwise the server doesn't shut down correctly
|
|
|
|
// and keep these Connection instances alive.
|
|
|
|
this.httpdConnection.close();
|
2019-02-14 12:20:20 +03:00
|
|
|
}
|
|
|
|
|
2019-01-29 18:18:42 +03:00
|
|
|
onClosed(status) {}
|
|
|
|
|
|
|
|
toString() {
|
|
|
|
return `[object Connection ${this.id}]`;
|
|
|
|
}
|
2019-02-12 17:44:54 +03:00
|
|
|
}
|