mirror of
https://github.com/coder/code-server.git
synced 2026-05-06 12:31:58 +02:00
chore(vscode): update to 1.56.0
This commit is contained in:
@@ -1,80 +0,0 @@
|
||||
<!-- Copyright (C) Microsoft Corporation. All rights reserved. -->
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<script>
|
||||
performance.mark('code/didStartRenderer')
|
||||
</script>
|
||||
<meta charset="utf-8" />
|
||||
|
||||
<!-- Disable pinch zooming -->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
|
||||
|
||||
<!-- Workbench Configuration -->
|
||||
<meta id="vscode-workbench-web-configuration" data-settings="{{WORKBENCH_WEB_CONFIGURATION}}">
|
||||
|
||||
<!-- Workbench Auth Session -->
|
||||
<meta id="vscode-workbench-auth-session" data-settings="{{WORKBENCH_AUTH_SESSION}}">
|
||||
|
||||
<!-- Workbench Icon/Manifest/CSS -->
|
||||
<link rel="icon" href="{{WORKBENCH_WEB_BASE_URL}}/favicon.ico" type="image/x-icon" />
|
||||
<link rel="manifest" href="{{WORKBENCH_WEB_BASE_URL}}/manifest.json">
|
||||
<link data-name="vs/workbench/workbench.web.api" rel="stylesheet" href="{{WORKBENCH_WEB_BASE_URL}}/out/vs/workbench/workbench.web.api.css">
|
||||
|
||||
</head>
|
||||
|
||||
<body aria-label="">
|
||||
</body>
|
||||
|
||||
<!-- Startup (do not modify order of script tags!) -->
|
||||
<script>
|
||||
var baseUrl = '{{WORKBENCH_WEB_BASE_URL}}';
|
||||
self.require = {
|
||||
baseUrl: `${baseUrl}/out`,
|
||||
recordStats: true,
|
||||
trustedTypesPolicy: window.trustedTypes?.createPolicy('amdLoader', {
|
||||
createScriptURL(value) {
|
||||
if(value.startsWith(baseUrl)) {
|
||||
return value;
|
||||
}
|
||||
throw new Error(`Invalid script url: ${value}`)
|
||||
}
|
||||
}),
|
||||
paths: {
|
||||
'vscode-textmate': `${baseUrl}/node_modules/vscode-textmate/release/main`,
|
||||
'vscode-oniguruma': `${baseUrl}/node_modules/vscode-oniguruma/release/main`,
|
||||
'xterm': `${baseUrl}/node_modules/xterm/lib/xterm.js`,
|
||||
'xterm-addon-search': `${baseUrl}/node_modules/xterm-addon-search/lib/xterm-addon-search.js`,
|
||||
'xterm-addon-unicode11': `${baseUrl}/node_modules/xterm-addon-unicode11/lib/xterm-addon-unicode11.js`,
|
||||
'xterm-addon-webgl': `${baseUrl}/node_modules/xterm-addon-webgl/lib/xterm-addon-webgl.js`,
|
||||
'tas-client-umd': `${baseUrl}/node_modules/tas-client-umd/lib/tas-client-umd.js`,
|
||||
'iconv-lite-umd': `${baseUrl}/node_modules/iconv-lite-umd/lib/iconv-lite-umd.js`,
|
||||
'jschardet': `${baseUrl}/node_modules/jschardet/dist/jschardet.min.js`,
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<script src="{{WORKBENCH_WEB_BASE_URL}}/out/vs/loader.js"></script>
|
||||
<script>
|
||||
performance.mark('code/willLoadWorkbenchMain');
|
||||
</script>
|
||||
|
||||
<script>
|
||||
if ("{{WORKBENCH_DEV}}" === "true") {
|
||||
const workbench = document.createElement('script');
|
||||
workbench.innerText = "require(['vs/code/browser/workbench/workbench'], function() {});";
|
||||
document.body.appendChild(workbench);
|
||||
} else {
|
||||
const nls = document.createElement('script');
|
||||
nls.setAttribute('src', '{{WORKBENCH_WEB_BASE_URL}}/out/vs/workbench/workbench.web.api.nls.js');
|
||||
document.body.appendChild(nls);
|
||||
|
||||
const api = document.createElement('script');
|
||||
api.setAttribute('src', '{{WORKBENCH_WEB_BASE_URL}}/out/vs/workbench/workbench.web.api.js');
|
||||
document.body.appendChild(api);
|
||||
|
||||
const workbench = document.createElement('script');
|
||||
workbench.setAttribute('src', '{{WORKBENCH_WEB_BASE_URL}}/out/vs/code/browser/workbench/workbench.js');
|
||||
document.body.appendChild(workbench);
|
||||
}
|
||||
</script>
|
||||
</html>
|
||||
@@ -282,23 +282,28 @@ class WorkspaceProvider implements IWorkspaceProvider {
|
||||
public readonly payload: object
|
||||
) { }
|
||||
|
||||
async open(workspace: IWorkspace, options?: { reuse?: boolean, payload?: object }): Promise<void> {
|
||||
async open(workspace: IWorkspace, options?: { reuse?: boolean, payload?: object }): Promise<boolean> {
|
||||
if (options?.reuse && !options.payload && this.isSame(this.workspace, workspace)) {
|
||||
return; // return early if workspace and environment is not changing and we are reusing window
|
||||
return true; // return early if workspace and environment is not changing and we are reusing window
|
||||
}
|
||||
|
||||
const targetHref = this.createTargetUrl(workspace, options);
|
||||
if (targetHref) {
|
||||
if (options?.reuse) {
|
||||
window.location.href = targetHref;
|
||||
return true;
|
||||
} else {
|
||||
let result;
|
||||
if (isStandalone) {
|
||||
window.open(targetHref, '_blank', 'toolbar=no'); // ensures to open another 'standalone' window!
|
||||
result = window.open(targetHref, '_blank', 'toolbar=no'); // ensures to open another 'standalone' window!
|
||||
} else {
|
||||
window.open(targetHref);
|
||||
result = window.open(targetHref);
|
||||
}
|
||||
|
||||
return !!result;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private createTargetUrl(workspace: IWorkspace, options?: { reuse?: boolean, payload?: object }): string | undefined {
|
||||
@@ -429,13 +434,6 @@ class WindowIndicator implements IWindowIndicator {
|
||||
config.folderUri.authority = normalizeAuthority(config.folderUri.authority);
|
||||
}
|
||||
|
||||
// Revive static extension locations
|
||||
if (Array.isArray(config.staticExtensions)) {
|
||||
config.staticExtensions.forEach(extension => {
|
||||
extension.extensionLocation = URI.revive(extension.extensionLocation);
|
||||
});
|
||||
}
|
||||
|
||||
// Find workspace to open and payload
|
||||
let foundWorkspace = false;
|
||||
let workspace: IWorkspace;
|
||||
@@ -497,6 +495,13 @@ class WindowIndicator implements IWindowIndicator {
|
||||
// Finally create workbench
|
||||
create(document.body, {
|
||||
...config,
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
developmentOptions: {
|
||||
logLevel: logLevel ? parseLogLevel(logLevel) : undefined,
|
||||
...config.developmentOptions
|
||||
},
|
||||
>>>>>>> 58ce849223667f77dc0d6d7658870ca3f815e17f
|
||||
settingsSyncOptions,
|
||||
windowIndicator,
|
||||
productQualityChangeHandler,
|
||||
|
||||
@@ -16,10 +16,15 @@
|
||||
// Load shared process into window
|
||||
bootstrapWindow.load(['vs/code/electron-browser/sharedProcess/sharedProcessMain'], function (sharedProcess, configuration) {
|
||||
return sharedProcess.main(configuration);
|
||||
});
|
||||
|
||||
|
||||
//#region Globals
|
||||
},
|
||||
{
|
||||
configureDeveloperSettings: function () {
|
||||
return {
|
||||
disallowReloadKeybinding: true
|
||||
};
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* @returns {{ avoidMonkeyPatchFromAppInsights: () => void; }}
|
||||
@@ -30,12 +35,27 @@
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {{ load: (modules: string[], resultCallback: (result, configuration: object) => any, options?: object) => unknown }}
|
||||
* @typedef {import('../../../base/parts/sandbox/common/sandboxTypes').ISandboxConfiguration} ISandboxConfiguration
|
||||
*
|
||||
* @returns {{
|
||||
* load: (
|
||||
* modules: string[],
|
||||
* resultCallback: (result, configuration: ISandboxConfiguration) => unknown,
|
||||
* options?: {
|
||||
* configureDeveloperSettings?: (config: ISandboxConfiguration) => {
|
||||
* forceEnableDeveloperKeybindings?: boolean,
|
||||
* disallowReloadKeybinding?: boolean,
|
||||
* removeDeveloperKeybindingsAfterLoad?: boolean
|
||||
* },
|
||||
* canModifyDOM?: (config: ISandboxConfiguration) => void,
|
||||
* beforeLoaderConfig?: (loaderConfig: object) => void,
|
||||
* beforeRequire?: () => void
|
||||
* }
|
||||
* ) => Promise<unknown>
|
||||
* }}
|
||||
*/
|
||||
function bootstrapWindowLib() {
|
||||
// @ts-ignore (defined in bootstrap-window.js)
|
||||
return window.MonacoBootstrapWindow;
|
||||
}
|
||||
|
||||
//#endregion
|
||||
}());
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as fs from 'fs';
|
||||
import { release } from 'os';
|
||||
import { release, hostname } from 'os';
|
||||
import { gracefulify } from 'graceful-fs';
|
||||
import { ipcRenderer } from 'electron';
|
||||
import product from 'vs/platform/product/common/product';
|
||||
@@ -30,7 +30,7 @@ import { TelemetryAppenderChannel } from 'vs/platform/telemetry/common/telemetry
|
||||
import { TelemetryService } from 'vs/platform/telemetry/common/telemetryService';
|
||||
import { AppInsightsAppender } from 'vs/platform/telemetry/node/appInsightsAppender';
|
||||
import { ILogService, ILoggerService, MultiplexLogService, ConsoleLogger } from 'vs/platform/log/common/log';
|
||||
import { LogLevelChannelClient, FollowerLogService } from 'vs/platform/log/common/logIpc';
|
||||
import { LogLevelChannelClient, FollowerLogService, LoggerChannelClient } from 'vs/platform/log/common/logIpc';
|
||||
import { LocalizationsService } from 'vs/platform/localizations/node/localizations';
|
||||
import { ILocalizationsService } from 'vs/platform/localizations/common/localizations';
|
||||
import { combinedDisposable, Disposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
@@ -42,7 +42,6 @@ import { StorageDataCleaner } from 'vs/code/electron-browser/sharedProcess/contr
|
||||
import { LogsDataCleaner } from 'vs/code/electron-browser/sharedProcess/contrib/logsDataCleaner';
|
||||
import { IMainProcessService } from 'vs/platform/ipc/electron-sandbox/services';
|
||||
import { MessagePortMainProcessService } from 'vs/platform/ipc/electron-browser/mainProcessService';
|
||||
import { SpdLogLogger } from 'vs/platform/log/node/spdlogLog';
|
||||
import { DiagnosticsService } from 'vs/platform/diagnostics/node/diagnosticsService';
|
||||
import { IDiagnosticsService } from 'vs/platform/diagnostics/common/diagnostics';
|
||||
import { FileService } from 'vs/platform/files/common/fileService';
|
||||
@@ -55,7 +54,6 @@ import { UserDataSyncService } from 'vs/platform/userDataSync/common/userDataSyn
|
||||
import { UserDataSyncStoreService, UserDataSyncStoreManagementService } from 'vs/platform/userDataSync/common/userDataSyncStoreService';
|
||||
import { UserDataSyncUtilServiceClient, UserDataAutoSyncChannel, UserDataSyncMachinesServiceChannel, UserDataSyncAccountServiceChannel, UserDataSyncStoreManagementServiceChannel } from 'vs/platform/userDataSync/common/userDataSyncIpc';
|
||||
import { INativeHostService } from 'vs/platform/native/electron-sandbox/native';
|
||||
import { LoggerService } from 'vs/platform/log/node/loggerService';
|
||||
import { UserDataSyncLogService } from 'vs/platform/userDataSync/common/userDataSyncLog';
|
||||
import { UserDataAutoSyncService } from 'vs/platform/userDataSync/electron-sandbox/userDataAutoSyncService';
|
||||
import { NativeStorageService } from 'vs/platform/storage/electron-sandbox/storageService';
|
||||
@@ -79,7 +77,6 @@ import { LocalizationsUpdater } from 'vs/code/electron-browser/sharedProcess/con
|
||||
import { DeprecatedExtensionsCleaner } from 'vs/code/electron-browser/sharedProcess/contrib/deprecatedExtensionsCleaner';
|
||||
import { onUnexpectedError, setUnexpectedErrorHandler } from 'vs/base/common/errors';
|
||||
import { toErrorMessage } from 'vs/base/common/errorMessage';
|
||||
import { join } from 'vs/base/common/path';
|
||||
import { TerminalIpcChannels } from 'vs/platform/terminal/common/terminal';
|
||||
import { PtyHostService } from 'vs/platform/terminal/node/ptyHostService';
|
||||
import { ILocalPtyService } from 'vs/platform/terminal/electron-sandbox/terminal';
|
||||
@@ -87,6 +84,8 @@ import { UserDataSyncChannel } from 'vs/platform/userDataSync/common/userDataSyn
|
||||
import { IChecksumService } from 'vs/platform/checksum/common/checksumService';
|
||||
import { ChecksumService } from 'vs/platform/checksum/node/checksumService';
|
||||
import { CustomEndpointTelemetryService } from 'vs/platform/telemetry/node/customEndpointTelemetryService';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { joinPath } from 'vs/base/common/resources';
|
||||
|
||||
class SharedProcessMain extends Disposable {
|
||||
|
||||
@@ -148,25 +147,29 @@ class SharedProcessMain extends Disposable {
|
||||
const productService = { _serviceBrand: undefined, ...product };
|
||||
services.set(IProductService, productService);
|
||||
|
||||
// Main Process
|
||||
const mainRouter = new StaticRouter(ctx => ctx === 'main');
|
||||
const mainProcessService = new MessagePortMainProcessService(this.server, mainRouter);
|
||||
services.set(IMainProcessService, mainProcessService);
|
||||
|
||||
// Environment
|
||||
const environmentService = new NativeEnvironmentService(this.configuration.args, productService);
|
||||
services.set(INativeEnvironmentService, environmentService);
|
||||
|
||||
// Logger
|
||||
const logLevelClient = new LogLevelChannelClient(this.server.getChannel('logLevel', mainRouter));
|
||||
const loggerService = new LoggerChannelClient(this.configuration.logLevel, logLevelClient.onDidChangeLogLevel, mainProcessService.getChannel('logger'));
|
||||
services.set(ILoggerService, loggerService);
|
||||
|
||||
// Log
|
||||
const mainRouter = new StaticRouter(ctx => ctx === 'main');
|
||||
const logLevelClient = new LogLevelChannelClient(this.server.getChannel('logLevel', mainRouter)); // we only use this for log levels
|
||||
const multiplexLogger = this._register(new MultiplexLogService([
|
||||
this._register(new ConsoleLogger(this.configuration.logLevel)),
|
||||
this._register(new SpdLogLogger('sharedprocess', join(environmentService.logsPath, 'sharedprocess.log'), true, this.configuration.logLevel))
|
||||
this._register(loggerService.createLogger(joinPath(URI.file(environmentService.logsPath), 'sharedprocess.log'), { name: 'sharedprocess' }))
|
||||
]));
|
||||
|
||||
const logService = this._register(new FollowerLogService(logLevelClient, multiplexLogger));
|
||||
services.set(ILogService, logService);
|
||||
|
||||
// Main Process
|
||||
const mainProcessService = new MessagePortMainProcessService(this.server, mainRouter);
|
||||
services.set(IMainProcessService, mainProcessService);
|
||||
|
||||
// Files
|
||||
const fileService = this._register(new FileService(logService));
|
||||
services.set(IFileService, fileService);
|
||||
@@ -205,18 +208,14 @@ class SharedProcessMain extends Disposable {
|
||||
const activeWindowRouter = new StaticRouter(ctx => activeWindowManager.getActiveClientId().then(id => ctx === id));
|
||||
services.set(IExtensionRecommendationNotificationService, new ExtensionRecommendationNotificationServiceChannelClient(this.server.getChannel('extensionRecommendationNotification', activeWindowRouter)));
|
||||
|
||||
// Logger
|
||||
const loggerService = this._register(new LoggerService(logService, fileService));
|
||||
services.set(ILoggerService, loggerService);
|
||||
|
||||
// Telemetry
|
||||
const { appRoot, extensionsPath, extensionDevelopmentLocationURI, isBuilt, installSourcePath } = environmentService;
|
||||
|
||||
let telemetryService: ITelemetryService;
|
||||
let telemetryAppender: ITelemetryAppender;
|
||||
if (!extensionDevelopmentLocationURI && !environmentService.disableTelemetry && productService.enableTelemetry) {
|
||||
if (!environmentService.isExtensionDevelopment && !environmentService.disableTelemetry && productService.enableTelemetry) {
|
||||
telemetryAppender = new TelemetryLogAppender(loggerService, environmentService);
|
||||
|
||||
const { appRoot, extensionsPath, isBuilt, installSourcePath } = environmentService;
|
||||
|
||||
// Application Insights
|
||||
if (productService.aiConfig && productService.aiConfig.asimovKey && isBuilt) {
|
||||
const appInsightsAppender = new AppInsightsAppender('monacoworkbench', null, productService.aiConfig.asimovKey);
|
||||
@@ -226,7 +225,7 @@ class SharedProcessMain extends Disposable {
|
||||
|
||||
telemetryService = new TelemetryService({
|
||||
appender: telemetryAppender,
|
||||
commonProperties: resolveCommonProperties(fileService, release(), process.arch, productService.commit, productService.version, this.configuration.machineId, productService.msftInternalDomains, installSourcePath),
|
||||
commonProperties: resolveCommonProperties(fileService, release(), hostname(), process.arch, productService.commit, productService.version, this.configuration.machineId, productService.msftInternalDomains, installSourcePath),
|
||||
sendErrorTelemetry: true,
|
||||
piiPaths: [appRoot, extensionsPath]
|
||||
}, configurationService);
|
||||
@@ -273,7 +272,7 @@ class SharedProcessMain extends Disposable {
|
||||
services.set(IUserDataSyncService, new SyncDescriptor(UserDataSyncService));
|
||||
|
||||
// Terminal
|
||||
services.set(ILocalPtyService, this._register(new PtyHostService(logService)));
|
||||
services.set(ILocalPtyService, this._register(new PtyHostService(logService, telemetryService)));
|
||||
|
||||
return new InstantiationService(services);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src 'self' https: data: blob: vscode-remote-resource:; media-src 'none'; frame-src 'self' vscode-webview: https://*.vscode-webview-test.com; object-src 'self'; script-src 'self' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; connect-src 'self' https: ws:; font-src 'self' https: vscode-remote-resource:;">
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src 'self' https: data: blob: vscode-remote-resource:; media-src 'none'; frame-src 'self' vscode-webview:; object-src 'self'; script-src 'self' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; connect-src 'self' https: ws:; font-src 'self' https: vscode-remote-resource:;">
|
||||
<meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script'; trusted-types default TrustedFunctionWorkaround ExtensionScripts amdLoader cellRendererEditorText defaultWorkerFactory diffEditorWidget domLineBreaksComputer editorViewLayer diffReview extensionHostWorker insane notebookOutputRenderer safeInnerHtml standaloneColorizer tokenizeToString webNestedWorkerExtensionHost webWorkerExtensionHost;">
|
||||
</head>
|
||||
<body aria-label="">
|
||||
|
||||
@@ -32,15 +32,38 @@
|
||||
return require('vs/workbench/electron-browser/desktop.main').main(configuration);
|
||||
},
|
||||
{
|
||||
removeDeveloperKeybindingsAfterLoad: true,
|
||||
configureDeveloperSettings: function (windowConfig) {
|
||||
return {
|
||||
// disable automated devtools opening on error when running extension tests
|
||||
// as this can lead to undeterministic test exectuion (devtools steals focus)
|
||||
forceDisableShowDevtoolsOnError: typeof windowConfig.extensionTestsPath === 'string',
|
||||
// enable devtools keybindings in extension development window
|
||||
forceEnableDeveloperKeybindings: Array.isArray(windowConfig.extensionDevelopmentPath) && windowConfig.extensionDevelopmentPath.length > 0,
|
||||
removeDeveloperKeybindingsAfterLoad: true
|
||||
};
|
||||
},
|
||||
canModifyDOM: function (windowConfig) {
|
||||
showPartsSplash(windowConfig);
|
||||
},
|
||||
beforeLoaderConfig: function (windowConfig, loaderConfig) {
|
||||
beforeLoaderConfig: function (loaderConfig) {
|
||||
loaderConfig.recordStats = true;
|
||||
},
|
||||
beforeRequire: function () {
|
||||
performance.mark('code/willLoadWorkbenchMain');
|
||||
|
||||
// It looks like browsers only lazily enable
|
||||
// the <canvas> element when needed. Since we
|
||||
// leverage canvas elements in our code in many
|
||||
// locations, we try to help the browser to
|
||||
// initialize canvas when it is idle, right
|
||||
// before we wait for the scripts to be loaded.
|
||||
// @ts-ignore
|
||||
window.requestIdleCallback(() => {
|
||||
const canvas = document.createElement('canvas');
|
||||
const context = canvas.getContext('2d');
|
||||
context.clearRect(0, 0, canvas.width, canvas.height);
|
||||
canvas.remove();
|
||||
}, { timeout: 50 });
|
||||
}
|
||||
}
|
||||
);
|
||||
@@ -62,12 +85,27 @@
|
||||
}
|
||||
});
|
||||
|
||||
//region Helpers
|
||||
//#region Helpers
|
||||
|
||||
/**
|
||||
* @typedef {import('../../../platform/windows/common/windows').INativeWindowConfiguration} INativeWindowConfiguration
|
||||
*
|
||||
* @returns {{
|
||||
* load: (modules: string[], resultCallback: (result, configuration: import('../../../platform/windows/common/windows').INativeWindowConfiguration) => any, options: object) => unknown,
|
||||
* globals: () => typeof import('../../../base/parts/sandbox/electron-sandbox/globals')
|
||||
* load: (
|
||||
* modules: string[],
|
||||
* resultCallback: (result, configuration: INativeWindowConfiguration) => unknown,
|
||||
* options?: {
|
||||
* configureDeveloperSettings?: (config: INativeWindowConfiguration & object) => {
|
||||
* forceDisableShowDevtoolsOnError?: boolean,
|
||||
* forceEnableDeveloperKeybindings?: boolean,
|
||||
* disallowReloadKeybinding?: boolean,
|
||||
* removeDeveloperKeybindingsAfterLoad?: boolean
|
||||
* },
|
||||
* canModifyDOM?: (config: INativeWindowConfiguration & object) => void,
|
||||
* beforeLoaderConfig?: (loaderConfig: object) => void,
|
||||
* beforeRequire?: () => void
|
||||
* }
|
||||
* ) => Promise<unknown>
|
||||
* }}
|
||||
*/
|
||||
function bootstrapWindowLib() {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { release } from 'os';
|
||||
import { release, hostname } from 'os';
|
||||
import { statSync } from 'fs';
|
||||
import { app, ipcMain, systemPreferences, contentTracing, protocol, BrowserWindow, dialog, session } from 'electron';
|
||||
import { IProcessEnvironment, isWindows, isMacintosh, isLinux, isLinuxSnap } from 'vs/base/common/platform';
|
||||
@@ -35,7 +35,6 @@ import { TelemetryService, ITelemetryServiceConfig } from 'vs/platform/telemetry
|
||||
import { resolveCommonProperties } from 'vs/platform/telemetry/common/commonProperties';
|
||||
import { IProductService } from 'vs/platform/product/common/productService';
|
||||
import { ProxyAuthHandler } from 'vs/code/electron-main/auth';
|
||||
import { FileProtocolHandler } from 'vs/code/electron-main/protocol';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { IWindowsMainService, ICodeWindow, OpenContext, WindowError } from 'vs/platform/windows/electron-main/windows';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
@@ -72,7 +71,7 @@ import { withNullAsUndefined } from 'vs/base/common/types';
|
||||
import { mnemonicButtonLabel, getPathLabel } from 'vs/base/common/labels';
|
||||
import { WebviewMainService } from 'vs/platform/webview/electron-main/webviewMainService';
|
||||
import { IWebviewManagerService } from 'vs/platform/webview/common/webviewManagerService';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { FileOperationError, FileOperationResult, IFileService } from 'vs/platform/files/common/files';
|
||||
import { stripComments } from 'vs/base/common/json';
|
||||
import { generateUuid } from 'vs/base/common/uuid';
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
@@ -94,6 +93,7 @@ import { ISignService } from 'vs/platform/sign/common/sign';
|
||||
* even if the user starts many instances (e.g. from the command line).
|
||||
*/
|
||||
export class CodeApplication extends Disposable {
|
||||
|
||||
private windowsMainService: IWindowsMainService | undefined;
|
||||
private nativeHostMainService: INativeHostMainService | undefined;
|
||||
|
||||
@@ -187,7 +187,7 @@ export class CodeApplication extends Disposable {
|
||||
|
||||
const uri = URI.parse(source);
|
||||
if (uri.scheme === Schemas.vscodeWebview) {
|
||||
return uri.path === '/index.html' || uri.path === '/electron-browser/index.html';
|
||||
return uri.path === '/index.html' || uri.path === '/electron-browser-index.html';
|
||||
}
|
||||
|
||||
const srcUri = uri.fsPath.toLowerCase();
|
||||
@@ -226,17 +226,18 @@ export class CodeApplication extends Disposable {
|
||||
this.nativeHostMainService?.openExternal(undefined, url);
|
||||
});
|
||||
|
||||
const webviewFrameUrl = 'about:blank?webviewFrame';
|
||||
const isUrlFromWebview = (requestingUrl: string) =>
|
||||
requestingUrl.startsWith(`${Schemas.vscodeWebview}://`);
|
||||
|
||||
session.defaultSession.setPermissionRequestHandler((_webContents, permission /* 'media' | 'geolocation' | 'notifications' | 'midiSysex' | 'pointerLock' | 'fullscreen' | 'openExternal' */, callback, details) => {
|
||||
if (details.requestingUrl === webviewFrameUrl) {
|
||||
if (isUrlFromWebview(details.requestingUrl)) {
|
||||
return callback(permission === 'clipboard-read');
|
||||
}
|
||||
return callback(false);
|
||||
});
|
||||
|
||||
session.defaultSession.setPermissionCheckHandler((_webContents, permission /* 'media' */, _origin, details) => {
|
||||
if (details.requestingUrl === webviewFrameUrl) {
|
||||
if (isUrlFromWebview(details.requestingUrl)) {
|
||||
return permission === 'clipboard-read';
|
||||
}
|
||||
return false;
|
||||
@@ -282,71 +283,73 @@ export class CodeApplication extends Disposable {
|
||||
//#region Bootstrap IPC Handlers
|
||||
|
||||
let slowShellResolveWarningShown = false;
|
||||
ipcMain.on('vscode:fetchShellEnv', async event => {
|
||||
ipcMain.handle('vscode:fetchShellEnv', event => {
|
||||
return new Promise(async resolve => {
|
||||
|
||||
// DO NOT remove: not only usual windows are fetching the
|
||||
// shell environment but also shared process, issue reporter
|
||||
// etc, so we need to reply via `webContents` always
|
||||
const webContents = event.sender;
|
||||
// DO NOT remove: not only usual windows are fetching the
|
||||
// shell environment but also shared process, issue reporter
|
||||
// etc, so we need to reply via `webContents` always
|
||||
const webContents = event.sender;
|
||||
|
||||
let replied = false;
|
||||
let replied = false;
|
||||
|
||||
function acceptShellEnv(env: NodeJS.ProcessEnv): void {
|
||||
clearTimeout(shellEnvSlowWarningHandle);
|
||||
clearTimeout(shellEnvTimeoutErrorHandle);
|
||||
function acceptShellEnv(env: IProcessEnvironment): void {
|
||||
clearTimeout(shellEnvSlowWarningHandle);
|
||||
clearTimeout(shellEnvTimeoutErrorHandle);
|
||||
|
||||
if (!replied) {
|
||||
replied = true;
|
||||
if (!replied) {
|
||||
replied = true;
|
||||
|
||||
if (!webContents.isDestroyed()) {
|
||||
webContents.send('vscode:acceptShellEnv', env);
|
||||
if (!webContents.isDestroyed()) {
|
||||
resolve(env);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle slow shell environment resolve calls:
|
||||
// - a warning after 3s but continue to resolve (only once in active window)
|
||||
// - an error after 10s and stop trying to resolve (in every window where this happens)
|
||||
const cts = new CancellationTokenSource();
|
||||
// Handle slow shell environment resolve calls:
|
||||
// - a warning after 3s but continue to resolve (only once in active window)
|
||||
// - an error after 10s and stop trying to resolve (in every window where this happens)
|
||||
const cts = new CancellationTokenSource();
|
||||
|
||||
const shellEnvSlowWarningHandle = setTimeout(() => {
|
||||
if (!slowShellResolveWarningShown) {
|
||||
this.windowsMainService?.sendToFocused('vscode:showShellEnvSlowWarning', cts.token);
|
||||
slowShellResolveWarningShown = true;
|
||||
const shellEnvSlowWarningHandle = setTimeout(() => {
|
||||
if (!slowShellResolveWarningShown) {
|
||||
this.windowsMainService?.sendToFocused('vscode:showShellEnvSlowWarning', cts.token);
|
||||
slowShellResolveWarningShown = true;
|
||||
}
|
||||
}, 3000);
|
||||
|
||||
const window = this.windowsMainService?.getWindowByWebContents(event.sender); // Note: this can be `undefined` for the shared process!!
|
||||
const shellEnvTimeoutErrorHandle = setTimeout(() => {
|
||||
cts.dispose(true);
|
||||
window?.sendWhenReady('vscode:showShellEnvTimeoutError', CancellationToken.None);
|
||||
acceptShellEnv({});
|
||||
}, 10000);
|
||||
|
||||
// Prefer to use the args and env from the target window
|
||||
// when resolving the shell env. It is possible that
|
||||
// a first window was opened from the UI but a second
|
||||
// from the CLI and that has implications for whether to
|
||||
// resolve the shell environment or not.
|
||||
//
|
||||
// Window can be undefined for e.g. the shared process
|
||||
// that is not part of our windows registry!
|
||||
let args: NativeParsedArgs;
|
||||
let env: IProcessEnvironment;
|
||||
if (window?.config) {
|
||||
args = window.config;
|
||||
env = { ...process.env, ...window.config.userEnv };
|
||||
} else {
|
||||
args = this.environmentMainService.args;
|
||||
env = process.env;
|
||||
}
|
||||
}, 3000);
|
||||
|
||||
const window = this.windowsMainService?.getWindowByWebContents(event.sender); // Note: this can be `undefined` for the shared process!!
|
||||
const shellEnvTimeoutErrorHandle = setTimeout(() => {
|
||||
cts.dispose(true);
|
||||
window?.sendWhenReady('vscode:showShellEnvTimeoutError', CancellationToken.None);
|
||||
acceptShellEnv({});
|
||||
}, 10000);
|
||||
|
||||
// Prefer to use the args and env from the target window
|
||||
// when resolving the shell env. It is possible that
|
||||
// a first window was opened from the UI but a second
|
||||
// from the CLI and that has implications for whether to
|
||||
// resolve the shell environment or not.
|
||||
//
|
||||
// Window can be undefined for e.g. the shared process
|
||||
// that is not part of our windows registry!
|
||||
let args: NativeParsedArgs;
|
||||
let env: NodeJS.ProcessEnv;
|
||||
if (window?.config) {
|
||||
args = window.config;
|
||||
env = { ...process.env, ...window.config.userEnv };
|
||||
} else {
|
||||
args = this.environmentMainService.args;
|
||||
env = process.env;
|
||||
}
|
||||
|
||||
// Resolve shell env
|
||||
const shellEnv = await resolveShellEnv(this.logService, args, env);
|
||||
acceptShellEnv(shellEnv);
|
||||
// Resolve shell env
|
||||
const shellEnv = await resolveShellEnv(this.logService, args, env);
|
||||
acceptShellEnv(shellEnv);
|
||||
});
|
||||
});
|
||||
|
||||
ipcMain.handle('vscode:writeNlsFile', async (event, path: unknown, data: unknown) => {
|
||||
ipcMain.handle('vscode:writeNlsFile', (event, path: unknown, data: unknown) => {
|
||||
const uri = this.validateNlsPath([path]);
|
||||
if (!uri || typeof data !== 'string') {
|
||||
throw new Error('Invalid operation (vscode:writeNlsFile)');
|
||||
@@ -416,6 +419,18 @@ export class CodeApplication extends Disposable {
|
||||
this.logService.debug(`from: ${this.environmentMainService.appRoot}`);
|
||||
this.logService.debug('args:', this.environmentMainService.args);
|
||||
|
||||
// TODO@bpasero TODO@deepak1556 workaround for #120655
|
||||
try {
|
||||
const cachedDataPath = URI.file(this.environmentMainService.chromeCachedDataDir);
|
||||
this.logService.trace(`Deleting Chrome cached data path: ${cachedDataPath.fsPath}`);
|
||||
|
||||
await this.fileService.del(cachedDataPath, { recursive: true });
|
||||
} catch (error) {
|
||||
if ((<FileOperationError>error).fileOperationResult !== FileOperationResult.FILE_NOT_FOUND) {
|
||||
this.logService.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure we associate the program with the app user model id
|
||||
// This will help Windows to associate the running program with
|
||||
// any shortcut that is pinned to the taskbar and prevent showing
|
||||
@@ -439,9 +454,6 @@ export class CodeApplication extends Disposable {
|
||||
this.logService.error(error);
|
||||
}
|
||||
|
||||
// Setup Protocol Handler
|
||||
const fileProtocolHandler = this._register(this.mainInstantiationService.createInstance(FileProtocolHandler));
|
||||
|
||||
// Main process server (electron IPC based)
|
||||
const mainProcessElectronServer = new ElectronIPCServer();
|
||||
|
||||
@@ -471,7 +483,7 @@ export class CodeApplication extends Disposable {
|
||||
appInstantiationService.invokeFunction(accessor => this.initChannels(accessor, mainProcessElectronServer, sharedProcessClient));
|
||||
|
||||
// Open Windows
|
||||
const windows = appInstantiationService.invokeFunction(accessor => this.openFirstWindow(accessor, mainProcessElectronServer, fileProtocolHandler));
|
||||
const windows = appInstantiationService.invokeFunction(accessor => this.openFirstWindow(accessor, mainProcessElectronServer));
|
||||
|
||||
// Post Open Windows Tasks
|
||||
appInstantiationService.invokeFunction(accessor => this.afterWindowOpen(accessor, sharedProcess));
|
||||
@@ -553,7 +565,7 @@ export class CodeApplication extends Disposable {
|
||||
services.set(IDiagnosticsService, ProxyChannel.toService(getDelayedChannel(sharedProcessReady.then(client => client.getChannel('diagnostics')))));
|
||||
|
||||
// Issues
|
||||
services.set(IIssueMainService, new SyncDescriptor(IssueMainService, [machineId, this.userEnv]));
|
||||
services.set(IIssueMainService, new SyncDescriptor(IssueMainService, [this.userEnv]));
|
||||
|
||||
// Encryption
|
||||
services.set(IEncryptionMainService, new SyncDescriptor(EncryptionMainService, [machineId]));
|
||||
@@ -592,7 +604,7 @@ export class CodeApplication extends Disposable {
|
||||
if (!this.environmentMainService.isExtensionDevelopment && !this.environmentMainService.args['disable-telemetry'] && !!this.productService.enableTelemetry) {
|
||||
const channel = getDelayedChannel(sharedProcessReady.then(client => client.getChannel('telemetryAppender')));
|
||||
const appender = new TelemetryAppenderClient(channel);
|
||||
const commonProperties = resolveCommonProperties(this.fileService, release(), process.arch, this.productService.commit, this.productService.version, machineId, this.productService.msftInternalDomains, this.environmentMainService.installSourcePath);
|
||||
const commonProperties = resolveCommonProperties(this.fileService, release(), hostname(), process.arch, this.productService.commit, this.productService.version, machineId, this.productService.msftInternalDomains, this.environmentMainService.installSourcePath);
|
||||
const piiPaths = [this.environmentMainService.appRoot, this.environmentMainService.extensionsPath];
|
||||
const config: ITelemetryServiceConfig = { appender, commonProperties, piiPaths, sendErrorTelemetry: true };
|
||||
|
||||
@@ -675,13 +687,14 @@ export class CodeApplication extends Disposable {
|
||||
// Logger
|
||||
const loggerChannel = new LoggerChannel(accessor.get(ILoggerService),);
|
||||
mainProcessElectronServer.registerChannel('logger', loggerChannel);
|
||||
sharedProcessClient.then(client => client.registerChannel('logger', loggerChannel));
|
||||
|
||||
// Extension Host Debug Broadcasting
|
||||
const electronExtensionHostDebugBroadcastChannel = new ElectronExtensionHostDebugBroadcastChannel(accessor.get(IWindowsMainService));
|
||||
mainProcessElectronServer.registerChannel('extensionhostdebugservice', electronExtensionHostDebugBroadcastChannel);
|
||||
}
|
||||
|
||||
private openFirstWindow(accessor: ServicesAccessor, mainProcessElectronServer: ElectronIPCServer, fileProtocolHandler: FileProtocolHandler): ICodeWindow[] {
|
||||
private openFirstWindow(accessor: ServicesAccessor, mainProcessElectronServer: ElectronIPCServer): ICodeWindow[] {
|
||||
const windowsMainService = this.windowsMainService = accessor.get(IWindowsMainService);
|
||||
const urlService = accessor.get(IURLService);
|
||||
const nativeHostMainService = accessor.get(INativeHostMainService);
|
||||
@@ -689,9 +702,6 @@ export class CodeApplication extends Disposable {
|
||||
// Signal phase: ready (services set)
|
||||
this.lifecycleMainService.phase = LifecycleMainPhase.Ready;
|
||||
|
||||
// Forward windows main service to protocol handler
|
||||
fileProtocolHandler.injectWindowsMainService(this.windowsMainService);
|
||||
|
||||
// Check for initial URLs to handle from protocol link invocations
|
||||
const pendingWindowOpenablesFromProtocolLinks: IWindowOpenable[] = [];
|
||||
const pendingProtocolLinksToHandle = [
|
||||
@@ -906,6 +916,8 @@ export class CodeApplication extends Disposable {
|
||||
|
||||
if (hasWorkspaceFileExtension(path)) {
|
||||
return { workspaceUri: remoteUri };
|
||||
} else if (/:[\d]+$/.test(path)) { // path with :line:column syntax
|
||||
return { fileUri: remoteUri };
|
||||
} else {
|
||||
return { folderUri: remoteUri };
|
||||
}
|
||||
@@ -938,6 +950,8 @@ export class CodeApplication extends Disposable {
|
||||
this.lifecycleMainService.phase = LifecycleMainPhase.AfterWindowOpen;
|
||||
|
||||
// Observe shared process for errors
|
||||
let willShutdown = false;
|
||||
once(this.lifecycleMainService.onWillShutdown)(() => willShutdown = true);
|
||||
const telemetryService = accessor.get(ITelemetryService);
|
||||
this._register(sharedProcess.onDidError(({ type, details }) => {
|
||||
|
||||
@@ -955,16 +969,19 @@ export class CodeApplication extends Disposable {
|
||||
type: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth', isMeasurement: true };
|
||||
reason: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth', isMeasurement: true };
|
||||
visible: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth', isMeasurement: true };
|
||||
shuttingdown: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth', isMeasurement: true };
|
||||
};
|
||||
type SharedProcessErrorEvent = {
|
||||
type: WindowError;
|
||||
reason: string | undefined;
|
||||
visible: boolean;
|
||||
shuttingdown: boolean;
|
||||
};
|
||||
telemetryService.publicLog2<SharedProcessErrorEvent, SharedProcessErrorClassification>('sharedprocesserror', {
|
||||
type,
|
||||
reason: typeof details !== 'string' ? details?.reason : undefined,
|
||||
visible: sharedProcess.isVisible()
|
||||
visible: sharedProcess.isVisible(),
|
||||
shuttingdown: willShutdown
|
||||
});
|
||||
}));
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import { app, dialog } from 'electron';
|
||||
import { promises, unlinkSync } from 'fs';
|
||||
import { localize } from 'vs/nls';
|
||||
import { isWindows, IProcessEnvironment, isMacintosh } from 'vs/base/common/platform';
|
||||
import { mark } from 'vs/base/common/performance';
|
||||
import product from 'vs/platform/product/common/product';
|
||||
import { parseMainProcessArgv, addArg } from 'vs/platform/environment/node/argvHelper';
|
||||
import { createWaitMarkerFile } from 'vs/platform/environment/node/wait';
|
||||
@@ -54,6 +55,8 @@ import { toErrorMessage } from 'vs/base/common/errorMessage';
|
||||
import { NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils';
|
||||
import { LoggerService } from 'vs/platform/log/node/loggerService';
|
||||
import { cwd } from 'vs/base/common/process';
|
||||
import { IProtocolMainService } from 'vs/platform/protocol/electron-main/protocol';
|
||||
import { ProtocolMainService } from 'vs/platform/protocol/electron-main/protocolMainService';
|
||||
|
||||
/**
|
||||
* The main VS Code entry point.
|
||||
@@ -80,11 +83,8 @@ class CodeMain {
|
||||
// default electron error dialog popping up
|
||||
setUnexpectedErrorHandler(err => console.error(err));
|
||||
|
||||
// Resolve command line arguments
|
||||
const args = this.resolveArgs();
|
||||
|
||||
// Create services
|
||||
const [instantiationService, instanceEnvironment, environmentService, configurationService, stateService, bufferLogService, productService] = this.createServices(args);
|
||||
const [instantiationService, instanceEnvironment, environmentService, configurationService, stateService, bufferLogService, productService] = this.createServices();
|
||||
|
||||
try {
|
||||
|
||||
@@ -108,7 +108,7 @@ class CodeMain {
|
||||
// Create the main IPC server by trying to be the server
|
||||
// If this throws an error it means we are not the first
|
||||
// instance of VS Code running and so we would quit.
|
||||
const mainProcessNodeIpcServer = await this.doStartup(args, logService, environmentService, lifecycleMainService, instantiationService, productService, true);
|
||||
const mainProcessNodeIpcServer = await this.claimInstance(logService, environmentService, lifecycleMainService, instantiationService, productService, true);
|
||||
|
||||
// Delay creation of spdlog for perf reasons (https://github.com/microsoft/vscode/issues/72906)
|
||||
bufferLogService.logger = new SpdLogLogger('main', join(environmentService.logsPath, 'main.log'), true, bufferLogService.getLevel());
|
||||
@@ -126,7 +126,7 @@ class CodeMain {
|
||||
}
|
||||
}
|
||||
|
||||
private createServices(args: NativeParsedArgs): [IInstantiationService, IProcessEnvironment, IEnvironmentMainService, ConfigurationService, StateService, BufferLogService, IProductService] {
|
||||
private createServices(): [IInstantiationService, IProcessEnvironment, IEnvironmentMainService, ConfigurationService, StateService, BufferLogService, IProductService] {
|
||||
const services = new ServiceCollection();
|
||||
|
||||
// Product
|
||||
@@ -134,7 +134,7 @@ class CodeMain {
|
||||
services.set(IProductService, productService);
|
||||
|
||||
// Environment
|
||||
const environmentMainService = new EnvironmentMainService(args, productService);
|
||||
const environmentMainService = new EnvironmentMainService(this.resolveArgs(), productService);
|
||||
const instanceEnvironment = this.patchEnvironment(environmentMainService); // Patch `process.env` with the instance's environment
|
||||
services.set(IEnvironmentMainService, environmentMainService);
|
||||
|
||||
@@ -178,6 +178,9 @@ class CodeMain {
|
||||
// Tunnel
|
||||
services.set(ITunnelService, new SyncDescriptor(TunnelService));
|
||||
|
||||
// Protocol
|
||||
services.set(IProtocolMainService, new SyncDescriptor(ProtocolMainService));
|
||||
|
||||
return [new InstantiationService(services, true), instanceEnvironment, environmentMainService, configurationService, stateService, bufferLogService, productService];
|
||||
}
|
||||
|
||||
@@ -201,7 +204,7 @@ class CodeMain {
|
||||
private initServices(environmentMainService: IEnvironmentMainService, configurationService: ConfigurationService, stateService: StateService): Promise<unknown> {
|
||||
|
||||
// Environment service (paths)
|
||||
const environmentServiceInitialization = Promise.all<void | undefined>([
|
||||
const environmentServiceInitialization = Promise.all<string | undefined>([
|
||||
environmentMainService.extensionsPath,
|
||||
environmentMainService.nodeCachedDataDir,
|
||||
environmentMainService.logsPath,
|
||||
@@ -219,14 +222,16 @@ class CodeMain {
|
||||
return Promise.all([environmentServiceInitialization, configurationServiceInitialization, stateServiceInitialization]);
|
||||
}
|
||||
|
||||
private async doStartup(args: NativeParsedArgs, logService: ILogService, environmentMainService: IEnvironmentMainService, lifecycleMainService: ILifecycleMainService, instantiationService: IInstantiationService, productService: IProductService, retry: boolean): Promise<NodeIPCServer> {
|
||||
private async claimInstance(logService: ILogService, environmentMainService: IEnvironmentMainService, lifecycleMainService: ILifecycleMainService, instantiationService: IInstantiationService, productService: IProductService, retry: boolean): Promise<NodeIPCServer> {
|
||||
|
||||
// Try to setup a server for running. If that succeeds it means
|
||||
// we are the first instance to startup. Otherwise it is likely
|
||||
// that another instance is already running.
|
||||
let mainProcessNodeIpcServer: NodeIPCServer;
|
||||
try {
|
||||
mark('code/willStartMainServer');
|
||||
mainProcessNodeIpcServer = await nodeIPCServe(environmentMainService.mainIPCHandle);
|
||||
mark('code/didStartMainServer');
|
||||
once(lifecycleMainService.onWillShutdown)(() => mainProcessNodeIpcServer.dispose());
|
||||
} catch (error) {
|
||||
|
||||
@@ -271,7 +276,7 @@ class CodeMain {
|
||||
throw error;
|
||||
}
|
||||
|
||||
return this.doStartup(args, logService, environmentMainService, lifecycleMainService, instantiationService, productService, false);
|
||||
return this.claimInstance(logService, environmentMainService, lifecycleMainService, instantiationService, productService, false);
|
||||
}
|
||||
|
||||
// Tests from CLI require to be the only instance currently
|
||||
@@ -287,7 +292,7 @@ class CodeMain {
|
||||
// Skip this if we are running with --wait where it is expected that we wait for a while.
|
||||
// Also skip when gathering diagnostics (--status) which can take a longer time.
|
||||
let startupWarningDialogHandle: NodeJS.Timeout | undefined = undefined;
|
||||
if (!args.wait && !args.status) {
|
||||
if (!environmentMainService.args.wait && !environmentMainService.args.status) {
|
||||
startupWarningDialogHandle = setTimeout(() => {
|
||||
this.showStartupWarningDialog(
|
||||
localize('secondInstanceNoResponse', "Another instance of {0} is running but not responding", productService.nameShort),
|
||||
@@ -300,7 +305,7 @@ class CodeMain {
|
||||
const launchService = ProxyChannel.toService<ILaunchMainService>(client.getChannel('launch'), { disableMarshalling: true });
|
||||
|
||||
// Process Info
|
||||
if (args.status) {
|
||||
if (environmentMainService.args.status) {
|
||||
return instantiationService.invokeFunction(async () => {
|
||||
const diagnosticsService = new DiagnosticsService(NullTelemetryService, productService);
|
||||
const mainProcessInfo = await launchService.getMainProcessInfo();
|
||||
@@ -319,7 +324,7 @@ class CodeMain {
|
||||
|
||||
// Send environment over...
|
||||
logService.trace('Sending env to running instance...');
|
||||
await launchService.start(args, process.env as IProcessEnvironment);
|
||||
await launchService.start(environmentMainService.args, process.env as IProcessEnvironment);
|
||||
|
||||
// Cleanup
|
||||
client.dispose();
|
||||
@@ -333,7 +338,7 @@ class CodeMain {
|
||||
}
|
||||
|
||||
// Print --status usage info
|
||||
if (args.status) {
|
||||
if (environmentMainService.args.status) {
|
||||
logService.warn('Warning: The --status argument can only be used if Code is already running. Please run it again after Code has started.');
|
||||
|
||||
throw new ExpectedError('Terminating...');
|
||||
|
||||
@@ -1,148 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { Disposable, DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { FileAccess, Schemas } from 'vs/base/common/network';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { INativeEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { session } from 'electron';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { TernarySearchTree } from 'vs/base/common/map';
|
||||
import { isLinux, isPreferringBrowserCodeLoad } from 'vs/base/common/platform';
|
||||
import { IWindowsMainService } from 'vs/platform/windows/electron-main/windows';
|
||||
import { extname } from 'vs/base/common/resources';
|
||||
|
||||
type ProtocolCallback = { (result: string | Electron.FilePathWithHeaders | { error: number }): void };
|
||||
|
||||
export class FileProtocolHandler extends Disposable {
|
||||
|
||||
private readonly validRoots = TernarySearchTree.forUris<boolean>(() => !isLinux);
|
||||
private readonly validExtensions = new Set(['.png', '.jpg', '.jpeg', '.gif', '.bmp']); // https://github.com/microsoft/vscode/issues/119384
|
||||
|
||||
constructor(
|
||||
@INativeEnvironmentService environmentService: INativeEnvironmentService,
|
||||
@ILogService private readonly logService: ILogService
|
||||
) {
|
||||
super();
|
||||
|
||||
const { defaultSession } = session;
|
||||
|
||||
// Define an initial set of roots we allow loading from
|
||||
// - appRoot : all files installed as part of the app
|
||||
// - extensions : all files shipped from extensions
|
||||
// - storage : all files in global and workspace storage (https://github.com/microsoft/vscode/issues/116735)
|
||||
this.validRoots.set(URI.file(environmentService.appRoot), true);
|
||||
this.validRoots.set(URI.file(environmentService.extensionsPath), true);
|
||||
this.validRoots.set(environmentService.globalStorageHome, true);
|
||||
this.validRoots.set(environmentService.workspaceStorageHome, true);
|
||||
|
||||
// Register vscode-file:// handler
|
||||
defaultSession.protocol.registerFileProtocol(Schemas.vscodeFileResource, (request, callback) => this.handleResourceRequest(request, callback as unknown as ProtocolCallback));
|
||||
|
||||
// Intercept any file:// access
|
||||
defaultSession.protocol.interceptFileProtocol(Schemas.file, (request, callback) => this.handleFileRequest(request, callback as unknown as ProtocolCallback));
|
||||
|
||||
// Cleanup
|
||||
this._register(toDisposable(() => {
|
||||
defaultSession.protocol.unregisterProtocol(Schemas.vscodeFileResource);
|
||||
defaultSession.protocol.uninterceptProtocol(Schemas.file);
|
||||
}));
|
||||
}
|
||||
|
||||
injectWindowsMainService(windowsMainService: IWindowsMainService): void {
|
||||
this._register(windowsMainService.onDidSignalReadyWindow(window => {
|
||||
if (window.config?.extensionDevelopmentPath || window.config?.extensionTestsPath) {
|
||||
const disposables = new DisposableStore();
|
||||
disposables.add(Event.any(window.onDidClose, window.onDidDestroy)(() => disposables.dispose()));
|
||||
|
||||
// Allow access to extension development path
|
||||
if (window.config.extensionDevelopmentPath) {
|
||||
for (const extensionDevelopmentPath of window.config.extensionDevelopmentPath) {
|
||||
disposables.add(this.addValidRoot(URI.file(extensionDevelopmentPath)));
|
||||
}
|
||||
}
|
||||
|
||||
// Allow access to extension tests path
|
||||
if (window.config.extensionTestsPath) {
|
||||
disposables.add(this.addValidRoot(URI.file(window.config.extensionTestsPath)));
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
private addValidRoot(root: URI): IDisposable {
|
||||
if (!this.validRoots.get(root)) {
|
||||
this.validRoots.set(root, true);
|
||||
|
||||
return toDisposable(() => this.validRoots.delete(root));
|
||||
}
|
||||
|
||||
return Disposable.None;
|
||||
}
|
||||
|
||||
private async handleFileRequest(request: Electron.ProtocolRequest, callback: ProtocolCallback) {
|
||||
const fileUri = URI.parse(request.url);
|
||||
|
||||
// isPreferringBrowserCodeLoad: false
|
||||
if (!isPreferringBrowserCodeLoad) {
|
||||
|
||||
// first check by validRoots
|
||||
if (this.validRoots.findSubstr(fileUri)) {
|
||||
return callback({
|
||||
path: fileUri.fsPath
|
||||
});
|
||||
}
|
||||
|
||||
// then check by validExtensions
|
||||
if (this.validExtensions.has(extname(fileUri))) {
|
||||
return callback({
|
||||
path: fileUri.fsPath
|
||||
});
|
||||
}
|
||||
|
||||
// finally block to load the resource
|
||||
this.logService.error(`${Schemas.file}: Refused to load resource ${fileUri.fsPath} from ${Schemas.file}: protocol (original URL: ${request.url})`);
|
||||
|
||||
return callback({ error: -3 /* ABORTED */ });
|
||||
}
|
||||
|
||||
// isPreferringBrowserCodeLoad: true
|
||||
// => block any file request
|
||||
else {
|
||||
this.logService.error(`Refused to load resource ${fileUri.fsPath} from ${Schemas.file}: protocol (original URL: ${request.url})`);
|
||||
|
||||
return callback({ error: -3 /* ABORTED */ });
|
||||
}
|
||||
}
|
||||
|
||||
private async handleResourceRequest(request: Electron.ProtocolRequest, callback: ProtocolCallback) {
|
||||
const uri = URI.parse(request.url);
|
||||
|
||||
// Restore the `vscode-file` URI to a `file` URI so that we can
|
||||
// ensure the root is valid and properly tell Chrome where the
|
||||
// resource is at.
|
||||
const fileUri = FileAccess.asFileUri(uri);
|
||||
|
||||
// first check by validRoots
|
||||
if (this.validRoots.findSubstr(fileUri)) {
|
||||
return callback({
|
||||
path: fileUri.fsPath
|
||||
});
|
||||
}
|
||||
|
||||
// then check by validExtensions
|
||||
if (this.validExtensions.has(extname(fileUri))) {
|
||||
return callback({
|
||||
path: fileUri.fsPath
|
||||
});
|
||||
}
|
||||
|
||||
// finally block to load the resource
|
||||
this.logService.error(`${Schemas.vscodeFileResource}: Refused to load resource ${fileUri.fsPath} from ${Schemas.vscodeFileResource}: protocol (original URL: ${request.url})`);
|
||||
|
||||
return callback({ error: -3 /* ABORTED */ });
|
||||
}
|
||||
}
|
||||
@@ -11,19 +11,40 @@
|
||||
|
||||
// Load issue reporter into window
|
||||
bootstrapWindow.load(['vs/code/electron-sandbox/issue/issueReporterMain'], function (issueReporter, configuration) {
|
||||
issueReporter.startup(configuration);
|
||||
}, { forceEnableDeveloperKeybindings: true, disallowReloadKeybinding: true });
|
||||
|
||||
|
||||
//#region Globals
|
||||
return issueReporter.startup(configuration);
|
||||
},
|
||||
{
|
||||
configureDeveloperSettings: function () {
|
||||
return {
|
||||
forceEnableDeveloperKeybindings: true,
|
||||
disallowReloadKeybinding: true
|
||||
};
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* @returns {{ load: (modules: string[], resultCallback: (result, configuration: object) => any, options?: object) => unknown }}
|
||||
* @typedef {import('../../../base/parts/sandbox/common/sandboxTypes').ISandboxConfiguration} ISandboxConfiguration
|
||||
*
|
||||
* @returns {{
|
||||
* load: (
|
||||
* modules: string[],
|
||||
* resultCallback: (result, configuration: ISandboxConfiguration) => unknown,
|
||||
* options?: {
|
||||
* configureDeveloperSettings?: (config: ISandboxConfiguration) => {
|
||||
* forceEnableDeveloperKeybindings?: boolean,
|
||||
* disallowReloadKeybinding?: boolean,
|
||||
* removeDeveloperKeybindingsAfterLoad?: boolean
|
||||
* },
|
||||
* canModifyDOM?: (config: ISandboxConfiguration) => void,
|
||||
* beforeLoaderConfig?: (loaderConfig: object) => void,
|
||||
* beforeRequire?: () => void
|
||||
* }
|
||||
* ) => Promise<unknown>
|
||||
* }}
|
||||
*/
|
||||
function bootstrapWindowLib() {
|
||||
// @ts-ignore (defined in bootstrap-window.js)
|
||||
return window.MonacoBootstrapWindow;
|
||||
}
|
||||
|
||||
//#endregion
|
||||
}());
|
||||
|
||||
@@ -11,10 +11,10 @@ import { ipcRenderer } from 'vs/base/parts/sandbox/electron-sandbox/globals';
|
||||
import { applyZoom, zoomIn, zoomOut } from 'vs/platform/windows/electron-sandbox/window';
|
||||
import { $, reset, safeInnerHtml, windowOpenNoOpener } from 'vs/base/browser/dom';
|
||||
import { Button } from 'vs/base/browser/ui/button/button';
|
||||
import * as collections from 'vs/base/common/collections';
|
||||
import { groupBy } from 'vs/base/common/collections';
|
||||
import { debounce } from 'vs/base/common/decorators';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import * as platform from 'vs/base/common/platform';
|
||||
import { isWindows, isLinux, isLinuxSnap, isMacintosh } from 'vs/base/common/platform';
|
||||
import { escape } from 'vs/base/common/strings';
|
||||
import { normalizeGitHubUrl } from 'vs/platform/issue/common/issueReporterUtil';
|
||||
import { IssueReporterData as IssueReporterModelData, IssueReporterModel } from 'vs/code/electron-sandbox/issue/issueReporterModel';
|
||||
@@ -23,8 +23,7 @@ import { localize } from 'vs/nls';
|
||||
import { isRemoteDiagnosticError, SystemInfo } from 'vs/platform/diagnostics/common/diagnostics';
|
||||
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
|
||||
import { IMainProcessService } from 'vs/platform/ipc/electron-sandbox/services';
|
||||
import { IssueReporterData, IssueReporterExtensionData, IssueReporterFeatures, IssueReporterStyles, IssueType } from 'vs/platform/issue/common/issue';
|
||||
import { IWindowConfiguration } from 'vs/platform/windows/common/windows';
|
||||
import { IssueReporterWindowConfiguration, IssueReporterData, IssueReporterExtensionData, IssueReporterStyles, IssueType } from 'vs/platform/issue/common/issue';
|
||||
import { Codicon } from 'vs/base/common/codicons';
|
||||
import { renderIcon } from 'vs/base/browser/ui/iconLabel/iconLabels';
|
||||
import { ElectronIPCMainProcessService } from 'vs/platform/ipc/electron-sandbox/mainProcessService';
|
||||
@@ -43,28 +42,8 @@ enum IssueSource {
|
||||
Marketplace = 'marketplace'
|
||||
}
|
||||
|
||||
export interface IssueReporterConfiguration extends IWindowConfiguration {
|
||||
windowId: number;
|
||||
disableExtensions: boolean;
|
||||
data: IssueReporterData;
|
||||
features: IssueReporterFeatures;
|
||||
os: {
|
||||
type: string;
|
||||
arch: string;
|
||||
release: string;
|
||||
},
|
||||
product: {
|
||||
nameShort: string;
|
||||
version: string;
|
||||
commit: string | undefined;
|
||||
date: string | undefined;
|
||||
reportIssueUrl: string | undefined;
|
||||
reportMarketplaceIssueUrl: string | undefined;
|
||||
}
|
||||
}
|
||||
|
||||
export function startup(configuration: IssueReporterConfiguration) {
|
||||
const platformClass = platform.isWindows ? 'windows' : platform.isLinux ? 'linux' : 'mac';
|
||||
export function startup(configuration: IssueReporterWindowConfiguration) {
|
||||
const platformClass = isWindows ? 'windows' : isLinux ? 'linux' : 'mac';
|
||||
document.body.classList.add(platformClass); // used by our fonts
|
||||
|
||||
safeInnerHtml(document.body, BaseHtml());
|
||||
@@ -86,7 +65,7 @@ export class IssueReporter extends Disposable {
|
||||
|
||||
private readonly previewButton!: Button;
|
||||
|
||||
constructor(private readonly configuration: IssueReporterConfiguration) {
|
||||
constructor(private readonly configuration: IssueReporterWindowConfiguration) {
|
||||
super();
|
||||
|
||||
this.initServices(configuration);
|
||||
@@ -95,8 +74,8 @@ export class IssueReporter extends Disposable {
|
||||
this.issueReporterModel = new IssueReporterModel({
|
||||
issueType: configuration.data.issueType || IssueType.Bug,
|
||||
versionInfo: {
|
||||
vscodeVersion: `${configuration.product.nameShort} ${configuration.product.version} (${configuration.product.commit || 'Commit unknown'}, ${configuration.product.date || 'Date unknown'})`,
|
||||
os: `${this.configuration.os.type} ${this.configuration.os.arch} ${this.configuration.os.release}${platform.isLinuxSnap ? ' snap' : ''}`
|
||||
vscodeVersion: `${configuration.product.nameShort} ${!!configuration.product.darwinUniversalAssetId ? `${configuration.product.version} (Universal)` : configuration.product.version} (${configuration.product.commit || 'Commit unknown'}, ${configuration.product.date || 'Date unknown'})`,
|
||||
os: `${this.configuration.os.type} ${this.configuration.os.arch} ${this.configuration.os.release}${isLinuxSnap ? ' snap' : ''}`
|
||||
},
|
||||
extensionsDisabled: !!configuration.disableExtensions,
|
||||
fileOnExtension: configuration.data.extensionId ? !targetExtension?.isBuiltin : undefined,
|
||||
@@ -257,7 +236,7 @@ export class IssueReporter extends Disposable {
|
||||
|
||||
private handleExtensionData(extensions: IssueReporterExtensionData[]) {
|
||||
const installedExtensions = extensions.filter(x => !x.isBuiltin);
|
||||
const { nonThemes, themes } = collections.groupBy(installedExtensions, ext => {
|
||||
const { nonThemes, themes } = groupBy(installedExtensions, ext => {
|
||||
return ext.isTheme ? 'themes' : 'nonThemes';
|
||||
});
|
||||
|
||||
@@ -272,7 +251,7 @@ export class IssueReporter extends Disposable {
|
||||
this.updateExtensionSelector(installedExtensions);
|
||||
}
|
||||
|
||||
private initServices(configuration: IssueReporterConfiguration): void {
|
||||
private initServices(configuration: IssueReporterWindowConfiguration): void {
|
||||
const serviceCollection = new ServiceCollection();
|
||||
const mainProcessService = new ElectronIPCMainProcessService(configuration.windowId);
|
||||
serviceCollection.set(IMainProcessService, mainProcessService);
|
||||
@@ -400,7 +379,7 @@ export class IssueReporter extends Disposable {
|
||||
});
|
||||
|
||||
document.onkeydown = async (e: KeyboardEvent) => {
|
||||
const cmdOrCtrlKey = platform.isMacintosh ? e.metaKey : e.ctrlKey;
|
||||
const cmdOrCtrlKey = isMacintosh ? e.metaKey : e.ctrlKey;
|
||||
// Cmd/Ctrl+Enter previews issue and closes window
|
||||
if (cmdOrCtrlKey && e.keyCode === 13) {
|
||||
if (await this.createIssue()) {
|
||||
@@ -434,7 +413,7 @@ export class IssueReporter extends Disposable {
|
||||
|
||||
// With latest electron upgrade, cmd+a is no longer propagating correctly for inputs in this window on mac
|
||||
// Manually perform the selection
|
||||
if (platform.isMacintosh) {
|
||||
if (isMacintosh) {
|
||||
if (cmdOrCtrlKey && e.keyCode === 65 && e.target) {
|
||||
if (e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement) {
|
||||
(<HTMLInputElement>e.target).select();
|
||||
|
||||
@@ -12,7 +12,7 @@ suite('IssueReporter', () => {
|
||||
|
||||
test('sets defaults to include all data', () => {
|
||||
const issueReporterModel = new IssueReporterModel();
|
||||
assert.deepEqual(issueReporterModel.getData(), {
|
||||
assert.deepStrictEqual(issueReporterModel.getData(), {
|
||||
allExtensions: [],
|
||||
includeSystemInfo: true,
|
||||
includeWorkspaceInfo: true,
|
||||
@@ -25,7 +25,7 @@ suite('IssueReporter', () => {
|
||||
|
||||
test('serializes model skeleton when no data is provided', () => {
|
||||
const issueReporterModel = new IssueReporterModel({});
|
||||
assert.equal(issueReporterModel.serialize(),
|
||||
assert.strictEqual(issueReporterModel.serialize(),
|
||||
`
|
||||
Issue Type: <b>Bug</b>
|
||||
|
||||
@@ -55,7 +55,7 @@ Extensions: none
|
||||
}
|
||||
}
|
||||
});
|
||||
assert.equal(issueReporterModel.serialize(),
|
||||
assert.strictEqual(issueReporterModel.serialize(),
|
||||
`
|
||||
Issue Type: <b>Bug</b>
|
||||
|
||||
@@ -98,7 +98,7 @@ OS version: undefined
|
||||
},
|
||||
experimentInfo: 'vsliv695:30137379\nvsins829:30139715'
|
||||
});
|
||||
assert.equal(issueReporterModel.serialize(),
|
||||
assert.strictEqual(issueReporterModel.serialize(),
|
||||
`
|
||||
Issue Type: <b>Bug</b>
|
||||
|
||||
@@ -152,7 +152,7 @@ vsins829:30139715
|
||||
}
|
||||
}
|
||||
});
|
||||
assert.equal(issueReporterModel.serialize(),
|
||||
assert.strictEqual(issueReporterModel.serialize(),
|
||||
`
|
||||
Issue Type: <b>Bug</b>
|
||||
|
||||
@@ -208,7 +208,7 @@ OS version: undefined
|
||||
]
|
||||
}
|
||||
});
|
||||
assert.equal(issueReporterModel.serialize(),
|
||||
assert.strictEqual(issueReporterModel.serialize(),
|
||||
`
|
||||
Issue Type: <b>Bug</b>
|
||||
|
||||
@@ -256,7 +256,7 @@ Remote OS version: Linux x64 4.18.0
|
||||
gpuStatus: {}
|
||||
}
|
||||
});
|
||||
assert.equal(issueReporterModel.serialize(),
|
||||
assert.strictEqual(issueReporterModel.serialize(),
|
||||
`
|
||||
Issue Type: <b>Bug</b>
|
||||
|
||||
@@ -291,7 +291,7 @@ OS version: undefined
|
||||
'https://github.com/repo/issues/new',
|
||||
'https://github.com/repo/issues/new/'
|
||||
].forEach(url => {
|
||||
assert.equal('https://github.com/repo', normalizeGitHubUrl(url));
|
||||
assert.strictEqual('https://github.com/repo', normalizeGitHubUrl(url));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -306,7 +306,7 @@ OS version: undefined
|
||||
fileOnExtension: true
|
||||
});
|
||||
|
||||
assert.equal(issueReporterModel.fileOnExtension(), true);
|
||||
assert.strictEqual(issueReporterModel.fileOnExtension(), true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -11,19 +11,37 @@
|
||||
|
||||
// Load process explorer into window
|
||||
bootstrapWindow.load(['vs/code/electron-sandbox/processExplorer/processExplorerMain'], function (processExplorer, configuration) {
|
||||
processExplorer.startup(configuration.windowId, configuration.data);
|
||||
}, { forceEnableDeveloperKeybindings: true });
|
||||
|
||||
|
||||
//#region Globals
|
||||
return processExplorer.startup(configuration);
|
||||
}, {
|
||||
configureDeveloperSettings: function () {
|
||||
return {
|
||||
forceEnableDeveloperKeybindings: true
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* @returns {{ load: (modules: string[], resultCallback: (result, configuration: object) => any, options?: object) => unknown }}
|
||||
* @typedef {import('../../../base/parts/sandbox/common/sandboxTypes').ISandboxConfiguration} ISandboxConfiguration
|
||||
*
|
||||
* @returns {{
|
||||
* load: (
|
||||
* modules: string[],
|
||||
* resultCallback: (result, configuration: ISandboxConfiguration) => unknown,
|
||||
* options?: {
|
||||
* configureDeveloperSettings?: (config: ISandboxConfiguration) => {
|
||||
* forceEnableDeveloperKeybindings?: boolean,
|
||||
* disallowReloadKeybinding?: boolean,
|
||||
* removeDeveloperKeybindingsAfterLoad?: boolean
|
||||
* },
|
||||
* canModifyDOM?: (config: ISandboxConfiguration) => void,
|
||||
* beforeLoaderConfig?: (loaderConfig: object) => void,
|
||||
* beforeRequire?: () => void
|
||||
* }
|
||||
* ) => Promise<unknown>
|
||||
* }}
|
||||
*/
|
||||
function bootstrapWindowLib() {
|
||||
// @ts-ignore (defined in bootstrap-window.js)
|
||||
return window.MonacoBootstrapWindow;
|
||||
}
|
||||
|
||||
//#endregion
|
||||
}());
|
||||
|
||||
@@ -9,13 +9,12 @@ import { INativeHostService } from 'vs/platform/native/electron-sandbox/native';
|
||||
import { NativeHostService } from 'vs/platform/native/electron-sandbox/nativeHostService';
|
||||
import { ipcRenderer } from 'vs/base/parts/sandbox/electron-sandbox/globals';
|
||||
import { localize } from 'vs/nls';
|
||||
import { ProcessExplorerStyles, ProcessExplorerData } from 'vs/platform/issue/common/issue';
|
||||
import { ProcessExplorerStyles, ProcessExplorerData, ProcessExplorerWindowConfiguration } from 'vs/platform/issue/common/issue';
|
||||
import { applyZoom, zoomIn, zoomOut } from 'vs/platform/windows/electron-sandbox/window';
|
||||
import { IContextMenuItem } from 'vs/base/parts/contextmenu/common/contextmenu';
|
||||
import { popup } from 'vs/base/parts/contextmenu/electron-sandbox/contextmenu';
|
||||
import { ProcessItem } from 'vs/base/common/processes';
|
||||
import * as dom from 'vs/base/browser/dom';
|
||||
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { append, $ } from 'vs/base/browser/dom';
|
||||
import { isRemoteDiagnosticError, IRemoteDiagnosticError } from 'vs/platform/diagnostics/common/diagnostics';
|
||||
import { ElectronIPCMainProcessService } from 'vs/platform/ipc/electron-sandbox/mainProcessService';
|
||||
import { ByteSize } from 'vs/platform/files/common/files';
|
||||
@@ -105,11 +104,11 @@ class ProcessHeaderTreeRenderer implements ITreeRenderer<ProcessInformation, voi
|
||||
templateId: string = 'header';
|
||||
renderTemplate(container: HTMLElement): IProcessItemTemplateData {
|
||||
const data = Object.create(null);
|
||||
const row = dom.append(container, dom.$('.row'));
|
||||
data.name = dom.append(row, dom.$('.nameLabel'));
|
||||
data.CPU = dom.append(row, dom.$('.cpu'));
|
||||
data.memory = dom.append(row, dom.$('.memory'));
|
||||
data.PID = dom.append(row, dom.$('.pid'));
|
||||
const row = append(container, $('.row'));
|
||||
data.name = append(row, $('.nameLabel'));
|
||||
data.CPU = append(row, $('.cpu'));
|
||||
data.memory = append(row, $('.memory'));
|
||||
data.PID = append(row, $('.pid'));
|
||||
return data;
|
||||
}
|
||||
renderElement(node: ITreeNode<ProcessInformation, void>, index: number, templateData: IProcessItemTemplateData, height: number | undefined): void {
|
||||
@@ -128,8 +127,8 @@ class MachineRenderer implements ITreeRenderer<MachineProcessInformation, void,
|
||||
templateId: string = 'machine';
|
||||
renderTemplate(container: HTMLElement): IProcessRowTemplateData {
|
||||
const data = Object.create(null);
|
||||
const row = dom.append(container, dom.$('.row'));
|
||||
data.name = dom.append(row, dom.$('.nameLabel'));
|
||||
const row = append(container, $('.row'));
|
||||
data.name = append(row, $('.nameLabel'));
|
||||
return data;
|
||||
}
|
||||
renderElement(node: ITreeNode<MachineProcessInformation, void>, index: number, templateData: IProcessRowTemplateData, height: number | undefined): void {
|
||||
@@ -144,8 +143,8 @@ class ErrorRenderer implements ITreeRenderer<IRemoteDiagnosticError, void, IProc
|
||||
templateId: string = 'error';
|
||||
renderTemplate(container: HTMLElement): IProcessRowTemplateData {
|
||||
const data = Object.create(null);
|
||||
const row = dom.append(container, dom.$('.row'));
|
||||
data.name = dom.append(row, dom.$('.nameLabel'));
|
||||
const row = append(container, $('.row'));
|
||||
data.name = append(row, $('.nameLabel'));
|
||||
return data;
|
||||
}
|
||||
renderElement(node: ITreeNode<IRemoteDiagnosticError, void>, index: number, templateData: IProcessRowTemplateData, height: number | undefined): void {
|
||||
@@ -163,12 +162,12 @@ class ProcessRenderer implements ITreeRenderer<ProcessItem, void, IProcessItemTe
|
||||
templateId: string = 'process';
|
||||
renderTemplate(container: HTMLElement): IProcessItemTemplateData {
|
||||
const data = <IProcessItemTemplateData>Object.create(null);
|
||||
const row = dom.append(container, dom.$('.row'));
|
||||
const row = append(container, $('.row'));
|
||||
|
||||
data.name = dom.append(row, dom.$('.nameLabel'));
|
||||
data.CPU = dom.append(row, dom.$('.cpu'));
|
||||
data.memory = dom.append(row, dom.$('.memory'));
|
||||
data.PID = dom.append(row, dom.$('.pid'));
|
||||
data.name = append(row, $('.nameLabel'));
|
||||
data.CPU = append(row, $('.cpu'));
|
||||
data.memory = append(row, $('.memory'));
|
||||
data.PID = append(row, $('.pid'));
|
||||
|
||||
return data;
|
||||
}
|
||||
@@ -226,8 +225,6 @@ class ProcessExplorer {
|
||||
|
||||
private mapPidToWindowTitle = new Map<number, string>();
|
||||
|
||||
private listeners = new DisposableStore();
|
||||
|
||||
private nativeHostService: INativeHostService;
|
||||
|
||||
private tree: DataTree<any, ProcessTree | MachineProcessInformation | ProcessItem | ProcessInformation | IRemoteDiagnosticError, any> | undefined;
|
||||
@@ -237,6 +234,7 @@ class ProcessExplorer {
|
||||
this.nativeHostService = new NativeHostService(windowId, mainProcessService) as INativeHostService;
|
||||
|
||||
this.applyStyles(data.styles);
|
||||
this.setEventHandlers(data);
|
||||
|
||||
// Map window process pids to titles, annotate process names with this when rendering to distinguish between them
|
||||
ipcRenderer.on('vscode:windowsInfoResponse', (event: unknown, windows: any[]) => {
|
||||
@@ -263,6 +261,32 @@ class ProcessExplorer {
|
||||
this.lastRequestTime = Date.now();
|
||||
ipcRenderer.send('vscode:windowsInfoRequest');
|
||||
ipcRenderer.send('vscode:listProcesses');
|
||||
|
||||
|
||||
}
|
||||
|
||||
private setEventHandlers(data: ProcessExplorerData): void {
|
||||
document.onkeydown = (e: KeyboardEvent) => {
|
||||
const cmdOrCtrlKey = data.platform === 'darwin' ? e.metaKey : e.ctrlKey;
|
||||
|
||||
// Cmd/Ctrl + w closes issue window
|
||||
if (cmdOrCtrlKey && e.keyCode === 87) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
|
||||
ipcRenderer.send('vscode:closeProcessExplorer');
|
||||
}
|
||||
|
||||
// Cmd/Ctrl + zooms in
|
||||
if (cmdOrCtrlKey && e.keyCode === 187) {
|
||||
zoomIn();
|
||||
}
|
||||
|
||||
// Cmd/Ctrl - zooms out
|
||||
if (cmdOrCtrlKey && e.keyCode === 189) {
|
||||
zoomOut();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private async createProcessTree(processRoots: MachineProcessInformation[]): Promise<void> {
|
||||
@@ -449,39 +473,12 @@ class ProcessExplorer {
|
||||
}
|
||||
}, 200);
|
||||
}
|
||||
|
||||
public dispose() {
|
||||
this.listeners.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
export function startup(windowId: number, data: ProcessExplorerData): void {
|
||||
const platformClass = data.platform === 'win32' ? 'windows' : data.platform === 'linux' ? 'linux' : 'mac';
|
||||
export function startup(configuration: ProcessExplorerWindowConfiguration): void {
|
||||
const platformClass = configuration.data.platform === 'win32' ? 'windows' : configuration.data.platform === 'linux' ? 'linux' : 'mac';
|
||||
document.body.classList.add(platformClass); // used by our fonts
|
||||
applyZoom(data.zoomLevel);
|
||||
applyZoom(configuration.data.zoomLevel);
|
||||
|
||||
const processExplorer = new ProcessExplorer(windowId, data);
|
||||
|
||||
document.onkeydown = (e: KeyboardEvent) => {
|
||||
const cmdOrCtrlKey = data.platform === 'darwin' ? e.metaKey : e.ctrlKey;
|
||||
|
||||
// Cmd/Ctrl + w closes issue window
|
||||
if (cmdOrCtrlKey && e.keyCode === 87) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
|
||||
processExplorer.dispose();
|
||||
ipcRenderer.send('vscode:closeProcessExplorer');
|
||||
}
|
||||
|
||||
// Cmd/Ctrl + zooms in
|
||||
if (cmdOrCtrlKey && e.keyCode === 187) {
|
||||
zoomIn();
|
||||
}
|
||||
|
||||
// Cmd/Ctrl - zooms out
|
||||
if (cmdOrCtrlKey && e.keyCode === 189) {
|
||||
zoomOut();
|
||||
}
|
||||
};
|
||||
new ProcessExplorer(configuration.windowId, configuration.data);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src 'self' https: data: blob: vscode-remote-resource:; media-src 'none'; frame-src 'self' vscode-webview: https://*.vscode-webview-test.com; object-src 'self'; script-src 'self' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; connect-src 'self' https: ws:; font-src 'self' https: vscode-remote-resource:;">
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src 'self' https: data: blob: vscode-remote-resource:; media-src 'none'; frame-src 'self' vscode-webview:; object-src 'self'; script-src 'self' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; connect-src 'self' https: ws:; font-src 'self' https: vscode-remote-resource:;">
|
||||
<meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script'; trusted-types default TrustedFunctionWorkaround ExtensionScripts amdLoader cellRendererEditorText defaultWorkerFactory diffEditorWidget domLineBreaksComputer editorViewLayer diffReview extensionHostWorker insane notebookOutputRenderer safeInnerHtml standaloneColorizer tokenizeToString webNestedWorkerExtensionHost webWorkerExtensionHost;">
|
||||
</head>
|
||||
<body aria-label="">
|
||||
|
||||
@@ -32,15 +32,38 @@
|
||||
return require('vs/workbench/electron-sandbox/desktop.main').main(configuration);
|
||||
},
|
||||
{
|
||||
removeDeveloperKeybindingsAfterLoad: true,
|
||||
configureDeveloperSettings: function (windowConfig) {
|
||||
return {
|
||||
// disable automated devtools opening on error when running extension tests
|
||||
// as this can lead to undeterministic test exectuion (devtools steals focus)
|
||||
forceDisableShowDevtoolsOnError: typeof windowConfig.extensionTestsPath === 'string',
|
||||
// enable devtools keybindings in extension development window
|
||||
forceEnableDeveloperKeybindings: Array.isArray(windowConfig.extensionDevelopmentPath) && windowConfig.extensionDevelopmentPath.length > 0,
|
||||
removeDeveloperKeybindingsAfterLoad: true
|
||||
};
|
||||
},
|
||||
canModifyDOM: function (windowConfig) {
|
||||
// TODO@sandbox part-splash is non-sandboxed only
|
||||
},
|
||||
beforeLoaderConfig: function (windowConfig, loaderConfig) {
|
||||
beforeLoaderConfig: function (loaderConfig) {
|
||||
loaderConfig.recordStats = true;
|
||||
},
|
||||
beforeRequire: function () {
|
||||
performance.mark('code/willLoadWorkbenchMain');
|
||||
|
||||
// It looks like browsers only lazily enable
|
||||
// the <canvas> element when needed. Since we
|
||||
// leverage canvas elements in our code in many
|
||||
// locations, we try to help the browser to
|
||||
// initialize canvas when it is idle, right
|
||||
// before we wait for the scripts to be loaded.
|
||||
// @ts-ignore
|
||||
window.requestIdleCallback(() => {
|
||||
const canvas = document.createElement('canvas');
|
||||
const context = canvas.getContext('2d');
|
||||
context.clearRect(0, 0, canvas.width, canvas.height);
|
||||
canvas.remove();
|
||||
}, { timeout: 50 });
|
||||
}
|
||||
}
|
||||
);
|
||||
@@ -62,12 +85,26 @@
|
||||
}
|
||||
});
|
||||
|
||||
//region Helpers
|
||||
//#region Helpers
|
||||
|
||||
/**
|
||||
* @typedef {import('../../../platform/windows/common/windows').INativeWindowConfiguration} INativeWindowConfiguration
|
||||
*
|
||||
* @returns {{
|
||||
* load: (modules: string[], resultCallback: (result, configuration: import('../../../platform/windows/common/windows').INativeWindowConfiguration) => any, options: object) => unknown,
|
||||
* globals: () => typeof import('../../../base/parts/sandbox/electron-sandbox/globals')
|
||||
* load: (
|
||||
* modules: string[],
|
||||
* resultCallback: (result, configuration: INativeWindowConfiguration) => unknown,
|
||||
* options?: {
|
||||
* configureDeveloperSettings?: (config: INativeWindowConfiguration & object) => {
|
||||
* forceEnableDeveloperKeybindings?: boolean,
|
||||
* disallowReloadKeybinding?: boolean,
|
||||
* removeDeveloperKeybindingsAfterLoad?: boolean
|
||||
* },
|
||||
* canModifyDOM?: (config: INativeWindowConfiguration & object) => void,
|
||||
* beforeLoaderConfig?: (loaderConfig: object) => void,
|
||||
* beforeRequire?: () => void
|
||||
* }
|
||||
* ) => Promise<unknown>
|
||||
* }}
|
||||
*/
|
||||
function bootstrapWindowLib() {
|
||||
|
||||
@@ -14,7 +14,7 @@ import product from 'vs/platform/product/common/product';
|
||||
import { isAbsolute, join } from 'vs/base/common/path';
|
||||
import { whenDeleted, writeFileSync } from 'vs/base/node/pfs';
|
||||
import { findFreePort, randomPort } from 'vs/base/node/ports';
|
||||
import { isWindows, isLinux } from 'vs/base/common/platform';
|
||||
import { isWindows, isLinux, IProcessEnvironment } from 'vs/base/common/platform';
|
||||
import type { ProfilingSession, Target } from 'v8-inspect-profiler';
|
||||
import { isString } from 'vs/base/common/types';
|
||||
import { hasStdinWithoutTty, stdinDataListener, getStdinFilePath, readFromStdin } from 'vs/platform/environment/node/stdin';
|
||||
@@ -116,9 +116,8 @@ export async function main(argv: string[]): Promise<any> {
|
||||
|
||||
// Just Code
|
||||
else {
|
||||
const env: NodeJS.ProcessEnv = {
|
||||
const env: IProcessEnvironment = {
|
||||
...process.env,
|
||||
'VSCODE_CLI': '1', // this will signal Code that it was spawned from this module
|
||||
'ELECTRON_NO_ATTACH_CONSOLE': '1'
|
||||
};
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { release } from 'os';
|
||||
import { release, hostname } from 'os';
|
||||
import * as fs from 'fs';
|
||||
import { gracefulify } from 'graceful-fs';
|
||||
import { isAbsolute, join } from 'vs/base/common/path';
|
||||
@@ -135,8 +135,6 @@ class CliMain extends Disposable {
|
||||
const stateService = new StateService(environmentService, logService);
|
||||
services.set(IStateService, stateService);
|
||||
|
||||
const { appRoot, extensionsPath, extensionDevelopmentLocationURI, isBuilt, installSourcePath } = environmentService;
|
||||
|
||||
// Request
|
||||
services.set(IRequestService, new SyncDescriptor(RequestService));
|
||||
|
||||
@@ -150,15 +148,17 @@ class CliMain extends Disposable {
|
||||
|
||||
// Telemetry
|
||||
const appenders: AppInsightsAppender[] = [];
|
||||
if (isBuilt && !extensionDevelopmentLocationURI && !environmentService.disableTelemetry && productService.enableTelemetry) {
|
||||
if (environmentService.isBuilt && !environmentService.isExtensionDevelopment && !environmentService.disableTelemetry && productService.enableTelemetry) {
|
||||
if (productService.aiConfig && productService.aiConfig.asimovKey) {
|
||||
appenders.push(new AppInsightsAppender('monacoworkbench', null, productService.aiConfig.asimovKey));
|
||||
}
|
||||
|
||||
const { appRoot, extensionsPath, installSourcePath } = environmentService;
|
||||
|
||||
const config: ITelemetryServiceConfig = {
|
||||
appender: combinedAppender(...appenders),
|
||||
sendErrorTelemetry: false,
|
||||
commonProperties: resolveCommonProperties(fileService, release(), process.arch, productService.commit, productService.version, stateService.getItem('telemetry.machineId'), productService.msftInternalDomains, installSourcePath),
|
||||
commonProperties: resolveCommonProperties(fileService, release(), hostname(), process.arch, productService.commit, productService.version, stateService.getItem('telemetry.machineId'), productService.msftInternalDomains, installSourcePath),
|
||||
piiPaths: [appRoot, extensionsPath]
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user