"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CdpTarget = void 0; const Deferred_js_1 = require("../../../utils/Deferred.js"); const LogManager_js_1 = require("../log/LogManager.js"); const NetworkManager_js_1 = require("../network/NetworkManager.js"); class CdpTarget { #targetId; #cdpClient; #cdpSessionId; #eventManager; #preloadScriptStorage; #networkStorage; #targetUnblocked = new Deferred_js_1.Deferred(); static create(targetId, cdpClient, cdpSessionId, realmStorage, eventManager, preloadScriptStorage, networkStorage) { const cdpTarget = new CdpTarget(targetId, cdpClient, cdpSessionId, eventManager, preloadScriptStorage, networkStorage); LogManager_js_1.LogManager.create(cdpTarget, realmStorage, eventManager); NetworkManager_js_1.NetworkManager.create(cdpTarget, networkStorage); cdpTarget.#setEventListeners(); // No need to await. // Deferred will be resolved when the target is unblocked. void cdpTarget.#unblock(); return cdpTarget; } constructor(targetId, cdpClient, cdpSessionId, eventManager, preloadScriptStorage, networkStorage) { this.#targetId = targetId; this.#cdpClient = cdpClient; this.#cdpSessionId = cdpSessionId; this.#eventManager = eventManager; this.#preloadScriptStorage = preloadScriptStorage; this.#networkStorage = networkStorage; } /** Returns a promise that resolves when the target is unblocked. */ get targetUnblocked() { return this.#targetUnblocked; } get targetId() { return this.#targetId; } get cdpClient() { return this.#cdpClient; } /** Needed for CDP escape path. */ get cdpSessionId() { return this.#cdpSessionId; } /** Calls `Fetch.enable` with the added network intercepts. */ async fetchEnable() { await this.#cdpClient.sendCommand('Fetch.enable', this.#networkStorage.getFetchEnableParams()); } /** Calls `Fetch.disable`. */ async fetchDisable() { await this.#cdpClient.sendCommand('Fetch.disable'); } /** * Calls `Fetch.disable` followed by `Fetch.enable`. * The order is important. Do not use `Promise.all`. * * This is necessary because `Fetch.disable` removes all intercepts. * In a situation where there are two or more intercepts and one of them is * removed, the `Fetch.enable` call will restore the remaining intercepts. */ async fetchApply() { await this.fetchDisable(); await this.fetchEnable(); } /** * Enables all the required CDP domains and unblocks the target. */ async #unblock() { try { await Promise.all([ this.#cdpClient.sendCommand('Runtime.enable'), this.#cdpClient.sendCommand('Page.enable'), this.#cdpClient.sendCommand('Page.setLifecycleEventsEnabled', { enabled: true, }), // XXX: #1080: Do not always enable the network domain globally. // TODO: enable Network domain for OOPiF targets. this.#cdpClient.sendCommand('Network.enable'), this.fetchApply(), this.#cdpClient.sendCommand('Target.setAutoAttach', { autoAttach: true, waitForDebuggerOnStart: true, flatten: true, }), this.#initAndEvaluatePreloadScripts(), this.#cdpClient.sendCommand('Runtime.runIfWaitingForDebugger'), ]); } catch (error) { // The target might have been closed before the initialization finished. if (!this.#cdpClient.isCloseError(error)) { this.#targetUnblocked.resolve({ kind: 'error', error, }); return; } } this.#targetUnblocked.resolve({ kind: 'success', value: undefined, }); } #setEventListeners() { this.#cdpClient.on('*', (event, params) => { // We may encounter uses for EventEmitter other than CDP events, // which we want to skip. if (typeof event !== 'string') { return; } this.#eventManager.registerEvent({ type: 'event', method: `cdp.${event}`, params: { event, params, session: this.#cdpSessionId, }, }, null); }); } /** * All the ProxyChannels from all the preload scripts of the given * BrowsingContext. */ getChannels() { return this.#preloadScriptStorage .find() .flatMap((script) => script.channels); } /** Loads all top-level preload scripts. */ async #initAndEvaluatePreloadScripts() { for (const script of this.#preloadScriptStorage.find()) { await script.initInTarget(this, true); } } } exports.CdpTarget = CdpTarget; //# sourceMappingURL=CdpTarget.js.map