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

@@ -91,6 +91,36 @@ export class BrowserWorkbenchEnvironmentService implements IEnvironmentService {
this.webviewEndpoint = configuration.webviewEndpoint;
this.untitledWorkspacesHome = URI.from({ scheme: Schemas.untitled, path: 'Workspaces' });
if (document && document.location && document.location.search) {
const map = new Map<string, string>();
const query = document.location.search.substring(1);
const vars = query.split('&');
for (let p of vars) {
const pair = p.split('=');
if (pair.length >= 2) {
map.set(decodeURIComponent(pair[0]), decodeURIComponent(pair[1]));
}
}
const edp = map.get('edp');
if (edp) {
this.extensionDevelopmentLocationURI = [URI.parse(edp)];
this.isExtensionDevelopment = true;
}
const di = map.get('di');
if (di) {
this.debugExtensionHost.debugId = di;
}
const ibe = map.get('ibe');
if (ibe) {
this.debugExtensionHost.port = parseInt(ibe);
this.debugExtensionHost.break = false;
}
}
}
untitledWorkspacesHome: URI;
@@ -119,7 +149,7 @@ export class BrowserWorkbenchEnvironmentService implements IEnvironmentService {
isExtensionDevelopment: boolean;
disableExtensions: boolean | string[];
builtinExtensionsPath: string;
extensionsPath: string;
extensionsPath?: string;
extensionDevelopmentLocationURI?: URI[];
extensionTestsPath?: string;
debugExtensionHost: IExtensionHostDebugParams;
@@ -143,6 +173,7 @@ export class BrowserWorkbenchEnvironmentService implements IEnvironmentService {
driverHandle?: string;
driverVerbose: boolean;
webviewEndpoint?: string;
galleryMachineIdResource?: URI;
get webviewResourceRoot(): string {
return this.webviewEndpoint ? this.webviewEndpoint + '/vscode-resource{{resource}}' : 'vscode-resource:{{resource}}';

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

@@ -5,22 +5,20 @@
import { Event, EventMultiplexer } from 'vs/base/common/event';
import {
IExtensionManagementService, ILocalExtension, IGalleryExtension, InstallExtensionEvent, DidInstallExtensionEvent, IExtensionIdentifier, DidUninstallExtensionEvent, IReportedExtension, IGalleryMetadata,
IExtensionManagementServerService, IExtensionManagementServer, IExtensionGalleryService
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 { getManifest } from 'vs/platform/extensionManagement/node/extensionManagementUtil';
import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
import { localize } from 'vs/nls';
import { isUIExtension } from 'vs/workbench/services/extensions/common/extensionsUtil';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { IProductService } from 'vs/platform/product/common/product';
export class MultiExtensionManagementService extends Disposable implements IExtensionManagementService {
export class ExtensionManagementService extends Disposable implements IExtensionManagementService {
_serviceBrand: any;
@@ -29,16 +27,21 @@ export class MultiExtensionManagementService extends Disposable implements IExte
readonly onUninstallExtension: Event<IExtensionIdentifier>;
readonly onDidUninstallExtension: Event<DidUninstallExtensionEvent>;
private readonly servers: IExtensionManagementServer[];
protected readonly servers: IExtensionManagementServer[] = [];
constructor(
@IExtensionManagementServerService private readonly extensionManagementServerService: IExtensionManagementServerService,
@IExtensionManagementServerService protected readonly extensionManagementServerService: IExtensionManagementServerService,
@IExtensionGalleryService private readonly extensionGalleryService: IExtensionGalleryService,
@IConfigurationService private readonly configurationService: IConfigurationService,
@IProductService private readonly productService: IProductService,
@IConfigurationService protected readonly configurationService: IConfigurationService,
@IProductService protected readonly productService: IProductService,
) {
super();
this.servers = this.extensionManagementServerService.remoteExtensionManagementServer ? [this.extensionManagementServerService.localExtensionManagementServer, this.extensionManagementServerService.remoteExtensionManagementServer] : [this.extensionManagementServerService.localExtensionManagementServer];
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;
@@ -53,31 +56,33 @@ export class MultiExtensionManagementService extends Disposable implements IExte
.catch(e => installedExtensions);
}
async uninstall(extension: ILocalExtension, force?: boolean): Promise<void> {
if (this.extensionManagementServerService.remoteExtensionManagementServer) {
const server = this.getServer(extension);
if (!server) {
return Promise.reject(`Invalid location ${extension.location.toString()}`);
}
if (isLanguagePackExtension(extension.manifest)) {
return this.uninstallEverywhere(extension, force);
}
return this.uninstallInServer(extension, server, force);
async uninstall(extension: ILocalExtension): Promise<void> {
const server = this.getServer(extension);
if (!server) {
return Promise.reject(`Invalid location ${extension.location.toString()}`);
}
return this.extensionManagementServerService.localExtensionManagementServer.extensionManagementService.uninstall(extension, force);
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, force?: boolean): Promise<void> {
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 = server === this.extensionManagementServerService.localExtensionManagementServer ? this.extensionManagementServerService.remoteExtensionManagementServer! : this.extensionManagementServerService.localExtensionManagementServer;
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 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;
}
@@ -133,25 +138,17 @@ export class MultiExtensionManagementService extends Disposable implements IExte
}
async install(vsix: URI): Promise<ILocalExtension> {
if (this.extensionManagementServerService.localExtensionManagementServer) {
return this.extensionManagementServerService.localExtensionManagementServer.extensionManagementService.install(vsix);
}
if (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);
}
return this.extensionManagementServerService.localExtensionManagementServer.extensionManagementService.install(vsix);
return Promise.reject('No Servers to Install');
}
async installFromGallery(gallery: IGalleryExtension): Promise<ILocalExtension> {
if (this.extensionManagementServerService.remoteExtensionManagementServer) {
if (this.extensionManagementServerService.localExtensionManagementServer && this.extensionManagementServerService.remoteExtensionManagementServer) {
const manifest = await this.extensionGalleryService.getManifest(gallery, CancellationToken.None);
if (manifest) {
if (isLanguagePackExtension(manifest)) {
@@ -168,16 +165,26 @@ export class MultiExtensionManagementService extends Disposable implements IExte
return Promise.reject(localize('Manifest is not found', "Installing Extension {0} failed: Manifest is not found.", gallery.displayName || gallery.name));
}
}
return this.extensionManagementServerService.localExtensionManagementServer.extensionManagementService.installFromGallery(gallery);
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[]> {
return this.extensionManagementServerService.localExtensionManagementServer.extensionManagementService.getExtensionsReport();
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);
}
}
registerSingleton(IExtensionManagementService, MultiExtensionManagementService);

View File

@@ -6,8 +6,9 @@
import { localize } from 'vs/nls';
import { Schemas } from 'vs/base/common/network';
import { URI } from 'vs/base/common/uri';
import { IExtensionManagementServer, IExtensionManagementServerService, IExtensionGalleryService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { ExtensionManagementChannelClient } from 'vs/platform/extensionManagement/node/extensionManagementIpc';
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';
@@ -17,6 +18,7 @@ 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';
@@ -26,6 +28,7 @@ export class ExtensionManagementServerService implements IExtensionManagementSer
readonly localExtensionManagementServer: IExtensionManagementServer;
readonly remoteExtensionManagementServer: IExtensionManagementServer | null = null;
readonly isSingleServer: boolean = false;
constructor(
@ISharedProcessService sharedProcessService: ISharedProcessService,
@@ -33,7 +36,8 @@ export class ExtensionManagementServerService implements IExtensionManagementSer
@IExtensionGalleryService galleryService: IExtensionGalleryService,
@IConfigurationService configurationService: IConfigurationService,
@IProductService productService: IProductService,
@ILogService logService: ILogService
@ILogService logService: ILogService,
@ILabelService labelService: ILabelService,
) {
const localExtensionManagementService = new ExtensionManagementChannelClient(sharedProcessService.getChannel('extensions'));
@@ -41,7 +45,10 @@ export class ExtensionManagementServerService implements IExtensionManagementSer
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, label: localize('remote', "Remote") };
this.remoteExtensionManagementServer = {
authority: remoteAgentConnection.remoteAuthority, extensionManagementService,
get label() { return labelService.getHostLabel(REMOTE_HOST_SCHEME, remoteAgentConnection!.remoteAuthority) || localize('remote', "Remote"); }
};
}
}

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 });
}

View File

@@ -5,7 +5,7 @@
import * as nls from 'vs/nls';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import { IExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { IExtensionEnablementService } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';

View File

@@ -10,7 +10,7 @@ import { Disposable } from 'vs/base/common/lifecycle';
import * as perf from 'vs/base/common/performance';
import { isEqualOrParent } from 'vs/base/common/resources';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import { IExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { IExtensionEnablementService } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
import { BetterMergeId } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';

View File

@@ -1,53 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { Event } from 'vs/base/common/event';
import { IRemoteConsoleLog } from 'vs/base/common/console';
export const IExtensionHostDebugService = createDecorator<IExtensionHostDebugService>('extensionHostDebugService');
export interface IAttachSessionEvent {
sessionId: string;
subId?: string;
port: number;
}
export interface ILogToSessionEvent {
sessionId: string;
log: IRemoteConsoleLog;
}
export interface ITerminateSessionEvent {
sessionId: string;
subId?: string;
}
export interface IReloadSessionEvent {
sessionId: string;
}
export interface ICloseSessionEvent {
sessionId: string;
}
export interface IExtensionHostDebugService {
_serviceBrand: any;
reload(sessionId: string): void;
onReload: Event<IReloadSessionEvent>;
close(sessionId: string): void;
onClose: Event<ICloseSessionEvent>;
attachSession(sessionId: string, port: number, subId?: string): void;
onAttachSession: Event<IAttachSessionEvent>;
logToSession(sessionId: string, log: IRemoteConsoleLog): void;
onLogToSession: Event<ILogToSessionEvent>;
terminateSession(sessionId: string, subId?: string): void;
onTerminateSession: Event<ITerminateSessionEvent>;
}

View File

@@ -8,7 +8,8 @@ import { Action } from 'vs/base/common/actions';
import { IDisposable, toDisposable, combinedDisposable } from 'vs/base/common/lifecycle';
import { URI } from 'vs/base/common/uri';
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
import { EnablementState, IExtensionEnablementService, IExtensionGalleryService, IExtensionIdentifier, IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { IExtensionGalleryService, IExtensionIdentifier, IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { IExtensionEnablementService, EnablementState } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { INotificationHandle, INotificationService, Severity } from 'vs/platform/notification/common/notification';
@@ -190,7 +191,7 @@ export class ExtensionUrlHandler implements IExtensionUrlHandler, IURLHandler {
return;
}
await this.extensionEnablementService.setEnablement([extension], EnablementState.Enabled);
await this.extensionEnablementService.setEnablement([extension], EnablementState.EnabledGlobally);
await this.reloadAndHandle(uri);
}
}

View File

@@ -24,7 +24,7 @@ import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle';
import { PersistentProtocol } from 'vs/base/parts/ipc/common/ipc.net';
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import { VSBuffer } from 'vs/base/common/buffer';
import { IExtensionHostDebugService } from 'vs/workbench/services/extensions/common/extensionHostDebug';
import { IExtensionHostDebugService } from 'vs/platform/debug/common/extensionHostDebug';
import { IProductService } from 'vs/platform/product/common/product';
import { ISignService } from 'vs/platform/sign/common/sign';

View File

@@ -15,7 +15,7 @@ import { originalFSPath } from 'vs/base/common/resources';
import { URI } from 'vs/base/common/uri';
import * as pfs from 'vs/base/node/pfs';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { IExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { IExtensionEnablementService } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
import { BUILTIN_MANIFEST_CACHE_FILE, MANIFEST_CACHE_FOLDER, USER_MANIFEST_CACHE_FILE, ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import pkg from 'vs/platform/product/node/package';
import product from 'vs/platform/product/node/product';

View File

@@ -35,7 +35,7 @@ import { withNullAsUndefined } from 'vs/base/common/types';
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import { parseExtensionDevOptions } from '../common/extensionDevOptions';
import { VSBuffer } from 'vs/base/common/buffer';
import { IExtensionHostDebugService } from 'vs/workbench/services/extensions/common/extensionHostDebug';
import { IExtensionHostDebugService } from 'vs/platform/debug/common/extensionHostDebug';
import { IExtensionHostStarter } from 'vs/workbench/services/extensions/common/extensions';
import { isEqualOrParent } from 'vs/base/common/resources';

View File

@@ -3,128 +3,17 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Event, Emitter } from 'vs/base/common/event';
import { IWindowService } from 'vs/platform/windows/common/windows';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { IExtensionHostDebugService, IAttachSessionEvent, ITerminateSessionEvent, ILogToSessionEvent, IReloadSessionEvent, ICloseSessionEvent } from 'vs/workbench/services/extensions/common/extensionHostDebug';
import { IRemoteConsoleLog } from 'vs/base/common/console';
import { ipcRenderer as ipc } from 'electron';
import { IExtensionHostDebugService } from 'vs/platform/debug/common/extensionHostDebug';
import { IMainProcessService } from 'vs/platform/ipc/electron-browser/mainProcessService';
import { ExtensionHostDebugChannelClient, ExtensionHostDebugBroadcastChannel } from 'vs/platform/debug/common/extensionHostDebugIpc';
interface IReloadBroadcast extends IReloadSessionEvent {
type: 'vscode:extensionReload';
}
interface IAttachSessionBroadcast extends IAttachSessionEvent {
type: 'vscode:extensionAttach';
}
interface ICloseBroadcast extends ICloseSessionEvent {
type: 'vscode:extensionCloseExtensionHost';
}
interface ILogToSessionBroadcast extends ILogToSessionEvent {
type: 'vscode:extensionLog';
}
interface ITerminateSessionBroadcast extends ITerminateSessionEvent {
type: 'vscode:extensionTerminate';
}
const CHANNEL = 'vscode:extensionHostDebug';
class ExtensionHostDebugService implements IExtensionHostDebugService {
_serviceBrand: any;
private windowId: number;
private readonly _onReload = new Emitter<IReloadSessionEvent>();
private readonly _onClose = new Emitter<ICloseSessionEvent>();
private readonly _onAttachSession = new Emitter<IAttachSessionEvent>();
private readonly _onLogToSession = new Emitter<ILogToSessionEvent>();
private readonly _onTerminateSession = new Emitter<ITerminateSessionEvent>();
export class ExtensionHostDebugService extends ExtensionHostDebugChannelClient {
constructor(
@IWindowService readonly windowService: IWindowService,
@IMainProcessService readonly windowService: IMainProcessService,
) {
this.windowId = windowService.windowId;
ipc.on(CHANNEL, (_: unknown, broadcast: IReloadBroadcast | ICloseBroadcast | IAttachSessionBroadcast | ILogToSessionBroadcast | ITerminateSessionBroadcast) => {
switch (broadcast.type) {
case 'vscode:extensionReload':
this._onReload.fire(broadcast);
break;
case 'vscode:extensionCloseExtensionHost':
this._onClose.fire(broadcast);
break;
case 'vscode:extensionAttach':
this._onAttachSession.fire(broadcast);
break;
case 'vscode:extensionLog':
this._onLogToSession.fire(broadcast);
break;
case 'vscode:extensionTerminate':
this._onTerminateSession.fire(broadcast);
break;
}
});
}
reload(sessionId: string): void {
ipc.send(CHANNEL, this.windowId, <IReloadBroadcast>{
type: 'vscode:extensionReload',
sessionId
});
}
get onReload(): Event<IReloadSessionEvent> {
return this._onReload.event;
}
close(sessionId: string): void {
ipc.send(CHANNEL, this.windowId, <ICloseBroadcast>{
type: 'vscode:extensionCloseExtensionHost',
sessionId
});
}
get onClose(): Event<ICloseSessionEvent> {
return this._onClose.event;
}
attachSession(sessionId: string, port: number, subId?: string): void {
ipc.send(CHANNEL, this.windowId, <IAttachSessionBroadcast>{
type: 'vscode:extensionAttach',
sessionId,
port,
subId
});
}
get onAttachSession(): Event<IAttachSessionEvent> {
return this._onAttachSession.event;
}
logToSession(sessionId: string, log: IRemoteConsoleLog): void {
ipc.send(CHANNEL, this.windowId, <ILogToSessionBroadcast>{
type: 'vscode:extensionLog',
sessionId,
log
});
}
get onLogToSession(): Event<ILogToSessionEvent> {
return this._onLogToSession.event;
}
terminateSession(sessionId: string, subId?: string): void {
ipc.send(CHANNEL, this.windowId, <ITerminateSessionBroadcast>{
type: 'vscode:extensionTerminate',
sessionId,
subId
});
}
get onTerminateSession(): Event<ITerminateSessionEvent> {
return this._onTerminateSession.event;
super(windowService.getChannel(ExtensionHostDebugBroadcastChannel.ChannelName));
}
}

View File

@@ -14,7 +14,8 @@ import * as path from 'vs/base/common/path';
import { runWhenIdle } from 'vs/base/common/async';
import { URI } from 'vs/base/common/uri';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import { IExtensionEnablementService, IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { IExtensionEnablementService } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IInitDataProvider, RemoteExtensionHostClient } from 'vs/workbench/services/extensions/common/remoteExtensionHostClient';
import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';

View File

@@ -18,7 +18,7 @@ import { CancellationToken } from 'vs/base/common/cancellation';
import { localize } from 'vs/nls';
import { IProductService } from 'vs/platform/product/common/product';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ExtensionManagementChannelClient } from 'vs/platform/extensionManagement/node/extensionManagementIpc';
import { ExtensionManagementChannelClient } from 'vs/platform/extensionManagement/common/extensionManagementIpc';
export class RemoteExtensionManagementChannelClient extends ExtensionManagementChannelClient {

View File

@@ -5,7 +5,7 @@
import * as nls from 'vs/nls';
import * as path from 'vs/base/common/path';
import * as semver from 'semver';
import * as semver from 'semver-umd';
import * as json from 'vs/base/common/json';
import * as arrays from 'vs/base/common/arrays';
import { getParseErrorMessage } from 'vs/base/common/jsonErrorMessages';

View File

@@ -0,0 +1,170 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ITelemetryService, ITelemetryInfo, ITelemetryData } from 'vs/platform/telemetry/common/telemetry';
import { NullTelemetryService, combinedAppender, LogAppender, ITelemetryAppender, validateTelemetryData } from 'vs/platform/telemetry/common/telemetryUtils';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { Disposable } from 'vs/base/common/lifecycle';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import { ILogService } from 'vs/platform/log/common/log';
import { TelemetryService as BaseTelemetryService, ITelemetryServiceConfig } from 'vs/platform/telemetry/common/telemetryService';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { ClassifiedEvent, StrictPropertyCheck, GDPRClassification } from 'vs/platform/telemetry/common/gdprTypings';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { resolveWorkbenchCommonProperties } from 'vs/platform/telemetry/browser/workbenchCommonProperties';
import { IProductService } from 'vs/platform/product/common/product';
interface IConfig {
instrumentationKey?: string;
endpointUrl?: string;
emitLineDelimitedJson?: boolean;
accountId?: string;
sessionRenewalMs?: number;
sessionExpirationMs?: number;
maxBatchSizeInBytes?: number;
maxBatchInterval?: number;
enableDebug?: boolean;
disableExceptionTracking?: boolean;
disableTelemetry?: boolean;
verboseLogging?: boolean;
diagnosticLogInterval?: number;
samplingPercentage?: number;
autoTrackPageVisitTime?: boolean;
disableAjaxTracking?: boolean;
overridePageViewDuration?: boolean;
maxAjaxCallsPerView?: number;
disableDataLossAnalysis?: boolean;
disableCorrelationHeaders?: boolean;
correlationHeaderExcludedDomains?: string[];
disableFlushOnBeforeUnload?: boolean;
enableSessionStorageBuffer?: boolean;
isCookieUseDisabled?: boolean;
cookieDomain?: string;
isRetryDisabled?: boolean;
url?: string;
isStorageUseDisabled?: boolean;
isBeaconApiDisabled?: boolean;
sdkExtension?: string;
isBrowserLinkTrackingEnabled?: boolean;
appId?: string;
enableCorsCorrelation?: boolean;
}
declare class Microsoft {
public static ApplicationInsights: {
Initialization: {
new(init: { config: IConfig }): AppInsights;
}
};
}
declare interface IAppInsightsClient {
config: IConfig;
/** Log a user action or other occurrence. */
trackEvent: (name: string, properties?: { [key: string]: string }, measurements?: { [key: string]: number }) => void;
/** Immediately send all queued telemetry. Synchronous. */
flush(): void;
}
interface AppInsights {
loadAppInsights: () => IAppInsightsClient;
}
export class WebTelemetryAppender implements ITelemetryAppender {
private _aiClient?: IAppInsightsClient;
constructor(aiKey: string, private _logService: ILogService) {
const initConfig = {
config: {
instrumentationKey: aiKey,
endpointUrl: 'https://vortex.data.microsoft.com/collect/v1',
emitLineDelimitedJson: true,
autoTrackPageVisitTime: false,
disableExceptionTracking: true,
disableAjaxTracking: true
}
};
const appInsights = new Microsoft.ApplicationInsights.Initialization(initConfig);
this._aiClient = appInsights.loadAppInsights();
}
log(eventName: string, data: any): void {
if (!this._aiClient) {
return;
}
data = validateTelemetryData(data);
this._logService.trace(`telemetry/${eventName}`, data);
this._aiClient.trackEvent('monacoworkbench/' + eventName, data.properties, data.measurements);
}
dispose(): Promise<any> | undefined {
if (this._aiClient) {
return new Promise(resolve => {
this._aiClient!.flush();
this._aiClient = undefined;
resolve(undefined);
});
}
return undefined;
}
}
export class TelemetryService extends Disposable implements ITelemetryService {
_serviceBrand: any;
private impl: ITelemetryService;
constructor(
@IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService,
@ILogService logService: ILogService,
@IConfigurationService configurationService: IConfigurationService,
@IStorageService storageService: IStorageService,
@IProductService productService: IProductService
) {
super();
const aiKey = productService.aiConfig && productService.aiConfig.asimovKey;
if (!environmentService.isExtensionDevelopment && !environmentService.args['disable-telemetry'] && !!productService.enableTelemetry && !!aiKey) {
const config: ITelemetryServiceConfig = {
appender: combinedAppender(new WebTelemetryAppender(aiKey, logService), new LogAppender(logService)),
commonProperties: resolveWorkbenchCommonProperties(storageService, productService.commit, productService.version, environmentService.configuration.machineId, environmentService.configuration.remoteAuthority),
piiPaths: [environmentService.appRoot]
};
this.impl = this._register(new BaseTelemetryService(config, configurationService));
} else {
this.impl = NullTelemetryService;
}
}
setEnabled(value: boolean): void {
return this.impl.setEnabled(value);
}
get isOptedIn(): boolean {
return this.impl.isOptedIn;
}
publicLog(eventName: string, data?: ITelemetryData, anonymizeFilePaths?: boolean): Promise<void> {
return this.impl.publicLog(eventName, data, anonymizeFilePaths);
}
publicLog2<E extends ClassifiedEvent<T> = never, T extends GDPRClassification<T> = never>(eventName: string, data?: StrictPropertyCheck<T, E>, anonymizeFilePaths?: boolean) {
return this.publicLog(eventName, data as ITelemetryData, anonymizeFilePaths);
}
getTelemetryInfo(): Promise<ITelemetryInfo> {
return this.impl.getTelemetryInfo();
}
}
registerSingleton(ITelemetryService, TelemetryService);

View File

@@ -39,7 +39,7 @@ export class TelemetryService extends Disposable implements ITelemetryService {
const config: ITelemetryServiceConfig = {
appender: combinedAppender(new TelemetryAppenderClient(channel), new LogAppender(logService)),
commonProperties: resolveWorkbenchCommonProperties(storageService, productService.commit, productService.version, environmentService.configuration.machineId, environmentService.installSourcePath, environmentService.configuration.remoteAuthority),
piiPaths: [environmentService.appRoot, environmentService.extensionsPath]
piiPaths: environmentService.extensionsPath ? [environmentService.appRoot, environmentService.extensionsPath] : [environmentService.appRoot]
};
this.impl = this._register(new BaseTelemetryService(config, configurationService));