diff options
Diffstat (limited to 'devtools/client/shared/remote-debugging/remote-client-manager.js')
-rw-r--r-- | devtools/client/shared/remote-debugging/remote-client-manager.js | 146 |
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(), +}; |