summaryrefslogtreecommitdiffstats
path: root/devtools/client/shared/remote-debugging/remote-client-manager.js
diff options
context:
space:
mode:
Diffstat (limited to 'devtools/client/shared/remote-debugging/remote-client-manager.js')
-rw-r--r--devtools/client/shared/remote-debugging/remote-client-manager.js146
1 files changed, 146 insertions, 0 deletions
diff --git a/devtools/client/shared/remote-debugging/remote-client-manager.js b/devtools/client/shared/remote-debugging/remote-client-manager.js
new file mode 100644
index 0000000000..45e7a1be4a
--- /dev/null
+++ b/devtools/client/shared/remote-debugging/remote-client-manager.js
@@ -0,0 +1,146 @@
+/* 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";
+
+const {
+ CONNECTION_TYPES,
+} = require("resource://devtools/client/shared/remote-debugging/constants.js");
+
+/**
+ * This class is designed to be a singleton shared by all DevTools to get access to
+ * existing clients created for remote debugging.
+ */
+class RemoteClientManager {
+ constructor() {
+ this._clients = new Map();
+ this._runtimeInfoMap = new Map();
+ this._onClientClosed = this._onClientClosed.bind(this);
+ }
+
+ /**
+ * Store a remote client that is already connected.
+ *
+ * @param {String} id
+ * Remote runtime id (see devtools/client/aboutdebugging/src/types).
+ * @param {String} type
+ * Remote runtime type (see devtools/client/aboutdebugging/src/types).
+ * @param {DevToolsClient} client
+ * @param {Object} runtimeInfo
+ * See runtimeInfo type from client/aboutdebugging/src/types/runtime.js
+ */
+ setClient(id, type, client, runtimeInfo) {
+ const key = this._getKey(id, type);
+ this._clients.set(key, client);
+ if (runtimeInfo) {
+ this._runtimeInfoMap.set(key, runtimeInfo);
+ }
+ client.once("closed", this._onClientClosed);
+ }
+
+ // See JSDoc for id, type from setClient.
+ hasClient(id, type) {
+ return this._clients.has(this._getKey(id, type));
+ }
+
+ // See JSDoc for id, type from setClient.
+ getClient(id, type) {
+ return this._clients.get(this._getKey(id, type));
+ }
+
+ // See JSDoc for id, type from setClient.
+ removeClient(id, type) {
+ const key = this._getKey(id, type);
+ this._removeClientByKey(key);
+ }
+
+ removeAllClients() {
+ const keys = [...this._clients.keys()];
+ for (const key of keys) {
+ this._removeClientByKey(key);
+ }
+ }
+
+ /**
+ * Retrieve a unique, url-safe key based on a runtime id and type.
+ */
+ getRemoteId(id, type) {
+ return encodeURIComponent(this._getKey(id, type));
+ }
+
+ /**
+ * Retrieve a managed client for a remote id. The remote id should have been generated
+ * using getRemoteId.
+ */
+ getClientByRemoteId(remoteId) {
+ const key = this._getKeyByRemoteId(remoteId);
+ return this._clients.get(key);
+ }
+
+ /**
+ * Retrieve the runtime info for a remote id. To display metadata about a runtime, such
+ * as name, device name, version... this runtimeInfo should be used rather than calling
+ * APIs on the client.
+ */
+ getRuntimeInfoByRemoteId(remoteId) {
+ const key = this._getKeyByRemoteId(remoteId);
+ return this._runtimeInfoMap.get(key);
+ }
+
+ /**
+ * Retrieve a managed client for a remote id. The remote id should have been generated
+ * using getRemoteId.
+ */
+ getConnectionTypeByRemoteId(remoteId) {
+ const key = this._getKeyByRemoteId(remoteId);
+ for (const type of Object.values(CONNECTION_TYPES)) {
+ if (key.endsWith(type)) {
+ return type;
+ }
+ }
+ return CONNECTION_TYPES.UNKNOWN;
+ }
+
+ _getKey(id, type) {
+ return id + "-" + type;
+ }
+
+ _getKeyByRemoteId(remoteId) {
+ if (!remoteId) {
+ // If no remote id was provided, return the key corresponding to the local
+ // this-firefox runtime.
+ const { THIS_FIREFOX } = CONNECTION_TYPES;
+ return this._getKey(THIS_FIREFOX, THIS_FIREFOX);
+ }
+
+ return decodeURIComponent(remoteId);
+ }
+
+ _removeClientByKey(key) {
+ const client = this._clients.get(key);
+ if (client) {
+ client.off("closed", this._onClientClosed);
+ this._clients.delete(key);
+ this._runtimeInfoMap.delete(key);
+ }
+ }
+
+ /**
+ * Cleanup all closed clients when a "closed" notification is received from a client.
+ */
+ _onClientClosed() {
+ const closedClientKeys = [...this._clients.keys()].filter(key => {
+ return this._clients.get(key)._transportClosed;
+ });
+
+ for (const key of closedClientKeys) {
+ this._removeClientByKey(key);
+ }
+ }
+}
+
+// Expose a singleton of RemoteClientManager.
+module.exports = {
+ remoteClientManager: new RemoteClientManager(),
+};