Merge from vscode aba87f135229c17c4624341b7a2499dcedafcb87 (#6430)

* Merge from vscode aba87f135229c17c4624341b7a2499dcedafcb87

* fix compile errors
This commit is contained in:
Anthony Dresser
2019-07-18 18:32:57 -07:00
committed by GitHub
parent bf4815d364
commit ee3663c1cd
158 changed files with 3101 additions and 2361 deletions

View File

@@ -6,7 +6,8 @@
import { localize } from 'vs/nls';
import { Event, Emitter } from 'vs/base/common/event';
import { Disposable } from 'vs/base/common/lifecycle';
import { IExtensionManagementService, DidUninstallExtensionEvent, IExtensionEnablementService, IExtensionIdentifier, EnablementState, DidInstallExtensionEvent, InstallOperation, IExtensionManagementServerService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { IExtensionManagementService, DidUninstallExtensionEvent, IExtensionIdentifier, DidInstallExtensionEvent, InstallOperation } from 'vs/platform/extensionManagement/common/extensionManagement';
import { IExtensionEnablementService, EnablementState, IExtensionManagementServerService } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
import { IStorageService, StorageScope, IWorkspaceStorageChangeEvent } from 'vs/platform/storage/common/storage';
@@ -55,30 +56,34 @@ export class ExtensionEnablementService extends Disposable implements IExtension
}
getEnablementState(extension: IExtension): EnablementState {
if (this._isSystemDisabled(extension)) {
return EnablementState.Disabled;
if (this._isDisabledInEnv(extension)) {
return EnablementState.DisabledByEnvironemt;
}
if (this._isDisabledByExtensionKind(extension)) {
return EnablementState.DisabledByExtensionKind;
}
const identifier = extension.identifier;
if (this.hasWorkspace) {
if (this._getEnabledExtensions(StorageScope.WORKSPACE).filter(e => areSameExtensions(e, identifier))[0]) {
return EnablementState.WorkspaceEnabled;
return EnablementState.EnabledWorkspace;
}
if (this._getDisabledExtensions(StorageScope.WORKSPACE).filter(e => areSameExtensions(e, identifier))[0]) {
return EnablementState.WorkspaceDisabled;
return EnablementState.DisabledWorkspace;
}
}
if (this._getDisabledExtensions(StorageScope.GLOBAL).filter(e => areSameExtensions(e, identifier))[0]) {
return EnablementState.Disabled;
return EnablementState.DisabledGlobally;
}
return EnablementState.Enabled;
return EnablementState.EnabledGlobally;
}
canChangeEnablement(extension: IExtension): boolean {
if (extension.manifest && extension.manifest.contributes && extension.manifest.contributes.localizations && extension.manifest.contributes.localizations.length) {
return false;
}
if (this._isSystemDisabled(extension)) {
const enablementState = this.getEnablementState(extension);
if (enablementState === EnablementState.DisabledByEnvironemt || enablementState === EnablementState.DisabledByExtensionKind) {
return false;
}
return true;
@@ -86,7 +91,7 @@ export class ExtensionEnablementService extends Disposable implements IExtension
async setEnablement(extensions: IExtension[], newState: EnablementState): Promise<boolean[]> {
const workspace = newState === EnablementState.WorkspaceDisabled || newState === EnablementState.WorkspaceEnabled;
const workspace = newState === EnablementState.DisabledWorkspace || newState === EnablementState.EnabledWorkspace;
if (workspace && !this.hasWorkspace) {
return Promise.reject(new Error(localize('noWorkspace', "No workspace.")));
}
@@ -108,16 +113,16 @@ export class ExtensionEnablementService extends Disposable implements IExtension
}
switch (newState) {
case EnablementState.Enabled:
case EnablementState.EnabledGlobally:
this._enableExtension(extension.identifier);
break;
case EnablementState.Disabled:
case EnablementState.DisabledGlobally:
this._disableExtension(extension.identifier);
break;
case EnablementState.WorkspaceEnabled:
case EnablementState.EnabledWorkspace:
this._enableExtensionInWorkspace(extension.identifier);
break;
case EnablementState.WorkspaceDisabled:
case EnablementState.DisabledWorkspace:
this._disableExtensionInWorkspace(extension.identifier);
break;
}
@@ -127,10 +132,10 @@ export class ExtensionEnablementService extends Disposable implements IExtension
isEnabled(extension: IExtension): boolean {
const enablementState = this.getEnablementState(extension);
return enablementState === EnablementState.WorkspaceEnabled || enablementState === EnablementState.Enabled;
return enablementState === EnablementState.EnabledWorkspace || enablementState === EnablementState.EnabledGlobally;
}
private _isSystemDisabled(extension: IExtension): boolean {
private _isDisabledInEnv(extension: IExtension): boolean {
if (this.allUserExtensionsDisabled) {
return extension.type === ExtensionType.User;
}
@@ -138,7 +143,11 @@ export class ExtensionEnablementService extends Disposable implements IExtension
if (Array.isArray(disabledExtensions)) {
return disabledExtensions.some(id => areSameExtensions({ id }, extension.identifier));
}
if (this.environmentService.configuration.remoteAuthority) {
return false;
}
private _isDisabledByExtensionKind(extension: IExtension): boolean {
if (this.extensionManagementServerService.localExtensionManagementServer && this.extensionManagementServerService.remoteExtensionManagementServer) {
const server = isUIExtension(extension.manifest, this.productService, this.configurationService) ? this.extensionManagementServerService.localExtensionManagementServer : this.extensionManagementServerService.remoteExtensionManagementServer;
return this.extensionManagementServerService.getExtensionManagementServer(extension.location) !== server;
}
@@ -148,17 +157,17 @@ export class ExtensionEnablementService extends Disposable implements IExtension
private _getEnablementState(identifier: IExtensionIdentifier): EnablementState {
if (this.hasWorkspace) {
if (this._getEnabledExtensions(StorageScope.WORKSPACE).filter(e => areSameExtensions(e, identifier))[0]) {
return EnablementState.WorkspaceEnabled;
return EnablementState.EnabledWorkspace;
}
if (this._getDisabledExtensions(StorageScope.WORKSPACE).filter(e => areSameExtensions(e, identifier))[0]) {
return EnablementState.WorkspaceDisabled;
return EnablementState.DisabledWorkspace;
}
}
if (this._getDisabledExtensions(StorageScope.GLOBAL).filter(e => areSameExtensions(e, identifier))[0]) {
return EnablementState.Disabled;
return EnablementState.DisabledGlobally;
}
return EnablementState.Enabled;
return EnablementState.EnabledGlobally;
}
private _enableExtension(identifier: IExtensionIdentifier): void {

View File

@@ -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 { 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 { IWorkspace, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
export const IExtensionManagementServerService = createDecorator<IExtensionManagementServerService>('extensionManagementServerService');
export interface IExtensionManagementServer {
extensionManagementService: IExtensionManagementService;
authority: string;
label: string;
}
export interface IExtensionManagementServerService {
_serviceBrand: any;
readonly localExtensionManagementServer: IExtensionManagementServer | null;
readonly remoteExtensionManagementServer: IExtensionManagementServer | null;
getExtensionManagementServer(location: URI): IExtensionManagementServer | null;
}
export const enum EnablementState {
DisabledByExtensionKind,
DisabledByEnvironemt,
DisabledGlobally,
DisabledWorkspace,
EnabledGlobally,
EnabledWorkspace
}
export const IExtensionEnablementService = createDecorator<IExtensionEnablementService>('extensionEnablementService');
export interface IExtensionEnablementService {
_serviceBrand: any;
readonly allUserExtensionsDisabled: boolean;
/**
* Event to listen on for extension enablement changes
*/
onEnablementChanged: Event<IExtension[]>;
/**
* Returns the enablement state for the given extension
*/
getEnablementState(extension: IExtension): EnablementState;
/**
* Returns `true` if the enablement can be changed.
*/
canChangeEnablement(extension: IExtension): boolean;
/**
* Returns `true` if the given extension identifier is enabled.
*/
isEnabled(extension: IExtension): boolean;
/**
* Enable or disable the given extension.
* if `workspace` is `true` then enablement is done for workspace, otherwise globally.
*
* Returns a promise that resolves to boolean value.
* if resolves to `true` then requires restart for the change to take effect.
*
* Throws error if enablement is requested for workspace and there is no workspace
*/
setEnablement(extensions: IExtension[], state: EnablementState): Promise<boolean[]>;
}
export interface IExtensionsConfigContent {
recommendations: string[];
unwantedRecommendations: string[];
}
export type RecommendationChangeNotification = {
extensionId: string,
isRecommended: boolean
};
export type DynamicRecommendation = 'dynamic';
export type ExecutableRecommendation = 'executable';
export type CachedRecommendation = 'cached';
export type ApplicationRecommendation = 'application';
export type ExtensionRecommendationSource = IWorkspace | IWorkspaceFolder | URI | DynamicRecommendation | ExecutableRecommendation | CachedRecommendation | ApplicationRecommendation;
export interface IExtensionRecommendation {
extensionId: string;
sources: ExtensionRecommendationSource[];
}
export const IExtensionTipsService = createDecorator<IExtensionTipsService>('extensionTipsService');
export interface IExtensionTipsService {
_serviceBrand: any;
getAllRecommendationsWithReason(): { [id: string]: { reasonId: ExtensionRecommendationReason, reasonText: string }; };
getFileBasedRecommendations(): IExtensionRecommendation[];
getOtherRecommendations(): Promise<IExtensionRecommendation[]>;
getWorkspaceRecommendations(): Promise<IExtensionRecommendation[]>;
getKeymapRecommendations(): IExtensionRecommendation[];
toggleIgnoredRecommendation(extensionId: string, shouldIgnore: boolean): void;
getAllIgnoredRecommendations(): { global: string[], workspace: string[] };
onRecommendationChange: Event<RecommendationChangeNotification>;
}
export const enum ExtensionRecommendationReason {
Workspace,
File,
Executable,
DynamicWorkspace,
Experimental
}

View File

@@ -0,0 +1,45 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
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';
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';
export class ExtensionManagementServerService implements IExtensionManagementServerService {
_serviceBrand: any;
readonly localExtensionManagementServer: IExtensionManagementServer | null = null;
readonly remoteExtensionManagementServer: IExtensionManagementServer | null = null;
constructor(
@IRemoteAgentService remoteAgentService: IRemoteAgentService,
@ILabelService labelService: ILabelService,
) {
const remoteAgentConnection = remoteAgentService.getConnection();
if (remoteAgentConnection) {
const extensionManagementService = new ExtensionManagementChannelClient(remoteAgentConnection!.getChannel<IChannel>('extensions'));
this.remoteExtensionManagementServer = {
authority: remoteAgentConnection.remoteAuthority, extensionManagementService,
get label() { return labelService.getHostLabel(REMOTE_HOST_SCHEME, remoteAgentConnection!.remoteAuthority) || localize('remote', "Remote"); }
};
}
}
getExtensionManagementServer(location: URI): IExtensionManagementServer | null {
if (location.scheme === REMOTE_HOST_SCHEME) {
return this.remoteExtensionManagementServer;
}
return null;
}
}
registerSingleton(IExtensionManagementServerService, ExtensionManagementServerService);

View File

@@ -0,0 +1,190 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Event, EventMultiplexer } from 'vs/base/common/event';
import {
IExtensionManagementService, ILocalExtension, IGalleryExtension, InstallExtensionEvent, DidInstallExtensionEvent, IExtensionIdentifier, DidUninstallExtensionEvent, IReportedExtension, IGalleryMetadata, IExtensionGalleryService
} from 'vs/platform/extensionManagement/common/extensionManagement';
import { IExtensionManagementServer, IExtensionManagementServerService } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
import { ExtensionType, isLanguagePackExtension } from 'vs/platform/extensions/common/extensions';
import { URI } from 'vs/base/common/uri';
import { Disposable } from 'vs/base/common/lifecycle';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { CancellationToken } from 'vs/base/common/cancellation';
import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
import { localize } from 'vs/nls';
import { isUIExtension } from 'vs/workbench/services/extensions/common/extensionsUtil';
import { IProductService } from 'vs/platform/product/common/product';
export class ExtensionManagementService extends Disposable implements IExtensionManagementService {
_serviceBrand: any;
readonly onInstallExtension: Event<InstallExtensionEvent>;
readonly onDidInstallExtension: Event<DidInstallExtensionEvent>;
readonly onUninstallExtension: Event<IExtensionIdentifier>;
readonly onDidUninstallExtension: Event<DidUninstallExtensionEvent>;
protected readonly servers: IExtensionManagementServer[] = [];
constructor(
@IExtensionManagementServerService protected readonly extensionManagementServerService: IExtensionManagementServerService,
@IExtensionGalleryService private readonly extensionGalleryService: IExtensionGalleryService,
@IConfigurationService protected readonly configurationService: IConfigurationService,
@IProductService protected readonly productService: IProductService,
) {
super();
if (this.extensionManagementServerService.localExtensionManagementServer) {
this.servers.push(this.extensionManagementServerService.localExtensionManagementServer);
}
if (this.extensionManagementServerService.remoteExtensionManagementServer) {
this.servers.push(this.extensionManagementServerService.remoteExtensionManagementServer);
}
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;
this.onUninstallExtension = this._register(this.servers.reduce((emitter: EventMultiplexer<IExtensionIdentifier>, server) => { emitter.add(server.extensionManagementService.onUninstallExtension); return emitter; }, new EventMultiplexer<IExtensionIdentifier>())).event;
this.onDidUninstallExtension = this._register(this.servers.reduce((emitter: EventMultiplexer<DidUninstallExtensionEvent>, server) => { emitter.add(server.extensionManagementService.onDidUninstallExtension); return emitter; }, new EventMultiplexer<DidUninstallExtensionEvent>())).event;
}
getInstalled(type?: ExtensionType): Promise<ILocalExtension[]> {
const installedExtensions: ILocalExtension[] = [];
return Promise.all(this.servers.map(({ extensionManagementService }) => extensionManagementService.getInstalled(type).then(extensions => installedExtensions.push(...extensions))))
.then(_ => installedExtensions)
.catch(e => installedExtensions);
}
async uninstall(extension: ILocalExtension): Promise<void> {
const server = this.getServer(extension);
if (!server) {
return Promise.reject(`Invalid location ${extension.location.toString()}`);
}
if (this.extensionManagementServerService.localExtensionManagementServer && this.extensionManagementServerService.remoteExtensionManagementServer) {
if (isLanguagePackExtension(extension.manifest)) {
return this.uninstallEverywhere(extension);
}
return this.uninstallInServer(extension, server);
}
return server.extensionManagementService.uninstall(extension);
}
private async uninstallEverywhere(extension: ILocalExtension): Promise<void> {
const server = this.getServer(extension);
if (!server) {
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);
}
}
return promise;
}
private async uninstallInServer(extension: ILocalExtension, server: IExtensionManagementServer, force?: boolean): Promise<void> {
if (server === this.extensionManagementServerService.localExtensionManagementServer) {
const installedExtensions = await this.extensionManagementServerService.remoteExtensionManagementServer!.extensionManagementService.getInstalled(ExtensionType.User);
const dependentNonUIExtensions = installedExtensions.filter(i => !isUIExtension(i.manifest, this.productService, this.configurationService)
&& i.manifest.extensionDependencies && i.manifest.extensionDependencies.some(id => areSameExtensions({ id }, extension.identifier)));
if (dependentNonUIExtensions.length) {
return Promise.reject(new Error(this.getDependentsErrorMessage(extension, dependentNonUIExtensions)));
}
}
return server.extensionManagementService.uninstall(extension, force);
}
private getDependentsErrorMessage(extension: ILocalExtension, dependents: ILocalExtension[]): string {
if (dependents.length === 1) {
return localize('singleDependentError', "Cannot uninstall extension '{0}'. Extension '{1}' depends on this.",
extension.manifest.displayName || extension.manifest.name, dependents[0].manifest.displayName || dependents[0].manifest.name);
}
if (dependents.length === 2) {
return localize('twoDependentsError', "Cannot uninstall extension '{0}'. Extensions '{1}' and '{2}' depend on this.",
extension.manifest.displayName || extension.manifest.name, dependents[0].manifest.displayName || dependents[0].manifest.name, dependents[1].manifest.displayName || dependents[1].manifest.name);
}
return localize('multipleDependentsError', "Cannot uninstall extension '{0}'. Extensions '{1}', '{2}' and others depend on this.",
extension.manifest.displayName || extension.manifest.name, dependents[0].manifest.displayName || dependents[0].manifest.name, dependents[1].manifest.displayName || dependents[1].manifest.name);
}
reinstallFromGallery(extension: ILocalExtension): Promise<void> {
const server = this.getServer(extension);
if (server) {
return server.extensionManagementService.reinstallFromGallery(extension);
}
return Promise.reject(`Invalid location ${extension.location.toString()}`);
}
updateMetadata(extension: ILocalExtension, metadata: IGalleryMetadata): Promise<ILocalExtension> {
const server = this.getServer(extension);
if (server) {
return server.extensionManagementService.updateMetadata(extension, metadata);
}
return Promise.reject(`Invalid location ${extension.location.toString()}`);
}
zip(extension: ILocalExtension): Promise<URI> {
throw new Error('Not Supported');
}
unzip(zipLocation: URI, type: ExtensionType): Promise<IExtensionIdentifier> {
return Promise.all(this.servers.map(({ extensionManagementService }) => extensionManagementService.unzip(zipLocation, type))).then(([extensionIdentifier]) => extensionIdentifier);
}
async install(vsix: URI): Promise<ILocalExtension> {
if (this.extensionManagementServerService.localExtensionManagementServer) {
return this.extensionManagementServerService.localExtensionManagementServer.extensionManagementService.install(vsix);
}
if (this.extensionManagementServerService.remoteExtensionManagementServer) {
return this.extensionManagementServerService.remoteExtensionManagementServer.extensionManagementService.install(vsix);
}
return Promise.reject('No Servers to Install');
}
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 (isUIExtension(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) {
return this.extensionManagementServerService.localExtensionManagementServer.extensionManagementService.installFromGallery(gallery);
}
if (this.extensionManagementServerService.remoteExtensionManagementServer) {
return this.extensionManagementServerService.remoteExtensionManagementServer.extensionManagementService.installFromGallery(gallery);
}
return Promise.reject('No Servers to Install');
}
getExtensionsReport(): Promise<IReportedExtension[]> {
if (this.extensionManagementServerService.localExtensionManagementServer) {
return this.extensionManagementServerService.localExtensionManagementServer.extensionManagementService.getExtensionsReport();
}
if (this.extensionManagementServerService.remoteExtensionManagementServer) {
return this.extensionManagementServerService.remoteExtensionManagementServer.extensionManagementService.getExtensionsReport();
}
return Promise.resolve([]);
}
private getServer(extension: ILocalExtension): IExtensionManagementServer | null {
return this.extensionManagementServerService.getExtensionManagementServer(extension.location);
}
}

View File

@@ -0,0 +1,66 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
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';
import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
import { REMOTE_HOST_SCHEME } from 'vs/platform/remote/common/remoteHosts';
import { IChannel } from 'vs/base/parts/ipc/common/ipc';
import { ISharedProcessService } from 'vs/platform/ipc/electron-browser/sharedProcessService';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { ILogService } from 'vs/platform/log/common/log';
import { RemoteExtensionManagementChannelClient } from 'vs/workbench/services/extensions/electron-browser/remoteExtensionManagementIpc';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IProductService } from 'vs/platform/product/common/product';
import { ILabelService } from 'vs/platform/label/common/label';
const localExtensionManagementServerAuthority: string = 'vscode-local';
export class ExtensionManagementServerService implements IExtensionManagementServerService {
_serviceBrand: any;
readonly localExtensionManagementServer: IExtensionManagementServer;
readonly remoteExtensionManagementServer: IExtensionManagementServer | null = null;
readonly isSingleServer: boolean = false;
constructor(
@ISharedProcessService sharedProcessService: ISharedProcessService,
@IRemoteAgentService remoteAgentService: IRemoteAgentService,
@IExtensionGalleryService galleryService: IExtensionGalleryService,
@IConfigurationService configurationService: IConfigurationService,
@IProductService productService: IProductService,
@ILogService logService: ILogService,
@ILabelService labelService: ILabelService,
) {
const localExtensionManagementService = new ExtensionManagementChannelClient(sharedProcessService.getChannel('extensions'));
this.localExtensionManagementServer = { extensionManagementService: localExtensionManagementService, authority: localExtensionManagementServerAuthority, 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, extensionManagementService,
get label() { return labelService.getHostLabel(REMOTE_HOST_SCHEME, remoteAgentConnection!.remoteAuthority) || localize('remote', "Remote"); }
};
}
}
getExtensionManagementServer(location: URI): IExtensionManagementServer | null {
if (location.scheme === Schemas.file) {
return this.localExtensionManagementServer;
}
if (location.scheme === REMOTE_HOST_SCHEME) {
return this.remoteExtensionManagementServer;
}
return null;
}
}
registerSingleton(IExtensionManagementServerService, ExtensionManagementServerService);

View File

@@ -0,0 +1,36 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ILocalExtension } from 'vs/platform/extensionManagement/common/extensionManagement';
import { isLanguagePackExtension } from 'vs/platform/extensions/common/extensions';
import { URI } from 'vs/base/common/uri';
import { getManifest } from 'vs/platform/extensionManagement/node/extensionManagementUtil';
import { isUIExtension } from 'vs/workbench/services/extensions/common/extensionsUtil';
import { ExtensionManagementService as BaseExtensionManagementService } from 'vs/workbench/services/extensionManagement/common/extensionManagementService';
export class ExtensionManagementService extends BaseExtensionManagementService {
async install(vsix: URI): Promise<ILocalExtension> {
if (this.extensionManagementServerService.localExtensionManagementServer && this.extensionManagementServerService.remoteExtensionManagementServer) {
const manifest = await getManifest(vsix.fsPath);
if (isLanguagePackExtension(manifest)) {
// Install on both servers
const [local] = await Promise.all(this.servers.map(server => server.extensionManagementService.install(vsix)));
return local;
}
if (isUIExtension(manifest, this.productService, this.configurationService)) {
// Install only on local server
return this.extensionManagementServerService.localExtensionManagementServer.extensionManagementService.install(vsix);
}
// Install only on remote server
return this.extensionManagementServerService.remoteExtensionManagementServer.extensionManagementService.install(vsix);
}
if (this.extensionManagementServerService.localExtensionManagementServer) {
return this.extensionManagementServerService.localExtensionManagementServer.extensionManagementService.install(vsix);
}
return Promise.reject('No Servers to Install');
}
}

View File

@@ -4,8 +4,9 @@
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import * as sinon from 'sinon';
import { IExtensionManagementService, IExtensionEnablementService, DidUninstallExtensionEvent, EnablementState, ILocalExtension, DidInstallExtensionEvent, InstallOperation, IExtensionManagementServerService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { ExtensionEnablementService } from 'vs/workbench/services/extensionManagement/node/extensionEnablementService';
import { IExtensionManagementService, DidUninstallExtensionEvent, ILocalExtension, DidInstallExtensionEvent, InstallOperation } from 'vs/platform/extensionManagement/common/extensionManagement';
import { IExtensionEnablementService, EnablementState, IExtensionManagementServerService } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
import { ExtensionEnablementService } from 'vs/workbench/services/extensionManagement/common/extensionEnablementService';
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
import { Emitter } from 'vs/base/common/event';
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
@@ -16,6 +17,11 @@ import { isUndefinedOrNull } from 'vs/base/common/types';
import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ProductService } from 'vs/platform/product/node/productService';
import { URI } from 'vs/base/common/uri';
import { Schemas } from 'vs/base/common/network';
import { REMOTE_HOST_SCHEME } from 'vs/platform/remote/common/remoteHosts';
import { assign } from 'vs/base/common/objects';
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
function storageService(instantiationService: TestInstantiationService): IStorageService {
let service = instantiationService.get(IStorageService);
@@ -55,7 +61,7 @@ export class TestExtensionEnablementService extends ExtensionEnablementService {
if (workspaceEnabledExtensions.length) {
extensions = extensions.filter(r => !workspaceEnabledExtensions.some(e => areSameExtensions(e, r)));
}
extensions.forEach(d => this.setEnablement([aLocalExtension(d.id)], EnablementState.Enabled));
extensions.forEach(d => this.setEnablement([aLocalExtension(d.id)], EnablementState.EnabledGlobally));
}
}
@@ -69,7 +75,13 @@ suite('ExtensionEnablementService Test', () => {
setup(() => {
instantiationService = new TestInstantiationService();
instantiationService.stub(IConfigurationService, new TestConfigurationService());
instantiationService.stub(IExtensionManagementService, { onDidUninstallExtension: didUninstallEvent.event, onDidInstallExtension: didInstallEvent.event, getInstalled: () => Promise.resolve([] as ILocalExtension[]) } as IExtensionManagementService);
instantiationService.stub(IExtensionManagementServerService, <IExtensionManagementServerService>{
localExtensionManagementServer: {
extensionManagementService: instantiationService.get(IExtensionManagementService)
}
});
testObject = new TestExtensionEnablementService(instantiationService);
});
@@ -79,20 +91,20 @@ suite('ExtensionEnablementService Test', () => {
test('test disable an extension globally', async () => {
const extension = aLocalExtension('pub.a');
await testObject.setEnablement([extension], EnablementState.Disabled);
await testObject.setEnablement([extension], EnablementState.DisabledGlobally);
assert.ok(!testObject.isEnabled(extension));
assert.equal(testObject.getEnablementState(extension), EnablementState.Disabled);
assert.equal(testObject.getEnablementState(extension), EnablementState.DisabledGlobally);
});
test('test disable an extension globally should return truthy promise', () => {
return testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.Disabled)
return testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.DisabledGlobally)
.then(value => assert.ok(value));
});
test('test disable an extension globally triggers the change event', () => {
const target = sinon.spy();
testObject.onEnablementChanged(target);
return testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.Disabled)
return testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.DisabledGlobally)
.then(() => {
assert.ok(target.calledOnce);
assert.deepEqual((<IExtension>target.args[0][0][0]).identifier, { id: 'pub.a' });
@@ -100,116 +112,116 @@ suite('ExtensionEnablementService Test', () => {
});
test('test disable an extension globally again should return a falsy promise', () => {
return testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.Disabled)
.then(() => testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.Disabled))
return testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.DisabledGlobally)
.then(() => testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.DisabledGlobally))
.then(value => assert.ok(!value[0]));
});
test('test state of globally disabled extension', () => {
return testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.Disabled)
.then(() => assert.equal(testObject.getEnablementState(aLocalExtension('pub.a')), EnablementState.Disabled));
return testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.DisabledGlobally)
.then(() => assert.equal(testObject.getEnablementState(aLocalExtension('pub.a')), EnablementState.DisabledGlobally));
});
test('test state of globally enabled extension', () => {
return testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.Disabled)
.then(() => testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.Enabled))
.then(() => assert.equal(testObject.getEnablementState(aLocalExtension('pub.a')), EnablementState.Enabled));
return testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.DisabledGlobally)
.then(() => testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.EnabledGlobally))
.then(() => assert.equal(testObject.getEnablementState(aLocalExtension('pub.a')), EnablementState.EnabledGlobally));
});
test('test disable an extension for workspace', async () => {
const extension = aLocalExtension('pub.a');
await testObject.setEnablement([extension], EnablementState.WorkspaceDisabled);
await testObject.setEnablement([extension], EnablementState.DisabledWorkspace);
assert.ok(!testObject.isEnabled(extension));
assert.equal(testObject.getEnablementState(extension), EnablementState.WorkspaceDisabled);
assert.equal(testObject.getEnablementState(extension), EnablementState.DisabledWorkspace);
});
test('test disable an extension for workspace returns a truthy promise', () => {
return testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.WorkspaceDisabled)
return testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.DisabledWorkspace)
.then(value => assert.ok(value));
});
test('test disable an extension for workspace again should return a falsy promise', () => {
return testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.WorkspaceDisabled)
.then(() => testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.WorkspaceDisabled))
return testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.DisabledWorkspace)
.then(() => testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.DisabledWorkspace))
.then(value => assert.ok(!value[0]));
});
test('test state of workspace disabled extension', () => {
return testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.WorkspaceDisabled)
.then(() => assert.equal(testObject.getEnablementState(aLocalExtension('pub.a')), EnablementState.WorkspaceDisabled));
return testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.DisabledWorkspace)
.then(() => assert.equal(testObject.getEnablementState(aLocalExtension('pub.a')), EnablementState.DisabledWorkspace));
});
test('test state of workspace and globally disabled extension', () => {
return testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.Disabled)
.then(() => testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.WorkspaceDisabled))
.then(() => assert.equal(testObject.getEnablementState(aLocalExtension('pub.a')), EnablementState.WorkspaceDisabled));
return testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.DisabledGlobally)
.then(() => testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.DisabledWorkspace))
.then(() => assert.equal(testObject.getEnablementState(aLocalExtension('pub.a')), EnablementState.DisabledWorkspace));
});
test('test state of workspace enabled extension', () => {
return testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.WorkspaceDisabled)
.then(() => testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.WorkspaceEnabled))
.then(() => assert.equal(testObject.getEnablementState(aLocalExtension('pub.a')), EnablementState.WorkspaceEnabled));
return testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.DisabledWorkspace)
.then(() => testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.EnabledWorkspace))
.then(() => assert.equal(testObject.getEnablementState(aLocalExtension('pub.a')), EnablementState.EnabledWorkspace));
});
test('test state of globally disabled and workspace enabled extension', () => {
return testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.Disabled)
.then(() => testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.WorkspaceDisabled))
.then(() => testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.WorkspaceEnabled))
.then(() => assert.equal(testObject.getEnablementState(aLocalExtension('pub.a')), EnablementState.WorkspaceEnabled));
return testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.DisabledGlobally)
.then(() => testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.DisabledWorkspace))
.then(() => testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.EnabledWorkspace))
.then(() => assert.equal(testObject.getEnablementState(aLocalExtension('pub.a')), EnablementState.EnabledWorkspace));
});
test('test state of an extension when disabled for workspace from workspace enabled', () => {
return testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.WorkspaceDisabled)
.then(() => testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.WorkspaceEnabled))
.then(() => testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.WorkspaceDisabled))
.then(() => assert.equal(testObject.getEnablementState(aLocalExtension('pub.a')), EnablementState.WorkspaceDisabled));
return testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.DisabledWorkspace)
.then(() => testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.EnabledWorkspace))
.then(() => testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.DisabledWorkspace))
.then(() => assert.equal(testObject.getEnablementState(aLocalExtension('pub.a')), EnablementState.DisabledWorkspace));
});
test('test state of an extension when disabled globally from workspace enabled', () => {
return testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.WorkspaceDisabled)
.then(() => testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.WorkspaceEnabled))
.then(() => testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.Disabled))
.then(() => assert.equal(testObject.getEnablementState(aLocalExtension('pub.a')), EnablementState.Disabled));
return testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.DisabledWorkspace)
.then(() => testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.EnabledWorkspace))
.then(() => testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.DisabledGlobally))
.then(() => assert.equal(testObject.getEnablementState(aLocalExtension('pub.a')), EnablementState.DisabledGlobally));
});
test('test state of an extension when disabled globally from workspace disabled', () => {
return testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.WorkspaceDisabled)
.then(() => testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.Disabled))
.then(() => assert.equal(testObject.getEnablementState(aLocalExtension('pub.a')), EnablementState.Disabled));
return testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.DisabledWorkspace)
.then(() => testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.DisabledGlobally))
.then(() => assert.equal(testObject.getEnablementState(aLocalExtension('pub.a')), EnablementState.DisabledGlobally));
});
test('test state of an extension when enabled globally from workspace enabled', () => {
return testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.WorkspaceDisabled)
.then(() => testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.WorkspaceEnabled))
.then(() => testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.Enabled))
.then(() => assert.equal(testObject.getEnablementState(aLocalExtension('pub.a')), EnablementState.Enabled));
return testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.DisabledWorkspace)
.then(() => testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.EnabledWorkspace))
.then(() => testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.EnabledGlobally))
.then(() => assert.equal(testObject.getEnablementState(aLocalExtension('pub.a')), EnablementState.EnabledGlobally));
});
test('test state of an extension when enabled globally from workspace disabled', () => {
return testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.WorkspaceDisabled)
.then(() => testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.Enabled))
.then(() => assert.equal(testObject.getEnablementState(aLocalExtension('pub.a')), EnablementState.Enabled));
return testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.DisabledWorkspace)
.then(() => testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.EnabledGlobally))
.then(() => assert.equal(testObject.getEnablementState(aLocalExtension('pub.a')), EnablementState.EnabledGlobally));
});
test('test disable an extension for workspace and then globally', async () => {
const extension = aLocalExtension('pub.a');
await testObject.setEnablement([extension], EnablementState.WorkspaceDisabled);
await testObject.setEnablement([extension], EnablementState.Disabled);
await testObject.setEnablement([extension], EnablementState.DisabledWorkspace);
await testObject.setEnablement([extension], EnablementState.DisabledGlobally);
assert.ok(!testObject.isEnabled(extension));
assert.equal(testObject.getEnablementState(extension), EnablementState.Disabled);
assert.equal(testObject.getEnablementState(extension), EnablementState.DisabledGlobally);
});
test('test disable an extension for workspace and then globally return a truthy promise', () => {
return testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.WorkspaceDisabled)
.then(() => testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.Disabled))
return testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.DisabledWorkspace)
.then(() => testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.DisabledGlobally))
.then(value => assert.ok(value));
});
test('test disable an extension for workspace and then globally trigger the change event', () => {
const target = sinon.spy();
return testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.WorkspaceDisabled)
return testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.DisabledWorkspace)
.then(() => testObject.onEnablementChanged(target))
.then(() => testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.Disabled))
.then(() => testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.DisabledGlobally))
.then(() => {
assert.ok(target.calledOnce);
assert.deepEqual((<IExtension>target.args[0][0][0]).identifier, { id: 'pub.a' });
@@ -218,23 +230,23 @@ suite('ExtensionEnablementService Test', () => {
test('test disable an extension globally and then for workspace', async () => {
const extension = aLocalExtension('pub.a');
await testObject.setEnablement([extension], EnablementState.Disabled);
await testObject.setEnablement([extension], EnablementState.WorkspaceDisabled);
await testObject.setEnablement([extension], EnablementState.DisabledGlobally);
await testObject.setEnablement([extension], EnablementState.DisabledWorkspace);
assert.ok(!testObject.isEnabled(extension));
assert.equal(testObject.getEnablementState(extension), EnablementState.WorkspaceDisabled);
assert.equal(testObject.getEnablementState(extension), EnablementState.DisabledWorkspace);
});
test('test disable an extension globally and then for workspace return a truthy promise', () => {
return testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.Disabled)
.then(() => testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.WorkspaceDisabled))
return testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.DisabledGlobally)
.then(() => testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.DisabledWorkspace))
.then(value => assert.ok(value));
});
test('test disable an extension globally and then for workspace triggers the change event', () => {
const target = sinon.spy();
return testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.Disabled)
return testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.DisabledGlobally)
.then(() => testObject.onEnablementChanged(target))
.then(() => testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.WorkspaceDisabled))
.then(() => testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.DisabledWorkspace))
.then(() => {
assert.ok(target.calledOnce);
assert.deepEqual((<IExtension>target.args[0][0][0]).identifier, { id: 'pub.a' });
@@ -243,29 +255,29 @@ suite('ExtensionEnablementService Test', () => {
test('test disable an extension for workspace when there is no workspace throws error', () => {
instantiationService.stub(IWorkspaceContextService, 'getWorkbenchState', WorkbenchState.EMPTY);
return testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.WorkspaceDisabled)
return testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.DisabledWorkspace)
.then(() => assert.fail('should throw an error'), error => assert.ok(error));
});
test('test enable an extension globally', async () => {
const extension = aLocalExtension('pub.a');
await testObject.setEnablement([extension], EnablementState.Disabled);
await testObject.setEnablement([extension], EnablementState.Enabled);
await testObject.setEnablement([extension], EnablementState.DisabledGlobally);
await testObject.setEnablement([extension], EnablementState.EnabledGlobally);
assert.ok(testObject.isEnabled(extension));
assert.equal(testObject.getEnablementState(extension), EnablementState.Enabled);
assert.equal(testObject.getEnablementState(extension), EnablementState.EnabledGlobally);
});
test('test enable an extension globally return truthy promise', () => {
return testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.Disabled)
.then(() => testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.Enabled))
return testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.DisabledGlobally)
.then(() => testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.EnabledGlobally))
.then(value => assert.ok(value));
});
test('test enable an extension globally triggers change event', () => {
const target = sinon.spy();
return testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.Disabled)
return testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.DisabledGlobally)
.then(() => testObject.onEnablementChanged(target))
.then(() => testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.Enabled))
.then(() => testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.EnabledGlobally))
.then(() => {
assert.ok(target.calledOnce);
assert.deepEqual((<IExtension>target.args[0][0][0]).identifier, { id: 'pub.a' });
@@ -273,29 +285,29 @@ suite('ExtensionEnablementService Test', () => {
});
test('test enable an extension globally when already enabled return falsy promise', () => {
return testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.Enabled)
return testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.EnabledGlobally)
.then(value => assert.ok(!value[0]));
});
test('test enable an extension for workspace', async () => {
const extension = aLocalExtension('pub.a');
await testObject.setEnablement([extension], EnablementState.WorkspaceDisabled);
await testObject.setEnablement([extension], EnablementState.WorkspaceEnabled);
await testObject.setEnablement([extension], EnablementState.DisabledWorkspace);
await testObject.setEnablement([extension], EnablementState.EnabledWorkspace);
assert.ok(testObject.isEnabled(extension));
assert.equal(testObject.getEnablementState(extension), EnablementState.WorkspaceEnabled);
assert.equal(testObject.getEnablementState(extension), EnablementState.EnabledWorkspace);
});
test('test enable an extension for workspace return truthy promise', () => {
return testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.WorkspaceDisabled)
.then(() => testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.WorkspaceEnabled))
return testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.DisabledWorkspace)
.then(() => testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.EnabledWorkspace))
.then(value => assert.ok(value));
});
test('test enable an extension for workspace triggers change event', () => {
const target = sinon.spy();
return testObject.setEnablement([aLocalExtension('pub.b')], EnablementState.WorkspaceDisabled)
return testObject.setEnablement([aLocalExtension('pub.b')], EnablementState.DisabledWorkspace)
.then(() => testObject.onEnablementChanged(target))
.then(() => testObject.setEnablement([aLocalExtension('pub.b')], EnablementState.WorkspaceEnabled))
.then(() => testObject.setEnablement([aLocalExtension('pub.b')], EnablementState.EnabledWorkspace))
.then(() => {
assert.ok(target.calledOnce);
assert.deepEqual((<IExtension>target.args[0][0][0]).identifier, { id: 'pub.b' });
@@ -303,48 +315,48 @@ suite('ExtensionEnablementService Test', () => {
});
test('test enable an extension for workspace when already enabled return truthy promise', () => {
return testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.WorkspaceEnabled)
return testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.EnabledWorkspace)
.then(value => assert.ok(value));
});
test('test enable an extension for workspace when disabled in workspace and gloablly', async () => {
const extension = aLocalExtension('pub.a');
await testObject.setEnablement([extension], EnablementState.WorkspaceDisabled);
await testObject.setEnablement([extension], EnablementState.Disabled);
await testObject.setEnablement([extension], EnablementState.WorkspaceEnabled);
await testObject.setEnablement([extension], EnablementState.DisabledWorkspace);
await testObject.setEnablement([extension], EnablementState.DisabledGlobally);
await testObject.setEnablement([extension], EnablementState.EnabledWorkspace);
assert.ok(testObject.isEnabled(extension));
assert.equal(testObject.getEnablementState(extension), EnablementState.WorkspaceEnabled);
assert.equal(testObject.getEnablementState(extension), EnablementState.EnabledWorkspace);
});
test('test enable an extension globally when disabled in workspace and gloablly', async () => {
const extension = aLocalExtension('pub.a');
await testObject.setEnablement([extension], EnablementState.WorkspaceEnabled);
await testObject.setEnablement([extension], EnablementState.WorkspaceDisabled);
await testObject.setEnablement([extension], EnablementState.Disabled);
await testObject.setEnablement([extension], EnablementState.Enabled);
await testObject.setEnablement([extension], EnablementState.EnabledWorkspace);
await testObject.setEnablement([extension], EnablementState.DisabledWorkspace);
await testObject.setEnablement([extension], EnablementState.DisabledGlobally);
await testObject.setEnablement([extension], EnablementState.EnabledGlobally);
assert.ok(testObject.isEnabled(extension));
assert.equal(testObject.getEnablementState(extension), EnablementState.Enabled);
assert.equal(testObject.getEnablementState(extension), EnablementState.EnabledGlobally);
});
test('test installing an extension re-eanbles it when disabled globally', async () => {
const local = aLocalExtension('pub.a');
await testObject.setEnablement([local], EnablementState.Disabled);
await testObject.setEnablement([local], EnablementState.DisabledGlobally);
didInstallEvent.fire({ local, identifier: local.identifier, operation: InstallOperation.Install });
assert.ok(testObject.isEnabled(local));
assert.equal(testObject.getEnablementState(local), EnablementState.Enabled);
assert.equal(testObject.getEnablementState(local), EnablementState.EnabledGlobally);
});
test('test updating an extension does not re-eanbles it when disabled globally', async () => {
const local = aLocalExtension('pub.a');
await testObject.setEnablement([local], EnablementState.Disabled);
await testObject.setEnablement([local], EnablementState.DisabledGlobally);
didInstallEvent.fire({ local, identifier: local.identifier, operation: InstallOperation.Update });
assert.ok(!testObject.isEnabled(local));
assert.equal(testObject.getEnablementState(local), EnablementState.Disabled);
assert.equal(testObject.getEnablementState(local), EnablementState.DisabledGlobally);
});
test('test installing an extension fires enablement change event when disabled globally', async () => {
const local = aLocalExtension('pub.a');
await testObject.setEnablement([local], EnablementState.Disabled);
await testObject.setEnablement([local], EnablementState.DisabledGlobally);
return new Promise((c, e) => {
testObject.onEnablementChanged(([e]) => {
if (e.identifier.id === local.identifier.id) {
@@ -358,7 +370,7 @@ suite('ExtensionEnablementService Test', () => {
test('test updating an extension does not fires enablement change event when disabled globally', async () => {
const target = sinon.spy();
const local = aLocalExtension('pub.a');
await testObject.setEnablement([local], EnablementState.Disabled);
await testObject.setEnablement([local], EnablementState.DisabledGlobally);
testObject.onEnablementChanged(target);
didInstallEvent.fire({ local, identifier: local.identifier, operation: InstallOperation.Update });
assert.ok(!target.called);
@@ -366,23 +378,23 @@ suite('ExtensionEnablementService Test', () => {
test('test installing an extension re-eanbles it when workspace disabled', async () => {
const local = aLocalExtension('pub.a');
await testObject.setEnablement([local], EnablementState.WorkspaceDisabled);
await testObject.setEnablement([local], EnablementState.DisabledWorkspace);
didInstallEvent.fire({ local, identifier: local.identifier, operation: InstallOperation.Install });
assert.ok(testObject.isEnabled(local));
assert.equal(testObject.getEnablementState(local), EnablementState.Enabled);
assert.equal(testObject.getEnablementState(local), EnablementState.EnabledGlobally);
});
test('test updating an extension does not re-eanbles it when workspace disabled', async () => {
const local = aLocalExtension('pub.a');
await testObject.setEnablement([local], EnablementState.WorkspaceDisabled);
await testObject.setEnablement([local], EnablementState.DisabledWorkspace);
didInstallEvent.fire({ local, identifier: local.identifier, operation: InstallOperation.Update });
assert.ok(!testObject.isEnabled(local));
assert.equal(testObject.getEnablementState(local), EnablementState.WorkspaceDisabled);
assert.equal(testObject.getEnablementState(local), EnablementState.DisabledWorkspace);
});
test('test installing an extension fires enablement change event when workspace disabled', async () => {
const local = aLocalExtension('pub.a');
await testObject.setEnablement([local], EnablementState.WorkspaceDisabled);
await testObject.setEnablement([local], EnablementState.DisabledWorkspace);
return new Promise((c, e) => {
testObject.onEnablementChanged(([e]) => {
if (e.identifier.id === local.identifier.id) {
@@ -396,7 +408,7 @@ suite('ExtensionEnablementService Test', () => {
test('test updating an extension does not fires enablement change event when workspace disabled', async () => {
const target = sinon.spy();
const local = aLocalExtension('pub.a');
await testObject.setEnablement([local], EnablementState.WorkspaceDisabled);
await testObject.setEnablement([local], EnablementState.DisabledWorkspace);
testObject.onEnablementChanged(target);
didInstallEvent.fire({ local, identifier: local.identifier, operation: InstallOperation.Update });
assert.ok(!target.called);
@@ -412,26 +424,26 @@ suite('ExtensionEnablementService Test', () => {
test('test remove an extension from disablement list when uninstalled', async () => {
const extension = aLocalExtension('pub.a');
await testObject.setEnablement([extension], EnablementState.WorkspaceDisabled);
await testObject.setEnablement([extension], EnablementState.Disabled);
await testObject.setEnablement([extension], EnablementState.DisabledWorkspace);
await testObject.setEnablement([extension], EnablementState.DisabledGlobally);
didUninstallEvent.fire({ identifier: { id: 'pub.a' } });
assert.ok(testObject.isEnabled(extension));
assert.equal(testObject.getEnablementState(extension), EnablementState.Enabled);
assert.equal(testObject.getEnablementState(extension), EnablementState.EnabledGlobally);
});
test('test isEnabled return false extension is disabled globally', () => {
return testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.Disabled)
return testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.DisabledGlobally)
.then(() => assert.ok(!testObject.isEnabled(aLocalExtension('pub.a'))));
});
test('test isEnabled return false extension is disabled in workspace', () => {
return testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.WorkspaceDisabled)
return testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.DisabledWorkspace)
.then(() => assert.ok(!testObject.isEnabled(aLocalExtension('pub.a'))));
});
test('test isEnabled return true extension is not disabled', () => {
return testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.WorkspaceDisabled)
.then(() => testObject.setEnablement([aLocalExtension('pub.c')], EnablementState.Disabled))
return testObject.setEnablement([aLocalExtension('pub.a')], EnablementState.DisabledWorkspace)
.then(() => testObject.setEnablement([aLocalExtension('pub.c')], EnablementState.DisabledGlobally))
.then(() => assert.ok(testObject.isEnabled(aLocalExtension('pub.b'))));
});
@@ -471,22 +483,109 @@ suite('ExtensionEnablementService Test', () => {
instantiationService.stub(IExtensionManagementService, { onDidUninstallExtension: didUninstallEvent.event, onDidInstallExtension: didInstallEvent.event, getInstalled: () => Promise.resolve([extension, aLocalExtension('pub.b')]) } as IExtensionManagementService);
testObject = new TestExtensionEnablementService(instantiationService);
assert.ok(!testObject.isEnabled(extension));
assert.deepEqual(testObject.getEnablementState(extension), EnablementState.Disabled);
assert.deepEqual(testObject.getEnablementState(extension), EnablementState.DisabledByEnvironemt);
});
test('test local workspace extension is disabled by kind', async () => {
instantiationService.stub(IExtensionManagementServerService, aMultiExtensionManagementServerService(instantiationService));
const localWorkspaceExtension = aLocalExtension2('pub.a', { extensionKind: 'workspace' }, { location: URI.file(`pub.a`) });
testObject = new TestExtensionEnablementService(instantiationService);
assert.ok(!testObject.isEnabled(localWorkspaceExtension));
assert.deepEqual(testObject.getEnablementState(localWorkspaceExtension), EnablementState.DisabledByExtensionKind);
});
test('test local ui extension is not disabled by kind', async () => {
instantiationService.stub(IExtensionManagementServerService, aMultiExtensionManagementServerService(instantiationService));
const localWorkspaceExtension = aLocalExtension2('pub.a', { extensionKind: 'ui' }, { location: URI.file(`pub.a`) });
testObject = new TestExtensionEnablementService(instantiationService);
assert.ok(testObject.isEnabled(localWorkspaceExtension));
assert.deepEqual(testObject.getEnablementState(localWorkspaceExtension), EnablementState.EnabledGlobally);
});
test('test canChangeEnablement return false when the local workspace extension is disabled by kind', () => {
instantiationService.stub(IExtensionManagementServerService, aMultiExtensionManagementServerService(instantiationService));
const localWorkspaceExtension = aLocalExtension2('pub.a', { extensionKind: 'workspace' }, { location: URI.file(`pub.a`) });
testObject = new TestExtensionEnablementService(instantiationService);
assert.equal(testObject.canChangeEnablement(localWorkspaceExtension), false);
});
test('test canChangeEnablement return true for local ui extension', () => {
instantiationService.stub(IExtensionManagementServerService, aMultiExtensionManagementServerService(instantiationService));
const localWorkspaceExtension = aLocalExtension2('pub.a', { extensionKind: 'ui' }, { location: URI.file(`pub.a`) });
testObject = new TestExtensionEnablementService(instantiationService);
assert.equal(testObject.canChangeEnablement(localWorkspaceExtension), true);
});
test('test remote ui extension is disabled by kind', async () => {
instantiationService.stub(IExtensionManagementServerService, aMultiExtensionManagementServerService(instantiationService));
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));
assert.deepEqual(testObject.getEnablementState(localWorkspaceExtension), EnablementState.DisabledByExtensionKind);
});
test('test remote workspace extension is not disabled by kind', async () => {
instantiationService.stub(IExtensionManagementServerService, aMultiExtensionManagementServerService(instantiationService));
const localWorkspaceExtension = aLocalExtension2('pub.a', { extensionKind: 'workspace' }, { location: URI.file(`pub.a`).with({ scheme: Schemas.vscodeRemote }) });
testObject = new TestExtensionEnablementService(instantiationService);
assert.ok(testObject.isEnabled(localWorkspaceExtension));
assert.deepEqual(testObject.getEnablementState(localWorkspaceExtension), EnablementState.EnabledGlobally);
});
test('test canChangeEnablement return false when the remote ui extension is disabled by kind', () => {
instantiationService.stub(IExtensionManagementServerService, aMultiExtensionManagementServerService(instantiationService));
const localWorkspaceExtension = aLocalExtension2('pub.a', { extensionKind: 'ui' }, { location: URI.file(`pub.a`).with({ scheme: Schemas.vscodeRemote }) });
testObject = new TestExtensionEnablementService(instantiationService);
assert.equal(testObject.canChangeEnablement(localWorkspaceExtension), false);
});
test('test canChangeEnablement return true for remote workspace extension', () => {
instantiationService.stub(IExtensionManagementServerService, aMultiExtensionManagementServerService(instantiationService));
const localWorkspaceExtension = aLocalExtension2('pub.a', { extensionKind: 'workspace' }, { location: URI.file(`pub.a`).with({ scheme: Schemas.vscodeRemote }) });
testObject = new TestExtensionEnablementService(instantiationService);
assert.equal(testObject.canChangeEnablement(localWorkspaceExtension), true);
});
});
function aMultiExtensionManagementServerService(instantiationService: TestInstantiationService): IExtensionManagementServerService {
const localExtensionManagementServer = {
authority: 'vscode-local',
label: 'local',
extensionManagementService: instantiationService.get(IExtensionManagementService)
};
const remoteExtensionManagementServer = {
authority: 'vscode-remote',
label: 'remote',
extensionManagementService: instantiationService.get(IExtensionManagementService)
};
return {
_serviceBrand: {},
localExtensionManagementServer,
remoteExtensionManagementServer,
getExtensionManagementServer: (location: URI) => {
if (location.scheme === Schemas.file) {
return localExtensionManagementServer;
}
if (location.scheme === REMOTE_HOST_SCHEME) {
return remoteExtensionManagementServer;
}
return null;
}
};
}
function aLocalExtension(id: string, contributes?: IExtensionContributions, type?: ExtensionType): ILocalExtension {
return aLocalExtension2(id, contributes ? { contributes } : {}, isUndefinedOrNull(type) ? {} : { type });
}
function aLocalExtension2(id: string, manifest: any = {}, properties: any = {}): ILocalExtension {
const [publisher, name] = id.split('.');
type = isUndefinedOrNull(type) ? ExtensionType.User : type;
return <ILocalExtension>Object.create({
properties = assign({
identifier: { id },
galleryIdentifier: { id, uuid: undefined },
manifest: {
name,
publisher,
contributes
},
type
});
type: ExtensionType.User
}, properties);
manifest = assign({ name, publisher }, manifest);
return <ILocalExtension>Object.create({ manifest, ...properties });
}