mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-10 18:22:34 -05:00
169 lines
7.9 KiB
TypeScript
169 lines
7.9 KiB
TypeScript
/*---------------------------------------------------------------------------------------------
|
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
|
*--------------------------------------------------------------------------------------------*/
|
|
|
|
import * as nls from 'vs/nls';
|
|
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
|
import { IWorkbenchExtensionEnablementService, IWebExtensionsScannerService } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
|
|
import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
|
|
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
|
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
|
import { IExtensionService, IExtensionHost } from 'vs/workbench/services/extensions/common/extensions';
|
|
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
|
import { IFileService } from 'vs/platform/files/common/files';
|
|
import { IProductService } from 'vs/platform/product/common/productService';
|
|
import { AbstractExtensionService, parseScannedExtension } from 'vs/workbench/services/extensions/common/abstractExtensionService';
|
|
import { RemoteExtensionHost, IRemoteExtensionHostDataProvider, IRemoteExtensionHostInitData } from 'vs/workbench/services/extensions/common/remoteExtensionHost';
|
|
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
|
|
import { WebWorkerExtensionHost } from 'vs/workbench/services/extensions/browser/webWorkerExtensionHost';
|
|
import { canExecuteOnWeb } from 'vs/workbench/services/extensions/common/extensionsUtil';
|
|
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
|
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
|
|
import { FetchFileSystemProvider } from 'vs/workbench/services/extensions/browser/webWorkerFileSystemProvider';
|
|
import { Schemas } from 'vs/base/common/network';
|
|
import { DisposableStore } from 'vs/base/common/lifecycle';
|
|
import { DeltaExtensionsResult } from 'vs/workbench/services/extensions/common/extensionDescriptionRegistry';
|
|
import { IRemoteAuthorityResolverService } from 'vs/platform/remote/common/remoteAuthorityResolver';
|
|
|
|
export class ExtensionService extends AbstractExtensionService implements IExtensionService {
|
|
|
|
private _disposables = new DisposableStore();
|
|
private _remoteInitData: IRemoteExtensionHostInitData | null = null;
|
|
|
|
constructor(
|
|
@IInstantiationService instantiationService: IInstantiationService,
|
|
@INotificationService notificationService: INotificationService,
|
|
@IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService,
|
|
@ITelemetryService telemetryService: ITelemetryService,
|
|
@IWorkbenchExtensionEnablementService extensionEnablementService: IWorkbenchExtensionEnablementService,
|
|
@IFileService fileService: IFileService,
|
|
@IProductService productService: IProductService,
|
|
@IRemoteAuthorityResolverService private readonly _remoteAuthorityResolverService: IRemoteAuthorityResolverService,
|
|
@IRemoteAgentService private readonly _remoteAgentService: IRemoteAgentService,
|
|
@IConfigurationService private readonly _configService: IConfigurationService,
|
|
@IWebExtensionsScannerService private readonly _webExtensionsScannerService: IWebExtensionsScannerService,
|
|
) {
|
|
super(
|
|
instantiationService,
|
|
notificationService,
|
|
environmentService,
|
|
telemetryService,
|
|
extensionEnablementService,
|
|
fileService,
|
|
productService,
|
|
);
|
|
|
|
this._initialize();
|
|
this._initFetchFileSystem();
|
|
}
|
|
|
|
dispose(): void {
|
|
this._disposables.dispose();
|
|
super.dispose();
|
|
}
|
|
|
|
private _initFetchFileSystem(): void {
|
|
const provider = new FetchFileSystemProvider();
|
|
this._disposables.add(this._fileService.registerProvider(Schemas.http, provider));
|
|
this._disposables.add(this._fileService.registerProvider(Schemas.https, provider));
|
|
}
|
|
|
|
private _createLocalExtensionHostDataProvider() {
|
|
return {
|
|
getInitData: async () => {
|
|
const allExtensions = await this.getExtensions();
|
|
const webExtensions = allExtensions.filter(ext => canExecuteOnWeb(ext, this._productService, this._configService));
|
|
return {
|
|
autoStart: true,
|
|
extensions: webExtensions
|
|
};
|
|
}
|
|
};
|
|
}
|
|
|
|
private _createRemoteExtensionHostDataProvider(remoteAuthority: string): IRemoteExtensionHostDataProvider {
|
|
return {
|
|
remoteAuthority: remoteAuthority,
|
|
getInitData: async () => {
|
|
await this.whenInstalledExtensionsRegistered();
|
|
return this._remoteInitData!;
|
|
}
|
|
};
|
|
}
|
|
|
|
protected _createExtensionHosts(_isInitialStart: boolean): IExtensionHost[] {
|
|
const result: IExtensionHost[] = [];
|
|
|
|
const webWorkerExtHost = this._instantiationService.createInstance(WebWorkerExtensionHost, this._createLocalExtensionHostDataProvider());
|
|
result.push(webWorkerExtHost);
|
|
|
|
const remoteAgentConnection = this._remoteAgentService.getConnection();
|
|
if (remoteAgentConnection) {
|
|
const remoteExtHost = this._instantiationService.createInstance(RemoteExtensionHost, this._createRemoteExtensionHostDataProvider(remoteAgentConnection.remoteAuthority), this._remoteAgentService.socketFactory);
|
|
result.push(remoteExtHost);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
protected async _scanAndHandleExtensions(): Promise<void> {
|
|
// fetch the remote environment
|
|
let [remoteEnv, localExtensions] = await Promise.all([
|
|
this._remoteAgentService.getEnvironment(),
|
|
this._webExtensionsScannerService.scanExtensions().then(extensions => extensions.map(parseScannedExtension))
|
|
]);
|
|
|
|
const remoteAgentConnection = this._remoteAgentService.getConnection();
|
|
|
|
let result: DeltaExtensionsResult;
|
|
|
|
// local: only enabled and web'ish extension
|
|
localExtensions = localExtensions!.filter(ext => this._isEnabled(ext) && canExecuteOnWeb(ext, this._productService, this._configService));
|
|
this._checkEnableProposedApi(localExtensions);
|
|
|
|
if (!remoteEnv || !remoteAgentConnection) {
|
|
result = this._registry.deltaExtensions(localExtensions, []);
|
|
|
|
} else {
|
|
// remote: only enabled and none-web'ish extension
|
|
remoteEnv.extensions = remoteEnv.extensions.filter(extension => this._isEnabled(extension) && !canExecuteOnWeb(extension, this._productService, this._configService));
|
|
this._checkEnableProposedApi(remoteEnv.extensions);
|
|
|
|
// in case of overlap, the remote wins
|
|
const isRemoteExtension = new Set<string>();
|
|
remoteEnv.extensions.forEach(extension => isRemoteExtension.add(ExtensionIdentifier.toKey(extension.identifier)));
|
|
localExtensions = localExtensions.filter(extension => !isRemoteExtension.has(ExtensionIdentifier.toKey(extension.identifier)));
|
|
|
|
// save for remote extension's init data
|
|
this._remoteInitData = {
|
|
connectionData: this._remoteAuthorityResolverService.getConnectionData(remoteAgentConnection.remoteAuthority),
|
|
pid: remoteEnv.pid,
|
|
appRoot: remoteEnv.appRoot,
|
|
appSettingsHome: remoteEnv.appSettingsHome,
|
|
extensionHostLogsPath: remoteEnv.extensionHostLogsPath,
|
|
globalStorageHome: remoteEnv.globalStorageHome,
|
|
userHome: remoteEnv.userHome,
|
|
extensions: remoteEnv.extensions,
|
|
allExtensions: remoteEnv.extensions.concat(localExtensions)
|
|
};
|
|
|
|
result = this._registry.deltaExtensions(remoteEnv.extensions.concat(localExtensions), []);
|
|
}
|
|
|
|
if (result.removedDueToLooping.length > 0) {
|
|
this._logOrShowMessage(Severity.Error, nls.localize('looping', "The following extensions contain dependency loops and have been disabled: {0}", result.removedDueToLooping.map(e => `'${e.identifier.value}'`).join(', ')));
|
|
}
|
|
this._doHandleExtensionPoints(this._registry.getAllExtensionDescriptions());
|
|
}
|
|
|
|
public _onExtensionHostExit(code: number): void {
|
|
// We log the exit code to the console. Do NOT remove this
|
|
// code as the automated integration tests in browser rely
|
|
// on this message to exit properly.
|
|
console.log(`vscode:exit ${code}`);
|
|
}
|
|
}
|
|
|
|
registerSingleton(IExtensionService, ExtensionService);
|