Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/platform/browserView/electron-main/browserViewCDPTarget.ts
13397 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { Emitter } from '../../../base/common/event.js';
7
import { Disposable } from '../../../base/common/lifecycle.js';
8
import { CDPTargetInfo, ICDPConnection, ICDPTarget } from '../common/cdp/types.js';
9
import type { BrowserView } from './browserView.js';
10
11
/**
12
* Wraps a {@link BrowserViewDebugger} transport as an {@link ICDPTarget},
13
* tracking sessions and forwarding target-info changes for a single
14
* CDP target (page, worker, iframe, etc.).
15
*/
16
export class BrowserViewCDPTarget extends Disposable implements ICDPTarget {
17
protected readonly _sessions = new Map<string, ICDPConnection>();
18
get sessions(): ReadonlyMap<string, ICDPConnection> { return this._sessions; }
19
20
private readonly _onSessionCreated = this._register(new Emitter<{ session: ICDPConnection; waitingForDebugger: boolean }>());
21
readonly onSessionCreated = this._onSessionCreated.event;
22
23
private readonly _onClose = this._register(new Emitter<void>());
24
readonly onClose = this._onClose.event;
25
26
private readonly _onTargetInfoChanged = this._register(new Emitter<CDPTargetInfo>());
27
readonly onTargetInfoChanged = this._onTargetInfoChanged.event;
28
29
private _isDisposed = false;
30
31
constructor(
32
readonly view: BrowserView,
33
protected readonly _targetInfo: CDPTargetInfo
34
) {
35
super();
36
37
this._register(this.view.debugger.onTargetInfoChanged(info => {
38
if (info.targetId !== this._targetInfo.targetId) {
39
return;
40
}
41
42
if (info.title !== this._targetInfo.title || info.url !== this._targetInfo.url) {
43
this._targetInfo.title = info.title;
44
this._targetInfo.url = info.url;
45
this._onTargetInfoChanged.fire(this.targetInfo);
46
}
47
}));
48
49
this._register(this.view.debugger.onTargetDestroyed(targetId => {
50
if (targetId === this._targetInfo.targetId) {
51
this.dispose();
52
}
53
}));
54
}
55
56
get targetInfo(): CDPTargetInfo {
57
return {
58
...this._targetInfo,
59
attached: this._sessions.size > 0,
60
browserContextId: this.view.session.id
61
};
62
}
63
64
async attach(): Promise<ICDPConnection> {
65
const session = await this.view.debugger.attachToTarget(this.targetInfo.targetId);
66
this.notifySessionCreated(session, false);
67
return session;
68
}
69
70
notifySessionCreated(session: ICDPConnection, waitingForDebugger: boolean): void {
71
if (this._sessions.has(session.sessionId)) {
72
return;
73
}
74
if (this.sessions.size === 0) {
75
// First session attached, update target info to reflect attached state.
76
this._onTargetInfoChanged.fire(this.targetInfo);
77
}
78
79
this._sessions.set(session.sessionId, session);
80
session.onClose(() => {
81
this._sessions.delete(session.sessionId);
82
if (this.sessions.size === 0) {
83
// Last session detached, update target info to reflect detached state.
84
this._onTargetInfoChanged.fire(this.targetInfo);
85
}
86
});
87
88
this._onSessionCreated.fire({ session, waitingForDebugger });
89
}
90
91
override dispose(): void {
92
if (this._isDisposed) {
93
return;
94
}
95
this._isDisposed = true;
96
97
// Dispose owned sessions.
98
for (const [, session] of this._sessions) {
99
session.dispose();
100
}
101
this._sessions.clear();
102
103
// Signal target closure.
104
this._onClose.fire();
105
106
super.dispose();
107
}
108
}
109
110