Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/workbench/test/electron-browser/workbenchTestServices.ts
3296 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 { workbenchInstantiationService as browserWorkbenchInstantiationService, ITestInstantiationService, TestEncodingOracle, TestEnvironmentService, TestFileDialogService, TestFilesConfigurationService, TestFileService, TestLifecycleService, TestTextFileService } from '../browser/workbenchTestServices.js';
8
import { ISharedProcessService } from '../../../platform/ipc/electron-browser/services.js';
9
import { INativeHostService, INativeHostOptions, IOSProperties, IOSStatistics } from '../../../platform/native/common/native.js';
10
import { VSBuffer, VSBufferReadable, VSBufferReadableStream } from '../../../base/common/buffer.js';
11
import { DisposableStore, IDisposable } from '../../../base/common/lifecycle.js';
12
import { URI } from '../../../base/common/uri.js';
13
import { IFileDialogService, INativeOpenDialogOptions } from '../../../platform/dialogs/common/dialogs.js';
14
import { IPartsSplash } from '../../../platform/theme/common/themeService.js';
15
import { IOpenedMainWindow, IOpenEmptyWindowOptions, IWindowOpenable, IOpenWindowOptions, IColorScheme, IRectangle, IPoint } from '../../../platform/window/common/window.js';
16
import { TestConfigurationService } from '../../../platform/configuration/test/common/testConfigurationService.js';
17
import { IContextKeyService } from '../../../platform/contextkey/common/contextkey.js';
18
import { IEnvironmentService, INativeEnvironmentService } from '../../../platform/environment/common/environment.js';
19
import { IFileService } from '../../../platform/files/common/files.js';
20
import { IInstantiationService } from '../../../platform/instantiation/common/instantiation.js';
21
import { IEditorService } from '../../services/editor/common/editorService.js';
22
import { IPathService } from '../../services/path/common/pathService.js';
23
import { ITextEditorService } from '../../services/textfile/common/textEditorService.js';
24
import { ITextFileService } from '../../services/textfile/common/textfiles.js';
25
import { AbstractNativeExtensionTipsService } from '../../../platform/extensionManagement/common/extensionTipsService.js';
26
import { IExtensionManagementService } from '../../../platform/extensionManagement/common/extensionManagement.js';
27
import { IExtensionRecommendationNotificationService } from '../../../platform/extensionRecommendations/common/extensionRecommendations.js';
28
import { IProductService } from '../../../platform/product/common/productService.js';
29
import { IStorageService } from '../../../platform/storage/common/storage.js';
30
import { ITelemetryService } from '../../../platform/telemetry/common/telemetry.js';
31
import { IModelService } from '../../../editor/common/services/model.js';
32
import { ModelService } from '../../../editor/common/services/modelService.js';
33
import { IWorkspaceContextService } from '../../../platform/workspace/common/workspace.js';
34
import { IFilesConfigurationService } from '../../services/filesConfiguration/common/filesConfigurationService.js';
35
import { ILifecycleService } from '../../services/lifecycle/common/lifecycle.js';
36
import { IWorkingCopyBackupService } from '../../services/workingCopy/common/workingCopyBackup.js';
37
import { IWorkingCopyService } from '../../services/workingCopy/common/workingCopyService.js';
38
import { TestContextService } from '../common/workbenchTestServices.js';
39
import { NativeTextFileService } from '../../services/textfile/electron-browser/nativeTextFileService.js';
40
import { insert } from '../../../base/common/arrays.js';
41
import { Schemas } from '../../../base/common/network.js';
42
import { FileService } from '../../../platform/files/common/fileService.js';
43
import { InMemoryFileSystemProvider } from '../../../platform/files/common/inMemoryFilesystemProvider.js';
44
import { NullLogService } from '../../../platform/log/common/log.js';
45
import { FileUserDataProvider } from '../../../platform/userData/common/fileUserDataProvider.js';
46
import { IWorkingCopyIdentifier } from '../../services/workingCopy/common/workingCopy.js';
47
import { NativeWorkingCopyBackupService } from '../../services/workingCopy/electron-browser/workingCopyBackupService.js';
48
import { CancellationToken } from '../../../base/common/cancellation.js';
49
import { UriIdentityService } from '../../../platform/uriIdentity/common/uriIdentityService.js';
50
import { UserDataProfilesService } from '../../../platform/userDataProfile/common/userDataProfile.js';
51
import { AuthInfo, Credentials } from '../../../platform/request/common/request.js';
52
53
export class TestSharedProcessService implements ISharedProcessService {
54
55
declare readonly _serviceBrand: undefined;
56
57
createRawConnection(): never { throw new Error('Not Implemented'); }
58
getChannel(channelName: string): any { return undefined; }
59
registerChannel(channelName: string, channel: any): void { }
60
notifyRestored(): void { }
61
}
62
63
export class TestNativeHostService implements INativeHostService {
64
declare readonly _serviceBrand: undefined;
65
66
readonly windowId = -1;
67
68
onDidOpenMainWindow: Event<number> = Event.None;
69
onDidMaximizeWindow: Event<number> = Event.None;
70
onDidUnmaximizeWindow: Event<number> = Event.None;
71
onDidFocusMainWindow: Event<number> = Event.None;
72
onDidBlurMainWindow: Event<number> = Event.None;
73
onDidFocusMainOrAuxiliaryWindow: Event<number> = Event.None;
74
onDidBlurMainOrAuxiliaryWindow: Event<number> = Event.None;
75
onDidResumeOS: Event<unknown> = Event.None;
76
onDidChangeColorScheme = Event.None;
77
onDidChangePassword = Event.None;
78
onDidTriggerWindowSystemContextMenu: Event<{ windowId: number; x: number; y: number }> = Event.None;
79
onDidChangeWindowFullScreen = Event.None;
80
onDidChangeWindowAlwaysOnTop = Event.None;
81
onDidChangeDisplay = Event.None;
82
83
windowCount = Promise.resolve(1);
84
getWindowCount(): Promise<number> { return this.windowCount; }
85
86
async getWindows(): Promise<IOpenedMainWindow[]> { return []; }
87
async getActiveWindowId(): Promise<number | undefined> { return undefined; }
88
async getActiveWindowPosition(): Promise<IRectangle | undefined> { return undefined; }
89
async getNativeWindowHandle(windowId: number): Promise<VSBuffer | undefined> { return undefined; }
90
91
openWindow(options?: IOpenEmptyWindowOptions): Promise<void>;
92
openWindow(toOpen: IWindowOpenable[], options?: IOpenWindowOptions): Promise<void>;
93
openWindow(arg1?: IOpenEmptyWindowOptions | IWindowOpenable[], arg2?: IOpenWindowOptions): Promise<void> {
94
throw new Error('Method not implemented.');
95
}
96
97
async toggleFullScreen(): Promise<void> { }
98
async isMaximized(): Promise<boolean> { return true; }
99
async isFullScreen(): Promise<boolean> { return true; }
100
async maximizeWindow(): Promise<void> { }
101
async unmaximizeWindow(): Promise<void> { }
102
async minimizeWindow(): Promise<void> { }
103
async moveWindowTop(options?: INativeHostOptions): Promise<void> { }
104
async isWindowAlwaysOnTop(options?: INativeHostOptions): Promise<boolean> { return false; }
105
async toggleWindowAlwaysOnTop(options?: INativeHostOptions): Promise<void> { }
106
async setWindowAlwaysOnTop(alwaysOnTop: boolean, options?: INativeHostOptions): Promise<void> { }
107
async getCursorScreenPoint(): Promise<{ readonly point: IPoint; readonly display: IRectangle }> { throw new Error('Method not implemented.'); }
108
async positionWindow(position: IRectangle, options?: INativeHostOptions): Promise<void> { }
109
async updateWindowControls(options: { height?: number; backgroundColor?: string; foregroundColor?: string }): Promise<void> { }
110
async updateWindowAccentColor(color: string): Promise<void> { }
111
async setMinimumSize(width: number | undefined, height: number | undefined): Promise<void> { }
112
async saveWindowSplash(value: IPartsSplash): Promise<void> { }
113
async setBackgroundThrottling(throttling: boolean): Promise<void> { }
114
async focusWindow(options?: INativeHostOptions): Promise<void> { }
115
async showMessageBox(options: Electron.MessageBoxOptions): Promise<Electron.MessageBoxReturnValue> { throw new Error('Method not implemented.'); }
116
async showSaveDialog(options: Electron.SaveDialogOptions): Promise<Electron.SaveDialogReturnValue> { throw new Error('Method not implemented.'); }
117
async showOpenDialog(options: Electron.OpenDialogOptions): Promise<Electron.OpenDialogReturnValue> { throw new Error('Method not implemented.'); }
118
async pickFileFolderAndOpen(options: INativeOpenDialogOptions): Promise<void> { }
119
async pickFileAndOpen(options: INativeOpenDialogOptions): Promise<void> { }
120
async pickFolderAndOpen(options: INativeOpenDialogOptions): Promise<void> { }
121
async pickWorkspaceAndOpen(options: INativeOpenDialogOptions): Promise<void> { }
122
async showItemInFolder(path: string): Promise<void> { }
123
async setRepresentedFilename(path: string): Promise<void> { }
124
async isAdmin(): Promise<boolean> { return false; }
125
async writeElevated(source: URI, target: URI): Promise<void> { }
126
async isRunningUnderARM64Translation(): Promise<boolean> { return false; }
127
async getOSProperties(): Promise<IOSProperties> { return Object.create(null); }
128
async getOSStatistics(): Promise<IOSStatistics> { return Object.create(null); }
129
async getOSVirtualMachineHint(): Promise<number> { return 0; }
130
async getOSColorScheme(): Promise<IColorScheme> { return { dark: true, highContrast: false }; }
131
async hasWSLFeatureInstalled(): Promise<boolean> { return false; }
132
async getProcessId(): Promise<number> { throw new Error('Method not implemented.'); }
133
async killProcess(): Promise<void> { }
134
async setDocumentEdited(edited: boolean): Promise<void> { }
135
async openExternal(url: string, defaultApplication?: string): Promise<boolean> { return false; }
136
async updateTouchBar(): Promise<void> { }
137
async moveItemToTrash(): Promise<void> { }
138
async newWindowTab(): Promise<void> { }
139
async showPreviousWindowTab(): Promise<void> { }
140
async showNextWindowTab(): Promise<void> { }
141
async moveWindowTabToNewWindow(): Promise<void> { }
142
async mergeAllWindowTabs(): Promise<void> { }
143
async toggleWindowTabsBar(): Promise<void> { }
144
async installShellCommand(): Promise<void> { }
145
async uninstallShellCommand(): Promise<void> { }
146
async notifyReady(): Promise<void> { }
147
async relaunch(options?: { addArgs?: string[] | undefined; removeArgs?: string[] | undefined } | undefined): Promise<void> { }
148
async reload(): Promise<void> { }
149
async closeWindow(): Promise<void> { }
150
async quit(): Promise<void> { }
151
async exit(code: number): Promise<void> { }
152
async openDevTools(options?: Partial<Electron.OpenDevToolsOptions> & INativeHostOptions | undefined): Promise<void> { }
153
async toggleDevTools(): Promise<void> { }
154
async stopTracing(): Promise<void> { }
155
async openDevToolsWindow(url: string): Promise<void> { }
156
async openGPUInfoWindow(): Promise<void> { }
157
async resolveProxy(url: string): Promise<string | undefined> { return undefined; }
158
async lookupAuthorization(authInfo: AuthInfo): Promise<Credentials | undefined> { return undefined; }
159
async lookupKerberosAuthorization(url: string): Promise<string | undefined> { return undefined; }
160
async loadCertificates(): Promise<string[]> { return []; }
161
async isPortFree() { return Promise.resolve(true); }
162
async findFreePort(startPort: number, giveUpAfter: number, timeout: number, stride?: number): Promise<number> { return -1; }
163
async readClipboardText(type?: 'selection' | 'clipboard' | undefined): Promise<string> { return ''; }
164
async writeClipboardText(text: string, type?: 'selection' | 'clipboard' | undefined): Promise<void> { }
165
async readClipboardFindText(): Promise<string> { return ''; }
166
async writeClipboardFindText(text: string): Promise<void> { }
167
async writeClipboardBuffer(format: string, buffer: VSBuffer, type?: 'selection' | 'clipboard' | undefined): Promise<void> { }
168
async triggerPaste(options?: INativeHostOptions): Promise<void> { }
169
async readImage(): Promise<Uint8Array> { return Uint8Array.from([]); }
170
async readClipboardBuffer(format: string): Promise<VSBuffer> { return VSBuffer.wrap(Uint8Array.from([])); }
171
async hasClipboard(format: string, type?: 'selection' | 'clipboard' | undefined): Promise<boolean> { return false; }
172
async windowsGetStringRegKey(hive: 'HKEY_CURRENT_USER' | 'HKEY_LOCAL_MACHINE' | 'HKEY_CLASSES_ROOT' | 'HKEY_USERS' | 'HKEY_CURRENT_CONFIG', path: string, name: string): Promise<string | undefined> { return undefined; }
173
async profileRenderer(): Promise<any> { throw new Error(); }
174
async getScreenshot(rect?: IRectangle): Promise<VSBuffer | undefined> { return undefined; }
175
}
176
177
export class TestExtensionTipsService extends AbstractNativeExtensionTipsService {
178
179
constructor(
180
@INativeEnvironmentService environmentService: INativeEnvironmentService,
181
@ITelemetryService telemetryService: ITelemetryService,
182
@IExtensionManagementService extensionManagementService: IExtensionManagementService,
183
@IStorageService storageService: IStorageService,
184
@INativeHostService nativeHostService: INativeHostService,
185
@IExtensionRecommendationNotificationService extensionRecommendationNotificationService: IExtensionRecommendationNotificationService,
186
@IFileService fileService: IFileService,
187
@IProductService productService: IProductService,
188
) {
189
super(environmentService.userHome, nativeHostService, telemetryService, extensionManagementService, storageService, extensionRecommendationNotificationService, fileService, productService);
190
}
191
}
192
193
export function workbenchInstantiationService(overrides?: {
194
environmentService?: (instantiationService: IInstantiationService) => IEnvironmentService;
195
fileService?: (instantiationService: IInstantiationService) => IFileService;
196
configurationService?: (instantiationService: IInstantiationService) => TestConfigurationService;
197
textFileService?: (instantiationService: IInstantiationService) => ITextFileService;
198
pathService?: (instantiationService: IInstantiationService) => IPathService;
199
editorService?: (instantiationService: IInstantiationService) => IEditorService;
200
contextKeyService?: (instantiationService: IInstantiationService) => IContextKeyService;
201
textEditorService?: (instantiationService: IInstantiationService) => ITextEditorService;
202
}, disposables = new DisposableStore()): ITestInstantiationService {
203
const instantiationService = browserWorkbenchInstantiationService({
204
workingCopyBackupService: () => disposables.add(new TestNativeWorkingCopyBackupService()),
205
...overrides
206
}, disposables);
207
208
instantiationService.stub(INativeHostService, new TestNativeHostService());
209
210
return instantiationService;
211
}
212
213
export class TestServiceAccessor {
214
constructor(
215
@ILifecycleService public lifecycleService: TestLifecycleService,
216
@ITextFileService public textFileService: TestTextFileService,
217
@IFilesConfigurationService public filesConfigurationService: TestFilesConfigurationService,
218
@IWorkspaceContextService public contextService: TestContextService,
219
@IModelService public modelService: ModelService,
220
@IFileService public fileService: TestFileService,
221
@INativeHostService public nativeHostService: TestNativeHostService,
222
@IFileDialogService public fileDialogService: TestFileDialogService,
223
@IWorkingCopyBackupService public workingCopyBackupService: TestNativeWorkingCopyBackupService,
224
@IWorkingCopyService public workingCopyService: IWorkingCopyService,
225
@IEditorService public editorService: IEditorService
226
) {
227
}
228
}
229
230
export class TestNativeTextFileServiceWithEncodingOverrides extends NativeTextFileService {
231
232
private _testEncoding: TestEncodingOracle | undefined;
233
override get encoding(): TestEncodingOracle {
234
if (!this._testEncoding) {
235
this._testEncoding = this._register(this.instantiationService.createInstance(TestEncodingOracle));
236
}
237
238
return this._testEncoding;
239
}
240
}
241
242
export class TestNativeWorkingCopyBackupService extends NativeWorkingCopyBackupService implements IDisposable {
243
244
private backupResourceJoiners: Function[];
245
private discardBackupJoiners: Function[];
246
discardedBackups: IWorkingCopyIdentifier[];
247
discardedAllBackups: boolean;
248
private pendingBackupsArr: Promise<void>[];
249
250
constructor() {
251
const environmentService = TestEnvironmentService;
252
const logService = new NullLogService();
253
const fileService = new FileService(logService);
254
const lifecycleService = new TestLifecycleService();
255
super(environmentService as any, fileService, logService, lifecycleService);
256
257
const inMemoryFileSystemProvider = this._register(new InMemoryFileSystemProvider());
258
this._register(fileService.registerProvider(Schemas.inMemory, inMemoryFileSystemProvider));
259
const uriIdentityService = this._register(new UriIdentityService(fileService));
260
const userDataProfilesService = this._register(new UserDataProfilesService(environmentService, fileService, uriIdentityService, logService));
261
this._register(fileService.registerProvider(Schemas.vscodeUserData, this._register(new FileUserDataProvider(Schemas.file, inMemoryFileSystemProvider, Schemas.vscodeUserData, userDataProfilesService, uriIdentityService, logService))));
262
263
this.backupResourceJoiners = [];
264
this.discardBackupJoiners = [];
265
this.discardedBackups = [];
266
this.pendingBackupsArr = [];
267
this.discardedAllBackups = false;
268
269
this._register(fileService);
270
this._register(lifecycleService);
271
}
272
273
testGetFileService(): IFileService {
274
return this.fileService;
275
}
276
277
async waitForAllBackups(): Promise<void> {
278
await Promise.all(this.pendingBackupsArr);
279
}
280
281
joinBackupResource(): Promise<void> {
282
return new Promise(resolve => this.backupResourceJoiners.push(resolve));
283
}
284
285
override async backup(identifier: IWorkingCopyIdentifier, content?: VSBufferReadableStream | VSBufferReadable, versionId?: number, meta?: any, token?: CancellationToken): Promise<void> {
286
const p = super.backup(identifier, content, versionId, meta, token);
287
const removeFromPendingBackups = insert(this.pendingBackupsArr, p.then(undefined, undefined));
288
289
try {
290
await p;
291
} finally {
292
removeFromPendingBackups();
293
}
294
295
while (this.backupResourceJoiners.length) {
296
this.backupResourceJoiners.pop()!();
297
}
298
}
299
300
joinDiscardBackup(): Promise<void> {
301
return new Promise(resolve => this.discardBackupJoiners.push(resolve));
302
}
303
304
override async discardBackup(identifier: IWorkingCopyIdentifier): Promise<void> {
305
await super.discardBackup(identifier);
306
this.discardedBackups.push(identifier);
307
308
while (this.discardBackupJoiners.length) {
309
this.discardBackupJoiners.pop()!();
310
}
311
}
312
313
override async discardBackups(filter?: { except: IWorkingCopyIdentifier[] }): Promise<void> {
314
this.discardedAllBackups = true;
315
316
return super.discardBackups(filter);
317
}
318
319
async getBackupContents(identifier: IWorkingCopyIdentifier): Promise<string> {
320
const backupResource = this.toBackupResource(identifier);
321
322
const fileContents = await this.fileService.readFile(backupResource);
323
324
return fileContents.value.toString();
325
}
326
}
327
328