diff --git a/src/vs/base/parts/sandbox/electron-browser/preload.js b/src/vs/base/parts/sandbox/electron-browser/preload.js index aa1eba1f6b5..dfad98f286d 100644 --- a/src/vs/base/parts/sandbox/electron-browser/preload.js +++ b/src/vs/base/parts/sandbox/electron-browser/preload.js @@ -203,15 +203,7 @@ */ function resolveEnv() { return new Promise(function (resolve) { - const handle = setTimeout(function () { - console.warn('Preload: Unable to resolve shell environment in a reasonable time'); - - // It took too long to fetch the shell environment, return - resolve(); - }, 3000); - ipcRenderer.once('vscode:acceptShellEnv', function (event, shellEnv) { - clearTimeout(handle); // Assign all keys of the shell environment to our process environment Object.assign(process.env, shellEnv); diff --git a/src/vs/code/electron-browser/workbench/workbench.js b/src/vs/code/electron-browser/workbench/workbench.js index 3dd6691d3a0..3999f28558c 100644 --- a/src/vs/code/electron-browser/workbench/workbench.js +++ b/src/vs/code/electron-browser/workbench/workbench.js @@ -187,5 +187,5 @@ } //#endregion - + }()); diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index 1b8424f8247..f3dd84ea104 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -263,17 +263,32 @@ export class CodeApplication extends Disposable { ipc.on('vscode:fetchShellEnv', async (event: IpcMainEvent) => { const webContents = event.sender; + const window = this.windowsMainService?.getWindowByWebContents(event.sender); + if (!window) { + return; + } + + let replied = false; + + function acceptShellEnv(env: NodeJS.ProcessEnv): void { + clearTimeout(shellEnvTimeoutWarningHandle); + + if (!replied) { + webContents.send('vscode:acceptShellEnv', env); + replied = true; + } + } + + const shellEnvTimeoutWarningHandle = setTimeout(function () { + window.sendWhenReady('vscode:showShellEnvTimeoutWarningMessage'); + acceptShellEnv({}); + }, 10000); try { const shellEnv = await getShellEnvironment(this.logService, this.environmentService); - - if (!webContents.isDestroyed()) { - webContents.send('vscode:acceptShellEnv', shellEnv); - } + acceptShellEnv(shellEnv); } catch (error) { - if (!webContents.isDestroyed()) { - webContents.send('vscode:acceptShellEnv', {}); - } + acceptShellEnv({}); this.logService.error('Error fetching shell env', error); } diff --git a/src/vs/code/node/cli.ts b/src/vs/code/node/cli.ts index c93e5a6169e..c6415a551c8 100644 --- a/src/vs/code/node/cli.ts +++ b/src/vs/code/node/cli.ts @@ -123,10 +123,6 @@ export async function main(argv: string[]): Promise { 'ELECTRON_NO_ATTACH_CONSOLE': '1' }; - if (args['force-user-env']) { - env['VSCODE_FORCE_USER_ENV'] = '1'; - } - delete env['ELECTRON_RUN_AS_NODE']; const processCallbacks: ((child: ChildProcess) => Promise)[] = []; diff --git a/src/vs/code/node/shellEnv.ts b/src/vs/code/node/shellEnv.ts index 619886d0fd3..d1dd0bc6dfb 100644 --- a/src/vs/code/node/shellEnv.ts +++ b/src/vs/code/node/shellEnv.ts @@ -91,17 +91,21 @@ let shellEnvPromise: Promise | undefined = undefined; */ export function getShellEnvironment(logService: ILogService, environmentService: INativeEnvironmentService): Promise { if (!shellEnvPromise) { - if (environmentService.args['disable-user-env-probe']) { - logService.trace('getShellEnvironment: disable-user-env-probe set, skipping'); + if (environmentService.args['force-disable-user-env']) { + logService.trace('getShellEnvironment(): skipped (--force-disable-user-env)'); shellEnvPromise = Promise.resolve({}); } else if (isWindows) { - logService.trace('getShellEnvironment: running on Windows, skipping'); + logService.trace('getShellEnvironment(): skipped (Windows)'); shellEnvPromise = Promise.resolve({}); - } else if (process.env['VSCODE_CLI'] === '1' && process.env['VSCODE_FORCE_USER_ENV'] !== '1') { - logService.trace('getShellEnvironment: running on CLI, skipping'); + } else if (process.env['VSCODE_CLI'] === '1' && !environmentService.args['force-user-env']) { + logService.trace('getShellEnvironment(): skipped (VSCODE_CLI is set)'); shellEnvPromise = Promise.resolve({}); } else { - logService.trace('getShellEnvironment: running on Unix'); + if (process.env['VSCODE_CLI'] === '1') { + logService.trace('getShellEnvironment(): running (--force-user-env)'); + } else { + logService.trace('getShellEnvironment(): running (macOS/Linux)'); + } shellEnvPromise = getUnixShellEnvironment(logService); } } diff --git a/src/vs/platform/environment/common/argv.ts b/src/vs/platform/environment/common/argv.ts index 434804ca643..e719e129c60 100644 --- a/src/vs/platform/environment/common/argv.ts +++ b/src/vs/platform/environment/common/argv.ts @@ -72,10 +72,10 @@ export interface NativeParsedArgs { 'driver'?: string; 'driver-verbose'?: boolean; 'remote'?: string; - 'disable-user-env-probe'?: boolean; 'force'?: boolean; 'do-not-sync'?: boolean; 'force-user-env'?: boolean; + 'force-disable-user-env'?: boolean; 'sync'?: 'on' | 'off'; '__sandbox'?: boolean; 'logsPath'?: string; diff --git a/src/vs/platform/environment/node/argv.ts b/src/vs/platform/environment/node/argv.ts index 637ce482401..7263bcbf756 100644 --- a/src/vs/platform/environment/node/argv.ts +++ b/src/vs/platform/environment/node/argv.ts @@ -97,7 +97,6 @@ export const OPTIONS: OptionDescriptions> = { 'disable-crash-reporter': { type: 'boolean' }, 'crash-reporter-directory': { type: 'string' }, 'crash-reporter-id': { type: 'string' }, - 'disable-user-env-probe': { type: 'boolean' }, 'skip-add-to-recently-opened': { type: 'boolean' }, 'unity-launch': { type: 'boolean' }, 'open-url': { type: 'boolean' }, @@ -111,6 +110,7 @@ export const OPTIONS: OptionDescriptions> = { 'trace-category-filter': { type: 'string' }, 'trace-options': { type: 'string' }, 'force-user-env': { type: 'boolean' }, + 'force-disable-user-env': { type: 'boolean' }, 'open-devtools': { type: 'boolean' }, '__sandbox': { type: 'boolean' }, 'logsPath': { type: 'string' }, diff --git a/src/vs/platform/windows/electron-main/windows.ts b/src/vs/platform/windows/electron-main/windows.ts index e1f5be82b02..c9e740bd59e 100644 --- a/src/vs/platform/windows/electron-main/windows.ts +++ b/src/vs/platform/windows/electron-main/windows.ts @@ -12,7 +12,7 @@ import { IProcessEnvironment } from 'vs/base/common/platform'; import { IWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces'; import { ISerializableCommandAction } from 'vs/platform/actions/common/actions'; import { URI } from 'vs/base/common/uri'; -import { Rectangle, BrowserWindow } from 'electron'; +import { Rectangle, BrowserWindow, WebContents } from 'electron'; import { IDisposable } from 'vs/base/common/lifecycle'; export interface IWindowState { @@ -113,6 +113,7 @@ export interface IWindowsMainService { getLastActiveWindow(): ICodeWindow | undefined; getWindowById(windowId: number): ICodeWindow | undefined; + getWindowByWebContents(webContents: WebContents): ICodeWindow | undefined; getWindows(): ICodeWindow[]; getWindowCount(): number; } diff --git a/src/vs/platform/windows/electron-main/windowsMainService.ts b/src/vs/platform/windows/electron-main/windowsMainService.ts index 679accfd132..cc1d0a1288b 100644 --- a/src/vs/platform/windows/electron-main/windowsMainService.ts +++ b/src/vs/platform/windows/electron-main/windowsMainService.ts @@ -14,7 +14,7 @@ import { IEnvironmentMainService } from 'vs/platform/environment/electron-main/e import { NativeParsedArgs } from 'vs/platform/environment/common/argv'; import { IStateService } from 'vs/platform/state/node/state'; import { CodeWindow, defaultWindowState } from 'vs/code/electron-main/window'; -import { screen, BrowserWindow, MessageBoxOptions, Display, app } from 'electron'; +import { screen, BrowserWindow, MessageBoxOptions, Display, app, WebContents } from 'electron'; import { ILifecycleMainService, UnloadReason, LifecycleMainService, LifecycleMainPhase } from 'vs/platform/lifecycle/electron-main/lifecycleMainService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ILogService } from 'vs/platform/log/common/log'; @@ -1700,6 +1700,15 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic return arrays.firstOrDefault(res); } + getWindowByWebContents(webContents: WebContents): ICodeWindow | undefined { + const browserWindow = BrowserWindow.fromWebContents(webContents); + if (!browserWindow) { + return undefined; + } + + return this.getWindowById(browserWindow.id); + } + getWindows(): ICodeWindow[] { return WindowsMainService.WINDOWS; } diff --git a/src/vs/workbench/electron-sandbox/window.ts b/src/vs/workbench/electron-sandbox/window.ts index bb569ca8995..96da9d6389b 100644 --- a/src/vs/workbench/electron-sandbox/window.ts +++ b/src/vs/workbench/electron-sandbox/window.ts @@ -185,9 +185,15 @@ export class NativeWindow extends Disposable { ipcRenderer.on('vscode:addFolders', (event: unknown, request: IAddFoldersRequest) => this.onAddFoldersRequest(request)); // Message support - ipcRenderer.on('vscode:showInfoMessage', (event: unknown, message: string) => { - this.notificationService.info(message); - }); + ipcRenderer.on('vscode:showInfoMessage', (event: unknown, message: string) => this.notificationService.info(message)); + ipcRenderer.on('vscode:showShellEnvTimeoutWarningMessage', () => this.notificationService.prompt( + Severity.Warning, + nls.localize('shellEnvTimeoutWarning', "It took more than 10s to resolve your shell environment. Please review your shell configuration."), + [{ + label: nls.localize('learnMode', "Learn More"), + run: () => this.openerService.open('https://go.microsoft.com/fwlink/?linkid=2149667') + }] + )); // Display change events ipcRenderer.on('vscode:displayChanged', () => {