mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-28 17:23:19 -05:00
Vscode merge (#4582)
* Merge from vscode 37cb23d3dd4f9433d56d4ba5ea3203580719a0bd * fix issues with merges * bump node version in azpipe * replace license headers * remove duplicate launch task * fix build errors * fix build errors * fix tslint issues * working through package and linux build issues * more work * wip * fix packaged builds * working through linux build errors * wip * wip * wip * fix mac and linux file limits * iterate linux pipeline * disable editor typing * revert series to parallel * remove optimize vscode from linux * fix linting issues * revert testing change * add work round for new node * readd packaging for extensions * fix issue with angular not resolving decorator dependencies
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
import { app, ipcMain as ipc, systemPreferences, shell, Event, contentTracing, protocol, powerMonitor } from 'electron';
|
||||
import { IProcessEnvironment, isWindows, isMacintosh } from 'vs/base/common/platform';
|
||||
import { WindowsManager } from 'vs/code/electron-main/windows';
|
||||
import { IWindowsService, OpenContext, ActiveWindowManager } from 'vs/platform/windows/common/windows';
|
||||
import { IWindowsService, OpenContext, ActiveWindowManager, IURIToOpen } from 'vs/platform/windows/common/windows';
|
||||
import { WindowsChannel } from 'vs/platform/windows/node/windowsIpc';
|
||||
import { WindowsService } from 'vs/platform/windows/electron-main/windowsService';
|
||||
import { ILifecycleService, LifecycleService } from 'vs/platform/lifecycle/electron-main/lifecycleMain';
|
||||
@@ -16,7 +16,6 @@ import { UpdateChannel } from 'vs/platform/update/node/updateIpc';
|
||||
import { Server as ElectronIPCServer } from 'vs/base/parts/ipc/electron-main/ipc.electron-main';
|
||||
import { Server, connect, Client } from 'vs/base/parts/ipc/node/ipc.net';
|
||||
import { SharedProcess } from 'vs/code/electron-main/sharedProcess';
|
||||
import { Mutex } from 'windows-mutex';
|
||||
import { LaunchService, LaunchChannel, ILaunchService } from 'vs/platform/launch/electron-main/launchService';
|
||||
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
|
||||
@@ -33,14 +32,14 @@ import { TelemetryAppenderClient } from 'vs/platform/telemetry/node/telemetryIpc
|
||||
import { TelemetryService, ITelemetryServiceConfig } from 'vs/platform/telemetry/common/telemetryService';
|
||||
import { resolveCommonProperties } from 'vs/platform/telemetry/node/commonProperties';
|
||||
import { getDelayedChannel, StaticRouter } from 'vs/base/parts/ipc/node/ipc';
|
||||
import product from 'vs/platform/node/product';
|
||||
import pkg from 'vs/platform/node/package';
|
||||
import product from 'vs/platform/product/node/product';
|
||||
import pkg from 'vs/platform/product/node/package';
|
||||
import { ProxyAuthHandler } from 'vs/code/electron-main/auth';
|
||||
import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { ConfigurationService } from 'vs/platform/configuration/node/configurationService';
|
||||
import { IWindowsMainService, ICodeWindow } from 'vs/platform/windows/electron-main/windows';
|
||||
import { IHistoryMainService } from 'vs/platform/history/common/history';
|
||||
import { isUndefinedOrNull } from 'vs/base/common/types';
|
||||
import { isUndefinedOrNull, withUndefinedAsNull } from 'vs/base/common/types';
|
||||
import { KeyboardLayoutMonitor } from 'vs/code/electron-main/keyboard';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { WorkspacesChannel } from 'vs/platform/workspaces/node/workspacesIpc';
|
||||
@@ -56,7 +55,7 @@ import { LogLevelSetterChannel } from 'vs/platform/log/node/logIpc';
|
||||
import * as errors from 'vs/base/common/errors';
|
||||
import { ElectronURLListener } from 'vs/platform/url/electron-main/electronUrlListener';
|
||||
import { serve as serveDriver } from 'vs/platform/driver/electron-main/driver';
|
||||
import { connectRemoteAgentManagement, RemoteAgentConnectionContext } from 'vs/platform/remote/node/remoteAgentConnection';
|
||||
import { connectRemoteAgentManagement } from 'vs/platform/remote/node/remoteAgentConnection';
|
||||
import { IMenubarService } from 'vs/platform/menubar/common/menubar';
|
||||
import { MenubarService } from 'vs/platform/menubar/electron-main/menubarService';
|
||||
import { MenubarChannel } from 'vs/platform/menubar/node/menubarIpc';
|
||||
@@ -64,8 +63,8 @@ import { hasArgs } from 'vs/platform/environment/node/argv';
|
||||
import { RunOnceScheduler } from 'vs/base/common/async';
|
||||
import { registerContextMenuListener } from 'vs/base/parts/contextmenu/electron-main/contextmenu';
|
||||
import { storeBackgroundColor } from 'vs/code/electron-main/theme';
|
||||
import { nativeSep, join } from 'vs/base/common/paths';
|
||||
import { homedir } from 'os';
|
||||
import { join, sep } from 'vs/base/common/path';
|
||||
import { localize } from 'vs/nls';
|
||||
import { REMOTE_HOST_SCHEME } from 'vs/platform/remote/common/remoteHosts';
|
||||
import { REMOTE_FILE_SYSTEM_CHANNEL_NAME } from 'vs/platform/remote/node/remoteAgentFileSystemChannel';
|
||||
@@ -73,13 +72,13 @@ import { ResolvedAuthority } from 'vs/platform/remote/common/remoteAuthorityReso
|
||||
import { SnapUpdateService } from 'vs/platform/update/electron-main/updateService.snap';
|
||||
import { IStorageMainService, StorageMainService } from 'vs/platform/storage/node/storageMainService';
|
||||
import { GlobalStorageDatabaseChannel } from 'vs/platform/storage/node/storageIpc';
|
||||
import { generateUuid } from 'vs/base/common/uuid';
|
||||
import { startsWith } from 'vs/base/common/strings';
|
||||
import { BackupMainService } from 'vs/platform/backup/electron-main/backupMainService';
|
||||
import { IBackupMainService } from 'vs/platform/backup/common/backup';
|
||||
import { HistoryMainService } from 'vs/platform/history/electron-main/historyMainService';
|
||||
import { URLService } from 'vs/platform/url/common/urlService';
|
||||
import { WorkspacesMainService } from 'vs/platform/workspaces/electron-main/workspacesMainService';
|
||||
import { RemoteAgentConnectionContext } from 'vs/platform/remote/common/remoteAgentEnvironment';
|
||||
|
||||
export class CodeApplication extends Disposable {
|
||||
|
||||
@@ -93,8 +92,8 @@ export class CodeApplication extends Disposable {
|
||||
private sharedProcessClient: Promise<Client>;
|
||||
|
||||
constructor(
|
||||
private mainIpcServer: Server,
|
||||
private userEnv: IProcessEnvironment,
|
||||
private readonly mainIpcServer: Server,
|
||||
private readonly userEnv: IProcessEnvironment,
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
@ILogService private readonly logService: ILogService,
|
||||
@IEnvironmentService private readonly environmentService: IEnvironmentService,
|
||||
@@ -155,7 +154,7 @@ export class CodeApplication extends Disposable {
|
||||
const srcUri = URI.parse(source).fsPath.toLowerCase();
|
||||
const rootUri = URI.file(this.environmentService.appRoot).fsPath.toLowerCase();
|
||||
|
||||
return startsWith(srcUri, rootUri + nativeSep);
|
||||
return startsWith(srcUri, rootUri + sep);
|
||||
};
|
||||
|
||||
// Ensure defaults
|
||||
@@ -188,14 +187,14 @@ export class CodeApplication extends Disposable {
|
||||
});
|
||||
});
|
||||
|
||||
let macOpenFileURIs: URI[] = [];
|
||||
let macOpenFileURIs: IURIToOpen[] = [];
|
||||
let runningTimeout: any = null;
|
||||
app.on('open-file', (event: Event, path: string) => {
|
||||
this.logService.trace('App#open-file: ', path);
|
||||
event.preventDefault();
|
||||
|
||||
// Keep in array because more might come!
|
||||
macOpenFileURIs.push(URI.file(path));
|
||||
macOpenFileURIs.push({ uri: URI.file(path) });
|
||||
|
||||
// Clear previous handler if any
|
||||
if (runningTimeout !== null) {
|
||||
@@ -461,6 +460,7 @@ export class CodeApplication extends Disposable {
|
||||
|
||||
const appInstantiationService = this.instantiationService.createChild(services);
|
||||
|
||||
// Init services that require it
|
||||
return appInstantiationService.invokeFunction(accessor => Promise.all([
|
||||
this.initStorageService(accessor),
|
||||
this.initBackupService(accessor)
|
||||
@@ -473,35 +473,8 @@ export class CodeApplication extends Disposable {
|
||||
// Ensure to close storage on shutdown
|
||||
this.lifecycleService.onWillShutdown(e => e.join(storageMainService.close()));
|
||||
|
||||
// Initialize storage service
|
||||
return storageMainService.initialize().then(undefined, error => {
|
||||
errors.onUnexpectedError(error);
|
||||
this.logService.error(error);
|
||||
}).then(() => {
|
||||
return Promise.resolve();
|
||||
|
||||
// Apply global telemetry values as part of the initialization
|
||||
// These are global across all windows and thereby should be
|
||||
// written from the main process once.
|
||||
|
||||
const telemetryInstanceId = 'telemetry.instanceId';
|
||||
const instanceId = storageMainService.get(telemetryInstanceId, null);
|
||||
if (instanceId === null) {
|
||||
storageMainService.store(telemetryInstanceId, generateUuid());
|
||||
}
|
||||
|
||||
const telemetryFirstSessionDate = 'telemetry.firstSessionDate';
|
||||
const firstSessionDate = storageMainService.get(telemetryFirstSessionDate, null);
|
||||
if (firstSessionDate === null) {
|
||||
storageMainService.store(telemetryFirstSessionDate, new Date().toUTCString());
|
||||
}
|
||||
|
||||
const telemetryCurrentSessionDate = 'telemetry.currentSessionDate';
|
||||
const telemetryLastSessionDate = 'telemetry.lastSessionDate';
|
||||
const lastSessionDate = storageMainService.get(telemetryCurrentSessionDate, null); // previous session date was the "current" one at that time
|
||||
const currentSessionDate = new Date().toUTCString(); // current session date is "now"
|
||||
storageMainService.store(telemetryLastSessionDate, lastSessionDate);
|
||||
storageMainService.store(telemetryCurrentSessionDate, currentSessionDate);
|
||||
});
|
||||
}
|
||||
|
||||
private initBackupService(accessor: ServicesAccessor): Promise<void> {
|
||||
@@ -545,7 +518,7 @@ export class CodeApplication extends Disposable {
|
||||
this.electronIpcServer.registerChannel('url', urlChannel);
|
||||
|
||||
const storageMainService = accessor.get(IStorageMainService);
|
||||
const storageChannel = this._register(new GlobalStorageDatabaseChannel(storageMainService as StorageMainService));
|
||||
const storageChannel = this._register(new GlobalStorageDatabaseChannel(this.logService, storageMainService as StorageMainService));
|
||||
this.electronIpcServer.registerChannel('storage', storageChannel);
|
||||
|
||||
// Log level management
|
||||
@@ -584,13 +557,13 @@ export class CodeApplication extends Disposable {
|
||||
});
|
||||
}
|
||||
|
||||
// Register the multiple URL handker
|
||||
// Register the multiple URL handler
|
||||
urlService.registerHandler(multiplexURLHandler);
|
||||
|
||||
// Watch Electron URLs and forward them to the UrlService
|
||||
const args = this.environmentService.args;
|
||||
const urls = args['open-url'] ? args._urls : [];
|
||||
const urlListener = new ElectronURLListener(urls, urlService, this.windowsMainService);
|
||||
const urlListener = new ElectronURLListener(urls || [], urlService, this.windowsMainService);
|
||||
this._register(urlListener);
|
||||
|
||||
this.windowsMainService.ready(this.userEnv);
|
||||
@@ -607,7 +580,7 @@ export class CodeApplication extends Disposable {
|
||||
}
|
||||
|
||||
if (macOpenFiles && macOpenFiles.length && !hasCliArgs && !hasFolderURIs && !hasFileURIs) {
|
||||
return this.windowsMainService.open({ context: OpenContext.DOCK, cli: args, urisToOpen: macOpenFiles.map(file => URI.file(file)), initialStartup: true }); // mac: open-file event received on startup
|
||||
return this.windowsMainService.open({ context: OpenContext.DOCK, cli: args, urisToOpen: macOpenFiles.map(file => ({ uri: URI.file(file) })), initialStartup: true }); // mac: open-file event received on startup
|
||||
}
|
||||
|
||||
return this.windowsMainService.open({ context, cli: args, forceNewWindow: args['new-window'] || (!hasCliArgs && args['unity-launch']), diffMode: args.diff, initialStartup: true }); // default: read paths from cli
|
||||
@@ -617,13 +590,12 @@ export class CodeApplication extends Disposable {
|
||||
const windowsMainService = accessor.get(IWindowsMainService);
|
||||
const historyMainService = accessor.get(IHistoryMainService);
|
||||
|
||||
let windowsMutex: Mutex | null = null;
|
||||
if (isWindows) {
|
||||
|
||||
// Setup Windows mutex
|
||||
try {
|
||||
const Mutex = (require.__$__nodeRequire('windows-mutex') as any).Mutex;
|
||||
windowsMutex = new Mutex(product.win32MutexName);
|
||||
const windowsMutex = new Mutex(product.win32MutexName);
|
||||
this._register(toDisposable(() => windowsMutex.release()));
|
||||
} catch (e) {
|
||||
if (!this.environmentService.isBuilt) {
|
||||
@@ -677,17 +649,17 @@ export class CodeApplication extends Disposable {
|
||||
const isBuilt = this.environmentService.isBuilt;
|
||||
|
||||
class ActiveConnection {
|
||||
private _authority: string;
|
||||
private _client: Promise<Client<RemoteAgentConnectionContext>>;
|
||||
private _disposeRunner: RunOnceScheduler;
|
||||
private readonly _authority: string;
|
||||
private readonly _client: Promise<Client<RemoteAgentConnectionContext>>;
|
||||
private readonly _disposeRunner: RunOnceScheduler;
|
||||
|
||||
constructor(authority: string, host: string, port: number) {
|
||||
this._authority = authority;
|
||||
this._client = connectRemoteAgentManagement(authority, host, port, `main`, isBuilt);
|
||||
this._disposeRunner = new RunOnceScheduler(() => this._dispose(), 5000);
|
||||
this._disposeRunner = new RunOnceScheduler(() => this.dispose(), 5000);
|
||||
}
|
||||
|
||||
private _dispose(): void {
|
||||
dispose(): void {
|
||||
this._disposeRunner.dispose();
|
||||
connectionPool.delete(this._authority);
|
||||
this._client.then((connection) => {
|
||||
@@ -695,7 +667,7 @@ export class CodeApplication extends Disposable {
|
||||
});
|
||||
}
|
||||
|
||||
public getClient(): Promise<Client<RemoteAgentConnectionContext>> {
|
||||
getClient(): Promise<Client<RemoteAgentConnectionContext>> {
|
||||
this._disposeRunner.schedule();
|
||||
return this._client;
|
||||
}
|
||||
@@ -703,42 +675,49 @@ export class CodeApplication extends Disposable {
|
||||
|
||||
const resolvedAuthorities = new Map<string, ResolvedAuthority>();
|
||||
ipc.on('vscode:remoteAuthorityResolved', (event: any, data: ResolvedAuthority) => {
|
||||
this.logService.info('Received resolved authority', data.authority);
|
||||
resolvedAuthorities.set(data.authority, data);
|
||||
// Make sure to close and remove any existing connections
|
||||
if (connectionPool.has(data.authority)) {
|
||||
connectionPool.get(data.authority)!.dispose();
|
||||
}
|
||||
});
|
||||
|
||||
const resolveAuthority = (authority: string): ResolvedAuthority | null => {
|
||||
this.logService.info('Resolving authority', authority);
|
||||
if (authority.indexOf('+') >= 0) {
|
||||
if (resolvedAuthorities.has(authority)) {
|
||||
return resolvedAuthorities.get(authority);
|
||||
return withUndefinedAsNull(resolvedAuthorities.get(authority));
|
||||
}
|
||||
this.logService.info('Didnot find resolved authority for', authority);
|
||||
return null;
|
||||
} else {
|
||||
const [host, strPort] = authority.split(':');
|
||||
const port = parseInt(strPort, 10);
|
||||
return { authority, host, port, syncExtensions: false };
|
||||
return { authority, host, port };
|
||||
}
|
||||
};
|
||||
|
||||
protocol.registerBufferProtocol(REMOTE_HOST_SCHEME, async (request, callback) => {
|
||||
if (request.method !== 'GET') {
|
||||
return callback(null);
|
||||
return callback(undefined);
|
||||
}
|
||||
const uri = URI.parse(request.url);
|
||||
|
||||
let activeConnection: ActiveConnection = null;
|
||||
let activeConnection: ActiveConnection | undefined;
|
||||
if (connectionPool.has(uri.authority)) {
|
||||
activeConnection = connectionPool.get(uri.authority);
|
||||
} else {
|
||||
let resolvedAuthority = resolveAuthority(uri.authority);
|
||||
const resolvedAuthority = resolveAuthority(uri.authority);
|
||||
if (!resolvedAuthority) {
|
||||
callback(null);
|
||||
callback(undefined);
|
||||
return;
|
||||
}
|
||||
activeConnection = new ActiveConnection(uri.authority, resolvedAuthority.host, resolvedAuthority.port);
|
||||
connectionPool.set(uri.authority, activeConnection);
|
||||
}
|
||||
try {
|
||||
const rawClient = await activeConnection.getClient();
|
||||
const rawClient = await activeConnection!.getClient();
|
||||
if (connectionPool.has(uri.authority)) { // not disposed in the meantime
|
||||
const channel = rawClient.getChannel(REMOTE_FILE_SYSTEM_CHANNEL_NAME);
|
||||
|
||||
@@ -746,11 +725,11 @@ export class CodeApplication extends Disposable {
|
||||
const fileContents = await channel.call<Uint8Array>('readFile', [uri]);
|
||||
callback(Buffer.from(fileContents));
|
||||
} else {
|
||||
callback(null);
|
||||
callback(undefined);
|
||||
}
|
||||
} catch (err) {
|
||||
errors.onUnexpectedError(err);
|
||||
callback(null);
|
||||
callback(undefined);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -6,10 +6,10 @@
|
||||
import * as os from 'os';
|
||||
import * as cp from 'child_process';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
|
||||
import * as path from 'vs/base/common/path';
|
||||
import { localize } from 'vs/nls';
|
||||
import product from 'vs/platform/node/product';
|
||||
import product from 'vs/platform/product/node/product';
|
||||
import { IRequestService } from 'vs/platform/request/node/request';
|
||||
import { IRequestContext } from 'vs/base/node/request';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
|
||||
@@ -7,15 +7,16 @@ import 'vs/code/code.main';
|
||||
import { app, dialog } from 'electron';
|
||||
import { assign } from 'vs/base/common/objects';
|
||||
import * as platform from 'vs/base/common/platform';
|
||||
import product from 'vs/platform/node/product';
|
||||
import { parseMainProcessArgv } from 'vs/platform/environment/node/argvHelper';
|
||||
import product from 'vs/platform/product/node/product';
|
||||
import { parseMainProcessArgv, createWaitMarkerFile } from 'vs/platform/environment/node/argvHelper';
|
||||
import { addArg } from 'vs/platform/environment/node/argv';
|
||||
import { mkdirp } from 'vs/base/node/pfs';
|
||||
import { validatePaths } from 'vs/code/node/paths';
|
||||
import { LifecycleService, ILifecycleService } from 'vs/platform/lifecycle/electron-main/lifecycleMain';
|
||||
import { Server, serve, connect } from 'vs/base/parts/ipc/node/ipc.net';
|
||||
import { LaunchChannelClient } from 'vs/platform/launch/electron-main/launchService';
|
||||
import { ServicesAccessor, IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { InstantiationService } from 'vs/platform/instantiation/node/instantiationService';
|
||||
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
|
||||
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
|
||||
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
|
||||
import { ILogService, ConsoleLogMainService, MultiplexLogService, getLogLevel } from 'vs/platform/log/common/log';
|
||||
@@ -36,7 +37,6 @@ import { IDiagnosticsService, DiagnosticsService } from 'vs/platform/diagnostics
|
||||
import { BufferLogService } from 'vs/platform/log/common/bufferLog';
|
||||
import { uploadLogs } from 'vs/code/electron-main/logUploader';
|
||||
import { setUnexpectedErrorHandler } from 'vs/base/common/errors';
|
||||
import { createWaitMarkerFile } from 'vs/code/node/wait';
|
||||
|
||||
class ExpectedError extends Error {
|
||||
readonly isExpected = true;
|
||||
@@ -114,7 +114,7 @@ function setupIPC(accessor: ServicesAccessor): Promise<Server> {
|
||||
client => {
|
||||
|
||||
// Tests from CLI require to be the only instance currently
|
||||
if (environmentService.extensionTestsPath && !environmentService.debugExtensionHost.break) {
|
||||
if (environmentService.extensionTestsLocationURI && !environmentService.debugExtensionHost.break) {
|
||||
const msg = 'Running extension tests from the command line is currently only supported if no other instance of Code is running.';
|
||||
logService.error(msg);
|
||||
client.dispose();
|
||||
@@ -158,7 +158,7 @@ function setupIPC(accessor: ServicesAccessor): Promise<Server> {
|
||||
logService.trace('Sending env to running instance...');
|
||||
|
||||
return allowSetForegroundWindow(service)
|
||||
.then(() => service.start(environmentService.args, process.env))
|
||||
.then(() => service.start(environmentService.args, process.env as platform.IProcessEnvironment))
|
||||
.then(() => client.dispose())
|
||||
.then(() => {
|
||||
|
||||
@@ -216,7 +216,7 @@ function handleStartupDataDirError(environmentService: IEnvironmentService, erro
|
||||
if (error.code === 'EACCES' || error.code === 'EPERM') {
|
||||
showStartupWarningDialog(
|
||||
localize('startupDataDirError', "Unable to write program user data."),
|
||||
localize('startupDataDirErrorDetail', "Please make sure the directory {0} is writeable.", environmentService.userDataPath)
|
||||
localize('startupDataDirErrorDetail', "Please make sure the directories {0} and {1} are writeable.", environmentService.userDataPath, environmentService.extensionsPath)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -316,14 +316,14 @@ function createServices(args: ParsedArgs, bufferLogService: BufferLogService): I
|
||||
function initServices(environmentService: IEnvironmentService, stateService: StateService): Promise<any> {
|
||||
|
||||
// Ensure paths for environment service exist
|
||||
const environmentServiceInitialization = Promise.all([
|
||||
const environmentServiceInitialization = Promise.all<boolean | undefined>([
|
||||
environmentService.extensionsPath,
|
||||
environmentService.nodeCachedDataDir,
|
||||
environmentService.logsPath,
|
||||
environmentService.globalStorageHome,
|
||||
environmentService.workspaceStorageHome,
|
||||
environmentService.backupHome
|
||||
].map(path => path && mkdirp(path)));
|
||||
].map((path): undefined | Promise<boolean> => path ? mkdirp(path) : undefined));
|
||||
|
||||
// State service
|
||||
const stateServiceInitialization = stateService.init();
|
||||
@@ -359,7 +359,7 @@ function main(): void {
|
||||
if (args.wait && !args.waitMarkerFilePath) {
|
||||
createWaitMarkerFile(args.verbose).then(waitMarkerFilePath => {
|
||||
if (waitMarkerFilePath) {
|
||||
process.argv.push('--waitMarkerFilePath', waitMarkerFilePath);
|
||||
addArg(process.argv, '--waitMarkerFilePath', waitMarkerFilePath);
|
||||
args.waitMarkerFilePath = waitMarkerFilePath;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as path from 'path';
|
||||
import * as path from 'vs/base/common/path';
|
||||
import * as objects from 'vs/base/common/objects';
|
||||
import * as nls from 'vs/nls';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
@@ -13,7 +13,7 @@ import { IEnvironmentService, ParsedArgs } from 'vs/platform/environment/common/
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { parseArgs } from 'vs/platform/environment/node/argv';
|
||||
import product from 'vs/platform/node/product';
|
||||
import product from 'vs/platform/product/node/product';
|
||||
import { IWindowSettings, MenuBarVisibility, IWindowConfiguration, ReadyState, IRunActionInWindowRequest, getTitleBarStyle } from 'vs/platform/windows/common/windows';
|
||||
import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { isLinux, isMacintosh, isWindows } from 'vs/base/common/platform';
|
||||
@@ -24,8 +24,8 @@ import { ISerializableCommandAction } from 'vs/platform/actions/common/actions';
|
||||
import * as perf from 'vs/base/common/performance';
|
||||
import { resolveMarketplaceHeaders } from 'vs/platform/extensionManagement/node/extensionGalleryService';
|
||||
import { getBackgroundColor } from 'vs/code/electron-main/theme';
|
||||
import { IStorageMainService } from 'vs/platform/storage/node/storageMainService';
|
||||
import { RunOnceScheduler } from 'vs/base/common/async';
|
||||
import { withNullAsUndefined } from 'vs/base/common/types';
|
||||
|
||||
export interface IWindowCreationOptions {
|
||||
state: IWindowState;
|
||||
@@ -70,14 +70,16 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
private currentMenuBarVisibility: MenuBarVisibility;
|
||||
private representedFilename: string;
|
||||
|
||||
private whenReadyCallbacks: { (window: ICodeWindow): void }[];
|
||||
private readonly whenReadyCallbacks: { (window: ICodeWindow): void }[];
|
||||
|
||||
private currentConfig: IWindowConfiguration;
|
||||
private pendingLoadConfig: IWindowConfiguration;
|
||||
private pendingLoadConfig?: IWindowConfiguration;
|
||||
|
||||
private marketplaceHeadersPromise: Promise<object>;
|
||||
|
||||
private touchBarGroups: Electron.TouchBarSegmentedControl[];
|
||||
private readonly touchBarGroups: Electron.TouchBarSegmentedControl[];
|
||||
|
||||
private nodeless: boolean;
|
||||
|
||||
constructor(
|
||||
config: IWindowCreationOptions,
|
||||
@@ -87,7 +89,6 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
@IStateService private readonly stateService: IStateService,
|
||||
@IWorkspacesMainService private readonly workspacesMainService: IWorkspacesMainService,
|
||||
@IBackupMainService private readonly backupMainService: IBackupMainService,
|
||||
@IStorageMainService private readonly storageMainService: IStorageMainService
|
||||
) {
|
||||
super();
|
||||
|
||||
@@ -96,6 +97,8 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
this._readyState = ReadyState.NONE;
|
||||
this.whenReadyCallbacks = [];
|
||||
|
||||
this.nodeless = !!(environmentService.args.nodeless && !environmentService.isBuilt);
|
||||
|
||||
// create browser window
|
||||
this.createBrowserWindow(config);
|
||||
|
||||
@@ -125,7 +128,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
height: this.windowState.height,
|
||||
x: this.windowState.x,
|
||||
y: this.windowState.y,
|
||||
backgroundColor: getBackgroundColor(this.stateService),
|
||||
backgroundColor: this.nodeless ? undefined : getBackgroundColor(this.stateService),
|
||||
minWidth: CodeWindow.MIN_WIDTH,
|
||||
minHeight: CodeWindow.MIN_HEIGHT,
|
||||
show: !isFullscreenOrMaximized,
|
||||
@@ -135,10 +138,14 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
// want to enforce that Code stays in the foreground. This triggers a disable_hidden_
|
||||
// flag that Electron provides via patch:
|
||||
// https://github.com/electron/libchromiumcontent/blob/master/patches/common/chromium/disable_hidden.patch
|
||||
'backgroundThrottling': false
|
||||
backgroundThrottling: false
|
||||
}
|
||||
};
|
||||
|
||||
if (this.nodeless) {
|
||||
options.webPreferences!.nodeIntegration = false; // simulate Electron 5 behaviour
|
||||
}
|
||||
|
||||
if (isLinux) {
|
||||
options.icon = path.join(this.environmentService.appRoot, 'resources/linux/code.png'); // Windows and Mac are better off using the embedded icon(s)
|
||||
}
|
||||
@@ -193,6 +200,10 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
}
|
||||
}
|
||||
|
||||
if (this.nodeless) {
|
||||
this._win.webContents.toggleDevTools();
|
||||
}
|
||||
|
||||
this._lastFocusTime = Date.now(); // since we show directly, we need to set the last focus time too
|
||||
}
|
||||
|
||||
@@ -208,7 +219,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
return !!this.config.extensionTestsPath;
|
||||
}
|
||||
|
||||
get extensionDevelopmentPath(): string {
|
||||
get extensionDevelopmentPath(): string | undefined {
|
||||
return this.config.extensionDevelopmentPath;
|
||||
}
|
||||
|
||||
@@ -256,19 +267,19 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
return this._lastFocusTime;
|
||||
}
|
||||
|
||||
get backupPath(): string {
|
||||
get backupPath(): string | undefined {
|
||||
return this.currentConfig ? this.currentConfig.backupPath : undefined;
|
||||
}
|
||||
|
||||
get openedWorkspace(): IWorkspaceIdentifier {
|
||||
get openedWorkspace(): IWorkspaceIdentifier | undefined {
|
||||
return this.currentConfig ? this.currentConfig.workspace : undefined;
|
||||
}
|
||||
|
||||
get openedFolderUri(): URI {
|
||||
get openedFolderUri(): URI | undefined {
|
||||
return this.currentConfig ? this.currentConfig.folderUri : undefined;
|
||||
}
|
||||
|
||||
get remoteAuthority(): string {
|
||||
get remoteAuthority(): string | undefined {
|
||||
return this.currentConfig ? this.currentConfig.remoteAuthority : undefined;
|
||||
}
|
||||
|
||||
@@ -305,7 +316,11 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
const urls = ['https://marketplace.visualstudio.com/*', 'https://*.vsassets.io/*'];
|
||||
this._win.webContents.session.webRequest.onBeforeSendHeaders({ urls }, (details: any, cb: any) => {
|
||||
this.marketplaceHeadersPromise.then(headers => {
|
||||
cb({ cancel: false, requestHeaders: objects.assign(details.requestHeaders, headers) });
|
||||
const requestHeaders = objects.assign(details.requestHeaders, headers);
|
||||
if (!this.configurationService.getValue('extensions.disableExperimentalAzureSearch')) {
|
||||
requestHeaders['Cookie'] = `${requestHeaders['Cookie'] ? requestHeaders['Cookie'] + ';' : ''}EnableExternalSearchForVSCode=true`;
|
||||
}
|
||||
cb({ cancel: false, requestHeaders });
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -313,7 +328,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
private registerListeners(): void {
|
||||
|
||||
// Prevent loading of svgs
|
||||
this._win.webContents.session.webRequest.onBeforeRequest(null, (details, callback) => {
|
||||
this._win.webContents.session.webRequest.onBeforeRequest(null!, (details, callback) => {
|
||||
if (details.url.indexOf('.svg') > 0) {
|
||||
const uri = URI.parse(details.url);
|
||||
if (uri && !uri.scheme.match(/file/i) && (uri.path as any).endsWith('.svg')) {
|
||||
@@ -324,7 +339,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
return callback({});
|
||||
});
|
||||
|
||||
this._win.webContents.session.webRequest.onHeadersReceived(null, (details: any, callback: any) => {
|
||||
this._win.webContents.session.webRequest.onHeadersReceived(null!, (details: any, callback: any) => {
|
||||
const contentType: string[] = (details.responseHeaders['content-type'] || details.responseHeaders['Content-Type']) as any;
|
||||
if (contentType && Array.isArray(contentType) && contentType.some(x => x.toLowerCase().indexOf('image/svg') >= 0)) {
|
||||
return callback({ cancel: true });
|
||||
@@ -341,7 +356,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
if (this.pendingLoadConfig) {
|
||||
this.currentConfig = this.pendingLoadConfig;
|
||||
|
||||
this.pendingLoadConfig = null;
|
||||
this.pendingLoadConfig = undefined;
|
||||
}
|
||||
|
||||
// To prevent flashing, we set the window visible after the page has finished to load but before Code is loaded
|
||||
@@ -392,7 +407,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
}
|
||||
|
||||
// Window (Un)Maximize
|
||||
this._win.on('maximize', e => {
|
||||
this._win.on('maximize', (e: Event) => {
|
||||
if (this.currentConfig) {
|
||||
this.currentConfig.maximized = true;
|
||||
}
|
||||
@@ -400,7 +415,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
app.emit('browser-window-maximize', e, this._win);
|
||||
});
|
||||
|
||||
this._win.on('unmaximize', e => {
|
||||
this._win.on('unmaximize', (e: Event) => {
|
||||
if (this.currentConfig) {
|
||||
this.currentConfig.maximized = false;
|
||||
}
|
||||
@@ -522,7 +537,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
|
||||
// Make window visible if it did not open in N seconds because this indicates an error
|
||||
// Only do this when running out of sources and not when running tests
|
||||
if (!this.environmentService.isBuilt && !this.environmentService.extensionTestsPath) {
|
||||
if (!this.environmentService.isBuilt && !this.environmentService.extensionTestsLocationURI) {
|
||||
this.showTimeoutHandle = setTimeout(() => {
|
||||
if (this._win && !this._win.isVisible() && !this._win.isMinimized()) {
|
||||
this._win.show();
|
||||
@@ -548,8 +563,8 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
// in extension development mode. These options are all development related.
|
||||
if (this.isExtensionDevelopmentHost && cli) {
|
||||
configuration.verbose = cli.verbose;
|
||||
configuration.debugPluginHost = cli.debugPluginHost;
|
||||
configuration.debugBrkPluginHost = cli.debugBrkPluginHost;
|
||||
configuration['inspect-extensions'] = cli['inspect-extensions'];
|
||||
configuration['inspect-brk-extensions'] = cli['inspect-brk-extensions'];
|
||||
configuration.debugId = cli.debugId;
|
||||
configuration['extensions-dir'] = cli['extensions-dir'];
|
||||
}
|
||||
@@ -593,7 +608,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
windowConfiguration.perfEntries = perf.exportEntries();
|
||||
|
||||
// Parts splash
|
||||
windowConfiguration.partsSplashData = this.storageMainService.get('parts-splash-data', undefined);
|
||||
windowConfiguration.partsSplashPath = path.join(this.environmentService.userDataPath, 'rapid_render.json');
|
||||
|
||||
// Config (combination of process.argv and window configuration)
|
||||
const environment = parseArgs(process.argv);
|
||||
@@ -623,6 +638,10 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
}
|
||||
|
||||
private doGetUrl(config: object): string {
|
||||
if (this.nodeless) {
|
||||
return `${require.toUrl('vs/code/electron-browser/workbench/workbench.nodeless.html')}?config=${encodeURIComponent(JSON.stringify(config))}`;
|
||||
}
|
||||
|
||||
return `${require.toUrl('vs/code/electron-browser/workbench/workbench.html')}?config=${encodeURIComponent(JSON.stringify(config))}`;
|
||||
}
|
||||
|
||||
@@ -688,7 +707,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
private restoreWindowState(state?: IWindowState): IWindowState {
|
||||
if (state) {
|
||||
try {
|
||||
state = this.validateWindowState(state);
|
||||
state = withNullAsUndefined(this.validateWindowState(state));
|
||||
} catch (err) {
|
||||
this.logService.warn(`Unexpected error validating window state: ${err}\n${err.stack}`); // somehow display API can be picky about the state to validate
|
||||
}
|
||||
@@ -706,7 +725,11 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ([state.x, state.y, state.width, state.height].some(n => typeof n !== 'number')) {
|
||||
if (typeof state.x !== 'number'
|
||||
|| typeof state.y !== 'number'
|
||||
|| typeof state.width !== 'number'
|
||||
|| typeof state.height !== 'number'
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1045,6 +1068,6 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
clearTimeout(this.showTimeoutHandle);
|
||||
}
|
||||
|
||||
this._win = null; // Important to dereference the window object to allow for GC
|
||||
this._win = null!; // Important to dereference the window object to allow for GC
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
86
src/vs/code/electron-main/windowsStateStorage.ts
Normal file
86
src/vs/code/electron-main/windowsStateStorage.ts
Normal file
@@ -0,0 +1,86 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { IWindowState as IWindowUIState } from 'vs/platform/windows/electron-main/windows';
|
||||
import { IWindowState, IWindowsState } from 'vs/code/electron-main/windows';
|
||||
|
||||
export type WindowsStateStorageData = object;
|
||||
|
||||
interface ISerializedWindowsState {
|
||||
lastActiveWindow?: ISerializedWindowState;
|
||||
lastPluginDevelopmentHostWindow?: ISerializedWindowState;
|
||||
openedWindows: ISerializedWindowState[];
|
||||
}
|
||||
|
||||
interface ISerializedWindowState {
|
||||
workspaceIdentifier?: { id: string; configURIPath: string };
|
||||
folder?: string;
|
||||
backupPath?: string;
|
||||
remoteAuthority?: string;
|
||||
uiState: IWindowUIState;
|
||||
|
||||
// deprecated
|
||||
folderUri?: UriComponents;
|
||||
folderPath?: string;
|
||||
workspace?: { id: string; configPath: string };
|
||||
}
|
||||
|
||||
export function restoreWindowsState(data: WindowsStateStorageData | undefined): IWindowsState {
|
||||
const result: IWindowsState = { openedWindows: [] };
|
||||
const windowsState = data as ISerializedWindowsState || { openedWindows: [] };
|
||||
|
||||
if (windowsState.lastActiveWindow) {
|
||||
result.lastActiveWindow = restoreWindowState(windowsState.lastActiveWindow);
|
||||
}
|
||||
if (windowsState.lastPluginDevelopmentHostWindow) {
|
||||
result.lastPluginDevelopmentHostWindow = restoreWindowState(windowsState.lastPluginDevelopmentHostWindow);
|
||||
}
|
||||
if (Array.isArray(windowsState.openedWindows)) {
|
||||
result.openedWindows = windowsState.openedWindows.map(windowState => restoreWindowState(windowState));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function restoreWindowState(windowState: ISerializedWindowState): IWindowState {
|
||||
const result: IWindowState = { uiState: windowState.uiState };
|
||||
if (windowState.backupPath) {
|
||||
result.backupPath = windowState.backupPath;
|
||||
}
|
||||
if (windowState.remoteAuthority) {
|
||||
result.remoteAuthority = windowState.remoteAuthority;
|
||||
}
|
||||
if (windowState.folder) {
|
||||
result.folderUri = URI.parse(windowState.folder);
|
||||
} else if (windowState.folderUri) {
|
||||
result.folderUri = URI.revive(windowState.folderUri);
|
||||
} else if (windowState.folderPath) {
|
||||
result.folderUri = URI.file(windowState.folderPath);
|
||||
}
|
||||
if (windowState.workspaceIdentifier) {
|
||||
result.workspace = { id: windowState.workspaceIdentifier.id, configPath: URI.parse(windowState.workspaceIdentifier.configURIPath) };
|
||||
} else if (windowState.workspace) {
|
||||
result.workspace = { id: windowState.workspace.id, configPath: URI.file(windowState.workspace.configPath) };
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function getWindowsStateStoreData(windowsState: IWindowsState): WindowsStateStorageData {
|
||||
return {
|
||||
lastActiveWindow: windowsState.lastActiveWindow && serializeWindowState(windowsState.lastActiveWindow),
|
||||
lastPluginDevelopmentHostWindow: windowsState.lastPluginDevelopmentHostWindow && serializeWindowState(windowsState.lastPluginDevelopmentHostWindow),
|
||||
openedWindows: windowsState.openedWindows.map(ws => serializeWindowState(ws))
|
||||
};
|
||||
}
|
||||
|
||||
function serializeWindowState(windowState: IWindowState): ISerializedWindowState {
|
||||
return {
|
||||
workspaceIdentifier: windowState.workspace && { id: windowState.workspace.id, configURIPath: windowState.workspace.configPath.toString() },
|
||||
folder: windowState.folderUri && windowState.folderUri.toString(),
|
||||
backupPath: windowState.backupPath,
|
||||
remoteAuthority: windowState.remoteAuthority,
|
||||
uiState: windowState.uiState
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user