diff --git a/src/vs/platform/extensionManagement/common/abstractExtensionManagementService.ts b/src/vs/platform/extensionManagement/common/abstractExtensionManagementService.ts index ea58b5a4aba..117e765ce8b 100644 --- a/src/vs/platform/extensionManagement/common/abstractExtensionManagementService.ts +++ b/src/vs/platform/extensionManagement/common/abstractExtensionManagementService.ts @@ -14,7 +14,7 @@ import { URI } from 'vs/base/common/uri'; import * as nls from 'vs/nls'; import { DidUninstallExtensionEvent, ExtensionManagementError, IExtensionGalleryService, IExtensionIdentifier, IExtensionManagementParticipant, IExtensionManagementService, IGalleryExtension, IGalleryMetadata, ILocalExtension, InstallExtensionEvent, InstallExtensionResult, InstallOperation, InstallOptions, - InstallVSIXOptions, IReportedExtension, StatisticType, UninstallOptions, TargetPlatform, isTargetPlatformCompatible, TargetPlatformToString, ExtensionManagementErrorCode + InstallVSIXOptions, IExtensionsControlManifest, StatisticType, UninstallOptions, TargetPlatform, isTargetPlatformCompatible, TargetPlatformToString, ExtensionManagementErrorCode } from 'vs/platform/extensionManagement/common/extensionManagement'; import { areSameExtensions, ExtensionIdentifierWithVersion, getGalleryExtensionTelemetryData, getLocalExtensionTelemetryData, getMaliciousExtensionsSet } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; import { ExtensionType, IExtensionManifest } from 'vs/platform/extensions/common/extensions'; @@ -46,7 +46,7 @@ export abstract class AbstractExtensionManagementService extends Disposable impl declare readonly _serviceBrand: undefined; - private reportedExtensions: Promise | undefined; + private extensionsControlManifest: Promise | undefined; private lastReportTimestamp = 0; private readonly installingExtensions = new Map(); private readonly uninstallingExtensions = new Map(); @@ -120,15 +120,15 @@ export abstract class AbstractExtensionManagementService extends Disposable impl await this.installFromGallery(galleryExtension); } - getExtensionsReport(): Promise { + getExtensionsControlManifest(): Promise { const now = new Date().getTime(); - if (!this.reportedExtensions || now - this.lastReportTimestamp > 1000 * 60 * 5) { // 5 minute cache freshness - this.reportedExtensions = this.updateReportCache(); + if (!this.extensionsControlManifest || now - this.lastReportTimestamp > 1000 * 60 * 5) { // 5 minute cache freshness + this.extensionsControlManifest = this.updateControlCache(); this.lastReportTimestamp = now; } - return this.reportedExtensions; + return this.extensionsControlManifest; } registerParticipant(participant: IExtensionManagementParticipant): void { @@ -403,7 +403,7 @@ export abstract class AbstractExtensionManagementService extends Disposable impl } private async isMalicious(extension: IGalleryExtension): Promise { - const report = await this.getExtensionsReport(); + const report = await this.getExtensionsControlManifest(); return getMaliciousExtensionsSet(report).has(extension.identifier.id); } @@ -579,15 +579,15 @@ export abstract class AbstractExtensionManagementService extends Disposable impl return galleryResult.firstPage[0]; } - private async updateReportCache(): Promise { + private async updateControlCache(): Promise { try { this.logService.trace('ExtensionManagementService.refreshReportedCache'); - const result = await this.galleryService.getExtensionsReport(); - this.logService.trace(`ExtensionManagementService.refreshReportedCache - got ${result.length} reported extensions from service`); - return result; + const manifest = await this.galleryService.getExtensionsControlManifest(); + this.logService.trace(`ExtensionManagementService.refreshControlCache`, manifest); + return manifest; } catch (err) { - this.logService.trace('ExtensionManagementService.refreshReportedCache - failed to get extension report'); - return []; + this.logService.trace('ExtensionManagementService.refreshControlCache - failed to get extension control manifest'); + return { malicious: [] }; } } diff --git a/src/vs/platform/extensionManagement/common/extensionGalleryService.ts b/src/vs/platform/extensionManagement/common/extensionGalleryService.ts index 02de3658557..8585f92a884 100644 --- a/src/vs/platform/extensionManagement/common/extensionGalleryService.ts +++ b/src/vs/platform/extensionManagement/common/extensionGalleryService.ts @@ -15,7 +15,7 @@ import { URI } from 'vs/base/common/uri'; import { IHeaders, IRequestContext, IRequestOptions } from 'vs/base/parts/request/common/request'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; -import { DefaultIconPath, getFallbackTargetPlarforms, getTargetPlatform, IExtensionGalleryService, IExtensionIdentifier, IExtensionIdentifierWithVersion, IGalleryExtension, IGalleryExtensionAsset, IGalleryExtensionAssets, IGalleryExtensionVersion, InstallOperation, IQueryOptions, IReportedExtension, isIExtensionIdentifier, isNotWebExtensionInWebTargetPlatform, isTargetPlatformCompatible, ITranslation, SortBy, SortOrder, StatisticType, TargetPlatform, toTargetPlatform, WEB_EXTENSION_TAG } from 'vs/platform/extensionManagement/common/extensionManagement'; +import { DefaultIconPath, getFallbackTargetPlarforms, getTargetPlatform, IExtensionGalleryService, IExtensionIdentifier, IExtensionIdentifierWithVersion, IGalleryExtension, IGalleryExtensionAsset, IGalleryExtensionAssets, IGalleryExtensionVersion, InstallOperation, IQueryOptions, IExtensionsControlManifest, isIExtensionIdentifier, isNotWebExtensionInWebTargetPlatform, isTargetPlatformCompatible, ITranslation, SortBy, SortOrder, StatisticType, TargetPlatform, toTargetPlatform, WEB_EXTENSION_TAG } from 'vs/platform/extensionManagement/common/extensionManagement'; import { adoptToGalleryExtensionId, areSameExtensions, getGalleryExtensionId, getGalleryExtensionTelemetryData } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; import { IExtensionManifest } from 'vs/platform/extensions/common/extensions'; import { isEngineValid } from 'vs/platform/extensions/common/extensionValidator'; @@ -438,7 +438,7 @@ function toExtension(galleryExtension: IRawGalleryExtension, version: IRawGaller }; } -interface IRawExtensionsReport { +interface IRawExtensionsControlManifest { malicious: string[]; slow: string[]; } @@ -942,13 +942,13 @@ abstract class AbstractExtensionGalleryService implements IExtensionGalleryServi return engine; } - async getExtensionsReport(): Promise { + async getExtensionsControlManifest(): Promise { if (!this.isEnabled()) { throw new Error('No extension gallery service configured.'); } if (!this.extensionsControlUrl) { - return []; + return { malicious: [] }; } const context = await this.requestService.request({ type: 'GET', url: this.extensionsControlUrl }, CancellationToken.None); @@ -956,18 +956,16 @@ abstract class AbstractExtensionGalleryService implements IExtensionGalleryServi throw new Error('Could not get extensions report.'); } - const result = await asJson(context); - const map = new Map(); + const result = await asJson(context); + const malicious: IExtensionIdentifier[] = []; if (result) { for (const id of result.malicious) { - const ext = map.get(id) || { id: { id }, malicious: true, slow: false }; - ext.malicious = true; - map.set(id, ext); + malicious.push({ id }); } } - return [...map.values()]; + return { malicious }; } } diff --git a/src/vs/platform/extensionManagement/common/extensionManagement.ts b/src/vs/platform/extensionManagement/common/extensionManagement.ts index 3d7442a3423..3964f4a6a95 100644 --- a/src/vs/platform/extensionManagement/common/extensionManagement.ts +++ b/src/vs/platform/extensionManagement/common/extensionManagement.ts @@ -310,9 +310,8 @@ export const enum StatisticType { Uninstall = 'uninstall' } -export interface IReportedExtension { - id: IExtensionIdentifier; - malicious: boolean; +export interface IExtensionsControlManifest { + malicious: IExtensionIdentifier[]; } export const enum InstallOperation { @@ -338,7 +337,7 @@ export interface IExtensionGalleryService { getManifest(extension: IGalleryExtension, token: CancellationToken): Promise; getChangelog(extension: IGalleryExtension, token: CancellationToken): Promise; getCoreTranslation(extension: IGalleryExtension, languageId: string): Promise; - getExtensionsReport(): Promise; + getExtensionsControlManifest(): Promise; isExtensionCompatible(extension: IGalleryExtension, includePreRelease: boolean, targetPlatform: TargetPlatform): Promise; getCompatibleExtension(extension: IGalleryExtension, includePreRelease: boolean, targetPlatform: TargetPlatform): Promise; getCompatibleExtension(id: IExtensionIdentifier, includePreRelease: boolean, targetPlatform: TargetPlatform): Promise; @@ -412,7 +411,7 @@ export interface IExtensionManagementService { uninstall(extension: ILocalExtension, options?: UninstallOptions): Promise; reinstallFromGallery(extension: ILocalExtension): Promise; getInstalled(type?: ExtensionType, donotIgnoreInvalidExtensions?: boolean): Promise; - getExtensionsReport(): Promise; + getExtensionsControlManifest(): Promise; updateMetadata(local: ILocalExtension, metadata: IGalleryMetadata): Promise; updateExtensionScope(local: ILocalExtension, isMachineScoped: boolean): Promise; diff --git a/src/vs/platform/extensionManagement/common/extensionManagementIpc.ts b/src/vs/platform/extensionManagement/common/extensionManagementIpc.ts index 5d92423d690..3141cf69855 100644 --- a/src/vs/platform/extensionManagement/common/extensionManagementIpc.ts +++ b/src/vs/platform/extensionManagement/common/extensionManagementIpc.ts @@ -9,7 +9,7 @@ import { cloneAndChange } from 'vs/base/common/objects'; import { URI, UriComponents } from 'vs/base/common/uri'; import { DefaultURITransformer, IURITransformer, transformAndReviveIncomingURIs } from 'vs/base/common/uriIpc'; import { IChannel, IServerChannel } from 'vs/base/parts/ipc/common/ipc'; -import { DidUninstallExtensionEvent, IExtensionIdentifier, IExtensionManagementService, IExtensionTipsService, IGalleryExtension, IGalleryMetadata, ILocalExtension, InstallExtensionEvent, InstallExtensionResult, InstallOptions, InstallVSIXOptions, IReportedExtension, isTargetPlatformCompatible, TargetPlatform, UninstallOptions } from 'vs/platform/extensionManagement/common/extensionManagement'; +import { DidUninstallExtensionEvent, IExtensionIdentifier, IExtensionManagementService, IExtensionTipsService, IGalleryExtension, IGalleryMetadata, ILocalExtension, InstallExtensionEvent, InstallExtensionResult, InstallOptions, InstallVSIXOptions, IExtensionsControlManifest, isTargetPlatformCompatible, TargetPlatform, UninstallOptions } from 'vs/platform/extensionManagement/common/extensionManagement'; import { ExtensionType, IExtensionManifest } from 'vs/platform/extensions/common/extensions'; function transformIncomingURI(uri: UriComponents, transformer: IURITransformer | null): URI { @@ -72,7 +72,7 @@ export class ExtensionManagementChannel implements IServerChannel { case 'getInstalled': return this.service.getInstalled(args[0]).then(extensions => extensions.map(e => transformOutgoingExtension(e, uriTransformer))); case 'updateMetadata': return this.service.updateMetadata(transformIncomingExtension(args[0], uriTransformer), args[1]).then(e => transformOutgoingExtension(e, uriTransformer)); case 'updateExtensionScope': return this.service.updateExtensionScope(transformIncomingExtension(args[0], uriTransformer), args[1]).then(e => transformOutgoingExtension(e, uriTransformer)); - case 'getExtensionsReport': return this.service.getExtensionsReport(); + case 'getExtensionsControlManifest': return this.service.getExtensionsControlManifest(); } throw new Error('Invalid call'); @@ -169,8 +169,8 @@ export class ExtensionManagementChannelClient extends Disposable implements IExt .then(extension => transformIncomingExtension(extension, null)); } - getExtensionsReport(): Promise { - return Promise.resolve(this.channel.call('getExtensionsReport')); + getExtensionsControlManifest(): Promise { + return Promise.resolve(this.channel.call('getExtensionsControlManifest')); } registerParticipant() { throw new Error('Not Supported'); } diff --git a/src/vs/platform/extensionManagement/common/extensionManagementUtil.ts b/src/vs/platform/extensionManagement/common/extensionManagementUtil.ts index dcf1a84bac3..e82c61f4749 100644 --- a/src/vs/platform/extensionManagement/common/extensionManagementUtil.ts +++ b/src/vs/platform/extensionManagement/common/extensionManagementUtil.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { compareIgnoreCase } from 'vs/base/common/strings'; -import { IExtensionIdentifier, IExtensionIdentifierWithVersion, IGalleryExtension, ILocalExtension, IReportedExtension } from 'vs/platform/extensionManagement/common/extensionManagement'; +import { IExtensionIdentifier, IExtensionIdentifierWithVersion, IGalleryExtension, ILocalExtension, IExtensionsControlManifest } from 'vs/platform/extensionManagement/common/extensionManagement'; import { ExtensionIdentifier, IExtension } from 'vs/platform/extensions/common/extensions'; export function areSameExtensions(a: IExtensionIdentifier, b: IExtensionIdentifier): boolean { @@ -117,12 +117,12 @@ export function getGalleryExtensionTelemetryData(extension: IGalleryExtension): export const BetterMergeId = new ExtensionIdentifier('pprice.better-merge'); -export function getMaliciousExtensionsSet(report: IReportedExtension[]): Set { +export function getMaliciousExtensionsSet(manifest: IExtensionsControlManifest): Set { const result = new Set(); - for (const extension of report) { - if (extension.malicious) { - result.add(extension.id.id); + if (manifest.malicious) { + for (const extension of manifest.malicious) { + result.add(extension.id); } } diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsViewlet.ts b/src/vs/workbench/contrib/extensions/browser/extensionsViewlet.ts index de0fad38d21..acf81dc6bfe 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsViewlet.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsViewlet.ts @@ -825,7 +825,7 @@ export class MaliciousExtensionChecker implements IWorkbenchContribution { } private checkForMaliciousExtensions(): Promise { - return this.extensionsManagementService.getExtensionsReport().then(report => { + return this.extensionsManagementService.getExtensionsControlManifest().then(report => { const maliciousSet = getMaliciousExtensionsSet(report); return this.extensionsManagementService.getInstalled(ExtensionType.User).then(installed => { diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts b/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts index 7e33ad4a640..9d9dff33d8e 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts @@ -749,7 +749,7 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension options.text = options.text ? this.resolveQueryText(options.text) : options.text; options.includePreRelease = isUndefined(options.includePreRelease) ? this.preferPreReleases : options.includePreRelease; - const report = await this.extensionManagementService.getExtensionsReport(); + const report = await this.extensionManagementService.getExtensionsControlManifest(); const maliciousSet = getMaliciousExtensionsSet(report); try { const result = await this.galleryService.query(options, token); diff --git a/src/vs/workbench/contrib/extensions/test/electron-browser/extensionRecommendationsService.test.ts b/src/vs/workbench/contrib/extensions/test/electron-browser/extensionRecommendationsService.test.ts index d6966d438b3..7f7e90d512e 100644 --- a/src/vs/workbench/contrib/extensions/test/electron-browser/extensionRecommendationsService.test.ts +++ b/src/vs/workbench/contrib/extensions/test/electron-browser/extensionRecommendationsService.test.ts @@ -218,7 +218,7 @@ suite('ExtensionRecommendationsService Test', () => { onDidUninstallExtension: didUninstallEvent.event, async getInstalled() { return []; }, async canInstall() { return true; }, - async getExtensionsReport() { return []; }, + async getExtensionsControlManifest() { return { malicious: [] }; }, async getTargetPlatform() { return getTargetPlatform(platform, arch); } }); instantiationService.stub(IExtensionService, >{ diff --git a/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsActions.test.ts b/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsActions.test.ts index d35aa41bb4a..d67171bd069 100644 --- a/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsActions.test.ts +++ b/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsActions.test.ts @@ -101,7 +101,7 @@ async function setupTest() { onUninstallExtension: uninstallEvent.event, onDidUninstallExtension: didUninstallEvent.event, async getInstalled() { return []; }, - async getExtensionsReport() { return []; }, + async getExtensionsControlManifest() { return { malicious: [] }; }, async updateMetadata(local: ILocalExtension, metadata: IGalleryMetadata) { local.identifier.uuid = metadata.id; local.publisherDisplayName = metadata.publisherDisplayName; diff --git a/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsViews.test.ts b/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsViews.test.ts index b7edf47f474..3b08938208a 100644 --- a/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsViews.test.ts +++ b/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsViews.test.ts @@ -98,7 +98,7 @@ suite('ExtensionsListView Tests', () => { onDidUninstallExtension: didUninstallEvent.event, async getInstalled() { return []; }, async canInstall() { return true; }, - async getExtensionsReport() { return []; }, + async getExtensionsControlManifest() { return { malicious: [] }; }, async getTargetPlatform() { return getTargetPlatform(platform, arch); } }); instantiationService.stub(IRemoteAgentService, RemoteAgentService); @@ -163,7 +163,7 @@ suite('ExtensionsListView Tests', () => { setup(async () => { instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [localEnabledTheme, localEnabledLanguage, localRandom, localDisabledTheme, localDisabledLanguage, builtInTheme, builtInBasic]); - instantiationService.stubPromise(IExtensionManagementService, 'getExtensionsReport', []); + instantiationService.stubPromise(IExtensionManagementService, 'getExtensgetExtensionsControlManifestionsReport', {}); instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage()); instantiationService.stubPromise(IExperimentService, 'getExperimentsByType', []); diff --git a/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsWorkbenchService.test.ts b/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsWorkbenchService.test.ts index c3a706d67cd..4b4320e05fc 100644 --- a/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsWorkbenchService.test.ts +++ b/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsWorkbenchService.test.ts @@ -94,7 +94,7 @@ suite('ExtensionsWorkbenchServiceTest', () => { onUninstallExtension: uninstallEvent.event, onDidUninstallExtension: didUninstallEvent.event, async getInstalled() { return []; }, - async getExtensionsReport() { return []; }, + async getExtensionsControlManifest() { return { malicious: [] }; }, async updateMetadata(local: ILocalExtension, metadata: IGalleryMetadata) { local.identifier.uuid = metadata.id; local.publisherDisplayName = metadata.publisherDisplayName; diff --git a/src/vs/workbench/services/extensionManagement/common/extensionManagementService.ts b/src/vs/workbench/services/extensionManagement/common/extensionManagementService.ts index 004a6db0ce0..2f61cd1075d 100644 --- a/src/vs/workbench/services/extensionManagement/common/extensionManagementService.ts +++ b/src/vs/workbench/services/extensionManagement/common/extensionManagementService.ts @@ -5,7 +5,7 @@ import { Event, EventMultiplexer } from 'vs/base/common/event'; import { - ILocalExtension, IGalleryExtension, IExtensionIdentifier, IReportedExtension, IGalleryMetadata, IExtensionGalleryService, InstallOptions, UninstallOptions, InstallVSIXOptions, InstallExtensionResult, TargetPlatform, ExtensionManagementError, ExtensionManagementErrorCode + ILocalExtension, IGalleryExtension, IExtensionIdentifier, IExtensionsControlManifest, IGalleryMetadata, IExtensionGalleryService, InstallOptions, UninstallOptions, InstallVSIXOptions, InstallExtensionResult, TargetPlatform, ExtensionManagementError, ExtensionManagementErrorCode } from 'vs/platform/extensionManagement/common/extensionManagement'; import { DidUninstallExtensionOnServerEvent, IExtensionManagementServer, IExtensionManagementServerService, InstallExtensionOnServerEvent, IWorkbenchExtensionManagementService, UninstallExtensionOnServerEvent } from 'vs/workbench/services/extensionManagement/common/extensionManagement'; import { ExtensionType, isLanguagePackExtension, IExtensionManifest, getWorkspaceSupportTypeMessage } from 'vs/platform/extensions/common/extensions'; @@ -369,14 +369,17 @@ export class ExtensionManagementService extends Disposable implements IWorkbench return false; } - getExtensionsReport(): Promise { + getExtensionsControlManifest(): Promise { if (this.extensionManagementServerService.localExtensionManagementServer) { - return this.extensionManagementServerService.localExtensionManagementServer.extensionManagementService.getExtensionsReport(); + return this.extensionManagementServerService.localExtensionManagementServer.extensionManagementService.getExtensionsControlManifest(); } if (this.extensionManagementServerService.remoteExtensionManagementServer) { - return this.extensionManagementServerService.remoteExtensionManagementServer.extensionManagementService.getExtensionsReport(); + return this.extensionManagementServerService.remoteExtensionManagementServer.extensionManagementService.getExtensionsControlManifest(); } - return Promise.resolve([]); + if (this.extensionManagementServerService.webExtensionManagementServer) { + return this.extensionManagementServerService.webExtensionManagementServer.extensionManagementService.getExtensionsControlManifest(); + } + return Promise.resolve({ malicious: [] }); } private getServer(extension: ILocalExtension): IExtensionManagementServer | null {