Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/platform/diagnostics/electron-main/diagnosticsMainService.ts
3294 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 { app, BrowserWindow, Event as IpcEvent } from 'electron';
7
import { validatedIpcMain } from '../../../base/parts/ipc/electron-main/ipcMain.js';
8
import { CancellationToken } from '../../../base/common/cancellation.js';
9
import { URI } from '../../../base/common/uri.js';
10
import { IDiagnosticInfo, IDiagnosticInfoOptions, IMainProcessDiagnostics, IProcessDiagnostics, IRemoteDiagnosticError, IRemoteDiagnosticInfo, IWindowDiagnostics } from '../common/diagnostics.js';
11
import { createDecorator } from '../../instantiation/common/instantiation.js';
12
import { ICodeWindow } from '../../window/electron-main/window.js';
13
import { getAllWindowsExcludingOffscreen, IWindowsMainService } from '../../windows/electron-main/windows.js';
14
import { isSingleFolderWorkspaceIdentifier, isWorkspaceIdentifier } from '../../workspace/common/workspace.js';
15
import { IWorkspacesManagementMainService } from '../../workspaces/electron-main/workspacesManagementMainService.js';
16
import { assertReturnsDefined } from '../../../base/common/types.js';
17
import { ILogService } from '../../log/common/log.js';
18
import { UtilityProcess } from '../../utilityProcess/electron-main/utilityProcess.js';
19
20
export const ID = 'diagnosticsMainService';
21
export const IDiagnosticsMainService = createDecorator<IDiagnosticsMainService>(ID);
22
23
export interface IRemoteDiagnosticOptions {
24
includeProcesses?: boolean;
25
includeWorkspaceMetadata?: boolean;
26
}
27
28
export interface IDiagnosticsMainService {
29
readonly _serviceBrand: undefined;
30
getRemoteDiagnostics(options: IRemoteDiagnosticOptions): Promise<(IRemoteDiagnosticInfo | IRemoteDiagnosticError)[]>;
31
getMainDiagnostics(): Promise<IMainProcessDiagnostics>;
32
}
33
34
export class DiagnosticsMainService implements IDiagnosticsMainService {
35
36
declare readonly _serviceBrand: undefined;
37
38
constructor(
39
@IWindowsMainService private readonly windowsMainService: IWindowsMainService,
40
@IWorkspacesManagementMainService private readonly workspacesManagementMainService: IWorkspacesManagementMainService,
41
@ILogService private readonly logService: ILogService
42
) { }
43
44
async getRemoteDiagnostics(options: IRemoteDiagnosticOptions): Promise<(IRemoteDiagnosticInfo | IRemoteDiagnosticError)[]> {
45
const windows = this.windowsMainService.getWindows();
46
const diagnostics: Array<IDiagnosticInfo | IRemoteDiagnosticError | undefined> = await Promise.all(windows.map(async window => {
47
const remoteAuthority = window.remoteAuthority;
48
if (!remoteAuthority) {
49
return undefined;
50
}
51
52
const replyChannel = `vscode:getDiagnosticInfoResponse${window.id}`;
53
const args: IDiagnosticInfoOptions = {
54
includeProcesses: options.includeProcesses,
55
folders: options.includeWorkspaceMetadata ? await this.getFolderURIs(window) : undefined
56
};
57
58
return new Promise<IDiagnosticInfo | IRemoteDiagnosticError>(resolve => {
59
window.sendWhenReady('vscode:getDiagnosticInfo', CancellationToken.None, { replyChannel, args });
60
61
validatedIpcMain.once(replyChannel, (_: IpcEvent, data: IRemoteDiagnosticInfo) => {
62
// No data is returned if getting the connection fails.
63
if (!data) {
64
resolve({ hostName: remoteAuthority, errorMessage: `Unable to resolve connection to '${remoteAuthority}'.` });
65
}
66
67
resolve(data);
68
});
69
70
setTimeout(() => {
71
resolve({ hostName: remoteAuthority, errorMessage: `Connection to '${remoteAuthority}' could not be established` });
72
}, 5000);
73
});
74
}));
75
76
return diagnostics.filter((x): x is IRemoteDiagnosticInfo | IRemoteDiagnosticError => !!x);
77
}
78
79
async getMainDiagnostics(): Promise<IMainProcessDiagnostics> {
80
this.logService.trace('Received request for main process info from other instance.');
81
82
const windows: IWindowDiagnostics[] = [];
83
for (const window of getAllWindowsExcludingOffscreen()) {
84
const codeWindow = this.windowsMainService.getWindowById(window.id);
85
if (codeWindow) {
86
windows.push(await this.codeWindowToInfo(codeWindow));
87
} else {
88
windows.push(this.browserWindowToInfo(window));
89
}
90
}
91
92
const pidToNames: IProcessDiagnostics[] = [];
93
for (const { pid, name } of UtilityProcess.getAll()) {
94
pidToNames.push({ pid, name });
95
}
96
97
return {
98
mainPID: process.pid,
99
mainArguments: process.argv.slice(1),
100
windows,
101
pidToNames,
102
screenReader: !!app.accessibilitySupportEnabled,
103
gpuFeatureStatus: app.getGPUFeatureStatus()
104
};
105
}
106
107
private async codeWindowToInfo(window: ICodeWindow): Promise<IWindowDiagnostics> {
108
const folderURIs = await this.getFolderURIs(window);
109
const win = assertReturnsDefined(window.win);
110
111
return this.browserWindowToInfo(win, folderURIs, window.remoteAuthority);
112
}
113
114
private browserWindowToInfo(window: BrowserWindow, folderURIs: URI[] = [], remoteAuthority?: string): IWindowDiagnostics {
115
return {
116
id: window.id,
117
pid: window.webContents.getOSProcessId(),
118
title: window.getTitle(),
119
folderURIs,
120
remoteAuthority
121
};
122
}
123
124
private async getFolderURIs(window: ICodeWindow): Promise<URI[]> {
125
const folderURIs: URI[] = [];
126
127
const workspace = window.openedWorkspace;
128
if (isSingleFolderWorkspaceIdentifier(workspace)) {
129
folderURIs.push(workspace.uri);
130
} else if (isWorkspaceIdentifier(workspace)) {
131
const resolvedWorkspace = await this.workspacesManagementMainService.resolveLocalWorkspace(workspace.configPath); // workspace folders can only be shown for local (resolved) workspaces
132
if (resolvedWorkspace) {
133
const rootFolders = resolvedWorkspace.folders;
134
rootFolders.forEach(root => {
135
folderURIs.push(root.uri);
136
});
137
}
138
}
139
140
return folderURIs;
141
}
142
}
143
144