sussudio
Version:
An unofficial VS Code Internal API
686 lines (685 loc) • 30 kB
JavaScript
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
return function (target, key) { decorator(target, key, paramIndex); }
};
import { exec } from 'child_process';
import { app, BrowserWindow, clipboard, Menu, powerMonitor, screen, shell } from 'electron';
import { arch, cpus, freemem, loadavg, platform, release, totalmem, type } from 'os';
import { promisify } from 'util';
import { memoize } from "../../../base/common/decorators.mjs";
import { Emitter, Event } from "../../../base/common/event.mjs";
import { mnemonicButtonLabel } from "../../../base/common/labels.mjs";
import { Disposable } from "../../../base/common/lifecycle.mjs";
import { Schemas } from "../../../base/common/network.mjs";
import { dirname, join, resolve } from "../../../base/common/path.mjs";
import { isLinux, isLinuxSnap, isMacintosh, isWindows } from "../../../base/common/platform.mjs";
import { URI } from "../../../base/common/uri.mjs";
import { realpath } from "../../../base/node/extpath.mjs";
import { virtualMachineHint } from "../../../base/node/id.mjs";
import { Promises, SymlinkSupport } from "../../../base/node/pfs.mjs";
import { findFreePort } from "../../../base/node/ports.mjs";
import { localize } from "../../../nls.mjs";
import { IDialogMainService } from "../../dialogs/electron-main/dialogMainService.mjs";
import { IEnvironmentMainService } from "../../environment/electron-main/environmentMainService.mjs";
import { createDecorator } from "../../instantiation/common/instantiation.mjs";
import { ILifecycleMainService } from "../../lifecycle/electron-main/lifecycleMainService.mjs";
import { ILogService } from "../../log/common/log.mjs";
import { IProductService } from "../../product/common/productService.mjs";
import { IThemeMainService } from "../../theme/electron-main/themeMainService.mjs";
import { IWindowsMainService } from "../../windows/electron-main/windows.mjs";
import { isWorkspaceIdentifier, toWorkspaceIdentifier } from "../../workspace/common/workspace.mjs";
import { IWorkspacesManagementMainService } from "../../workspaces/electron-main/workspacesManagementMainService.mjs";
import { VSBuffer } from "../../../base/common/buffer.mjs";
import { hasWSLFeatureInstalled } from "../../remote/node/wsl.mjs";
import { WindowProfiler } from "../../profiling/electron-main/windowProfiling.mjs";
import { IStateMainService } from "../../state/electron-main/state.mjs";
export const INativeHostMainService = createDecorator('nativeHostMainService');
let NativeHostMainService = class NativeHostMainService extends Disposable {
sharedProcess;
windowsMainService;
dialogMainService;
lifecycleMainService;
environmentMainService;
logService;
productService;
themeMainService;
stateMainService;
workspacesManagementMainService;
constructor(sharedProcess, windowsMainService, dialogMainService, lifecycleMainService, environmentMainService, logService, productService, themeMainService, stateMainService, workspacesManagementMainService) {
super();
this.sharedProcess = sharedProcess;
this.windowsMainService = windowsMainService;
this.dialogMainService = dialogMainService;
this.lifecycleMainService = lifecycleMainService;
this.environmentMainService = environmentMainService;
this.logService = logService;
this.productService = productService;
this.themeMainService = themeMainService;
this.stateMainService = stateMainService;
this.workspacesManagementMainService = workspacesManagementMainService;
}
//#region Properties
get windowId() { throw new Error('Not implemented in electron-main'); }
//#endregion
//#region Events
onDidOpenWindow = Event.map(this.windowsMainService.onDidOpenWindow, window => window.id);
onDidTriggerSystemContextMenu = Event.filter(Event.map(this.windowsMainService.onDidTriggerSystemContextMenu, ({ window, x, y }) => { return { windowId: window.id, x, y }; }), ({ windowId }) => !!this.windowsMainService.getWindowById(windowId));
onDidMaximizeWindow = Event.filter(Event.fromNodeEventEmitter(app, 'browser-window-maximize', (event, window) => window.id), windowId => !!this.windowsMainService.getWindowById(windowId));
onDidUnmaximizeWindow = Event.filter(Event.fromNodeEventEmitter(app, 'browser-window-unmaximize', (event, window) => window.id), windowId => !!this.windowsMainService.getWindowById(windowId));
onDidBlurWindow = Event.filter(Event.fromNodeEventEmitter(app, 'browser-window-blur', (event, window) => window.id), windowId => !!this.windowsMainService.getWindowById(windowId));
onDidFocusWindow = Event.any(Event.map(Event.filter(Event.map(this.windowsMainService.onDidChangeWindowsCount, () => this.windowsMainService.getLastActiveWindow()), window => !!window), window => window.id), Event.filter(Event.fromNodeEventEmitter(app, 'browser-window-focus', (event, window) => window.id), windowId => !!this.windowsMainService.getWindowById(windowId)));
onDidResumeOS = Event.fromNodeEventEmitter(powerMonitor, 'resume');
onDidChangeColorScheme = this.themeMainService.onDidChangeColorScheme;
_onDidChangePassword = this._register(new Emitter());
onDidChangePassword = this._onDidChangePassword.event;
onDidChangeDisplay = Event.debounce(Event.any(Event.filter(Event.fromNodeEventEmitter(screen, 'display-metrics-changed', (event, display, changedMetrics) => changedMetrics), changedMetrics => {
// Electron will emit 'display-metrics-changed' events even when actually
// going fullscreen, because the dock hides. However, we do not want to
// react on this event as there is no change in display bounds.
return !(Array.isArray(changedMetrics) && changedMetrics.length === 1 && changedMetrics[0] === 'workArea');
}), Event.fromNodeEventEmitter(screen, 'display-added'), Event.fromNodeEventEmitter(screen, 'display-removed')), () => { }, 100);
//#endregion
//#region Window
async getWindows() {
const windows = this.windowsMainService.getWindows();
return windows.map(window => ({
id: window.id,
workspace: window.openedWorkspace ?? toWorkspaceIdentifier(window.backupPath, window.isExtensionDevelopmentHost),
title: window.win?.getTitle() ?? '',
filename: window.getRepresentedFilename(),
dirty: window.isDocumentEdited()
}));
}
async getWindowCount(windowId) {
return this.windowsMainService.getWindowCount();
}
async getActiveWindowId(windowId) {
const activeWindow = BrowserWindow.getFocusedWindow() || this.windowsMainService.getLastActiveWindow();
if (activeWindow) {
return activeWindow.id;
}
return undefined;
}
openWindow(windowId, arg1, arg2) {
if (Array.isArray(arg1)) {
return this.doOpenWindow(windowId, arg1, arg2);
}
return this.doOpenEmptyWindow(windowId, arg1);
}
async doOpenWindow(windowId, toOpen, options = Object.create(null)) {
if (toOpen.length > 0) {
await this.windowsMainService.open({
context: 5 /* OpenContext.API */,
contextWindowId: windowId,
urisToOpen: toOpen,
cli: this.environmentMainService.args,
forceNewWindow: options.forceNewWindow,
forceReuseWindow: options.forceReuseWindow,
preferNewWindow: options.preferNewWindow,
diffMode: options.diffMode,
mergeMode: options.mergeMode,
addMode: options.addMode,
gotoLineMode: options.gotoLineMode,
noRecentEntry: options.noRecentEntry,
waitMarkerFileURI: options.waitMarkerFileURI,
remoteAuthority: options.remoteAuthority || undefined
});
}
}
async doOpenEmptyWindow(windowId, options) {
await this.windowsMainService.openEmptyWindow({
context: 5 /* OpenContext.API */,
contextWindowId: windowId
}, options);
}
async toggleFullScreen(windowId) {
const window = this.windowById(windowId);
window?.toggleFullScreen();
}
async handleTitleDoubleClick(windowId) {
const window = this.windowById(windowId);
window?.handleTitleDoubleClick();
}
async isMaximized(windowId) {
const window = this.windowById(windowId);
if (window?.win) {
return window.win.isMaximized();
}
return false;
}
async maximizeWindow(windowId) {
const window = this.windowById(windowId);
if (window?.win) {
window.win.maximize();
}
}
async unmaximizeWindow(windowId) {
const window = this.windowById(windowId);
if (window?.win) {
window.win.unmaximize();
}
}
async minimizeWindow(windowId) {
const window = this.windowById(windowId);
if (window?.win) {
window.win.minimize();
}
}
async updateWindowControls(windowId, options) {
const window = this.windowById(windowId);
if (window) {
window.updateWindowControls(options);
}
}
async focusWindow(windowId, options) {
if (options && typeof options.windowId === 'number') {
windowId = options.windowId;
}
const window = this.windowById(windowId);
window?.focus({ force: options?.force ?? false });
}
async setMinimumSize(windowId, width, height) {
const window = this.windowById(windowId);
if (window?.win) {
const [windowWidth, windowHeight] = window.win.getSize();
const [minWindowWidth, minWindowHeight] = window.win.getMinimumSize();
const [newMinWindowWidth, newMinWindowHeight] = [width ?? minWindowWidth, height ?? minWindowHeight];
const [newWindowWidth, newWindowHeight] = [Math.max(windowWidth, newMinWindowWidth), Math.max(windowHeight, newMinWindowHeight)];
if (minWindowWidth !== newMinWindowWidth || minWindowHeight !== newMinWindowHeight) {
window.win.setMinimumSize(newMinWindowWidth, newMinWindowHeight);
}
if (windowWidth !== newWindowWidth || windowHeight !== newWindowHeight) {
window.win.setSize(newWindowWidth, newWindowHeight);
}
}
}
async saveWindowSplash(windowId, splash) {
this.themeMainService.saveWindowSplash(windowId, splash);
}
//#endregion
//#region macOS Shell Command
async installShellCommand(windowId) {
const { source, target } = await this.getShellCommandLink();
// Only install unless already existing
try {
const { symbolicLink } = await SymlinkSupport.stat(source);
if (symbolicLink && !symbolicLink.dangling) {
const linkTargetRealPath = await realpath(source);
if (target === linkTargetRealPath) {
return;
}
}
// Different source, delete it first
await Promises.unlink(source);
}
catch (error) {
if (error.code !== 'ENOENT') {
throw error; // throw on any error but file not found
}
}
try {
await Promises.symlink(target, source);
}
catch (error) {
if (error.code !== 'EACCES' && error.code !== 'ENOENT') {
throw error;
}
const { response } = await this.showMessageBox(windowId, {
title: this.productService.nameLong,
type: 'info',
message: localize('warnEscalation', "{0} will now prompt with 'osascript' for Administrator privileges to install the shell command.", this.productService.nameShort),
buttons: [
mnemonicButtonLabel(localize({ key: 'ok', comment: ['&& denotes a mnemonic'] }, "&&OK")),
mnemonicButtonLabel(localize({ key: 'cancel', comment: ['&& denotes a mnemonic'] }, "&&Cancel")),
],
noLink: true,
defaultId: 0,
cancelId: 1
});
if (response === 0 /* OK */) {
try {
const command = `osascript -e "do shell script \\"mkdir -p /usr/local/bin && ln -sf \'${target}\' \'${source}\'\\" with administrator privileges"`;
await promisify(exec)(command);
}
catch (error) {
throw new Error(localize('cantCreateBinFolder', "Unable to install the shell command '{0}'.", source));
}
}
}
}
async uninstallShellCommand(windowId) {
const { source } = await this.getShellCommandLink();
try {
await Promises.unlink(source);
}
catch (error) {
switch (error.code) {
case 'EACCES': {
const { response } = await this.showMessageBox(windowId, {
title: this.productService.nameLong,
type: 'info',
message: localize('warnEscalationUninstall', "{0} will now prompt with 'osascript' for Administrator privileges to uninstall the shell command.", this.productService.nameShort),
buttons: [
mnemonicButtonLabel(localize({ key: 'ok', comment: ['&& denotes a mnemonic'] }, "&&OK")),
mnemonicButtonLabel(localize({ key: 'cancel', comment: ['&& denotes a mnemonic'] }, "&&Cancel")),
],
noLink: true,
defaultId: 0,
cancelId: 1
});
if (response === 0 /* OK */) {
try {
const command = `osascript -e "do shell script \\"rm \'${source}\'\\" with administrator privileges"`;
await promisify(exec)(command);
}
catch (error) {
throw new Error(localize('cantUninstall', "Unable to uninstall the shell command '{0}'.", source));
}
}
break;
}
case 'ENOENT':
break; // ignore file not found
default:
throw error;
}
}
}
async getShellCommandLink() {
const target = resolve(this.environmentMainService.appRoot, 'bin', 'code');
const source = `/usr/local/bin/${this.productService.applicationName}`;
// Ensure source exists
const sourceExists = await Promises.exists(target);
if (!sourceExists) {
throw new Error(localize('sourceMissing', "Unable to find shell script in '{0}'", target));
}
return { source, target };
}
//#region Dialog
async showMessageBox(windowId, options) {
return this.dialogMainService.showMessageBox(options, this.toBrowserWindow(windowId));
}
async showSaveDialog(windowId, options) {
return this.dialogMainService.showSaveDialog(options, this.toBrowserWindow(windowId));
}
async showOpenDialog(windowId, options) {
return this.dialogMainService.showOpenDialog(options, this.toBrowserWindow(windowId));
}
toBrowserWindow(windowId) {
const window = this.windowById(windowId);
if (window?.win) {
return window.win;
}
return undefined;
}
async pickFileFolderAndOpen(windowId, options) {
const paths = await this.dialogMainService.pickFileFolder(options);
if (paths) {
await this.doOpenPicked(await Promise.all(paths.map(async (path) => (await SymlinkSupport.existsDirectory(path)) ? { folderUri: URI.file(path) } : { fileUri: URI.file(path) })), options, windowId);
}
}
async pickFolderAndOpen(windowId, options) {
const paths = await this.dialogMainService.pickFolder(options);
if (paths) {
await this.doOpenPicked(paths.map(path => ({ folderUri: URI.file(path) })), options, windowId);
}
}
async pickFileAndOpen(windowId, options) {
const paths = await this.dialogMainService.pickFile(options);
if (paths) {
await this.doOpenPicked(paths.map(path => ({ fileUri: URI.file(path) })), options, windowId);
}
}
async pickWorkspaceAndOpen(windowId, options) {
const paths = await this.dialogMainService.pickWorkspace(options);
if (paths) {
await this.doOpenPicked(paths.map(path => ({ workspaceUri: URI.file(path) })), options, windowId);
}
}
async doOpenPicked(openable, options, windowId) {
await this.windowsMainService.open({
context: 3 /* OpenContext.DIALOG */,
contextWindowId: windowId,
cli: this.environmentMainService.args,
urisToOpen: openable,
forceNewWindow: options.forceNewWindow,
/* remoteAuthority will be determined based on openable */
});
}
//#endregion
//#region OS
async showItemInFolder(windowId, path) {
shell.showItemInFolder(path);
}
async setRepresentedFilename(windowId, path) {
const window = this.windowById(windowId);
window?.setRepresentedFilename(path);
}
async setDocumentEdited(windowId, edited) {
const window = this.windowById(windowId);
window?.setDocumentEdited(edited);
}
async openExternal(windowId, url) {
if (isLinuxSnap) {
this.safeSnapOpenExternal(url);
}
else {
shell.openExternal(url);
}
return true;
}
safeSnapOpenExternal(url) {
// Remove some environment variables before opening to avoid issues...
const gdkPixbufModuleFile = process.env['GDK_PIXBUF_MODULE_FILE'];
const gdkPixbufModuleDir = process.env['GDK_PIXBUF_MODULEDIR'];
delete process.env['GDK_PIXBUF_MODULE_FILE'];
delete process.env['GDK_PIXBUF_MODULEDIR'];
shell.openExternal(url);
// ...but restore them after
process.env['GDK_PIXBUF_MODULE_FILE'] = gdkPixbufModuleFile;
process.env['GDK_PIXBUF_MODULEDIR'] = gdkPixbufModuleDir;
}
moveItemToTrash(windowId, fullPath) {
return shell.trashItem(fullPath);
}
async isAdmin() {
let isAdmin;
if (isWindows) {
isAdmin = (await import('native-is-elevated'))();
}
else {
isAdmin = process.getuid() === 0;
}
return isAdmin;
}
async writeElevated(windowId, source, target, options) {
const sudoPrompt = await import('@vscode/sudo-prompt');
return new Promise((resolve, reject) => {
const sudoCommand = [`"${this.cliPath}"`];
if (options?.unlock) {
sudoCommand.push('--file-chmod');
}
sudoCommand.push('--file-write', `"${source.fsPath}"`, `"${target.fsPath}"`);
const promptOptions = {
name: this.productService.nameLong.replace('-', ''),
icns: (isMacintosh && this.environmentMainService.isBuilt) ? join(dirname(this.environmentMainService.appRoot), `${this.productService.nameShort}.icns`) : undefined
};
sudoPrompt.exec(sudoCommand.join(' '), promptOptions, (error, stdout, stderr) => {
if (stdout) {
this.logService.trace(`[sudo-prompt] received stdout: ${stdout}`);
}
if (stderr) {
this.logService.trace(`[sudo-prompt] received stderr: ${stderr}`);
}
if (error) {
reject(error);
}
else {
resolve(undefined);
}
});
});
}
get cliPath() {
// Windows
if (isWindows) {
if (this.environmentMainService.isBuilt) {
return join(dirname(process.execPath), 'bin', `${this.productService.applicationName}.cmd`);
}
return join(this.environmentMainService.appRoot, 'scripts', 'code-cli.bat');
}
// Linux
if (isLinux) {
if (this.environmentMainService.isBuilt) {
return join(dirname(process.execPath), 'bin', `${this.productService.applicationName}`);
}
return join(this.environmentMainService.appRoot, 'scripts', 'code-cli.sh');
}
// macOS
if (this.environmentMainService.isBuilt) {
return join(this.environmentMainService.appRoot, 'bin', 'code');
}
return join(this.environmentMainService.appRoot, 'scripts', 'code-cli.sh');
}
async getOSStatistics() {
return {
totalmem: totalmem(),
freemem: freemem(),
loadavg: loadavg()
};
}
async getOSProperties() {
return {
arch: arch(),
platform: platform(),
release: release(),
type: type(),
cpus: cpus()
};
}
async getOSVirtualMachineHint() {
return virtualMachineHint.value();
}
async getOSColorScheme() {
return this.themeMainService.getColorScheme();
}
// WSL
async hasWSLFeatureInstalled() {
return isWindows && hasWSLFeatureInstalled();
}
//#endregion
//#region Process
async killProcess(windowId, pid, code) {
process.kill(pid, code);
}
//#endregion
//#region Clipboard
async readClipboardText(windowId, type) {
return clipboard.readText(type);
}
async writeClipboardText(windowId, text, type) {
return clipboard.writeText(text, type);
}
async readClipboardFindText(windowId) {
return clipboard.readFindText();
}
async writeClipboardFindText(windowId, text) {
return clipboard.writeFindText(text);
}
async writeClipboardBuffer(windowId, format, buffer, type) {
return clipboard.writeBuffer(format, Buffer.from(buffer.buffer), type);
}
async readClipboardBuffer(windowId, format) {
return VSBuffer.wrap(clipboard.readBuffer(format));
}
async hasClipboard(windowId, format, type) {
return clipboard.has(format, type);
}
//#endregion
//#region macOS Touchbar
async newWindowTab() {
await this.windowsMainService.open({
context: 5 /* OpenContext.API */,
cli: this.environmentMainService.args,
forceNewTabbedWindow: true,
forceEmpty: true,
remoteAuthority: this.environmentMainService.args.remote || undefined
});
}
async showPreviousWindowTab() {
Menu.sendActionToFirstResponder('selectPreviousTab:');
}
async showNextWindowTab() {
Menu.sendActionToFirstResponder('selectNextTab:');
}
async moveWindowTabToNewWindow() {
Menu.sendActionToFirstResponder('moveTabToNewWindow:');
}
async mergeAllWindowTabs() {
Menu.sendActionToFirstResponder('mergeAllWindows:');
}
async toggleWindowTabsBar() {
Menu.sendActionToFirstResponder('toggleTabBar:');
}
async updateTouchBar(windowId, items) {
const window = this.windowById(windowId);
window?.updateTouchBar(items);
}
//#endregion
//#region Lifecycle
async notifyReady(windowId) {
const window = this.windowById(windowId);
window?.setReady();
}
async relaunch(windowId, options) {
return this.lifecycleMainService.relaunch(options);
}
async reload(windowId, options) {
const window = this.windowById(windowId);
if (window) {
// Special case: support `transient` workspaces by preventing
// the reload and rather go back to an empty window. Transient
// workspaces should never restore, even when the user wants
// to reload.
// For: https://github.com/microsoft/vscode/issues/119695
if (isWorkspaceIdentifier(window.openedWorkspace)) {
const configPath = window.openedWorkspace.configPath;
if (configPath.scheme === Schemas.file) {
const workspace = await this.workspacesManagementMainService.resolveLocalWorkspace(configPath);
if (workspace?.transient) {
return this.openWindow(window.id, { forceReuseWindow: true });
}
}
}
// Proceed normally to reload the window
return this.lifecycleMainService.reload(window, options?.disableExtensions !== undefined ? { _: [], 'disable-extensions': options.disableExtensions } : undefined);
}
}
async closeWindow(windowId) {
this.closeWindowById(windowId, windowId);
}
async closeWindowById(currentWindowId, targetWindowId) {
const window = this.windowById(targetWindowId);
if (window?.win) {
return window.win.close();
}
}
async quit(windowId) {
// If the user selected to exit from an extension development host window, do not quit, but just
// close the window unless this is the last window that is opened.
const window = this.windowsMainService.getLastActiveWindow();
if (window?.isExtensionDevelopmentHost && this.windowsMainService.getWindowCount() > 1 && window.win) {
window.win.close();
}
// Otherwise: normal quit
else {
this.lifecycleMainService.quit();
}
}
async exit(windowId, code) {
await this.lifecycleMainService.kill(code);
}
//#endregion
//#region Connectivity
async resolveProxy(windowId, url) {
const window = this.windowById(windowId);
const session = window?.win?.webContents?.session;
if (session) {
return session.resolveProxy(url);
}
else {
return undefined;
}
}
findFreePort(windowId, startPort, giveUpAfter, timeout, stride = 1) {
return findFreePort(startPort, giveUpAfter, timeout, stride);
}
//#endregion
//#region Development
async openDevTools(windowId, options) {
const window = this.windowById(windowId);
if (window?.win) {
window.win.webContents.openDevTools(options);
}
}
async toggleDevTools(windowId) {
const window = this.windowById(windowId);
if (window?.win) {
const contents = window.win.webContents;
contents.toggleDevTools();
}
}
async sendInputEvent(windowId, event) {
const window = this.windowById(windowId);
if (window?.win && (event.type === 'mouseDown' || event.type === 'mouseUp')) {
window.win.webContents.sendInputEvent(event);
}
}
async enableSandbox(windowId, enabled) {
if (enabled) {
this.stateMainService.setItem('window.experimental.useSandbox', true);
}
else {
this.stateMainService.removeItem('window.experimental.useSandbox');
}
}
async toggleSharedProcessWindow() {
return this.sharedProcess.toggle();
}
//#endregion
// #region Performance
async profileRenderer(windowId, session, duration) {
const win = this.windowById(windowId);
if (!win || !win.win) {
throw new Error();
}
const profiler = new WindowProfiler(win.win, session, this.logService);
const result = await profiler.inspect(duration);
return result;
}
// #endregion
//#region Registry (windows)
async windowsGetStringRegKey(windowId, hive, path, name) {
if (!isWindows) {
return undefined;
}
const Registry = await import('@vscode/windows-registry');
try {
return Registry.GetStringRegKey(hive, path, name);
}
catch {
return undefined;
}
}
//#endregion
windowById(windowId) {
if (typeof windowId !== 'number') {
return undefined;
}
return this.windowsMainService.getWindowById(windowId);
}
};
__decorate([
memoize
], NativeHostMainService.prototype, "cliPath", null);
NativeHostMainService = __decorate([
__param(1, IWindowsMainService),
__param(2, IDialogMainService),
__param(3, ILifecycleMainService),
__param(4, IEnvironmentMainService),
__param(5, ILogService),
__param(6, IProductService),
__param(7, IThemeMainService),
__param(8, IStateMainService),
__param(9, IWorkspacesManagementMainService)
], NativeHostMainService);
export { NativeHostMainService };