Bug 1806130 [wpt PR 37556] - URL: hash/search roundtripping with opaque paths, a...
[gecko.git] / remote / shared / WebSocketConnection.sys.mjs
blob2ce8ca2cddbdd5857feed9600370dbebb1b6eab8
1 /* This Source Code Form is subject to the terms of the Mozilla Public
3  * License, v. 2.0. If a copy of the MPL was not distributed with this
4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
8 const lazy = {};
10 ChromeUtils.defineESModuleGetters(lazy, {
11   Log: "chrome://remote/content/shared/Log.sys.mjs",
12   truncate: "chrome://remote/content/shared/Format.sys.mjs",
13   WebSocketTransport:
14     "chrome://remote/content/server/WebSocketTransport.sys.mjs",
15 });
17 XPCOMUtils.defineLazyGetter(lazy, "logger", () => lazy.Log.get());
19 export class WebSocketConnection {
20   /**
21    * @param {WebSocket} webSocket
22    *     The WebSocket server connection to wrap.
23    * @param {Connection} httpdConnection
24    *     Reference to the httpd.js's connection needed for clean-up.
25    */
26   constructor(webSocket, httpdConnection) {
27     this.id = Services.uuid
28       .generateUUID()
29       .toString()
30       .slice(1, -1);
32     this.httpdConnection = httpdConnection;
34     this.transport = new lazy.WebSocketTransport(webSocket);
35     this.transport.hooks = this;
36     this.transport.ready();
38     lazy.logger.debug(`${this.constructor.name} ${this.id} accepted`);
39   }
41   _log(direction, data) {
42     function replacer(key, value) {
43       if (typeof value === "string") {
44         return lazy.truncate`${value}`;
45       }
46       return value;
47     }
49     const payload = JSON.stringify(
50       data,
51       replacer,
52       lazy.Log.verbose ? "\t" : null
53     );
55     lazy.logger.trace(
56       `${this.constructor.name} ${this.id} ${direction} ${payload}`
57     );
58   }
60   /**
61    * Close the WebSocket connection.
62    */
63   close() {
64     this.transport.close();
66     // In addition to the WebSocket transport, we also have to close the
67     // connection used internally within httpd.js. Otherwise the server doesn't
68     // shut down correctly, and keeps these Connection instances alive.
69     this.httpdConnection.close();
70   }
72   /**
73    * Register a new Session to forward the messages to.
74    *
75    * Needs to be implemented in the sub class.
76    *
77    * @param Session session
78    *     The session to register.
79    */
80   registerSession(session) {
81     throw new Error("Not implemented");
82   }
84   /**
85    * Send the JSON-serializable object to the client.
86    *
87    * @param {Object} data
88    *     The object to be sent.
89    */
90   send(data) {
91     this._log("<-", data);
92     this.transport.send(data);
93   }
95   /**
96    * Send an error back to the client.
97    *
98    * Needs to be implemented in the sub class.
99    */
100   sendError() {
101     throw new Error("Not implemented");
102   }
104   /**
105    * Send an event back to the client.
106    *
107    * Needs to be implemented in the sub class.
108    */
109   sendEvent() {
110     throw new Error("Not implemented");
111   }
113   /**
114    * Send the result of a call to a method back to the client.
115    *
116    * Needs to be implemented in the sub class.
117    */
118   sendResult() {
119     throw new Error("Not implemented");
120   }
122   toString() {
123     return `[object ${this.constructor.name} ${this.id}]`;
124   }
126   // Transport hooks
128   /**
129    * Called by the `transport` when the connection is closed.
130    */
131   onClosed(status) {
132     lazy.logger.debug(`${this.constructor.name} ${this.id} closed`);
133   }
135   /**
136    * Receive a packet from the WebSocket layer.
137    *
138    * This packet is sent by a WebSocket client and is meant to execute
139    * a particular method.
140    *
141    * Needs to be implemented in the sub class.
142    *
143    * @param {Object} packet
144    *     JSON-serializable object sent by the client.
145    */
146   async onPacket(packet) {
147     this._log("->", packet);
148   }