Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/platform/browserView/node/playwrightChannel.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 { Event } from '../../../base/common/event.js';
7
import { Disposable, DisposableMap } from '../../../base/common/lifecycle.js';
8
import { IPCServer, IServerChannel } from '../../../base/parts/ipc/common/ipc.js';
9
import { IMainProcessService } from '../../ipc/common/mainProcessService.js';
10
import { ILogService } from '../../log/common/log.js';
11
import { IAgentNetworkFilterService } from '../../networkFilter/common/networkFilterService.js';
12
import { BrowserViewGroupRemoteService } from './browserViewGroupRemoteService.js';
13
import { PlaywrightService } from './playwrightService.js';
14
15
/**
16
* IPC channel for the Playwright service.
17
*
18
* Each connected window gets its own {@link PlaywrightService},
19
* keyed by the opaque IPC connection context. The client sends an
20
* `__initialize` call with its numeric window ID before any other
21
* method calls, which eagerly creates the instance. When a window
22
* disconnects the instance is automatically disposed.
23
*/
24
export class PlaywrightChannel extends Disposable implements IServerChannel<string> {
25
26
private readonly _instances = this._register(new DisposableMap<string, PlaywrightService>());
27
private readonly browserViewGroupRemoteService: BrowserViewGroupRemoteService;
28
29
constructor(
30
ipcServer: IPCServer<string>,
31
mainProcessService: IMainProcessService,
32
private readonly logService: ILogService,
33
private readonly agentNetworkFilterService: IAgentNetworkFilterService,
34
) {
35
super();
36
this.browserViewGroupRemoteService = new BrowserViewGroupRemoteService(mainProcessService);
37
this._register(ipcServer.onDidRemoveConnection(c => {
38
this._instances.deleteAndDispose(c.ctx);
39
}));
40
}
41
42
listen<T>(ctx: string, event: string): Event<T> {
43
const instance = this._instances.get(ctx);
44
if (!instance) {
45
throw new Error(`Window not initialized for context: ${ctx}`);
46
}
47
const source = (instance as unknown as Record<string, Event<unknown>>)[event];
48
if (typeof source !== 'function') {
49
throw new Error(`Event not found: ${event}`);
50
}
51
return source as Event<T>;
52
}
53
54
call<T>(ctx: string, command: string, arg?: unknown): Promise<T> {
55
// Handle the one-time initialization call that creates the instance
56
if (command === '__initialize') {
57
if (typeof arg !== 'number') {
58
throw new Error(`Invalid argument for __initialize: expected window ID as number, got ${typeof arg}`);
59
}
60
if (!this._instances.has(ctx)) {
61
const windowId = arg as number;
62
this._instances.set(ctx, new PlaywrightService(windowId, this.browserViewGroupRemoteService, this.logService, this.agentNetworkFilterService));
63
}
64
return Promise.resolve(undefined as T);
65
}
66
67
const instance = this._instances.get(ctx);
68
if (!instance) {
69
throw new Error(`Window not initialized for context: ${ctx}`);
70
}
71
72
const target = (instance as unknown as Record<string, unknown>)[command];
73
if (typeof target !== 'function') {
74
throw new Error(`Method not found: ${command}`);
75
}
76
77
const methodArgs = Array.isArray(arg) ? arg : [];
78
let res = target.apply(instance, methodArgs);
79
if (!(res instanceof Promise)) {
80
res = Promise.resolve(res);
81
}
82
return res;
83
}
84
}
85
86