Path: blob/main/src/vs/platform/browserView/electron-main/browserViewCDPTarget.ts
13397 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { Emitter } from '../../../base/common/event.js';6import { Disposable } from '../../../base/common/lifecycle.js';7import { CDPTargetInfo, ICDPConnection, ICDPTarget } from '../common/cdp/types.js';8import type { BrowserView } from './browserView.js';910/**11* Wraps a {@link BrowserViewDebugger} transport as an {@link ICDPTarget},12* tracking sessions and forwarding target-info changes for a single13* CDP target (page, worker, iframe, etc.).14*/15export class BrowserViewCDPTarget extends Disposable implements ICDPTarget {16protected readonly _sessions = new Map<string, ICDPConnection>();17get sessions(): ReadonlyMap<string, ICDPConnection> { return this._sessions; }1819private readonly _onSessionCreated = this._register(new Emitter<{ session: ICDPConnection; waitingForDebugger: boolean }>());20readonly onSessionCreated = this._onSessionCreated.event;2122private readonly _onClose = this._register(new Emitter<void>());23readonly onClose = this._onClose.event;2425private readonly _onTargetInfoChanged = this._register(new Emitter<CDPTargetInfo>());26readonly onTargetInfoChanged = this._onTargetInfoChanged.event;2728private _isDisposed = false;2930constructor(31readonly view: BrowserView,32protected readonly _targetInfo: CDPTargetInfo33) {34super();3536this._register(this.view.debugger.onTargetInfoChanged(info => {37if (info.targetId !== this._targetInfo.targetId) {38return;39}4041if (info.title !== this._targetInfo.title || info.url !== this._targetInfo.url) {42this._targetInfo.title = info.title;43this._targetInfo.url = info.url;44this._onTargetInfoChanged.fire(this.targetInfo);45}46}));4748this._register(this.view.debugger.onTargetDestroyed(targetId => {49if (targetId === this._targetInfo.targetId) {50this.dispose();51}52}));53}5455get targetInfo(): CDPTargetInfo {56return {57...this._targetInfo,58attached: this._sessions.size > 0,59browserContextId: this.view.session.id60};61}6263async attach(): Promise<ICDPConnection> {64const session = await this.view.debugger.attachToTarget(this.targetInfo.targetId);65this.notifySessionCreated(session, false);66return session;67}6869notifySessionCreated(session: ICDPConnection, waitingForDebugger: boolean): void {70if (this._sessions.has(session.sessionId)) {71return;72}73if (this.sessions.size === 0) {74// First session attached, update target info to reflect attached state.75this._onTargetInfoChanged.fire(this.targetInfo);76}7778this._sessions.set(session.sessionId, session);79session.onClose(() => {80this._sessions.delete(session.sessionId);81if (this.sessions.size === 0) {82// Last session detached, update target info to reflect detached state.83this._onTargetInfoChanged.fire(this.targetInfo);84}85});8687this._onSessionCreated.fire({ session, waitingForDebugger });88}8990override dispose(): void {91if (this._isDisposed) {92return;93}94this._isDisposed = true;9596// Dispose owned sessions.97for (const [, session] of this._sessions) {98session.dispose();99}100this._sessions.clear();101102// Signal target closure.103this._onClose.fire();104105super.dispose();106}107}108109110