Skip to content

Commit c55d704

Browse files
author
Benjamin Pasero
committed
debt - move pick & open into electron main service
1 parent ff09b48 commit c55d704

6 files changed

Lines changed: 68 additions & 101 deletions

File tree

src/vs/code/electron-main/app.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,7 @@ import { FileService } from 'vs/platform/files/common/fileService';
7474
import { IFileService } from 'vs/platform/files/common/files';
7575
import { DiskFileSystemProvider } from 'vs/platform/files/node/diskFileSystemProvider';
7676
import { ExtensionHostDebugBroadcastChannel } from 'vs/platform/debug/common/extensionHostDebugIpc';
77-
import { IElectronService } from 'vs/platform/electron/node/electron';
78-
import { ElectronMainService } from 'vs/platform/electron/electron-main/electronMainService';
77+
import { IElectronMainService, ElectronMainService } from 'vs/platform/electron/electron-main/electronMainService';
7978
import { ISharedProcessMainService, SharedProcessMainService } from 'vs/platform/ipc/electron-main/sharedProcessMainService';
8079
import { assign } from 'vs/base/common/objects';
8180
import { IDialogMainService, DialogMainService } from 'vs/platform/dialogs/electron-main/dialogs';
@@ -459,7 +458,7 @@ export class CodeApplication extends Disposable {
459458
services.set(IDiagnosticsService, new SyncDescriptor(DiagnosticsService, [diagnosticsChannel]));
460459

461460
services.set(IIssueService, new SyncDescriptor(IssueMainService, [machineId, this.userEnv]));
462-
services.set(IElectronService, new SyncDescriptor(ElectronMainService));
461+
services.set(IElectronMainService, new SyncDescriptor(ElectronMainService));
463462
services.set(IWorkspacesService, new SyncDescriptor(WorkspacesService));
464463
services.set(IMenubarService, new SyncDescriptor(MenubarMainService));
465464

@@ -546,8 +545,8 @@ export class CodeApplication extends Disposable {
546545
const issueChannel = createChannelReceiver(issueService);
547546
electronIpcServer.registerChannel('issue', issueChannel);
548547

549-
const electronService = accessor.get(IElectronService);
550-
const electronChannel = createChannelReceiver(electronService);
548+
const electronMainService = accessor.get(IElectronMainService);
549+
const electronChannel = createChannelReceiver(electronMainService);
551550
electronIpcServer.registerChannel('electron', electronChannel);
552551
sharedProcessClient.then(client => client.registerChannel('electron', electronChannel));
553552

@@ -605,7 +604,7 @@ export class CodeApplication extends Disposable {
605604
});
606605

607606
// Create a URL handler which forwards to the last active window
608-
const activeWindowManager = new ActiveWindowManager(electronService);
607+
const activeWindowManager = new ActiveWindowManager(electronMainService);
609608
const activeWindowRouter = new StaticRouter(ctx => activeWindowManager.getActiveClientId().then(id => ctx === id));
610609
const urlHandlerRouter = new URLHandlerRouter(activeWindowRouter);
611610
const urlHandlerChannel = electronIpcServer.getChannel('urlHandler', urlHandlerRouter);

src/vs/code/electron-main/main.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ class CodeMain {
299299
await launchService.start(environmentService.args, process.env as platform.IProcessEnvironment);
300300

301301
// Cleanup
302-
await client.dispose();
302+
client.dispose();
303303

304304
// Now that we started, make sure the warning dialog is prevented
305305
if (startupWarningDialogHandle) {

src/vs/code/electron-main/windows.ts

Lines changed: 2 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,10 @@ import { ILifecycleMainService, UnloadReason, LifecycleMainService, LifecycleMai
1919
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
2020
import { ILogService } from 'vs/platform/log/common/log';
2121
import { IWindowSettings, OpenContext, IPath, IWindowConfiguration, IPathsToWaitFor, isFileToOpen, isWorkspaceToOpen, isFolderToOpen, IWindowOpenable, IOpenEmptyWindowOptions, IAddFoldersRequest } from 'vs/platform/windows/common/windows';
22-
import { INativeOpenDialogOptions } from 'vs/platform/dialogs/node/dialogs';
2322
import { getLastActiveWindow, findBestWindowOrFolderForFile, findWindowOnWorkspace, findWindowOnExtensionDevelopmentPath, findWindowOnWorkspaceOrFolderUri } from 'vs/platform/windows/node/window';
2423
import { Event as CommonEvent, Emitter } from 'vs/base/common/event';
2524
import product from 'vs/platform/product/common/product';
26-
import { ITelemetryService, ITelemetryData } from 'vs/platform/telemetry/common/telemetry';
25+
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
2726
import { IWindowsMainService, IOpenConfiguration, IWindowsCountChangedEvent, ICodeWindow, IWindowState as ISingleWindowState, WindowMode } from 'vs/platform/windows/electron-main/windows';
2827
import { IWorkspacesHistoryMainService } from 'vs/platform/workspaces/electron-main/workspacesHistoryMainService';
2928
import { IProcessEnvironment, isMacintosh, isWindows } from 'vs/base/common/platform';
@@ -32,7 +31,6 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
3231
import { mnemonicButtonLabel } from 'vs/base/common/labels';
3332
import { Schemas } from 'vs/base/common/network';
3433
import { URI } from 'vs/base/common/uri';
35-
import { dirExists } from 'vs/base/node/pfs';
3634
import { getComparisonKey, isEqual, normalizePath, originalFSPath, hasTrailingPathSeparator, removeTrailingPathSeparator } from 'vs/base/common/resources';
3735
import { getRemoteAuthority } from 'vs/platform/remote/common/remoteHosts';
3836
import { restoreWindowsState, WindowsStateStorageData, getWindowsStateStoreData } from 'vs/code/electron-main/windowsStateStorage';
@@ -1718,6 +1716,7 @@ export class WindowsManager extends Disposable implements IWindowsMainService {
17181716
type: WindowError;
17191717
};
17201718
this.telemetryService.publicLog2<WindowErrorEvent, WindowErrorClassification>('windowerror', { type: error });
1719+
17211720
// Unresponsive
17221721
if (error === WindowError.UNRESPONSIVE) {
17231722
if (window.isExtensionDevelopmentHost || window.isExtensionTestHost || (window.win && window.win.webContents && window.win.webContents.isDevToolsOpened())) {
@@ -1790,80 +1789,6 @@ export class WindowsManager extends Disposable implements IWindowsMainService {
17901789
this._onWindowClose.fire(win.id);
17911790
}
17921791

1793-
async pickFileFolderAndOpen(options: INativeOpenDialogOptions, win?: ICodeWindow): Promise<void> {
1794-
const paths = await this.dialogMainService.pickFileFolder(options);
1795-
if (paths) {
1796-
this.sendPickerTelemetry(paths, options.telemetryEventName || 'openFileFolder', options.telemetryExtraData);
1797-
const urisToOpen = await Promise.all(paths.map(async path => {
1798-
const isDir = await dirExists(path);
1799-
1800-
return isDir ? { folderUri: URI.file(path) } : { fileUri: URI.file(path) };
1801-
}));
1802-
this.open({
1803-
context: OpenContext.DIALOG,
1804-
contextWindowId: win ? win.id : undefined,
1805-
cli: this.environmentService.args,
1806-
urisToOpen,
1807-
forceNewWindow: options.forceNewWindow
1808-
});
1809-
}
1810-
}
1811-
1812-
async pickFolderAndOpen(options: INativeOpenDialogOptions, win?: ICodeWindow): Promise<void> {
1813-
const paths = await this.dialogMainService.pickFolder(options);
1814-
if (paths) {
1815-
this.sendPickerTelemetry(paths, options.telemetryEventName || 'openFolder', options.telemetryExtraData);
1816-
this.open({
1817-
context: OpenContext.DIALOG,
1818-
contextWindowId: win ? win.id : undefined,
1819-
cli: this.environmentService.args,
1820-
urisToOpen: paths.map(path => ({ folderUri: URI.file(path) })),
1821-
forceNewWindow: options.forceNewWindow
1822-
});
1823-
}
1824-
}
1825-
1826-
async pickFileAndOpen(options: INativeOpenDialogOptions, win?: ICodeWindow): Promise<void> {
1827-
const paths = await this.dialogMainService.pickFile(options);
1828-
if (paths) {
1829-
this.sendPickerTelemetry(paths, options.telemetryEventName || 'openFile', options.telemetryExtraData);
1830-
this.open({
1831-
context: OpenContext.DIALOG,
1832-
contextWindowId: win ? win.id : undefined,
1833-
cli: this.environmentService.args,
1834-
urisToOpen: paths.map(path => ({ fileUri: URI.file(path) })),
1835-
forceNewWindow: options.forceNewWindow
1836-
});
1837-
}
1838-
}
1839-
1840-
async pickWorkspaceAndOpen(options: INativeOpenDialogOptions, win?: ICodeWindow): Promise<void> {
1841-
const paths = await this.dialogMainService.pickWorkspace(options);
1842-
if (paths) {
1843-
this.sendPickerTelemetry(paths, options.telemetryEventName || 'openWorkspace', options.telemetryExtraData);
1844-
this.open({
1845-
context: OpenContext.DIALOG,
1846-
contextWindowId: win ? win.id : undefined,
1847-
cli: this.environmentService.args,
1848-
urisToOpen: paths.map(path => ({ workspaceUri: URI.file(path) })),
1849-
forceNewWindow: options.forceNewWindow
1850-
});
1851-
}
1852-
1853-
}
1854-
1855-
private sendPickerTelemetry(paths: string[], telemetryEventName: string, telemetryExtraData?: ITelemetryData) {
1856-
const numberOfPaths = paths ? paths.length : 0;
1857-
1858-
// Telemetry
1859-
// __GDPR__TODO__ Dynamic event names and dynamic properties. Can not be registered statically.
1860-
this.telemetryService.publicLog(telemetryEventName, {
1861-
...telemetryExtraData,
1862-
outcome: numberOfPaths ? 'success' : 'canceled',
1863-
numberOfPaths
1864-
});
1865-
}
1866-
18671792
quit(): void {
18681793

18691794
// If the user selected to exit from an extension development host window, do not quit, but just

src/vs/platform/electron/electron-main/electronMainService.ts

Lines changed: 55 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,25 @@ import { ISerializableCommandAction } from 'vs/platform/actions/common/actions';
1616
import { IEnvironmentService, ParsedArgs } from 'vs/platform/environment/common/environment';
1717
import { AddFirstParameterToFunctions } from 'vs/base/common/types';
1818
import { IDialogMainService } from 'vs/platform/dialogs/electron-main/dialogs';
19+
import { dirExists } from 'vs/base/node/pfs';
20+
import { URI } from 'vs/base/common/uri';
21+
import { ITelemetryData, ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
22+
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
1923

20-
export class ElectronMainService implements AddFirstParameterToFunctions<IElectronService, Promise<any> /* only methods, not events */, number /* window ID */> {
24+
export interface IElectronMainService extends AddFirstParameterToFunctions<IElectronService, Promise<any> /* only methods, not events */, number /* window ID */> { }
25+
26+
export const IElectronMainService = createDecorator<IElectronService>('electronMainService');
27+
28+
export class ElectronMainService implements IElectronMainService {
2129

2230
_serviceBrand: undefined;
2331

2432
constructor(
2533
@IWindowsMainService private readonly windowsMainService: IWindowsMainService,
2634
@IDialogMainService private readonly dialogMainService: IDialogMainService,
2735
@ILifecycleMainService private readonly lifecycleMainService: ILifecycleMainService,
28-
@IEnvironmentService private readonly environmentService: IEnvironmentService
36+
@IEnvironmentService private readonly environmentService: IEnvironmentService,
37+
@ITelemetryService private readonly telemetryService: ITelemetryService
2938
) {
3039
}
3140

@@ -197,19 +206,57 @@ export class ElectronMainService implements AddFirstParameterToFunctions<IElectr
197206
}
198207

199208
async pickFileFolderAndOpen(windowId: number, options: INativeOpenDialogOptions): Promise<void> {
200-
return this.windowsMainService.pickFileFolderAndOpen(options, this.windowsMainService.getWindowById(windowId));
209+
const paths = await this.dialogMainService.pickFileFolder(options);
210+
if (paths) {
211+
this.sendPickerTelemetry(paths, options.telemetryEventName || 'openFileFolder', options.telemetryExtraData);
212+
this.doOpenPicked(await Promise.all(paths.map(async path => (await dirExists(path)) ? { folderUri: URI.file(path) } : { fileUri: URI.file(path) })), options, windowId);
213+
}
201214
}
202215

203-
async pickFileAndOpen(windowId: number, options: INativeOpenDialogOptions): Promise<void> {
204-
return this.windowsMainService.pickFileAndOpen(options, this.windowsMainService.getWindowById(windowId));
216+
async pickFolderAndOpen(windowId: number, options: INativeOpenDialogOptions): Promise<void> {
217+
const paths = await this.dialogMainService.pickFolder(options);
218+
if (paths) {
219+
this.sendPickerTelemetry(paths, options.telemetryEventName || 'openFolder', options.telemetryExtraData);
220+
this.doOpenPicked(paths.map(path => ({ folderUri: URI.file(path) })), options, windowId);
221+
}
205222
}
206223

207-
async pickFolderAndOpen(windowId: number, options: INativeOpenDialogOptions): Promise<void> {
208-
return this.windowsMainService.pickFolderAndOpen(options, this.windowsMainService.getWindowById(windowId));
224+
async pickFileAndOpen(windowId: number, options: INativeOpenDialogOptions): Promise<void> {
225+
const paths = await this.dialogMainService.pickFile(options);
226+
if (paths) {
227+
this.sendPickerTelemetry(paths, options.telemetryEventName || 'openFile', options.telemetryExtraData);
228+
this.doOpenPicked(paths.map(path => ({ fileUri: URI.file(path) })), options, windowId);
229+
}
209230
}
210231

211232
async pickWorkspaceAndOpen(windowId: number, options: INativeOpenDialogOptions): Promise<void> {
212-
return this.windowsMainService.pickWorkspaceAndOpen(options, this.windowsMainService.getWindowById(windowId));
233+
const paths = await this.dialogMainService.pickWorkspace(options);
234+
if (paths) {
235+
this.sendPickerTelemetry(paths, options.telemetryEventName || 'openWorkspace', options.telemetryExtraData);
236+
this.doOpenPicked(paths.map(path => ({ workspaceUri: URI.file(path) })), options, windowId);
237+
}
238+
}
239+
240+
private doOpenPicked(openable: IWindowOpenable[], options: INativeOpenDialogOptions, windowId: number): void {
241+
this.windowsMainService.open({
242+
context: OpenContext.DIALOG,
243+
contextWindowId: windowId,
244+
cli: this.environmentService.args,
245+
urisToOpen: openable,
246+
forceNewWindow: options.forceNewWindow
247+
});
248+
}
249+
250+
private sendPickerTelemetry(paths: string[], telemetryEventName: string, telemetryExtraData?: ITelemetryData) {
251+
const numberOfPaths = paths ? paths.length : 0;
252+
253+
// Telemetry
254+
// __GDPR__TODO__ Dynamic event names and dynamic properties. Can not be registered statically.
255+
this.telemetryService.publicLog(telemetryEventName, {
256+
...telemetryExtraData,
257+
outcome: numberOfPaths ? 'success' : 'canceled',
258+
numberOfPaths
259+
});
213260
}
214261

215262
//#endregion

src/vs/platform/menubar/electron-main/menubar.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import { URI } from 'vs/base/common/uri';
2222
import { IStateService } from 'vs/platform/state/node/state';
2323
import { ILifecycleMainService } from 'vs/platform/lifecycle/electron-main/lifecycleMainService';
2424
import { WorkbenchActionExecutedEvent, WorkbenchActionExecutedClassification } from 'vs/base/common/actions';
25+
import { IElectronMainService } from 'vs/platform/electron/electron-main/electronMainService';
2526

2627
const telemetryFrom = 'menu';
2728

@@ -69,7 +70,8 @@ export class Menubar {
6970
@IWorkspacesHistoryMainService private readonly workspacesHistoryMainService: IWorkspacesHistoryMainService,
7071
@IStateService private readonly stateService: IStateService,
7172
@ILifecycleMainService private readonly lifecycleMainService: ILifecycleMainService,
72-
@ILogService private readonly logService: ILogService
73+
@ILogService private readonly logService: ILogService,
74+
@IElectronMainService private readonly electronMainService: IElectronMainService
7375
) {
7476
this.menuUpdater = new RunOnceScheduler(() => this.doUpdateMenu(), 0);
7577

@@ -111,8 +113,8 @@ export class Menubar {
111113
// File Menu Items
112114
this.fallbackMenuHandlers['workbench.action.files.newUntitledFile'] = () => this.windowsMainService.openEmptyWindow(OpenContext.MENU);
113115
this.fallbackMenuHandlers['workbench.action.newWindow'] = () => this.windowsMainService.openEmptyWindow(OpenContext.MENU);
114-
this.fallbackMenuHandlers['workbench.action.files.openFileFolder'] = (menuItem, win, event) => this.windowsMainService.pickFileFolderAndOpen({ forceNewWindow: this.isOptionClick(event), telemetryExtraData: { from: telemetryFrom } });
115-
this.fallbackMenuHandlers['workbench.action.openWorkspace'] = (menuItem, win, event) => this.windowsMainService.pickWorkspaceAndOpen({ forceNewWindow: this.isOptionClick(event), telemetryExtraData: { from: telemetryFrom } });
116+
this.fallbackMenuHandlers['workbench.action.files.openFileFolder'] = (menuItem, win, event) => this.electronMainService.pickFileFolderAndOpen(-1, { forceNewWindow: this.isOptionClick(event), telemetryExtraData: { from: telemetryFrom } });
117+
this.fallbackMenuHandlers['workbench.action.openWorkspace'] = (menuItem, win, event) => this.electronMainService.pickWorkspaceAndOpen(-1, { forceNewWindow: this.isOptionClick(event), telemetryExtraData: { from: telemetryFrom } });
116118

117119
// Recent Menu Items
118120
this.fallbackMenuHandlers['workbench.action.clearRecentFiles'] = () => this.workspacesHistoryMainService.clearRecentlyOpened();

src/vs/platform/windows/electron-main/windows.ts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
*--------------------------------------------------------------------------------------------*/
55

66
import { OpenContext, IWindowConfiguration, IWindowOpenable, IOpenEmptyWindowOptions } from 'vs/platform/windows/common/windows';
7-
import { INativeOpenDialogOptions } from 'vs/platform/dialogs/node/dialogs';
87
import { ParsedArgs } from 'vs/platform/environment/common/environment';
98
import { Event } from 'vs/base/common/event';
109
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
@@ -97,11 +96,6 @@ export interface IWindowsMainService {
9796
openEmptyWindow(context: OpenContext, options?: IOpenEmptyWindowOptions): ICodeWindow[];
9897
openExtensionDevelopmentHostWindow(extensionDevelopmentPath: string[], openConfig: IOpenConfiguration): ICodeWindow[];
9998

100-
pickFileFolderAndOpen(options: INativeOpenDialogOptions, win?: ICodeWindow): Promise<void>;
101-
pickFolderAndOpen(options: INativeOpenDialogOptions, win?: ICodeWindow): Promise<void>;
102-
pickFileAndOpen(options: INativeOpenDialogOptions, win?: ICodeWindow): Promise<void>;
103-
pickWorkspaceAndOpen(options: INativeOpenDialogOptions, win?: ICodeWindow): Promise<void>;
104-
10599
sendToFocused(channel: string, ...args: any[]): void;
106100
sendToAll(channel: string, payload: any, windowIdsToIgnore?: number[]): void;
107101

0 commit comments

Comments
 (0)