| "use strict"; |
| var _a; |
| Object.defineProperty(exports, "__esModule", { value: true }); |
| exports.MapperCdpConnection = void 0; |
| const log_js_1 = require("../utils/log.js"); |
| const CdpClient_js_1 = require("./CdpClient.js"); |
| /** |
| * Represents a high-level CDP connection to the browser backend. |
| * |
| * Manages all CdpClients (each backed by a Session ID) instance for each active |
| * CDP session. |
| */ |
| class MapperCdpConnection { |
| static LOGGER_PREFIX_RECV = `${log_js_1.LogType.cdp}:RECV ◂`; |
| static LOGGER_PREFIX_SEND = `${log_js_1.LogType.cdp}:SEND ▸`; |
| #mainBrowserCdpClient; |
| #transport; |
| /** Map from session ID to CdpClient. |
| * `undefined` points to the main browser session. */ |
| #sessionCdpClients = new Map(); |
| #commandCallbacks = new Map(); |
| #logger; |
| #nextId = 0; |
| constructor(transport, logger) { |
| this.#transport = transport; |
| this.#logger = logger; |
| this.#transport.setOnMessage(this.#onMessage); |
| // Create default Browser CDP Session. |
| this.#mainBrowserCdpClient = this.#createCdpClient(undefined); |
| } |
| /** Closes the connection to the browser. */ |
| close() { |
| this.#transport.close(); |
| for (const [, { reject, error }] of this.#commandCallbacks) { |
| reject(error); |
| } |
| this.#commandCallbacks.clear(); |
| this.#sessionCdpClients.clear(); |
| } |
| async createBrowserSession() { |
| const { sessionId } = await this.#mainBrowserCdpClient.sendCommand('Target.attachToBrowserTarget'); |
| return this.#createCdpClient(sessionId); |
| } |
| /** |
| * Gets a CdpClient instance attached to the given session ID, |
| * or null if the session is not attached. |
| */ |
| getCdpClient(sessionId) { |
| const cdpClient = this.#sessionCdpClients.get(sessionId); |
| if (!cdpClient) { |
| throw new Error(`Unknown CDP session ID: ${sessionId}`); |
| } |
| return cdpClient; |
| } |
| sendCommand(method, params, sessionId) { |
| return new Promise((resolve, reject) => { |
| const id = this.#nextId++; |
| this.#commandCallbacks.set(id, { |
| sessionId, |
| resolve, |
| reject, |
| error: new CdpClient_js_1.CloseError(`${method} ${JSON.stringify(params)} ${sessionId ?? ''} call rejected because the connection has been closed.`), |
| }); |
| const cdpMessage = { id, method, params }; |
| if (sessionId) { |
| cdpMessage.sessionId = sessionId; |
| } |
| void this.#transport |
| .sendMessage(JSON.stringify(cdpMessage)) |
| ?.catch((error) => { |
| this.#logger?.(log_js_1.LogType.debugError, error); |
| this.#transport.close(); |
| }); |
| this.#logger?.(_a.LOGGER_PREFIX_SEND, cdpMessage); |
| }); |
| } |
| #onMessage = (json) => { |
| const message = JSON.parse(json); |
| this.#logger?.(_a.LOGGER_PREFIX_RECV, message); |
| // Update client map if a session is attached |
| // Listen for these events on every session. |
| if (message.method === 'Target.attachedToTarget') { |
| const { sessionId } = message.params; |
| this.#createCdpClient(sessionId); |
| } |
| if (message.id !== undefined) { |
| // Handle command response. |
| const callbacks = this.#commandCallbacks.get(message.id); |
| this.#commandCallbacks.delete(message.id); |
| if (callbacks) { |
| if (message.result) { |
| callbacks.resolve(message.result); |
| } |
| else if (message.error) { |
| callbacks.reject(message.error); |
| } |
| } |
| } |
| else if (message.method) { |
| const client = this.#sessionCdpClients.get(message.sessionId ?? undefined); |
| client?.emit(message.method, message.params || {}); |
| // Update client map if a session is detached |
| // But emit on that session |
| if (message.method === 'Target.detachedFromTarget') { |
| const { sessionId } = message.params; |
| const client = this.#sessionCdpClients.get(sessionId); |
| if (client) { |
| this.#sessionCdpClients.delete(sessionId); |
| client.removeAllListeners(); |
| } |
| // Reject all the pending commands for the detached session. |
| for (const callback of this.#commandCallbacks.values()) { |
| if (callback.sessionId === sessionId) { |
| callback.reject(callback.error); |
| } |
| } |
| } |
| } |
| }; |
| /** |
| * Creates a new CdpClient instance for the given session ID. |
| * @param sessionId either a string, or undefined for the main browser session. |
| * The main browser session is used only to create new browser sessions. |
| * @private |
| */ |
| #createCdpClient(sessionId) { |
| const cdpClient = new CdpClient_js_1.MapperCdpClient(this, sessionId); |
| this.#sessionCdpClients.set(sessionId, cdpClient); |
| return cdpClient; |
| } |
| } |
| exports.MapperCdpConnection = MapperCdpConnection; |
| _a = MapperCdpConnection; |
| //# sourceMappingURL=CdpConnection.js.map |