commit 1f5b7af922d6107dbf486213cae427a0ee0a93bf
parent 518739908a77156140f309e269ba850fb5fe9807
Author: Lorenz A <me@lorenzackermann.xyz>
Date: Tue, 16 Dec 2025 08:43:38 +0000
Bug 2004229 - [devtools] Turn devtools/shared/security/socket.js into an ES class. r=devtools-reviewers,nchevobbe
Differential Revision: https://phabricator.services.mozilla.com/D276566
Diffstat:
1 file changed, 115 insertions(+), 114 deletions(-)
diff --git a/devtools/shared/security/socket.js b/devtools/shared/security/socket.js
@@ -76,41 +76,41 @@ DevToolsUtils.defineLazyGetter(this, "socketTransportService", () => {
);
});
-var DebuggerSocket = {};
-
-/**
- * Connects to a devtools server socket.
- *
- * @param host string
- * The host name or IP address of the devtools server.
- * @param port number
- * The port number of the devtools server.
- * @param webSocket boolean (optional)
- * Whether to use WebSocket protocol to connect. Defaults to false.
- * @param authenticator Authenticator (optional)
- * |Authenticator| instance matching the mode in use by the server.
- * Defaults to a PROMPT instance if not supplied.
- * @return promise
- * Resolved to a DebuggerTransport instance.
- */
-DebuggerSocket.connect = async function (settings) {
- // Default to PROMPT |Authenticator| instance if not supplied
- if (!settings.authenticator) {
- settings.authenticator = new (Authenticators.get().Client)();
- }
- _validateSettings(settings);
- // eslint-disable-next-line no-shadow
- const { host, port, authenticator } = settings;
- const transport = await _getTransport(settings);
- await authenticator.authenticate({
- host,
- port,
- transport,
- });
- transport.connectionSettings = settings;
- return transport;
-};
-
+class DebuggerSocket {
+ /**
+ * Connects to a devtools server socket.
+ *
+ * @param {object} settings
+ * @param {string} settings.host
+ * The host name or IP address of the devtools server.
+ * @param {number} settings.port
+ * The port number of the devtools server.
+ * @param {boolean} [settings.webSocket]
+ * Whether to use WebSocket protocol to connect. Defaults to false.
+ * @param {Authenticator} [settings.authenticator]
+ * |Authenticator| instance matching the mode in use by the server.
+ * Defaults to a PROMPT instance if not supplied.
+ * @return {Promise}
+ * Resolved to a DebuggerTransport instance.
+ */
+ static async connect(settings) {
+ // Default to PROMPT |Authenticator| instance if not supplied
+ if (!settings.authenticator) {
+ settings.authenticator = new (Authenticators.get().Client)();
+ }
+ _validateSettings(settings);
+ // eslint-disable-next-line no-shadow
+ const { host, port, authenticator } = settings;
+ const transport = await _getTransport(settings);
+ await authenticator.authenticate({
+ host,
+ port,
+ transport,
+ });
+ transport.connectionSettings = settings;
+ return transport;
+ }
+}
/**
* Validate that the connection settings have been set to a supported configuration.
*/
@@ -314,68 +314,69 @@ function _isInputAlive(input) {
* are particular to one given listener mechanism vs. another.
* This can be closed at any later time by calling |close|.
* If remote connections are disabled, an error is thrown.
- *
- * @param {DevToolsServer} devToolsServer
- * @param {object} socketOptions
- * options of socket as follows
- * {
- * authenticator:
- * Controls the |Authenticator| used, which hooks various socket steps to
- * implement an authentication policy. It is expected that different use
- * cases may override pieces of the |Authenticator|. See auth.js.
- * We set the default |Authenticator|, which is |Prompt|.
- * discoverable:
- * Controls whether this listener is announced via the service discovery
- * mechanism. Defaults is false.
- * fromBrowserToolbox:
- * Should only be passed when opening a socket for a Browser Toolbox
- * session. DevToolsSocketStatus will track the socket separately to
- * avoid triggering the visual cue in the URL bar.
- * portOrPath:
- * The port or path to listen on.
- * If given an integer, the port to listen on. Use -1 to choose any available
- * port. Otherwise, the path to the unix socket domain file to listen on.
- * Defaults is null.
- * webSocket:
- * Whether to use WebSocket protocol. Defaults is false.
- * }
*/
-function SocketListener(devToolsServer, socketOptions) {
- this._devToolsServer = devToolsServer;
-
- // Set socket options with default value
- this._socketOptions = {
- authenticator:
- socketOptions.authenticator || new (Authenticators.get().Server)(),
- discoverable: !!socketOptions.discoverable,
- fromBrowserToolbox: !!socketOptions.fromBrowserToolbox,
- portOrPath: socketOptions.portOrPath || null,
- webSocket: !!socketOptions.webSocket,
- };
-
- EventEmitter.decorate(this);
-}
+class SocketListener extends EventEmitter {
+ /**
+ * @param {DevToolsServer} devToolsServer
+ * @param {object} socketOptions
+ * options of socket as follows
+ * {
+ * authenticator:
+ * Controls the |Authenticator| used, which hooks various socket steps to
+ * implement an authentication policy. It is expected that different use
+ * cases may override pieces of the |Authenticator|. See auth.js.
+ * We set the default |Authenticator|, which is |Prompt|.
+ * discoverable:
+ * Controls whether this listener is announced via the service discovery
+ * mechanism. Defaults is false.
+ * fromBrowserToolbox:
+ * Should only be passed when opening a socket for a Browser Toolbox
+ * session. DevToolsSocketStatus will track the socket separately to
+ * avoid triggering the visual cue in the URL bar.
+ * portOrPath:
+ * The port or path to listen on.
+ * If given an integer, the port to listen on. Use -1 to choose any available
+ * port. Otherwise, the path to the unix socket domain file to listen on.
+ * Defaults is null.
+ * webSocket:
+ * Whether to use WebSocket protocol. Defaults is false.
+ * }
+ */
+ constructor(devToolsServer, socketOptions) {
+ super();
+
+ this._devToolsServer = devToolsServer;
+
+ // Set socket options with default value
+ this._socketOptions = {
+ authenticator:
+ socketOptions.authenticator || new (Authenticators.get().Server)(),
+ discoverable: !!socketOptions.discoverable,
+ fromBrowserToolbox: !!socketOptions.fromBrowserToolbox,
+ portOrPath: socketOptions.portOrPath || null,
+ webSocket: !!socketOptions.webSocket,
+ };
+ }
-SocketListener.prototype = {
get authenticator() {
return this._socketOptions.authenticator;
- },
+ }
get discoverable() {
return this._socketOptions.discoverable;
- },
+ }
get fromBrowserToolbox() {
return this._socketOptions.fromBrowserToolbox;
- },
+ }
get portOrPath() {
return this._socketOptions.portOrPath;
- },
+ }
get webSocket() {
return this._socketOptions.webSocket;
- },
+ }
/**
* Validate that all options have been set to a supported configuration.
@@ -387,7 +388,7 @@ SocketListener.prototype = {
if (this.discoverable && !Number(this.portOrPath)) {
throw new Error("Discovery only supported for TCP sockets.");
}
- },
+ }
/**
* Listens on the given port or socket file for remote debugger connections.
@@ -437,7 +438,7 @@ SocketListener.prototype = {
);
this.close();
});
- },
+ }
_advertise() {
if (!this.discoverable || !this.port) {
@@ -451,13 +452,13 @@ SocketListener.prototype = {
this.authenticator.augmentAdvertisement(this, advertisement);
discovery.addService("devtools", advertisement);
- },
+ }
_createSocketInstance() {
return Cc["@mozilla.org/network/server-socket;1"].createInstance(
Ci.nsIServerSocket
);
- },
+ }
/**
* Closes the SocketListener. Notifies the server to remove the listener from
@@ -476,7 +477,7 @@ SocketListener.prototype = {
});
}
this._devToolsServer.removeSocketListener(this);
- },
+ }
get host() {
if (!this._socket) {
@@ -486,14 +487,14 @@ SocketListener.prototype = {
return "127.0.0.1";
}
return "0.0.0.0";
- },
+ }
/**
* Gets whether this listener uses a port number vs. a path.
*/
get isPortBased() {
return !!Number(this.portOrPath);
- },
+ }
/**
* Gets the port that a TCP socket listener is listening on, or null if this
@@ -504,55 +505,55 @@ SocketListener.prototype = {
return null;
}
return this._socket.port;
- },
+ }
onAllowedConnection(transport) {
dumpn("onAllowedConnection, transport: " + transport);
this.emit("accepted", transport, this);
- },
+ }
// nsIServerSocketListener implementation
- onSocketAccepted: DevToolsUtils.makeInfallible(function (
+ onSocketAccepted = DevToolsUtils.makeInfallible(function (
socket,
socketTransport
) {
const connection = new ServerSocketConnection(this, socketTransport);
connection.once("allowed", this.onAllowedConnection.bind(this));
- }, "SocketListener.onSocketAccepted"),
+ }, "SocketListener.onSocketAccepted");
onStopListening(socket, status) {
dumpn("onStopListening, status: " + status);
- },
-};
+ }
+}
/**
* A |ServerSocketConnection| is created by a |SocketListener| for each accepted
* incoming socket.
*/
-function ServerSocketConnection(listener, socketTransport) {
- this._listener = listener;
- this._socketTransport = socketTransport;
- this._handle();
- EventEmitter.decorate(this);
-}
+class ServerSocketConnection extends EventEmitter {
+ constructor(listener, socketTransport) {
+ super();
-ServerSocketConnection.prototype = {
+ this._listener = listener;
+ this._socketTransport = socketTransport;
+ this._handle();
+ }
get authentication() {
return this._listener.authenticator.mode;
- },
+ }
get host() {
return this._socketTransport.host;
- },
+ }
get port() {
return this._socketTransport.port;
- },
+ }
get address() {
return this.host + ":" + this.port;
- },
+ }
get client() {
const client = {
@@ -560,7 +561,7 @@ ServerSocketConnection.prototype = {
port: this.port,
};
return client;
- },
+ }
get server() {
const server = {
@@ -568,7 +569,7 @@ ServerSocketConnection.prototype = {
port: this._listener.port,
};
return server;
- },
+ }
/**
* This is the main authentication workflow. If any pieces reject a promise,
@@ -584,7 +585,7 @@ ServerSocketConnection.prototype = {
} catch (e) {
this.deny(e);
}
- },
+ }
/**
* We need to open the streams early on, as that is required in the case of
@@ -613,7 +614,7 @@ ServerSocketConnection.prototype = {
},
};
this._transport.ready();
- },
+ }
async _authenticate() {
const result = await this._listener.authenticator.authenticate({
@@ -638,7 +639,7 @@ ServerSocketConnection.prototype = {
// If we got an error (DISABLE_ALL, DENY, …), let's throw a NS_ERROR_CONNECTION_REFUSED
// exception
throw Components.Exception("", Cr.NS_ERROR_CONNECTION_REFUSED);
- },
+ }
deny(result) {
if (this._destroyed) {
@@ -660,7 +661,7 @@ ServerSocketConnection.prototype = {
}
this._socketTransport.close(result);
this.destroy();
- },
+ }
allow() {
if (this._destroyed) {
@@ -669,15 +670,15 @@ ServerSocketConnection.prototype = {
dumpn("Debugging connection allowed on " + this.address);
this.emit("allowed", this._transport);
this.destroy();
- },
+ }
destroy() {
this._destroyed = true;
this._listener = null;
this._socketTransport = null;
this._transport = null;
- },
-};
+ }
+}
exports.DebuggerSocket = DebuggerSocket;
exports.SocketListener = SocketListener;