chore(vscode): update to 1.55.2

This commit is contained in:
Akash Satheesan
2021-04-09 11:32:27 +05:30
1102 changed files with 39988 additions and 23544 deletions

View File

@@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { isMacintosh, isLinux, isWeb, IProcessEnvironment } from 'vs/base/common/platform';
import { isMacintosh, isLinux, isWeb, IProcessEnvironment, isNative } from 'vs/base/common/platform';
import { URI, UriComponents } from 'vs/base/common/uri';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
@@ -19,6 +19,14 @@ export const WindowMinimumSize = {
export interface IBaseOpenWindowsOptions {
readonly forceReuseWindow?: boolean;
/**
* The remote authority to use when windows are opened with either
* - no workspace (empty window)
* - a workspace that is neither `file://` nor `vscode-remote://`
* Use 'null' for a local window.
* If not set, defaults to the remote authority of the current window.
*/
readonly remoteAuthority?: string | null;
}
export interface IOpenWindowOptions extends IBaseOpenWindowsOptions {
@@ -48,7 +56,6 @@ export interface IOpenedWindow {
}
export interface IOpenEmptyWindowOptions extends IBaseOpenWindowsOptions {
readonly remoteAuthority?: string;
}
export type IWindowOpenable = IWorkspaceToOpen | IFolderToOpen | IFileToOpen;
@@ -87,7 +94,7 @@ export function getMenuBarVisibility(configurationService: IConfigurationService
const titleBarStyle = getTitleBarStyle(configurationService);
const menuBarVisibility = configurationService.getValue<MenuBarVisibility | 'default'>('window.menuBarVisibility');
if (menuBarVisibility === 'default' || (titleBarStyle === 'native' && menuBarVisibility === 'compact')) {
if (menuBarVisibility === 'default' || (titleBarStyle === 'native' && menuBarVisibility === 'compact') || (isMacintosh && isNative)) {
return 'classic';
} else {
return menuBarVisibility;
@@ -114,7 +121,6 @@ export interface IWindowSettings {
readonly enableMenuBarMnemonics: boolean;
readonly closeWhenEmpty: boolean;
readonly clickThroughInactive: boolean;
readonly enableExperimentalMainProcessWorkspaceStorage: boolean;
}
export function getTitleBarStyle(configurationService: IConfigurationService): 'native' | 'custom' {
@@ -254,8 +260,6 @@ export interface INativeWindowConfiguration extends IWindowConfiguration, Native
filesToWait?: IPathsToWaitFor;
os: IOSConfiguration;
enableExperimentalMainProcessWorkspaceStorage: boolean;
}
/**

View File

@@ -15,9 +15,9 @@ import { ILogService } from 'vs/platform/log/common/log';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { parseArgs, OPTIONS } from 'vs/platform/environment/node/argv';
import { NativeParsedArgs } from 'vs/platform/environment/common/argv';
import product from 'vs/platform/product/common/product';
import { IProductService } from 'vs/platform/product/common/productService';
import { WindowMinimumSize, IWindowSettings, MenuBarVisibility, getTitleBarStyle, getMenuBarVisibility, zoomLevelToZoomFactor, INativeWindowConfiguration } from 'vs/platform/windows/common/windows';
import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
import { Disposable } from 'vs/base/common/lifecycle';
import { browserCodeLoadingCacheStrategy, isLinux, isMacintosh, isWindows } from 'vs/base/common/platform';
import { defaultWindowState, ICodeWindow, ILoadEvent, IWindowState, WindowError, WindowMode } from 'vs/platform/windows/electron-main/windows';
import { ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, isWorkspaceIdentifier, IWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
@@ -26,7 +26,6 @@ import { IBackupMainService } from 'vs/platform/backup/electron-main/backup';
import { ISerializableCommandAction } from 'vs/platform/actions/common/actions';
import { resolveMarketplaceHeaders } from 'vs/platform/extensionManagement/common/extensionGalleryService';
import { IThemeMainService } from 'vs/platform/theme/electron-main/themeMainService';
import { RunOnceScheduler } from 'vs/base/common/async';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IDialogMainService } from 'vs/platform/dialogs/electron-main/dialogMainService';
import { mnemonicButtonLabel } from 'vs/base/common/labels';
@@ -37,6 +36,7 @@ import { ByteSize, IFileService } from 'vs/platform/files/common/files';
import { FileAccess, Schemas } from 'vs/base/common/network';
import { isLaunchedFromCli } from 'vs/platform/environment/node/argvHelper';
import { CancellationToken } from 'vs/base/common/cancellation';
import { INativeHostMainService } from 'vs/platform/native/electron-main/nativeHostMainService';
export interface IWindowCreationOptions {
state: IWindowState;
@@ -89,8 +89,6 @@ export class CodeWindow extends Disposable implements ICodeWindow {
private hiddenTitleBarStyle: boolean | undefined;
private showTimeoutHandle: NodeJS.Timeout | undefined;
private _lastFocusTime = -1;
private _readyState = ReadyState.NONE;
private windowState: IWindowState;
private currentMenuBarVisibility: MenuBarVisibility | undefined;
@@ -118,7 +116,9 @@ export class CodeWindow extends Disposable implements ICodeWindow {
@IBackupMainService private readonly backupMainService: IBackupMainService,
@ITelemetryService private readonly telemetryService: ITelemetryService,
@IDialogMainService private readonly dialogMainService: IDialogMainService,
@ILifecycleMainService private readonly lifecycleMainService: ILifecycleMainService
@ILifecycleMainService private readonly lifecycleMainService: ILifecycleMainService,
@INativeHostMainService private readonly nativeHostMainService: INativeHostMainService,
@IProductService private readonly productService: IProductService
) {
super();
@@ -143,7 +143,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
minWidth: WindowMinimumSize.WIDTH,
minHeight: WindowMinimumSize.HEIGHT,
show: !isFullscreenOrMaximized,
title: product.nameLong,
title: this.productService.nameLong,
webPreferences: {
preload: FileAccess.asFileUri('vs/base/parts/sandbox/electron-browser/preload.js', require).fsPath,
v8CacheOptions: browserCodeLoadingCacheStrategy,
@@ -195,7 +195,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
const useNativeTabs = isMacintosh && windowConfig?.nativeTabs === true;
if (useNativeTabs) {
options.tabbingIdentifier = product.nameShort; // this opts in to sierra tabs
options.tabbingIdentifier = this.productService.nameShort; // this opts in to sierra tabs
}
const useCustomTitleStyle = getTitleBarStyle(this.configurationService) === 'custom';
@@ -262,7 +262,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
this.createTouchBar();
// Request handling
this.marketplaceHeadersPromise = resolveMarketplaceHeaders(product.version, this.environmentMainService, this.fileService, {
this.marketplaceHeadersPromise = resolveMarketplaceHeaders(this.productService.version, this.environmentMainService, this.fileService, {
get: key => storageMainService.globalStorage.get(key),
store: (key, value) => storageMainService.globalStorage.set(key, value)
});
@@ -345,6 +345,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
this._win.focus();
}
private _lastFocusTime = -1;
get lastFocusTime(): number { return this._lastFocusTime; }
get backupPath(): string | undefined { return this.currentConfig?.backupPath; }
@@ -353,8 +354,10 @@ export class CodeWindow extends Disposable implements ICodeWindow {
get remoteAuthority(): string | undefined { return this.currentConfig?.remoteAuthority; }
private readyState = ReadyState.NONE;
setReady(): void {
this._readyState = ReadyState.READY;
this.readyState = ReadyState.READY;
// inform all waiting promises that we are ready now
while (this.whenReadyCallbacks.length) {
@@ -377,7 +380,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
}
get isReady(): boolean {
return this._readyState === ReadyState.READY;
return this.readyState === ReadyState.READY;
}
get whenClosedOrLoaded(): Promise<void> {
@@ -409,13 +412,14 @@ export class CodeWindow extends Disposable implements ICodeWindow {
this.dispose();
});
// Block all SVG requests from unsupported origins
const svgFileSchemes = new Set([Schemas.file, Schemas.vscodeFileResource, Schemas.vscodeRemoteResource, 'devtools']);
this._win.webContents.session.webRequest.onBeforeRequest((details, callback) => {
const uri = URI.parse(details.url);
// Prevent loading of remote svgs
if (uri && uri.path.endsWith('.svg')) {
const safeScheme = svgFileSchemes.has(uri.scheme) ||
uri.path.includes(Schemas.vscodeRemoteResource);
if (uri.path.endsWith('.svg')) {
const safeScheme = svgFileSchemes.has(uri.scheme) || uri.path.includes(Schemas.vscodeRemoteResource);
if (!safeScheme) {
return callback({ cancel: true });
}
@@ -424,25 +428,27 @@ export class CodeWindow extends Disposable implements ICodeWindow {
return callback({ cancel: false });
});
// Configure SVG header content type properly
this._win.webContents.session.webRequest.onHeadersReceived((details, callback) => {
const responseHeaders = details.responseHeaders as Record<string, (string) | (string[])>;
const contentType = (responseHeaders['content-type'] || responseHeaders['Content-Type']);
const contentTypes = (responseHeaders['content-type'] || responseHeaders['Content-Type']);
if (contentType && Array.isArray(contentType)) {
if (contentTypes && Array.isArray(contentTypes)) {
const uri = URI.parse(details.url);
// https://github.com/microsoft/vscode/issues/97564
// ensure local svg files have Content-Type image/svg+xml
if (uri && uri.path.endsWith('.svg')) {
if (uri.path.endsWith('.svg')) {
if (svgFileSchemes.has(uri.scheme)) {
responseHeaders['Content-Type'] = ['image/svg+xml'];
return callback({ cancel: false, responseHeaders });
}
}
// remote extension schemes have the following format
// http://127.0.0.1:<port>/vscode-remote-resource?path=
if (!uri.path.includes(Schemas.vscodeRemoteResource) &&
contentType.some(x => x.toLowerCase().includes('image/svg'))) {
if (!uri.path.includes(Schemas.vscodeRemoteResource) && contentTypes.some(contentType => contentType.toLowerCase().includes('image/svg'))) {
return callback({ cancel: true });
}
}
@@ -452,7 +458,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
// Remember that we loaded
this._win.webContents.on('did-finish-load', () => {
this._readyState = ReadyState.LOADING;
this.readyState = ReadyState.LOADING;
// Associate properties from the load request if provided
if (this.pendingLoadConfig) {
@@ -468,7 +474,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
});
if (isMacintosh) {
const displayChangedScheduler = this._register(new RunOnceScheduler(() => {
this._register(this.nativeHostMainService.onDidChangeDisplay(() => {
if (!this._win) {
return; // disposed
}
@@ -480,27 +486,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
this.setFullScreen(false);
this.setFullScreen(true);
}
}, 100));
const displayChangedListener = (event: Event, display: Display, changedMetrics?: string[]) => {
if (Array.isArray(changedMetrics) && changedMetrics.length === 1 && changedMetrics[0] === 'workArea') {
// 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;
}
displayChangedScheduler.schedule();
};
screen.on('display-metrics-changed', displayChangedListener);
this._register(toDisposable(() => screen.removeListener('display-metrics-changed', displayChangedListener)));
screen.on('display-added', displayChangedListener);
this._register(toDisposable(() => screen.removeListener('display-added', displayChangedListener)));
screen.on('display-removed', displayChangedListener);
this._register(toDisposable(() => screen.removeListener('display-removed', displayChangedListener)));
}));
}
// Window (Un)Maximize
@@ -578,7 +564,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
type: WindowError;
reason: string | undefined;
};
this.telemetryService.publicLog2<WindowErrorEvent, WindowErrorClassification>('windowerror', { type, reason: (details && typeof details !== 'string') ? details.reason : undefined });
this.telemetryService.publicLog2<WindowErrorEvent, WindowErrorClassification>('windowerror', { type, reason: typeof details !== 'string' ? details?.reason : undefined });
// Unresponsive
if (type === WindowError.UNRESPONSIVE) {
@@ -594,7 +580,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
// Show Dialog
const result = await this.dialogMainService.showMessageBox({
title: product.nameLong,
title: this.productService.nameLong,
type: 'warning',
buttons: [mnemonicButtonLabel(localize({ key: 'reopen', comment: ['&& denotes a mnemonic'] }, "&&Reopen")), mnemonicButtonLabel(localize({ key: 'wait', comment: ['&& denotes a mnemonic'] }, "&&Keep Waiting")), mnemonicButtonLabel(localize({ key: 'close', comment: ['&& denotes a mnemonic'] }, "&&Close"))],
message: localize('appStalled', "The window is no longer responding"),
@@ -624,7 +610,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
}
const result = await this.dialogMainService.showMessageBox({
title: product.nameLong,
title: this.productService.nameLong,
type: 'warning',
buttons: [mnemonicButtonLabel(localize({ key: 'reopen', comment: ['&& denotes a mnemonic'] }, "&&Reopen")), mnemonicButtonLabel(localize({ key: 'close', comment: ['&& denotes a mnemonic'] }, "&&Close"))],
message,
@@ -717,7 +703,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
// If this is the first time the window is loaded, we associate the paths
// directly with the window because we assume the loading will just work
if (this._readyState === ReadyState.NONE) {
if (this.readyState === ReadyState.NONE) {
this.currentConfig = config;
}
@@ -727,7 +713,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
// the window load event has fired.
else {
this.pendingLoadConfig = config;
this._readyState = ReadyState.NAVIGATING;
this.readyState = ReadyState.NAVIGATING;
}
// Add disable-extensions to the config, but do not preserve it on currentConfig or
@@ -750,7 +736,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
this.setRepresentedFilename('');
}
this._win.setTitle(product.nameLong);
this._win.setTitle(this.productService.nameLong);
}
// Load URL
@@ -870,8 +856,6 @@ export class CodeWindow extends Disposable implements ICodeWindow {
release: release()
};
windowConfiguration.enableExperimentalMainProcessWorkspaceStorage = !!(windowConfig?.enableExperimentalMainProcessWorkspaceStorage);
// Config (combination of process.argv and window configuration)
const environment = parseArgs(process.argv, OPTIONS);
const config = Object.assign(environment, windowConfiguration) as unknown as { [key: string]: unknown };

View File

@@ -197,6 +197,12 @@ export interface IOpenConfiguration extends IBaseOpenConfiguration {
readonly gotoLineMode?: boolean;
readonly initialStartup?: boolean;
readonly noRecentEntry?: boolean;
/**
* The remote authority to use when windows are opened with either
* - no workspace (empty window)
* - a workspace that is neither `file://` nor `vscode-remote://`
*/
readonly remoteAuthority?: string;
}
export interface IOpenEmptyConfiguration extends IBaseOpenConfiguration { }

View File

@@ -20,7 +20,7 @@ import { ILogService } from 'vs/platform/log/common/log';
import { IWindowSettings, IPath, isFileToOpen, isWorkspaceToOpen, isFolderToOpen, IWindowOpenable, IOpenEmptyWindowOptions, IAddFoldersRequest, IPathsToWaitFor, INativeWindowConfiguration, INativeOpenFileRequest } from 'vs/platform/windows/common/windows';
import { findWindowOnFile, findWindowOnWorkspaceOrFolder, findWindowOnExtensionDevelopmentPath } from 'vs/platform/windows/electron-main/windowsFinder';
import { Emitter } from 'vs/base/common/event';
import product from 'vs/platform/product/common/product';
import { IProductService } from 'vs/platform/product/common/productService';
import { IWindowsMainService, IOpenConfiguration, IWindowsCountChangedEvent, ICodeWindow, IOpenEmptyConfiguration, OpenContext } from 'vs/platform/windows/electron-main/windows';
import { IWorkspacesHistoryMainService } from 'vs/platform/workspaces/electron-main/workspacesHistoryMainService';
import { IProcessEnvironment, isMacintosh } from 'vs/base/common/platform';
@@ -41,6 +41,7 @@ import { CharCode } from 'vs/base/common/charCode';
import { getPathLabel } from 'vs/base/common/labels';
import { CancellationToken } from 'vs/base/common/cancellation';
import { IFileService } from 'vs/platform/files/common/files';
import { cwd } from 'vs/base/common/process';
//#region Helper Interfaces
@@ -68,6 +69,10 @@ interface IOpenBrowserWindowOptions {
interface IPathResolveOptions {
readonly ignoreFileNotFound?: boolean;
readonly gotoLineMode?: boolean;
readonly forceOpenWorkspaceAsFile?: boolean;
/**
* The remoteAuthority to use if the URL to open is neither file nor vscode-remote
*/
readonly remoteAuthority?: string;
}
@@ -145,7 +150,8 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
@IWorkspacesManagementMainService private readonly workspacesManagementMainService: IWorkspacesManagementMainService,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@IDialogMainService private readonly dialogMainService: IDialogMainService,
@IFileService private readonly fileService: IFileService
@IFileService private readonly fileService: IFileService,
@IProductService private readonly productService: IProductService
) {
super();
@@ -160,16 +166,12 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
openEmptyWindow(openConfig: IOpenEmptyConfiguration, options?: IOpenEmptyWindowOptions): ICodeWindow[] {
let cli = this.environmentMainService.args;
const remote = options?.remoteAuthority;
if (cli && (cli.remote !== remote)) {
cli = { ...cli, remote };
}
const remoteAuthority = options?.remoteAuthority || undefined;
const forceEmpty = true;
const forceReuseWindow = options?.forceReuseWindow;
const forceNewWindow = !forceReuseWindow;
return this.open({ ...openConfig, cli, forceEmpty, forceNewWindow, forceReuseWindow });
return this.open({ ...openConfig, cli, forceEmpty, forceNewWindow, forceReuseWindow, remoteAuthority });
}
open(openConfig: IOpenConfiguration): ICodeWindow[] {
@@ -298,11 +300,11 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
const recents: IRecent[] = [];
for (const pathToOpen of pathsToOpen) {
if (isWorkspacePathToOpen(pathToOpen)) {
recents.push({ label: pathToOpen.label, workspace: pathToOpen.workspace });
recents.push({ label: pathToOpen.label, workspace: pathToOpen.workspace, remoteAuthority: pathToOpen.remoteAuthority });
} else if (isSingleFolderWorkspacePathToOpen(pathToOpen)) {
recents.push({ label: pathToOpen.label, folderUri: pathToOpen.workspace.uri });
recents.push({ label: pathToOpen.label, folderUri: pathToOpen.workspace.uri, remoteAuthority: pathToOpen.remoteAuthority });
} else if (pathToOpen.fileUri) {
recents.push({ label: pathToOpen.label, fileUri: pathToOpen.fileUri });
recents.push({ label: pathToOpen.label, fileUri: pathToOpen.fileUri, remoteAuthority: pathToOpen.remoteAuthority });
}
}
@@ -507,7 +509,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
emptyToOpen++;
}
const remoteAuthority = filesToOpen ? filesToOpen.remoteAuthority : (openConfig.cli && openConfig.cli.remote || undefined);
const remoteAuthority = filesToOpen ? filesToOpen.remoteAuthority : openConfig.remoteAuthority;
for (let i = 0; i < emptyToOpen; i++) {
addUsedWindow(this.doOpenEmpty(openConfig, openFolderInNewWindow, remoteAuthority, filesToOpen), !!filesToOpen);
@@ -650,7 +652,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
private doExtractPathsFromAPI(openConfig: IOpenConfiguration): IPathToOpen[] {
const pathsToOpen: IPathToOpen[] = [];
const pathResolveOptions: IPathResolveOptions = { gotoLineMode: openConfig.gotoLineMode };
const pathResolveOptions: IPathResolveOptions = { gotoLineMode: openConfig.gotoLineMode, remoteAuthority: openConfig.remoteAuthority };
for (const pathToOpen of coalesce(openConfig.urisToOpen || [])) {
const path = this.resolveOpenable(pathToOpen, pathResolveOptions);
@@ -665,7 +667,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
const uri = this.resourceFromOpenable(pathToOpen);
const options: MessageBoxOptions = {
title: product.nameLong,
title: this.productService.nameLong,
type: 'info',
buttons: [localize('ok', "OK")],
message: uri.scheme === Schemas.file ? localize('pathNotExistTitle', "Path does not exist") : localize('uriInvalidTitle', "URI can not be opened"),
@@ -684,7 +686,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
private doExtractPathsFromCLI(cli: NativeParsedArgs): IPath[] {
const pathsToOpen: IPathToOpen[] = [];
const pathResolveOptions: IPathResolveOptions = { ignoreFileNotFound: true, gotoLineMode: cli.goto, remoteAuthority: cli.remote || undefined };
const pathResolveOptions: IPathResolveOptions = { ignoreFileNotFound: true, gotoLineMode: cli.goto, remoteAuthority: cli.remote || undefined, forceOpenWorkspaceAsFile: false };
// folder uris
const folderUris = cli['folder-uri'];
@@ -717,12 +719,11 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
// folder or file paths
const cliPaths = cli._;
for (const cliPath of cliPaths) {
const path = this.doResolveFileOpenable(cliPath, pathResolveOptions);
const path = cli.remote ? this.doResolvePathRemote(cliPath, cli.remote) : this.doResolveFilePath(cliPath, pathResolveOptions);
if (path) {
pathsToOpen.push(path);
}
}
return pathsToOpen;
}
@@ -819,7 +820,10 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
// handle file:// openables with some extra validation
let uri = this.resourceFromOpenable(openable);
if (uri.scheme === Schemas.file) {
return this.doResolveFileOpenable(openable, options);
if (isFileToOpen(openable)) {
options = { ...options, forceOpenWorkspaceAsFile: true };
}
return this.doResolveFilePath(uri.fsPath, options);
}
// handle non file:// openables
@@ -829,8 +833,8 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
private doResolveRemoteOpenable(openable: IWindowOpenable, options: IPathResolveOptions): IPathToOpen | undefined {
let uri = this.resourceFromOpenable(openable);
// open remote if either specified in the cli or if it's a remotehost URI
const remoteAuthority = options.remoteAuthority || getRemoteAuthority(uri);
// use remote authority from vscode
const remoteAuthority = getRemoteAuthority(uri) || options.remoteAuthority;
// normalize URI
uri = removeTrailingPathSeparator(normalizePath(uri));
@@ -867,17 +871,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
return openable.fileUri;
}
private doResolveFileOpenable(path: string, options: IPathResolveOptions): IPathToOpen | undefined;
private doResolveFileOpenable(openable: IWindowOpenable, options: IPathResolveOptions): IPathToOpen | undefined;
private doResolveFileOpenable(pathOrOpenable: string | IWindowOpenable, options: IPathResolveOptions): IPathToOpen | undefined {
let path: string;
let forceOpenWorkspaceAsFile = false;
if (typeof pathOrOpenable === 'string') {
path = pathOrOpenable;
} else {
path = this.resourceFromOpenable(pathOrOpenable).fsPath;
forceOpenWorkspaceAsFile = isFileToOpen(pathOrOpenable);
}
private doResolveFilePath(path: string, options: IPathResolveOptions): IPathToOpen | undefined {
// Extract line/col information from path
let lineNumber: number | undefined;
@@ -891,14 +885,44 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
path = parsedPath.path;
}
// With remote: resolve path as remote URI
const remoteAuthority = options.remoteAuthority;
if (remoteAuthority) {
return this.doResolvePathRemote(path, remoteAuthority, forceOpenWorkspaceAsFile);
// Ensure the path is normalized and absolute
path = sanitizeFilePath(normalize(path), cwd());
try {
const pathStat = statSync(path);
if (pathStat.isFile()) {
// Workspace (unless disabled via flag)
if (!options.forceOpenWorkspaceAsFile) {
const workspace = this.workspacesManagementMainService.resolveLocalWorkspaceSync(URI.file(path));
if (workspace) {
return { workspace: { id: workspace.id, configPath: workspace.configPath }, remoteAuthority: workspace.remoteAuthority, exists: true };
}
}
// File
return { fileUri: URI.file(path), lineNumber, columnNumber, exists: true };
}
// Folder (we check for isDirectory() because e.g. paths like /dev/null
// are neither file nor folder but some external tools might pass them
// over to us)
else if (pathStat.isDirectory()) {
return { workspace: getSingleFolderWorkspaceIdentifier(URI.file(path), pathStat), exists: true };
}
} catch (error) {
const fileUri = URI.file(path);
// since file does not seem to exist anymore, remove from recent
this.workspacesHistoryMainService.removeRecentlyOpened([fileUri]);
// assume this is a file that does not yet exist
if (options.ignoreFileNotFound) {
return { fileUri, exists: false };
}
}
// Without remote: resolve path as local URI
return this.doResolvePathLocal(path, options, lineNumber, columnNumber, forceOpenWorkspaceAsFile);
return undefined;
}
private doResolvePathRemote(path: string, remoteAuthority: string, forceOpenWorkspaceAsFile?: boolean): IPathToOpen | undefined {
@@ -938,48 +962,6 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
return { workspace: getSingleFolderWorkspaceIdentifier(uri), remoteAuthority };
}
private doResolvePathLocal(path: string, options: IPathResolveOptions, lineNumber: number | undefined, columnNumber: number | undefined, forceOpenWorkspaceAsFile?: boolean): IPathToOpen | undefined {
// Ensure the path is normalized and absolute
path = sanitizeFilePath(normalize(path), process.env['VSCODE_CWD'] || process.cwd());
try {
const pathStat = statSync(path);
if (pathStat.isFile()) {
// Workspace (unless disabled via flag)
if (!forceOpenWorkspaceAsFile) {
const workspace = this.workspacesManagementMainService.resolveLocalWorkspaceSync(URI.file(path));
if (workspace) {
return { workspace: { id: workspace.id, configPath: workspace.configPath }, remoteAuthority: workspace.remoteAuthority, exists: true };
}
}
// File
return { fileUri: URI.file(path), lineNumber, columnNumber, exists: true };
}
// Folder (we check for isDirectory() because e.g. paths like /dev/null
// are neither file nor folder but some external tools might pass them
// over to us)
else if (pathStat.isDirectory()) {
return { workspace: getSingleFolderWorkspaceIdentifier(URI.file(path), pathStat), exists: true };
}
} catch (error) {
const fileUri = URI.file(path);
// since file does not seem to exist anymore, remove from recent
this.workspacesHistoryMainService.removeRecentlyOpened([fileUri]);
// assume this is a file that does not yet exist
if (options?.ignoreFileNotFound) {
return { fileUri, exists: false };
}
}
return undefined;
}
private shouldOpenNewWindow(openConfig: IOpenConfiguration): { openFolderInNewWindow: boolean; openFilesInNewWindow: boolean; } {
// let the user settings override how folders are open in a new window or same window unless we are forced
@@ -1060,17 +1042,18 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
}
}
let authority = '';
let remoteAuthority = openConfig.remoteAuthority;
for (const extensionDevelopmentPath of extensionDevelopmentPaths) {
if (extensionDevelopmentPath.match(/^[a-zA-Z][a-zA-Z0-9\+\-\.]+:/)) {
const url = URI.parse(extensionDevelopmentPath);
if (url.scheme === Schemas.vscodeRemote) {
if (authority) {
if (url.authority !== authority) {
const extensionDevelopmentPathRemoteAuthority = getRemoteAuthority(url);
if (extensionDevelopmentPathRemoteAuthority) {
if (remoteAuthority) {
if (extensionDevelopmentPathRemoteAuthority !== remoteAuthority) {
this.logService.error('more than one extension development path authority');
}
} else {
authority = url.authority;
remoteAuthority = extensionDevelopmentPathRemoteAuthority;
}
}
}
@@ -1086,7 +1069,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
return false;
}
return uri.authority === authority;
return getRemoteAuthority(uri) === remoteAuthority;
});
folderUris = folderUris.filter(folderUriStr => {
@@ -1095,7 +1078,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
return false;
}
return folderUri ? folderUri.authority === authority : false;
return folderUri ? getRemoteAuthority(folderUri) === remoteAuthority : false;
});
fileUris = fileUris.filter(fileUriStr => {
@@ -1104,18 +1087,14 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
return false;
}
return fileUri ? fileUri.authority === authority : false;
return fileUri ? getRemoteAuthority(fileUri) === remoteAuthority : false;
});
openConfig.cli._ = cliArgs;
openConfig.cli['folder-uri'] = folderUris;
openConfig.cli['file-uri'] = fileUris;
// if there are no files or folders cli args left, use the "remote" cli argument
const noFilesOrFolders = !cliArgs.length && !folderUris.length && !fileUris.length;
if (noFilesOrFolders && authority) {
openConfig.cli.remote = authority;
}
// Open it
const openArgs: IOpenConfiguration = {
@@ -1125,7 +1104,8 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
forceEmpty: noFilesOrFolders,
userEnv: openConfig.userEnv,
noRecentEntry: true,
waitMarkerFileURI: openConfig.waitMarkerFileURI
waitMarkerFileURI: openConfig.waitMarkerFileURI,
remoteAuthority
};
return this.open(openArgs);

View File

@@ -9,7 +9,7 @@ import { findWindowOnFile } from 'vs/platform/windows/electron-main/windowsFinde
import { ICodeWindow, ILoadEvent, IWindowState } from 'vs/platform/windows/electron-main/windows';
import { IWorkspaceIdentifier, toWorkspaceFolders } from 'vs/platform/workspaces/common/workspaces';
import { URI } from 'vs/base/common/uri';
import { getPathFromAmdModule } from 'vs/base/common/amd';
import { getPathFromAmdModule } from 'vs/base/test/node/testUtils';
import { extUriBiasedIgnorePathCase } from 'vs/base/common/resources';
import { CancellationToken } from 'vs/base/common/cancellation';
import { Event } from 'vs/base/common/event';