From 7afa7684187228e129e6cbaf92ce2dc1c3eb6e11 Mon Sep 17 00:00:00 2001 From: Oliver Lin Date: Sat, 14 Nov 2026 14:37:23 +0800 Subject: [PATCH] feat: report extension compatibility version to Marketplace Add support for configuring a Marketplace extensions gallery in `product.json` and introduce an optional `extensionCompatibilityVersion` that forks can set to report an upstream VS Code version to the extension Marketplace while keeping their own branding version for `engines.vscode` checks. - Add `extensionCompatibilityVersion` to `IProductConfiguration` - Add helper to derive the compatibility product version - Use it when resolving compatible extension versions for install/update - Add `extensionsGallery` configuration to `product.json` - Relax the hygiene check that previously forbade `extensionsGallery` --- build/hygiene.ts | 7 +--- product.json | 35 +++++++++++++++++++ src/vs/base/common/product.ts | 6 ++++ .../abstractExtensionManagementService.ts | 5 +-- .../common/extensionGalleryService.ts | 31 ++++++---------- .../common/extensionManagement.ts | 13 +++++++ .../common/extensionsScannerService.ts | 7 ++-- .../node/extensionManagementService.ts | 7 ++-- .../browser/extensionsWorkbenchService.ts | 7 ++-- .../browser/webExtensionsScannerService.ts | 4 +-- .../extensionGalleryManifestService.ts | 3 +- .../browser/webWorkerExtensionHost.ts | 2 +- .../extensions/common/remoteExtensionHost.ts | 2 +- .../localProcessExtensionHost.ts | 2 +- 14 files changed, 86 insertions(+), 45 deletions(-) diff --git a/build/hygiene.ts b/build/hygiene.ts index 9a27171859ca..573514ae5c63 100644 --- a/build/hygiene.ts +++ b/build/hygiene.ts @@ -90,12 +90,7 @@ export function hygiene(some: NodeJS.ReadWriteStream | string[] | undefined, run let errorCount = 0; const productJson = es.through(function (file: VinylFile) { - const product = JSON.parse(file.contents!.toString('utf8')); - - if (product.extensionsGallery) { - console.error(`product.json: Contains 'extensionsGallery'`); - errorCount++; - } + JSON.parse(file.contents!.toString('utf8')); this.emit('data', file); }); diff --git a/product.json b/product.json index 5dcc29d84003..937eefd31487 100644 --- a/product.json +++ b/product.json @@ -2,6 +2,7 @@ "nameShort": "BlockIDE", "nameLong": "BlockIDE", "applicationName": "blockide", + "extensionCompatibilityVersion": "1.145.2", "dataFolderName": ".blockide", "sharedDataFolderName": ".blockide-shared", "win32MutexName": "blockide", @@ -245,6 +246,40 @@ "builtInExtensionsEnabledWithAutoUpdates": [ "GitHub.copilot-chat" ], + "extensionsGallery": { + "nlsBaseUrl": "https://www.vscode-unpkg.net/_lp/", + "serviceUrl": "https://marketplace.visualstudio.com/_apis/public/gallery", + "itemUrl": "https://marketplace.visualstudio.com/items", + "publisherUrl": "https://marketplace.visualstudio.com/publishers", + "resourceUrlTemplate": "https://{publisher}.vscode-unpkg.net/{publisher}/{name}/{version}/{path}", + "extensionUrlTemplate": "https://www.vscode-unpkg.net/_gallery/{publisher}/{name}/latest", + "controlUrl": "https://main.vscode-cdn.net/extensions/marketplace.json", + "mcpUrl": "https://main.vscode-cdn.net/mcp/servers.json", + "accessSKUs": [ + "copilot_enterprise_seat", + "copilot_enterprise_seat_quota", + "copilot_enterprise_seat_multi_quota", + "copilot_enterprise_seat_assignment", + "copilot_enterprise_seat_assignment_quota", + "copilot_enterprise_seat_assignment_multi_quota", + "copilot_enterprise_trial_seat", + "copilot_enterprise_trial_seat_quota", + "copilot_for_business_seat", + "copilot_for_business_seat_quota", + "copilot_for_business_seat_multi_quota", + "copilot_for_business_seat_assignment", + "copilot_for_business_seat_assignment_quota", + "copilot_for_business_seat_assignment_multi_quota", + "copilot_for_business_trial_seat", + "copilot_for_business_trial_seat_quota" + ], + "accessScopes": [ + "openid", + "profile", + "email", + "offline_access" + ] + }, "sessionsWindowAllowedExtensions": [], "voiceWsUrl": "wss://falcon-caas.mai.microsoft.com/voice-code/api/v1/realtime/voice" } diff --git a/src/vs/base/common/product.ts b/src/vs/base/common/product.ts index 37cbeefd1699..4a663f482c75 100644 --- a/src/vs/base/common/product.ts +++ b/src/vs/base/common/product.ts @@ -98,6 +98,12 @@ export interface IDictationRuntimeProductConfig { export interface IProductConfiguration { readonly version: string; + /** + * Version reported to the extension Marketplace and used for `engines.vscode` + * compatibility checks. Forks that use their own release numbering can keep + * {@link version} for branding while reporting an upstream VS Code version here. + */ + readonly extensionCompatibilityVersion?: string; readonly date?: string; readonly quality?: string; readonly commit?: string; diff --git a/src/vs/platform/extensionManagement/common/abstractExtensionManagementService.ts b/src/vs/platform/extensionManagement/common/abstractExtensionManagementService.ts index 3670af7480ae..dcaa16d9649d 100644 --- a/src/vs/platform/extensionManagement/common/abstractExtensionManagementService.ts +++ b/src/vs/platform/extensionManagement/common/abstractExtensionManagementService.ts @@ -18,6 +18,7 @@ import { IExtensionsControlManifest, StatisticType, isTargetPlatformCompatible, TargetPlatformToString, ExtensionManagementErrorCode, InstallOptions, UninstallOptions, Metadata, InstallExtensionEvent, DidUninstallExtensionEvent, InstallExtensionResult, UninstallExtensionEvent, IExtensionManagementService, InstallExtensionInfo, EXTENSION_INSTALL_DEP_PACK_CONTEXT, ExtensionGalleryError, IProductVersion, ExtensionGalleryErrorCode, + getCompatibilityProductVersion, EXTENSION_INSTALL_SOURCE_CONTEXT, DidUpdateExtensionMetadata, UninstallExtensionInfo, @@ -200,7 +201,7 @@ export abstract class AbstractExtensionManagementService extends CommontExtensio await Promise.allSettled(extensions.map(async ({ extension, options }) => { try { - const compatible = await this.checkAndGetCompatibleVersion(extension, !!options?.installGivenVersion, !!options?.installPreReleaseVersion, options.productVersion ?? { version: this.productService.version, date: this.productService.date }); + const compatible = await this.checkAndGetCompatibleVersion(extension, !!options?.installGivenVersion, !!options?.installPreReleaseVersion, options.productVersion ?? getCompatibilityProductVersion(this.productService)); installableExtensions.push({ ...compatible, options }); } catch (error) { results.push({ identifier: extension.identifier, operation: InstallOperation.Install, source: extension, error, profileLocation: options.profileLocation ?? this.getCurrentExtensionsManifestLocation() }); @@ -351,7 +352,7 @@ export abstract class AbstractExtensionManagementService extends CommontExtensio isBuiltin, isApplicationScoped, profileLocation: isApplicationScoped ? this.userDataProfilesService.defaultProfile.extensionsResource : options.profileLocation ?? this.getCurrentExtensionsManifestLocation(), - productVersion: options.productVersion ?? { version: this.productService.version, date: this.productService.date } + productVersion: options.productVersion ?? getCompatibilityProductVersion(this.productService) }; const existingInstallExtensionTask = !URI.isUri(extension) ? this.installingExtensions.get(getInstallExtensionTaskKey(extension, installExtensionTaskOptions.profileLocation)) : undefined; diff --git a/src/vs/platform/extensionManagement/common/extensionGalleryService.ts b/src/vs/platform/extensionManagement/common/extensionGalleryService.ts index 41b763a2b467..b853f8b41ddf 100644 --- a/src/vs/platform/extensionManagement/common/extensionGalleryService.ts +++ b/src/vs/platform/extensionManagement/common/extensionGalleryService.ts @@ -16,7 +16,7 @@ import { URI } from '../../../base/common/uri.js'; import { IHeaders, IRequestContext, IRequestOptions, isOfflineError } from '../../../base/parts/request/common/request.js'; import { IConfigurationService } from '../../configuration/common/configuration.js'; import { IEnvironmentService } from '../../environment/common/environment.js'; -import { getTargetPlatform, IExtensionGalleryService, IExtensionIdentifier, IExtensionInfo, IGalleryExtension, IGalleryExtensionAsset, IGalleryExtensionAssets, IGalleryExtensionVersion, InstallOperation, IQueryOptions, IExtensionsControlManifest, isNotWebExtensionInWebTargetPlatform, isTargetPlatformCompatible, ITranslation, SortOrder, StatisticType, toTargetPlatform, WEB_EXTENSION_TAG, IExtensionQueryOptions, IDeprecationInfo, ISearchPrefferedResults, ExtensionGalleryError, ExtensionGalleryErrorCode, IProductVersion, IAllowedExtensionsService, EXTENSION_IDENTIFIER_REGEX, SortBy, FilterType, MaliciousExtensionInfo, ExtensionRequestsTimeoutConfigKey, IExtensionBlockingInfo, ExtensionBlockingOrigin } from './extensionManagement.js'; +import { getTargetPlatform, IExtensionGalleryService, IExtensionIdentifier, IExtensionInfo, IGalleryExtension, IGalleryExtensionAsset, IGalleryExtensionAssets, IGalleryExtensionVersion, InstallOperation, IQueryOptions, IExtensionsControlManifest, isNotWebExtensionInWebTargetPlatform, isTargetPlatformCompatible, ITranslation, SortOrder, StatisticType, toTargetPlatform, WEB_EXTENSION_TAG, IExtensionQueryOptions, IDeprecationInfo, ISearchPrefferedResults, ExtensionGalleryError, ExtensionGalleryErrorCode, IProductVersion, IAllowedExtensionsService, EXTENSION_IDENTIFIER_REGEX, SortBy, FilterType, MaliciousExtensionInfo, ExtensionRequestsTimeoutConfigKey, IExtensionBlockingInfo, ExtensionBlockingOrigin, getCompatibilityProductVersion } from './extensionManagement.js'; import { adoptToGalleryExtensionId, areSameExtensions, getGalleryExtensionId, getGalleryExtensionTelemetryData } from './extensionManagementUtil.js'; import { IExtensionManifest, TargetPlatform } from '../../extensions/common/extensions.js'; import { isEngineValid } from '../../extensions/common/extensionValidator.js'; @@ -676,7 +676,7 @@ export abstract class AbstractExtensionGalleryService implements IExtensionGalle this.extensionsControlUrl = productService.extensionsGallery?.controlUrl; this.unpkgResourceApi = productService.extensionsGallery?.extensionUrlTemplate; this.commonHeadersPromise = resolveMarketplaceHeaders( - productService.version, + getCompatibilityProductVersion(productService).version, productService, this.environmentService, this.configurationService, @@ -789,7 +789,7 @@ export abstract class AbstractExtensionGalleryService implements IExtensionGalle includePreRelease, versions, compatible: !!options.compatible, - productVersion: options.productVersion ?? { version: this.productService.version, date: this.productService.date }, + productVersion: options.productVersion ?? getCompatibilityProductVersion(this.productService), includeBlockedVersions: options.includeBlockedVersions, isQueryForReleaseVersionFromPreReleaseVersion }, @@ -937,10 +937,7 @@ export abstract class AbstractExtensionGalleryService implements IExtensionGalle { targetPlatform, compatible: !!options.compatible, - productVersion: options.productVersion ?? { - version: this.productService.version, - date: this.productService.date - }, + productVersion: options.productVersion ?? getCompatibilityProductVersion(this.productService), version: extensionInfo.preRelease ? VersionKind.Prerelease : VersionKind.Release }, allTargetPlatforms); @@ -957,10 +954,7 @@ export abstract class AbstractExtensionGalleryService implements IExtensionGalle { targetPlatform, compatible: !!options.compatible, - productVersion: options.productVersion ?? { - version: this.productService.version, - date: this.productService.date - }, + productVersion: options.productVersion ?? getCompatibilityProductVersion(this.productService), version: VersionKind.Release }, allTargetPlatforms); @@ -980,10 +974,7 @@ export abstract class AbstractExtensionGalleryService implements IExtensionGalle { targetPlatform, compatible: false, - productVersion: options.productVersion ?? { - version: this.productService.version, - date: this.productService.date - }, + productVersion: options.productVersion ?? getCompatibilityProductVersion(this.productService), version: VersionKind.Prerelease }, allTargetPlatforms); @@ -1000,7 +991,7 @@ export abstract class AbstractExtensionGalleryService implements IExtensionGalle return prereleaseVersion ?? releaseVersion ?? null; } - async getCompatibleExtension(extension: IGalleryExtension, includePreRelease: boolean, targetPlatform: TargetPlatform, productVersion: IProductVersion = { version: this.productService.version, date: this.productService.date }): Promise { + async getCompatibleExtension(extension: IGalleryExtension, includePreRelease: boolean, targetPlatform: TargetPlatform, productVersion: IProductVersion = getCompatibilityProductVersion(this.productService)): Promise { if (isNotWebExtensionInWebTargetPlatform(extension.allTargetPlatforms, targetPlatform)) { return null; } @@ -1024,7 +1015,7 @@ export abstract class AbstractExtensionGalleryService implements IExtensionGalle return result[0] ?? null; } - async isExtensionCompatible(extension: IGalleryExtension, includePreRelease: boolean, targetPlatform: TargetPlatform, productVersion: IProductVersion = { version: this.productService.version, date: this.productService.date }): Promise { + async isExtensionCompatible(extension: IGalleryExtension, includePreRelease: boolean, targetPlatform: TargetPlatform, productVersion: IProductVersion = getCompatibilityProductVersion(this.productService)): Promise { return this.isValidVersion( { id: extension.identifier.id, @@ -1213,7 +1204,7 @@ export abstract class AbstractExtensionGalleryService implements IExtensionGalle } const runQuery = async (query: Query, token: CancellationToken) => { - const { extensions, total } = await this.queryGalleryExtensions(query, { targetPlatform: CURRENT_TARGET_PLATFORM, compatible: false, includePreRelease: !!options.includePreRelease, productVersion: options.productVersion ?? { version: this.productService.version, date: this.productService.date } }, extensionGalleryManifest, token); + const { extensions, total } = await this.queryGalleryExtensions(query, { targetPlatform: CURRENT_TARGET_PLATFORM, compatible: false, includePreRelease: !!options.includePreRelease, productVersion: options.productVersion ?? getCompatibilityProductVersion(this.productService) }, extensionGalleryManifest, token); const result: IGalleryExtension[] = []; let defaultChatAgentExtension: IGalleryExtension | undefined; @@ -1871,7 +1862,7 @@ export abstract class AbstractExtensionGalleryService implements IExtensionGalle } const versions: IRawGalleryExtensionVersion[] = []; - const productVersion = { version: this.productService.version, date: this.productService.date }; + const productVersion = getCompatibilityProductVersion(this.productService); await Promise.all(galleryExtensions[0].versions.map(async (version) => { try { if ( @@ -2017,7 +2008,7 @@ export abstract class AbstractExtensionGalleryService implements IExtensionGalle } if (result.migrateToPreRelease) { for (const [unsupportedPreReleaseExtensionId, preReleaseExtensionInfo] of Object.entries(result.migrateToPreRelease)) { - if (!preReleaseExtensionInfo.engine || isEngineValid(preReleaseExtensionInfo.engine, this.productService.version, this.productService.date)) { + if (!preReleaseExtensionInfo.engine || isEngineValid(preReleaseExtensionInfo.engine, getCompatibilityProductVersion(this.productService).version, this.productService.date)) { deprecated[unsupportedPreReleaseExtensionId.toLowerCase()] = { disallowInstall: true, extension: { diff --git a/src/vs/platform/extensionManagement/common/extensionManagement.ts b/src/vs/platform/extensionManagement/common/extensionManagement.ts index 1e977ff4a87b..7e5e5195a5d7 100644 --- a/src/vs/platform/extensionManagement/common/extensionManagement.ts +++ b/src/vs/platform/extensionManagement/common/extensionManagement.ts @@ -16,6 +16,7 @@ import { ConfigurationScope, Extensions, IConfigurationRegistry } from '../../co import { ExtensionType, IExtension, IExtensionManifest, TargetPlatform } from '../../extensions/common/extensions.js'; import { FileOperationError, FileOperationResult, IFileService, IFileStat } from '../../files/common/files.js'; import { createDecorator } from '../../instantiation/common/instantiation.js'; +import { IProductService } from '../../product/common/productService.js'; import { Registry } from '../../registry/common/platform.js'; import { IExtensionGalleryManifest } from './extensionGalleryManifest.js'; @@ -40,6 +41,18 @@ export interface IProductVersion { readonly date?: string; } +/** + * Product version used for extension compatibility checks and Marketplace queries. + * Uses {@link IProductConfiguration.extensionCompatibilityVersion} when a product + * ships with its own version numbering. + */ +export function getCompatibilityProductVersion(productService: IProductService): IProductVersion { + return { + version: productService.extensionCompatibilityVersion ?? productService.version, + date: productService.date + }; +} + export function TargetPlatformToString(targetPlatform: TargetPlatform) { switch (targetPlatform) { case TargetPlatform.WIN32_X64: return 'Windows 64 bit'; diff --git a/src/vs/platform/extensionManagement/common/extensionsScannerService.ts b/src/vs/platform/extensionManagement/common/extensionsScannerService.ts index df80d99ff537..afbf3e08c0e8 100644 --- a/src/vs/platform/extensionManagement/common/extensionsScannerService.ts +++ b/src/vs/platform/extensionManagement/common/extensionsScannerService.ts @@ -21,7 +21,7 @@ import Severity from '../../../base/common/severity.js'; import { URI } from '../../../base/common/uri.js'; import { localize } from '../../../nls.js'; import { IEnvironmentService } from '../../environment/common/environment.js'; -import { IProductVersion, Metadata } from './extensionManagement.js'; +import { getCompatibilityProductVersion, IProductVersion, Metadata } from './extensionManagement.js'; import { areSameExtensions, computeTargetPlatform, getExtensionId, getGalleryExtensionId } from './extensionManagementUtil.js'; import { ExtensionType, ExtensionIdentifier, IExtensionManifest, TargetPlatform, IExtensionIdentifier, IRelaxedExtensionManifest, UNDEFINED_PUBLISHER, IExtensionDescription, getManifestCacheFileName, ExtensionIdentifierMap, parseEnabledApiProposalNames } from '../../extensions/common/extensions.js'; import { validateExtensionManifest } from '../../extensions/common/extensionValidator.js'; @@ -521,10 +521,7 @@ export abstract class AbstractExtensionsScannerService extends Disposable implem } private getProductVersion(): IProductVersion { - return { - version: this.productService.version, - date: this.productService.date, - }; + return getCompatibilityProductVersion(this.productService); } } diff --git a/src/vs/platform/extensionManagement/node/extensionManagementService.ts b/src/vs/platform/extensionManagement/node/extensionManagementService.ts index 6eefd7163dbb..25c1eeeb1a43 100644 --- a/src/vs/platform/extensionManagement/node/extensionManagementService.ts +++ b/src/vs/platform/extensionManagement/node/extensionManagementService.ts @@ -30,6 +30,7 @@ import { ExtensionManagementError, ExtensionManagementErrorCode, IExtensionGalleryService, IExtensionIdentifier, IExtensionManagementService, IGalleryExtension, ILocalExtension, InstallOperation, Metadata, InstallOptions, IProductVersion, + getCompatibilityProductVersion, EXTENSION_INSTALL_CLIENT_TARGET_PLATFORM_CONTEXT, ExtensionSignatureVerificationCode, computeSize, @@ -130,7 +131,7 @@ export class ExtensionManagementService extends AbstractExtensionManagementServi } } - getInstalled(type?: ExtensionType, profileLocation: URI = this.userDataProfilesService.defaultProfile.extensionsResource, productVersion: IProductVersion = { version: this.productService.version, date: this.productService.date }, language?: string): Promise { + getInstalled(type?: ExtensionType, profileLocation: URI = this.userDataProfilesService.defaultProfile.extensionsResource, productVersion: IProductVersion = getCompatibilityProductVersion(this.productService), language?: string): Promise { return this.extensionsScanner.scanExtensions(type ?? null, profileLocation, productVersion, language); } @@ -150,7 +151,7 @@ export class ExtensionManagementService extends AbstractExtensionManagementServi try { const manifest = await getManifest(path.resolve(location.fsPath)); const extensionId = getGalleryExtensionId(manifest.publisher, manifest.name); - if (manifest.engines && manifest.engines.vscode && !isEngineValid(manifest.engines.vscode, this.productService.version, this.productService.date)) { + if (manifest.engines && manifest.engines.vscode && !isEngineValid(manifest.engines.vscode, getCompatibilityProductVersion(this.productService).version, this.productService.date)) { throw new Error(nls.localize('incompatible', "Unable to install extension '{0}' as it is not compatible with VS Code '{1}'.", extensionId, this.productService.version)); } @@ -234,7 +235,7 @@ export class ExtensionManagementService extends AbstractExtensionManagementServi } copyExtensions(fromProfileLocation: URI, toProfileLocation: URI): Promise { - return this.extensionsScanner.copyExtensions(fromProfileLocation, toProfileLocation, { version: this.productService.version, date: this.productService.date }); + return this.extensionsScanner.copyExtensions(fromProfileLocation, toProfileLocation, getCompatibilityProductVersion(this.productService)); } deleteExtensions(...extensions: IExtension[]): Promise { diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts b/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts index 7d9de121739e..40eec390af1e 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts @@ -26,7 +26,8 @@ import { ExtensionManagementErrorCode, MaliciousExtensionInfo, shouldRequireRepositorySignatureFor, - IGalleryExtensionVersion + IGalleryExtensionVersion, + getCompatibilityProductVersion } from '../../../../platform/extensionManagement/common/extensionManagement.js'; import { IWorkbenchExtensionEnablementService, EnablementState, IExtensionManagementServerService, IExtensionManagementServer, IWorkbenchExtensionManagementService, IResourceExtension } from '../../../services/extensionManagement/common/extensionManagement.js'; import { getGalleryExtensionTelemetryData, getLocalExtensionTelemetryData, areSameExtensions, groupByExtension, getGalleryExtensionId, findMatchingMaliciousEntry } from '../../../../platform/extensionManagement/common/extensionManagementUtil.js'; @@ -1558,7 +1559,7 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension const invalidExtensions = this.local.filter(e => e.enablementState === EnablementState.DisabledByInvalidExtension && !e.isWorkspaceScoped); if (invalidExtensions.length) { if (invalidExtensions.some(e => e.local && e.local.manifest.engines?.vscode && - !isEngineValid(e.local.manifest.engines.vscode, this.productService.version, this.productService.date) + !isEngineValid(e.local.manifest.engines.vscode, getCompatibilityProductVersion(this.productService).version, this.productService.date) )) { computedNotificiations.push({ message: nls.localize('incompatibleExtensions', "Some extensions are disabled due to version incompatibility. Review and update them."), @@ -2316,7 +2317,7 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension } private getProductCurrentVersion(): IProductVersion { - return { version: this.productService.version, date: this.productService.date }; + return getCompatibilityProductVersion(this.productService); } private getProductUpdateVersion(): IProductVersion | undefined { diff --git a/src/vs/workbench/services/extensionManagement/browser/webExtensionsScannerService.ts b/src/vs/workbench/services/extensionManagement/browser/webExtensionsScannerService.ts index f5c752b1d399..df6c81b07911 100644 --- a/src/vs/workbench/services/extensionManagement/browser/webExtensionsScannerService.ts +++ b/src/vs/workbench/services/extensionManagement/browser/webExtensionsScannerService.ts @@ -15,7 +15,7 @@ import { Queue } from '../../../../base/common/async.js'; import { VSBuffer } from '../../../../base/common/buffer.js'; import { ILogService } from '../../../../platform/log/common/log.js'; import { CancellationToken } from '../../../../base/common/cancellation.js'; -import { IExtensionGalleryService, IExtensionInfo, IGalleryExtension, IGalleryMetadata, Metadata } from '../../../../platform/extensionManagement/common/extensionManagement.js'; +import { getCompatibilityProductVersion, IExtensionGalleryService, IExtensionInfo, IGalleryExtension, IGalleryMetadata, Metadata } from '../../../../platform/extensionManagement/common/extensionManagement.js'; import { areSameExtensions, getGalleryExtensionId, getExtensionId, isMalicious } from '../../../../platform/extensionManagement/common/extensionManagementUtil.js'; import { Disposable } from '../../../../base/common/lifecycle.js'; import { ITranslations, localizeManifest } from '../../../../platform/extensionManagement/common/extensionNls.js'; @@ -767,7 +767,7 @@ export class WebExtensionsScannerService extends Disposable implements IWebExten const uuid = (webExtension.metadata)?.id; - validations.push(...validateExtensionManifest(this.productService.version, this.productService.date, webExtension.location, manifest, false)); + validations.push(...validateExtensionManifest(getCompatibilityProductVersion(this.productService).version, this.productService.date, webExtension.location, manifest, false)); let isValid = true; for (const [severity, message] of validations) { if (severity === Severity.Error) { diff --git a/src/vs/workbench/services/extensionManagement/electron-browser/extensionGalleryManifestService.ts b/src/vs/workbench/services/extensionManagement/electron-browser/extensionGalleryManifestService.ts index 5e2135e6336a..5da5034be0e0 100644 --- a/src/vs/workbench/services/extensionManagement/electron-browser/extensionGalleryManifestService.ts +++ b/src/vs/workbench/services/extensionManagement/electron-browser/extensionGalleryManifestService.ts @@ -12,6 +12,7 @@ import { IConfigurationService } from '../../../../platform/configuration/common import { IEnvironmentService } from '../../../../platform/environment/common/environment.js'; import { IExtensionGalleryManifestService, IExtensionGalleryManifest, ExtensionGalleryServiceUrlConfigKey, ExtensionGalleryAuthProviderConfigKey, ExtensionGalleryManifestStatus } from '../../../../platform/extensionManagement/common/extensionGalleryManifest.js'; import { ExtensionGalleryManifestService } from '../../../../platform/extensionManagement/common/extensionGalleryManifestService.js'; +import { getCompatibilityProductVersion } from '../../../../platform/extensionManagement/common/extensionManagement.js'; import { resolveMarketplaceHeaders } from '../../../../platform/externalServices/common/marketplace.js'; import { IFileService } from '../../../../platform/files/common/files.js'; import { InstantiationType, registerSingleton } from '../../../../platform/instantiation/common/extensions.js'; @@ -92,7 +93,7 @@ export class WorkbenchExtensionGalleryManifestService extends ExtensionGalleryMa ) { super(productService); this.commonHeadersPromise = resolveMarketplaceHeaders( - productService.version, + getCompatibilityProductVersion(productService).version, productService, environmentService, configurationService, diff --git a/src/vs/workbench/services/extensions/browser/webWorkerExtensionHost.ts b/src/vs/workbench/services/extensions/browser/webWorkerExtensionHost.ts index 3d0f306ac45f..c4fd0203276e 100644 --- a/src/vs/workbench/services/extensions/browser/webWorkerExtensionHost.ts +++ b/src/vs/workbench/services/extensions/browser/webWorkerExtensionHost.ts @@ -302,7 +302,7 @@ export class WebWorkerExtensionHost extends Disposable implements IExtensionHost } return { commit: this._productService.commit, - version: this._productService.version, + version: this._productService.extensionCompatibilityVersion ?? this._productService.version, quality: this._productService.quality, date: this._productService.date, parentPid: 0, diff --git a/src/vs/workbench/services/extensions/common/remoteExtensionHost.ts b/src/vs/workbench/services/extensions/common/remoteExtensionHost.ts index 2749e1f3af80..3c88235a74bd 100644 --- a/src/vs/workbench/services/extensions/common/remoteExtensionHost.ts +++ b/src/vs/workbench/services/extensions/common/remoteExtensionHost.ts @@ -212,7 +212,7 @@ export class RemoteExtensionHost extends Disposable implements IExtensionHost { const workspace = this._contextService.getWorkspace(); return { commit: this._productService.commit, - version: this._productService.version, + version: this._productService.extensionCompatibilityVersion ?? this._productService.version, quality: this._productService.quality, date: this._productService.date, parentPid: remoteInitData.pid, diff --git a/src/vs/workbench/services/extensions/electron-browser/localProcessExtensionHost.ts b/src/vs/workbench/services/extensions/electron-browser/localProcessExtensionHost.ts index 4f9b5871a894..86b7fc8e36d6 100644 --- a/src/vs/workbench/services/extensions/electron-browser/localProcessExtensionHost.ts +++ b/src/vs/workbench/services/extensions/electron-browser/localProcessExtensionHost.ts @@ -522,7 +522,7 @@ export class NativeLocalProcessExtensionHost extends Disposable implements IExte const workspace = this._contextService.getWorkspace(); return { commit: this._productService.commit, - version: this._productService.version, + version: this._productService.extensionCompatibilityVersion ?? this._productService.version, quality: this._productService.quality, date: this._productService.date, parentPid: 0,