mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-15 10:58:31 -05:00
Merge from vscode 2cd495805cf99b31b6926f08ff4348124b2cf73d
This commit is contained in:
committed by
AzureDataStudio
parent
a8a7559229
commit
1388493cc1
@@ -0,0 +1,72 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IBuiltinExtensionsScannerService, IScannedExtension, ExtensionType, IExtensionManifest } from 'vs/platform/extensions/common/extensions';
|
||||
import { isWeb } from 'vs/base/common/platform';
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentity';
|
||||
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { getGalleryExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
|
||||
|
||||
interface IScannedBuiltinExtension {
|
||||
extensionPath: string,
|
||||
packageJSON: IExtensionManifest,
|
||||
packageNLSPath?: string,
|
||||
readmePath?: string,
|
||||
changelogPath?: string,
|
||||
}
|
||||
|
||||
export class BuiltinExtensionsScannerService implements IBuiltinExtensionsScannerService {
|
||||
|
||||
declare readonly _serviceBrand: undefined;
|
||||
|
||||
private readonly builtinExtensions: IScannedExtension[] = [];
|
||||
|
||||
constructor(
|
||||
@IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService,
|
||||
@IUriIdentityService uriIdentityService: IUriIdentityService,
|
||||
) {
|
||||
|
||||
const builtinExtensionsServiceUrl = environmentService.options?.builtinExtensionsServiceUrl ? URI.parse(environmentService.options?.builtinExtensionsServiceUrl) : undefined;
|
||||
if (isWeb && builtinExtensionsServiceUrl) {
|
||||
|
||||
let scannedBuiltinExtensions: IScannedBuiltinExtension[] = [];
|
||||
|
||||
if (environmentService.isBuilt) {
|
||||
// Built time configuration (do NOT modify)
|
||||
scannedBuiltinExtensions = [/*BUILD->INSERT_BUILTIN_EXTENSIONS*/];
|
||||
} else {
|
||||
// Find builtin extensions by checking for DOM
|
||||
const builtinExtensionsElement = document.getElementById('vscode-workbench-builtin-extensions');
|
||||
const builtinExtensionsElementAttribute = builtinExtensionsElement ? builtinExtensionsElement.getAttribute('data-settings') : undefined;
|
||||
if (builtinExtensionsElementAttribute) {
|
||||
try {
|
||||
scannedBuiltinExtensions = JSON.parse(builtinExtensionsElementAttribute);
|
||||
} catch (error) { /* ignore error*/ }
|
||||
}
|
||||
}
|
||||
|
||||
this.builtinExtensions = scannedBuiltinExtensions.map(e => ({
|
||||
identifier: { id: getGalleryExtensionId(e.packageJSON.publisher, e.packageJSON.name) },
|
||||
location: uriIdentityService.extUri.joinPath(builtinExtensionsServiceUrl!, e.extensionPath),
|
||||
type: ExtensionType.System,
|
||||
packageJSON: e.packageJSON,
|
||||
packageNLSUrl: e.packageNLSPath ? uriIdentityService.extUri.joinPath(builtinExtensionsServiceUrl!, e.packageNLSPath) : undefined,
|
||||
readmeUrl: e.readmePath ? uriIdentityService.extUri.joinPath(builtinExtensionsServiceUrl!, e.readmePath) : undefined,
|
||||
changelogUrl: e.changelogPath ? uriIdentityService.extUri.joinPath(builtinExtensionsServiceUrl!, e.changelogPath) : undefined,
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
async scanBuiltinExtensions(): Promise<IScannedExtension[]> {
|
||||
if (isWeb) {
|
||||
return this.builtinExtensions;
|
||||
}
|
||||
throw new Error('not supported');
|
||||
}
|
||||
}
|
||||
|
||||
registerSingleton(IBuiltinExtensionsScannerService, BuiltinExtensionsScannerService);
|
||||
@@ -18,6 +18,7 @@ import { getExtensionKind } from 'vs/workbench/services/extensions/common/extens
|
||||
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
import { IProductService } from 'vs/platform/product/common/productService';
|
||||
import { StorageManager } from 'vs/platform/extensionManagement/common/extensionEnablementService';
|
||||
import { webWorkerExtHostConfig } from 'vs/workbench/services/extensions/common/extensions';
|
||||
|
||||
const SOURCE = 'IWorkbenchExtensionEnablementService';
|
||||
|
||||
@@ -137,8 +138,8 @@ export class ExtensionEnablementService extends Disposable implements IWorkbench
|
||||
}
|
||||
|
||||
private _isDisabledByExtensionKind(extension: IExtension): boolean {
|
||||
if (this.extensionManagementServerService.remoteExtensionManagementServer) {
|
||||
const server = this.extensionManagementServerService.getExtensionManagementServer(extension.location);
|
||||
if (this.extensionManagementServerService.remoteExtensionManagementServer || this.extensionManagementServerService.webExtensionManagementServer) {
|
||||
const server = this.extensionManagementServerService.getExtensionManagementServer(extension);
|
||||
for (const extensionKind of getExtensionKind(extension.manifest, this.productService, this.configurationService)) {
|
||||
if (extensionKind === 'ui') {
|
||||
if (this.extensionManagementServerService.localExtensionManagementServer && this.extensionManagementServerService.localExtensionManagementServer === server) {
|
||||
@@ -151,8 +152,13 @@ export class ExtensionEnablementService extends Disposable implements IWorkbench
|
||||
}
|
||||
}
|
||||
if (extensionKind === 'web') {
|
||||
// Web extensions are not yet supported to be disabled by kind. Enable them always on web.
|
||||
const enableLocalWebWorker = this.configurationService.getValue<boolean>(webWorkerExtHostConfig);
|
||||
if (enableLocalWebWorker) {
|
||||
// Web extensions are enabled on all configurations
|
||||
return false;
|
||||
}
|
||||
if (this.extensionManagementServerService.localExtensionManagementServer === null) {
|
||||
// Web extensions run only in the web
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,24 +6,25 @@
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IExtension } from 'vs/platform/extensions/common/extensions';
|
||||
import { IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
import { IExtension, IScannedExtension, ExtensionType } from 'vs/platform/extensions/common/extensions';
|
||||
import { IExtensionManagementService, IGalleryExtension, IExtensionIdentifier } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
import { IWorkspace, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
|
||||
import { IStringDictionary } from 'vs/base/common/collections';
|
||||
|
||||
export const IExtensionManagementServerService = createDecorator<IExtensionManagementServerService>('extensionManagementServerService');
|
||||
|
||||
export interface IExtensionManagementServer {
|
||||
extensionManagementService: IExtensionManagementService;
|
||||
authority: string;
|
||||
id: string;
|
||||
label: string;
|
||||
extensionManagementService: IExtensionManagementService;
|
||||
}
|
||||
|
||||
export interface IExtensionManagementServerService {
|
||||
readonly _serviceBrand: undefined;
|
||||
readonly localExtensionManagementServer: IExtensionManagementServer | null;
|
||||
readonly remoteExtensionManagementServer: IExtensionManagementServer | null;
|
||||
getExtensionManagementServer(location: URI): IExtensionManagementServer | null;
|
||||
readonly webExtensionManagementServer: IExtensionManagementServer | null;
|
||||
getExtensionManagementServer(extension: IExtension): IExtensionManagementServer | null;
|
||||
}
|
||||
|
||||
export const enum EnablementState {
|
||||
@@ -139,3 +140,11 @@ export interface IExtensionRecommendationsService {
|
||||
getRecommendedExtensionsByScenario(scenarioType: string): Promise<IExtensionRecommendation[]>; // {{SQL CARBON EDIT}}
|
||||
promptRecommendedExtensionsByScenario(scenarioType: string): void; // {{SQL CARBON EDIT}}
|
||||
}
|
||||
|
||||
export const IWebExtensionsScannerService = createDecorator<IWebExtensionsScannerService>('IWebExtensionsScannerService');
|
||||
export interface IWebExtensionsScannerService {
|
||||
readonly _serviceBrand: undefined;
|
||||
scanExtensions(type?: ExtensionType): Promise<IScannedExtension[]>;
|
||||
addExtension(galleryExtension: IGalleryExtension): Promise<IScannedExtension>;
|
||||
removeExtension(identifier: IExtensionIdentifier, version?: string): Promise<void>;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { localize } from 'vs/nls';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IExtensionManagementServer, IExtensionManagementServerService } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
|
||||
import { ExtensionManagementChannelClient } from 'vs/platform/extensionManagement/common/extensionManagementIpc';
|
||||
import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
|
||||
@@ -12,6 +11,10 @@ import { REMOTE_HOST_SCHEME } from 'vs/platform/remote/common/remoteHosts';
|
||||
import { IChannel } from 'vs/base/parts/ipc/common/ipc';
|
||||
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
import { ILabelService } from 'vs/platform/label/common/label';
|
||||
import { isWeb } from 'vs/base/common/platform';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { WebExtensionManagementService } from 'vs/workbench/services/extensionManagement/common/webExtensionManagementService';
|
||||
import { IExtension } from 'vs/platform/extensions/common/extensions';
|
||||
|
||||
export class ExtensionManagementServerService implements IExtensionManagementServerService {
|
||||
|
||||
@@ -19,27 +22,40 @@ export class ExtensionManagementServerService implements IExtensionManagementSer
|
||||
|
||||
readonly localExtensionManagementServer: IExtensionManagementServer | null = null;
|
||||
readonly remoteExtensionManagementServer: IExtensionManagementServer | null = null;
|
||||
readonly webExtensionManagementServer: IExtensionManagementServer | null = null;
|
||||
|
||||
constructor(
|
||||
@IRemoteAgentService remoteAgentService: IRemoteAgentService,
|
||||
@ILabelService labelService: ILabelService,
|
||||
@IInstantiationService instantiationService: IInstantiationService,
|
||||
) {
|
||||
const remoteAgentConnection = remoteAgentService.getConnection();
|
||||
if (remoteAgentConnection) {
|
||||
const extensionManagementService = new ExtensionManagementChannelClient(remoteAgentConnection!.getChannel<IChannel>('extensions'));
|
||||
this.remoteExtensionManagementServer = {
|
||||
authority: remoteAgentConnection.remoteAuthority,
|
||||
id: 'remote',
|
||||
extensionManagementService,
|
||||
get label() { return labelService.getHostLabel(REMOTE_HOST_SCHEME, remoteAgentConnection!.remoteAuthority) || localize('remote', "Remote"); }
|
||||
};
|
||||
}
|
||||
if (isWeb) {
|
||||
const extensionManagementService = instantiationService.createInstance(WebExtensionManagementService);
|
||||
this.webExtensionManagementServer = {
|
||||
id: 'web',
|
||||
extensionManagementService,
|
||||
label: localize('web', "Web")
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
getExtensionManagementServer(location: URI): IExtensionManagementServer | null {
|
||||
if (location.scheme === REMOTE_HOST_SCHEME) {
|
||||
return this.remoteExtensionManagementServer;
|
||||
getExtensionManagementServer(extension: IExtension): IExtensionManagementServer {
|
||||
if (extension.location.scheme === REMOTE_HOST_SCHEME) {
|
||||
return this.remoteExtensionManagementServer!;
|
||||
}
|
||||
return null;
|
||||
if (this.webExtensionManagementServer) {
|
||||
return this.webExtensionManagementServer;
|
||||
}
|
||||
throw new Error(`Invalid Extension ${extension.location}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
|
||||
import { localize } from 'vs/nls';
|
||||
import { prefersExecuteOnUI, canExecuteOnWorkspace } from 'vs/workbench/services/extensions/common/extensionsUtil';
|
||||
import { prefersExecuteOnUI, canExecuteOnWorkspace, prefersExecuteOnWorkspace, canExecuteOnUI, prefersExecuteOnWeb, canExecuteOnWeb } from 'vs/workbench/services/extensions/common/extensionsUtil';
|
||||
import { IProductService } from 'vs/platform/product/common/productService';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { IDownloadService } from 'vs/platform/download/common/download';
|
||||
@@ -45,6 +45,9 @@ export class ExtensionManagementService extends Disposable implements IExtension
|
||||
if (this.extensionManagementServerService.remoteExtensionManagementServer) {
|
||||
this.servers.push(this.extensionManagementServerService.remoteExtensionManagementServer);
|
||||
}
|
||||
if (this.extensionManagementServerService.webExtensionManagementServer) {
|
||||
this.servers.push(this.extensionManagementServerService.webExtensionManagementServer);
|
||||
}
|
||||
|
||||
this.onInstallExtension = this._register(this.servers.reduce((emitter: EventMultiplexer<InstallExtensionEvent>, server) => { emitter.add(server.extensionManagementService.onInstallExtension); return emitter; }, new EventMultiplexer<InstallExtensionEvent>())).event;
|
||||
this.onDidInstallExtension = this._register(this.servers.reduce((emitter: EventMultiplexer<DidInstallExtensionEvent>, server) => { emitter.add(server.extensionManagementService.onDidInstallExtension); return emitter; }, new EventMultiplexer<DidInstallExtensionEvent>())).event;
|
||||
@@ -64,7 +67,7 @@ export class ExtensionManagementService extends Disposable implements IExtension
|
||||
if (!server) {
|
||||
return Promise.reject(`Invalid location ${extension.location.toString()}`);
|
||||
}
|
||||
if (this.extensionManagementServerService.localExtensionManagementServer && this.extensionManagementServerService.remoteExtensionManagementServer) {
|
||||
if (this.servers.length > 1) {
|
||||
if (isLanguagePackExtension(extension.manifest)) {
|
||||
return this.uninstallEverywhere(extension);
|
||||
}
|
||||
@@ -79,12 +82,14 @@ export class ExtensionManagementService extends Disposable implements IExtension
|
||||
return Promise.reject(`Invalid location ${extension.location.toString()}`);
|
||||
}
|
||||
const promise = server.extensionManagementService.uninstall(extension);
|
||||
const anotherServer: IExtensionManagementServer | null = server === this.extensionManagementServerService.localExtensionManagementServer ? this.extensionManagementServerService.remoteExtensionManagementServer! : this.extensionManagementServerService.localExtensionManagementServer;
|
||||
if (anotherServer) {
|
||||
const installed = await anotherServer.extensionManagementService.getInstalled(ExtensionType.User);
|
||||
extension = installed.filter(i => areSameExtensions(i.identifier, extension.identifier))[0];
|
||||
if (extension) {
|
||||
await anotherServer.extensionManagementService.uninstall(extension);
|
||||
const otherServers: IExtensionManagementServer[] = this.servers.filter(s => s !== server);
|
||||
if (otherServers.length) {
|
||||
for (const otherServer of otherServers) {
|
||||
const installed = await otherServer.extensionManagementService.getInstalled(ExtensionType.User);
|
||||
extension = installed.filter(i => areSameExtensions(i.identifier, extension.identifier))[0];
|
||||
if (extension) {
|
||||
await otherServer.extensionManagementService.uninstall(extension);
|
||||
}
|
||||
}
|
||||
}
|
||||
return promise;
|
||||
@@ -141,7 +146,10 @@ export class ExtensionManagementService extends Disposable implements IExtension
|
||||
}
|
||||
|
||||
unzip(zipLocation: URI): Promise<IExtensionIdentifier> {
|
||||
return Promise.all(this.servers.map(({ extensionManagementService }) => extensionManagementService.unzip(zipLocation))).then(([extensionIdentifier]) => extensionIdentifier);
|
||||
return Promise.all(this.servers
|
||||
// Filter out web server
|
||||
.filter(server => server !== this.extensionManagementServerService.webExtensionManagementServer)
|
||||
.map(({ extensionManagementService }) => extensionManagementService.unzip(zipLocation))).then(([extensionIdentifier]) => extensionIdentifier);
|
||||
}
|
||||
|
||||
async install(vsix: URI): Promise<ILocalExtension> {
|
||||
@@ -149,7 +157,7 @@ export class ExtensionManagementService extends Disposable implements IExtension
|
||||
const manifest = await this.getManifest(vsix);
|
||||
if (isLanguagePackExtension(manifest)) {
|
||||
// Install on both servers
|
||||
const [local] = await Promise.all(this.servers.map(server => this.installVSIX(vsix, server)));
|
||||
const [local] = await Promise.all([this.extensionManagementServerService.localExtensionManagementServer, this.extensionManagementServerService.remoteExtensionManagementServer].map(server => this.installVSIX(vsix, server)));
|
||||
return local;
|
||||
}
|
||||
if (prefersExecuteOnUI(manifest, this.productService, this.configurationService)) {
|
||||
@@ -183,39 +191,61 @@ export class ExtensionManagementService extends Disposable implements IExtension
|
||||
}
|
||||
|
||||
async installFromGallery(gallery: IGalleryExtension): Promise<ILocalExtension> {
|
||||
if (this.extensionManagementServerService.localExtensionManagementServer && this.extensionManagementServerService.remoteExtensionManagementServer) {
|
||||
const manifest = await this.extensionGalleryService.getManifest(gallery, CancellationToken.None);
|
||||
if (manifest) {
|
||||
if (isLanguagePackExtension(manifest)) {
|
||||
// Install on both servers
|
||||
return Promise.all(this.servers.map(server => server.extensionManagementService.installFromGallery(gallery))).then(([local]) => local);
|
||||
}
|
||||
if (prefersExecuteOnUI(manifest, this.productService, this.configurationService)) {
|
||||
// Install only on local server
|
||||
return this.extensionManagementServerService.localExtensionManagementServer.extensionManagementService.installFromGallery(gallery);
|
||||
}
|
||||
// Install only on remote server
|
||||
return this.extensionManagementServerService.remoteExtensionManagementServer.extensionManagementService.installFromGallery(gallery);
|
||||
} else {
|
||||
return Promise.reject(localize('Manifest is not found', "Installing Extension {0} failed: Manifest is not found.", gallery.displayName || gallery.name));
|
||||
}
|
||||
}
|
||||
if (this.extensionManagementServerService.localExtensionManagementServer) {
|
||||
|
||||
// Only local server, install without any checks
|
||||
if (this.servers.length === 1 && this.extensionManagementServerService.localExtensionManagementServer) {
|
||||
return this.extensionManagementServerService.localExtensionManagementServer.extensionManagementService.installFromGallery(gallery);
|
||||
}
|
||||
if (this.extensionManagementServerService.remoteExtensionManagementServer) {
|
||||
const manifest = await this.extensionGalleryService.getManifest(gallery, CancellationToken.None);
|
||||
if (!manifest) {
|
||||
return Promise.reject(localize('Manifest is not found', "Installing Extension {0} failed: Manifest is not found.", gallery.displayName || gallery.name));
|
||||
}
|
||||
if (!isLanguagePackExtension(manifest) && !canExecuteOnWorkspace(manifest, this.productService, this.configurationService)) {
|
||||
const error = new Error(localize('cannot be installed', "Cannot install '{0}' because this extension has defined that it cannot run on the remote server.", gallery.displayName || gallery.name));
|
||||
error.name = INSTALL_ERROR_NOT_SUPPORTED;
|
||||
return Promise.reject(error);
|
||||
}
|
||||
|
||||
const manifest = await this.extensionGalleryService.getManifest(gallery, CancellationToken.None);
|
||||
if (!manifest) {
|
||||
return Promise.reject(localize('Manifest is not found', "Installing Extension {0} failed: Manifest is not found.", gallery.displayName || gallery.name));
|
||||
}
|
||||
|
||||
// Install Language pack on all servers
|
||||
if (isLanguagePackExtension(manifest)) {
|
||||
return Promise.all(this.servers.map(server => server.extensionManagementService.installFromGallery(gallery))).then(([local]) => local);
|
||||
}
|
||||
|
||||
// 1. Install on preferred location
|
||||
|
||||
// Install UI preferred extension on local server
|
||||
if (prefersExecuteOnUI(manifest, this.productService, this.configurationService) && this.extensionManagementServerService.localExtensionManagementServer) {
|
||||
return this.extensionManagementServerService.localExtensionManagementServer.extensionManagementService.installFromGallery(gallery);
|
||||
}
|
||||
// Install Workspace preferred extension on remote server
|
||||
if (prefersExecuteOnWorkspace(manifest, this.productService, this.configurationService) && this.extensionManagementServerService.remoteExtensionManagementServer) {
|
||||
return this.extensionManagementServerService.remoteExtensionManagementServer.extensionManagementService.installFromGallery(gallery);
|
||||
}
|
||||
return Promise.reject('No Servers to Install');
|
||||
// Install Web preferred extension on web server
|
||||
if (prefersExecuteOnWeb(manifest, this.productService, this.configurationService) && this.extensionManagementServerService.webExtensionManagementServer) {
|
||||
return this.extensionManagementServerService.webExtensionManagementServer.extensionManagementService.installFromGallery(gallery);
|
||||
}
|
||||
|
||||
// 2. Install on supported location
|
||||
|
||||
// Install UI supported extension on local server
|
||||
if (canExecuteOnUI(manifest, this.productService, this.configurationService) && this.extensionManagementServerService.localExtensionManagementServer) {
|
||||
return this.extensionManagementServerService.localExtensionManagementServer.extensionManagementService.installFromGallery(gallery);
|
||||
}
|
||||
// Install Workspace supported extension on remote server
|
||||
if (canExecuteOnWorkspace(manifest, this.productService, this.configurationService) && this.extensionManagementServerService.remoteExtensionManagementServer) {
|
||||
return this.extensionManagementServerService.remoteExtensionManagementServer.extensionManagementService.installFromGallery(gallery);
|
||||
}
|
||||
// Install Web supported extension on web server
|
||||
if (canExecuteOnWeb(manifest, this.productService, this.configurationService) && this.extensionManagementServerService.webExtensionManagementServer) {
|
||||
return this.extensionManagementServerService.webExtensionManagementServer.extensionManagementService.installFromGallery(gallery);
|
||||
}
|
||||
|
||||
if (this.extensionManagementServerService.remoteExtensionManagementServer) {
|
||||
const error = new Error(localize('cannot be installed', "Cannot install '{0}' because this extension has defined that it cannot run on the remote server.", gallery.displayName || gallery.name));
|
||||
error.name = INSTALL_ERROR_NOT_SUPPORTED;
|
||||
return Promise.reject(error);
|
||||
}
|
||||
|
||||
const error = new Error(localize('cannot be installed on web', "Cannot install '{0}' because this extension has defined that it cannot run on the web server.", gallery.displayName || gallery.name));
|
||||
error.name = INSTALL_ERROR_NOT_SUPPORTED;
|
||||
return Promise.reject(error);
|
||||
}
|
||||
|
||||
getExtensionsReport(): Promise<IReportedExtension[]> {
|
||||
@@ -229,6 +259,6 @@ export class ExtensionManagementService extends Disposable implements IExtension
|
||||
}
|
||||
|
||||
private getServer(extension: ILocalExtension): IExtensionManagementServer | null {
|
||||
return this.extensionManagementServerService.getExtensionManagementServer(extension.location);
|
||||
return this.extensionManagementServerService.getExtensionManagementServer(extension);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ExtensionType, IExtensionIdentifier, IExtensionManifest, IScannedExtension } from 'vs/platform/extensions/common/extensions';
|
||||
import { IExtensionManagementService, ILocalExtension, InstallExtensionEvent, DidInstallExtensionEvent, DidUninstallExtensionEvent, IGalleryExtension, IReportedExtension, IGalleryMetadata, InstallOperation } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IRequestService, isSuccess, asText } from 'vs/platform/request/common/request';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { localizeManifest } from 'vs/platform/extensionManagement/common/extensionNls';
|
||||
import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
|
||||
import { IWebExtensionsScannerService } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
|
||||
export class WebExtensionManagementService extends Disposable implements IExtensionManagementService {
|
||||
|
||||
declare readonly _serviceBrand: undefined;
|
||||
|
||||
private readonly _onInstallExtension = this._register(new Emitter<InstallExtensionEvent>());
|
||||
readonly onInstallExtension: Event<InstallExtensionEvent> = this._onInstallExtension.event;
|
||||
|
||||
private readonly _onDidInstallExtension = this._register(new Emitter<DidInstallExtensionEvent>());
|
||||
readonly onDidInstallExtension: Event<DidInstallExtensionEvent> = this._onDidInstallExtension.event;
|
||||
|
||||
private readonly _onUninstallExtension = this._register(new Emitter<IExtensionIdentifier>());
|
||||
readonly onUninstallExtension: Event<IExtensionIdentifier> = this._onUninstallExtension.event;
|
||||
|
||||
private _onDidUninstallExtension = this._register(new Emitter<DidUninstallExtensionEvent>());
|
||||
onDidUninstallExtension: Event<DidUninstallExtensionEvent> = this._onDidUninstallExtension.event;
|
||||
|
||||
constructor(
|
||||
@IWebExtensionsScannerService private readonly webExtensionsScannerService: IWebExtensionsScannerService,
|
||||
@IRequestService private readonly requestService: IRequestService,
|
||||
@ILogService private readonly logService: ILogService,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
async getInstalled(type?: ExtensionType): Promise<ILocalExtension[]> {
|
||||
const extensions = await this.webExtensionsScannerService.scanExtensions(type);
|
||||
return Promise.all(extensions.map(e => this.toLocalExtension(e)));
|
||||
}
|
||||
|
||||
async installFromGallery(gallery: IGalleryExtension): Promise<ILocalExtension> {
|
||||
this.logService.info('Installing extension:', gallery.identifier.id);
|
||||
this._onInstallExtension.fire({ identifier: gallery.identifier, gallery });
|
||||
try {
|
||||
const existingExtension = await this.getUserExtension(gallery.identifier);
|
||||
if (existingExtension && existingExtension.manifest.version !== gallery.version) {
|
||||
await this.webExtensionsScannerService.removeExtension(existingExtension.identifier, existingExtension.manifest.version);
|
||||
}
|
||||
const scannedExtension = await this.webExtensionsScannerService.addExtension(gallery);
|
||||
const local = await this.toLocalExtension(scannedExtension);
|
||||
this._onDidInstallExtension.fire({ local, identifier: gallery.identifier, operation: InstallOperation.Install, gallery });
|
||||
return local;
|
||||
} catch (error) {
|
||||
this._onDidInstallExtension.fire({ error, identifier: gallery.identifier, operation: InstallOperation.Install, gallery });
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async uninstall(extension: ILocalExtension): Promise<void> {
|
||||
this._onUninstallExtension.fire(extension.identifier);
|
||||
try {
|
||||
await this.webExtensionsScannerService.removeExtension(extension.identifier);
|
||||
this._onDidUninstallExtension.fire({ identifier: extension.identifier });
|
||||
} catch (error) {
|
||||
this.logService.error(error);
|
||||
this._onDidUninstallExtension.fire({ error, identifier: extension.identifier });
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async updateMetadata(local: ILocalExtension, metadata: IGalleryMetadata): Promise<ILocalExtension> {
|
||||
return local;
|
||||
}
|
||||
|
||||
private async getUserExtension(identifier: IExtensionIdentifier): Promise<ILocalExtension | undefined> {
|
||||
const userExtensions = await this.getInstalled(ExtensionType.User);
|
||||
return userExtensions.find(e => areSameExtensions(e.identifier, identifier));
|
||||
}
|
||||
|
||||
private async toLocalExtension(scannedExtension: IScannedExtension): Promise<ILocalExtension> {
|
||||
let manifest = scannedExtension.packageJSON;
|
||||
if (scannedExtension.packageNLSUrl) {
|
||||
try {
|
||||
const context = await this.requestService.request({ type: 'GET', url: scannedExtension.packageNLSUrl.toString() }, CancellationToken.None);
|
||||
if (isSuccess(context)) {
|
||||
const content = await asText(context);
|
||||
if (content) {
|
||||
manifest = localizeManifest(manifest, JSON.parse(content));
|
||||
}
|
||||
}
|
||||
} catch (error) { /* ignore */ }
|
||||
}
|
||||
return <ILocalExtension>{
|
||||
type: scannedExtension.type,
|
||||
identifier: scannedExtension.identifier,
|
||||
manifest,
|
||||
location: scannedExtension.location,
|
||||
isMachineScoped: false,
|
||||
publisherId: null,
|
||||
publisherDisplayName: null
|
||||
};
|
||||
}
|
||||
|
||||
zip(extension: ILocalExtension): Promise<URI> { throw new Error('unsupported'); }
|
||||
unzip(zipLocation: URI): Promise<IExtensionIdentifier> { throw new Error('unsupported'); }
|
||||
getManifest(vsix: URI): Promise<IExtensionManifest> { throw new Error('unsupported'); }
|
||||
install(vsix: URI, isMachineScoped?: boolean): Promise<ILocalExtension> { throw new Error('unsupported'); }
|
||||
reinstallFromGallery(extension: ILocalExtension): Promise<void> { throw new Error('unsupported'); }
|
||||
getExtensionsReport(): Promise<IReportedExtension[]> { throw new Error('unsupported'); }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,193 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as semver from 'semver-umd';
|
||||
import { IBuiltinExtensionsScannerService, IScannedExtension, ExtensionType, IExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
import { IWebExtensionsScannerService } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
|
||||
import { isWeb } from 'vs/base/common/platform';
|
||||
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
import { joinPath } from 'vs/base/common/resources';
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { Queue } from 'vs/base/common/async';
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
import { asText, isSuccess, IRequestService } from 'vs/platform/request/common/request';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { IGalleryExtension } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
import { groupByExtension, areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
|
||||
|
||||
interface IUserExtension {
|
||||
identifier: IExtensionIdentifier;
|
||||
version: string;
|
||||
uri: URI;
|
||||
readmeUri?: URI;
|
||||
changelogUri?: URI;
|
||||
packageNLSUri?: URI;
|
||||
}
|
||||
|
||||
interface IStoredUserExtension {
|
||||
identifier: IExtensionIdentifier;
|
||||
version: string;
|
||||
uri: UriComponents;
|
||||
readmeUri?: UriComponents;
|
||||
changelogUri?: UriComponents;
|
||||
packageNLSUri?: UriComponents;
|
||||
}
|
||||
|
||||
const AssetTypeWebResource = 'Microsoft.VisualStudio.Code.WebResources';
|
||||
|
||||
function getExtensionLocation(assetUri: URI): URI { return joinPath(assetUri, AssetTypeWebResource, 'extension'); }
|
||||
|
||||
export class WebExtensionsScannerService implements IWebExtensionsScannerService {
|
||||
|
||||
declare readonly _serviceBrand: undefined;
|
||||
|
||||
private readonly systemExtensionsPromise: Promise<IScannedExtension[]>;
|
||||
private readonly staticExtensions: IScannedExtension[];
|
||||
private readonly extensionsResource: URI;
|
||||
private readonly userExtensionsResourceLimiter: Queue<IUserExtension[]>;
|
||||
|
||||
constructor(
|
||||
@IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService,
|
||||
@IBuiltinExtensionsScannerService private readonly builtinExtensionsScannerService: IBuiltinExtensionsScannerService,
|
||||
@IFileService private readonly fileService: IFileService,
|
||||
@IRequestService private readonly requestService: IRequestService,
|
||||
@ILogService private readonly logService: ILogService,
|
||||
) {
|
||||
this.extensionsResource = joinPath(environmentService.userRoamingDataHome, 'extensions.json');
|
||||
this.userExtensionsResourceLimiter = new Queue<IUserExtension[]>();
|
||||
this.systemExtensionsPromise = isWeb ? this.builtinExtensionsScannerService.scanBuiltinExtensions() : Promise.resolve([]);
|
||||
const staticExtensions = environmentService.options && Array.isArray(environmentService.options.staticExtensions) ? environmentService.options.staticExtensions : [];
|
||||
this.staticExtensions = staticExtensions.map(data => <IScannedExtension>{
|
||||
location: data.extensionLocation,
|
||||
type: ExtensionType.User,
|
||||
packageJSON: data.packageJSON,
|
||||
});
|
||||
}
|
||||
|
||||
async scanExtensions(type?: ExtensionType): Promise<IScannedExtension[]> {
|
||||
const extensions = [];
|
||||
if (type === undefined || type === ExtensionType.System) {
|
||||
const systemExtensions = await this.systemExtensionsPromise;
|
||||
extensions.push(...systemExtensions);
|
||||
}
|
||||
if (type === undefined || type === ExtensionType.User) {
|
||||
extensions.push(...this.staticExtensions);
|
||||
const userExtensions = await this.scanUserExtensions();
|
||||
extensions.push(...userExtensions);
|
||||
}
|
||||
return extensions;
|
||||
}
|
||||
|
||||
async addExtension(galleryExtension: IGalleryExtension): Promise<IScannedExtension> {
|
||||
if (!galleryExtension.assetTypes.some(type => type.startsWith(AssetTypeWebResource))) {
|
||||
throw new Error(`Missing ${AssetTypeWebResource} asset type`);
|
||||
}
|
||||
|
||||
const packageNLSUri = joinPath(getExtensionLocation(galleryExtension.assetUri), 'package.nls.json');
|
||||
const context = await this.requestService.request({ type: 'GET', url: packageNLSUri.toString() }, CancellationToken.None);
|
||||
const packageNLSExists = isSuccess(context);
|
||||
|
||||
const userExtensions = await this.readUserExtensions();
|
||||
const userExtension: IUserExtension = {
|
||||
identifier: galleryExtension.identifier,
|
||||
version: galleryExtension.version,
|
||||
uri: galleryExtension.assetUri,
|
||||
readmeUri: galleryExtension.assets.readme ? URI.parse(galleryExtension.assets.readme.uri) : undefined,
|
||||
changelogUri: galleryExtension.assets.changelog ? URI.parse(galleryExtension.assets.changelog.uri) : undefined,
|
||||
packageNLSUri: packageNLSExists ? packageNLSUri : undefined
|
||||
};
|
||||
userExtensions.push(userExtension);
|
||||
await this.writeUserExtensions(userExtensions);
|
||||
|
||||
const scannedExtension = await this.toScannedExtension(userExtension);
|
||||
if (scannedExtension) {
|
||||
return scannedExtension;
|
||||
}
|
||||
throw new Error('Error while scanning extension');
|
||||
}
|
||||
|
||||
async removeExtension(identifier: IExtensionIdentifier, version?: string): Promise<void> {
|
||||
let userExtensions = await this.readUserExtensions();
|
||||
userExtensions = userExtensions.filter(extension => !(areSameExtensions(extension.identifier, identifier) && version ? extension.version === version : true));
|
||||
await this.writeUserExtensions(userExtensions);
|
||||
}
|
||||
|
||||
private async scanUserExtensions(): Promise<IScannedExtension[]> {
|
||||
let userExtensions = await this.readUserExtensions();
|
||||
const byExtension: IUserExtension[][] = groupByExtension(userExtensions, e => e.identifier);
|
||||
userExtensions = byExtension.map(p => p.sort((a, b) => semver.rcompare(a.version, b.version))[0]);
|
||||
const scannedExtensions: IScannedExtension[] = [];
|
||||
await Promise.all(userExtensions.map(async userExtension => {
|
||||
try {
|
||||
const scannedExtension = await this.toScannedExtension(userExtension);
|
||||
if (scannedExtension) {
|
||||
scannedExtensions.push(scannedExtension);
|
||||
}
|
||||
} catch (error) {
|
||||
this.logService.error(error, 'Error while scanning user extension', userExtension.identifier.id);
|
||||
}
|
||||
}));
|
||||
return scannedExtensions;
|
||||
}
|
||||
|
||||
private async toScannedExtension(userExtension: IUserExtension): Promise<IScannedExtension | null> {
|
||||
const context = await this.requestService.request({ type: 'GET', url: joinPath(userExtension.uri, 'Microsoft.VisualStudio.Code.Manifest').toString() }, CancellationToken.None);
|
||||
if (isSuccess(context)) {
|
||||
const content = await asText(context);
|
||||
if (content) {
|
||||
const packageJSON = JSON.parse(content);
|
||||
return {
|
||||
identifier: userExtension.identifier,
|
||||
location: getExtensionLocation(userExtension.uri),
|
||||
packageJSON,
|
||||
type: ExtensionType.User,
|
||||
readmeUrl: userExtension.readmeUri,
|
||||
changelogUrl: userExtension.changelogUri,
|
||||
packageNLSUrl: userExtension.packageNLSUri,
|
||||
};
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private readUserExtensions(): Promise<IUserExtension[]> {
|
||||
return this.userExtensionsResourceLimiter.queue(async () => {
|
||||
try {
|
||||
const content = await this.fileService.readFile(this.extensionsResource);
|
||||
const storedUserExtensions: IStoredUserExtension[] = JSON.parse(content.value.toString());
|
||||
return storedUserExtensions.map(e => ({
|
||||
identifier: e.identifier,
|
||||
version: e.version,
|
||||
uri: URI.revive(e.uri),
|
||||
readmeUri: URI.revive(e.readmeUri),
|
||||
changelogUri: URI.revive(e.changelogUri),
|
||||
packageNLSUri: URI.revive(e.packageNLSUri),
|
||||
}));
|
||||
} catch (error) { /* Ignore */ }
|
||||
return [];
|
||||
});
|
||||
}
|
||||
|
||||
private writeUserExtensions(userExtensions: IUserExtension[]): Promise<IUserExtension[]> {
|
||||
return this.userExtensionsResourceLimiter.queue(async () => {
|
||||
const storedUserExtensions: IStoredUserExtension[] = userExtensions.map(e => ({
|
||||
identifier: e.identifier,
|
||||
version: e.version,
|
||||
uri: e.uri.toJSON(),
|
||||
readmeUri: e.readmeUri?.toJSON(),
|
||||
changelogUri: e.changelogUri?.toJSON(),
|
||||
packageNLSUri: e.packageNLSUri?.toJSON(),
|
||||
}));
|
||||
await this.fileService.writeFile(this.extensionsResource, VSBuffer.fromString(JSON.stringify(storedUserExtensions)));
|
||||
return userExtensions;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
registerSingleton(IWebExtensionsScannerService, WebExtensionsScannerService);
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
import { localize } from 'vs/nls';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IExtensionGalleryService } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
import { IExtensionManagementServer, IExtensionManagementServerService } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
|
||||
import { ExtensionManagementChannelClient } from 'vs/platform/extensionManagement/common/extensionManagementIpc';
|
||||
@@ -19,19 +18,16 @@ import { RemoteExtensionManagementChannelClient } from 'vs/workbench/services/ex
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IProductService } from 'vs/platform/product/common/productService';
|
||||
import { ILabelService } from 'vs/platform/label/common/label';
|
||||
|
||||
const localExtensionManagementServerAuthority: string = 'vscode-local';
|
||||
import { IExtension } from 'vs/platform/extensions/common/extensions';
|
||||
|
||||
export class ExtensionManagementServerService implements IExtensionManagementServerService {
|
||||
|
||||
declare readonly _serviceBrand: undefined;
|
||||
|
||||
private readonly _localExtensionManagementServer: IExtensionManagementServer;
|
||||
public get localExtensionManagementServer(): IExtensionManagementServer {
|
||||
return this._localExtensionManagementServer;
|
||||
}
|
||||
public get localExtensionManagementServer(): IExtensionManagementServer { return this._localExtensionManagementServer; }
|
||||
readonly remoteExtensionManagementServer: IExtensionManagementServer | null = null;
|
||||
readonly isSingleServer: boolean = false;
|
||||
readonly webExtensionManagementServer: IExtensionManagementServer | null = null;
|
||||
|
||||
constructor(
|
||||
@ISharedProcessService sharedProcessService: ISharedProcessService,
|
||||
@@ -44,26 +40,26 @@ export class ExtensionManagementServerService implements IExtensionManagementSer
|
||||
) {
|
||||
const localExtensionManagementService = new ExtensionManagementChannelClient(sharedProcessService.getChannel('extensions'));
|
||||
|
||||
this._localExtensionManagementServer = { extensionManagementService: localExtensionManagementService, authority: localExtensionManagementServerAuthority, label: localize('local', "Local") };
|
||||
this._localExtensionManagementServer = { extensionManagementService: localExtensionManagementService, id: 'local', label: localize('local', "Local") };
|
||||
const remoteAgentConnection = remoteAgentService.getConnection();
|
||||
if (remoteAgentConnection) {
|
||||
const extensionManagementService = new RemoteExtensionManagementChannelClient(remoteAgentConnection.getChannel<IChannel>('extensions'), this.localExtensionManagementServer.extensionManagementService, galleryService, logService, configurationService, productService);
|
||||
this.remoteExtensionManagementServer = {
|
||||
authority: remoteAgentConnection.remoteAuthority,
|
||||
id: 'remote',
|
||||
extensionManagementService,
|
||||
get label() { return labelService.getHostLabel(REMOTE_HOST_SCHEME, remoteAgentConnection!.remoteAuthority) || localize('remote', "Remote"); }
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
getExtensionManagementServer(location: URI): IExtensionManagementServer | null {
|
||||
if (location.scheme === Schemas.file) {
|
||||
getExtensionManagementServer(extension: IExtension): IExtensionManagementServer {
|
||||
if (extension.location.scheme === Schemas.file) {
|
||||
return this.localExtensionManagementServer;
|
||||
}
|
||||
if (location.scheme === REMOTE_HOST_SCHEME) {
|
||||
if (this.remoteExtensionManagementServer && extension.location.scheme === REMOTE_HOST_SCHEME) {
|
||||
return this.remoteExtensionManagementServer;
|
||||
}
|
||||
return null;
|
||||
throw new Error(`Invalid Extension ${extension.location}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -461,7 +461,7 @@ suite('ExtensionEnablementService Test', () => {
|
||||
});
|
||||
|
||||
test('test remote ui extension is disabled by kind when there is no local server', async () => {
|
||||
instantiationService.stub(IExtensionManagementServerService, anExtensionManagementServerService(null, anExtensionManagementServer('vscode-remote', instantiationService)));
|
||||
instantiationService.stub(IExtensionManagementServerService, anExtensionManagementServerService(null, anExtensionManagementServer('vscode-remote', instantiationService), null));
|
||||
const localWorkspaceExtension = aLocalExtension2('pub.a', { extensionKind: ['ui'] }, { location: URI.file(`pub.a`).with({ scheme: Schemas.vscodeRemote }) });
|
||||
testObject = new TestExtensionEnablementService(instantiationService);
|
||||
assert.ok(!testObject.isEnabled(localWorkspaceExtension));
|
||||
@@ -499,7 +499,7 @@ suite('ExtensionEnablementService Test', () => {
|
||||
});
|
||||
|
||||
test('test web extension on remote server is not disabled by kind when there is no local server', async () => {
|
||||
instantiationService.stub(IExtensionManagementServerService, anExtensionManagementServerService(null, anExtensionManagementServer('vscode-remote', instantiationService)));
|
||||
instantiationService.stub(IExtensionManagementServerService, anExtensionManagementServerService(null, anExtensionManagementServer('vscode-remote', instantiationService), anExtensionManagementServer('web', instantiationService)));
|
||||
const localWorkspaceExtension = aLocalExtension2('pub.a', { extensionKind: ['web'] }, { location: URI.file(`pub.a`).with({ scheme: Schemas.vscodeRemote }) });
|
||||
testObject = new TestExtensionEnablementService(instantiationService);
|
||||
assert.ok(testObject.isEnabled(localWorkspaceExtension));
|
||||
@@ -507,7 +507,7 @@ suite('ExtensionEnablementService Test', () => {
|
||||
});
|
||||
|
||||
test('test web extension with no server is not disabled by kind when there is no local server', async () => {
|
||||
instantiationService.stub(IExtensionManagementServerService, anExtensionManagementServerService(null, anExtensionManagementServer('vscode-remote', instantiationService)));
|
||||
instantiationService.stub(IExtensionManagementServerService, anExtensionManagementServerService(null, anExtensionManagementServer('vscode-remote', instantiationService), anExtensionManagementServer('web', instantiationService)));
|
||||
const localWorkspaceExtension = aLocalExtension2('pub.a', { extensionKind: ['web'] }, { location: URI.file(`pub.a`).with({ scheme: Schemas.https }) });
|
||||
testObject = new TestExtensionEnablementService(instantiationService);
|
||||
assert.ok(testObject.isEnabled(localWorkspaceExtension));
|
||||
@@ -515,7 +515,7 @@ suite('ExtensionEnablementService Test', () => {
|
||||
});
|
||||
|
||||
test('test web extension with no server is not disabled by kind when there is no local and remote server', async () => {
|
||||
instantiationService.stub(IExtensionManagementServerService, anExtensionManagementServerService(null, null));
|
||||
instantiationService.stub(IExtensionManagementServerService, anExtensionManagementServerService(null, null, anExtensionManagementServer('web', instantiationService)));
|
||||
const localWorkspaceExtension = aLocalExtension2('pub.a', { extensionKind: ['web'] }, { location: URI.file(`pub.a`).with({ scheme: Schemas.https }) });
|
||||
testObject = new TestExtensionEnablementService(instantiationService);
|
||||
assert.ok(testObject.isEnabled(localWorkspaceExtension));
|
||||
@@ -526,7 +526,7 @@ suite('ExtensionEnablementService Test', () => {
|
||||
|
||||
function anExtensionManagementServer(authority: string, instantiationService: TestInstantiationService): IExtensionManagementServer {
|
||||
return {
|
||||
authority,
|
||||
id: authority,
|
||||
label: authority,
|
||||
extensionManagementService: instantiationService.get(IExtensionManagementService)
|
||||
};
|
||||
@@ -535,22 +535,23 @@ function anExtensionManagementServer(authority: string, instantiationService: Te
|
||||
function aMultiExtensionManagementServerService(instantiationService: TestInstantiationService): IExtensionManagementServerService {
|
||||
const localExtensionManagementServer = anExtensionManagementServer('vscode-local', instantiationService);
|
||||
const remoteExtensionManagementServer = anExtensionManagementServer('vscode-remote', instantiationService);
|
||||
return anExtensionManagementServerService(localExtensionManagementServer, remoteExtensionManagementServer);
|
||||
return anExtensionManagementServerService(localExtensionManagementServer, remoteExtensionManagementServer, null);
|
||||
}
|
||||
|
||||
function anExtensionManagementServerService(localExtensionManagementServer: IExtensionManagementServer | null, remoteExtensionManagementServer: IExtensionManagementServer | null): IExtensionManagementServerService {
|
||||
function anExtensionManagementServerService(localExtensionManagementServer: IExtensionManagementServer | null, remoteExtensionManagementServer: IExtensionManagementServer | null, webExtensionManagementServer: IExtensionManagementServer | null): IExtensionManagementServerService {
|
||||
return {
|
||||
_serviceBrand: undefined,
|
||||
localExtensionManagementServer,
|
||||
remoteExtensionManagementServer,
|
||||
getExtensionManagementServer: (location: URI) => {
|
||||
if (location.scheme === Schemas.file) {
|
||||
webExtensionManagementServer: null,
|
||||
getExtensionManagementServer: (extension: IExtension) => {
|
||||
if (extension.location.scheme === Schemas.file) {
|
||||
return localExtensionManagementServer;
|
||||
}
|
||||
if (location.scheme === REMOTE_HOST_SCHEME) {
|
||||
if (extension.location.scheme === REMOTE_HOST_SCHEME) {
|
||||
return remoteExtensionManagementServer;
|
||||
}
|
||||
return null;
|
||||
return webExtensionManagementServer;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user