Path: blob/main/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts
5270 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { IAction } from '../../../../base/common/actions.js';6import { CancellationToken } from '../../../../base/common/cancellation.js';7import { IStringDictionary } from '../../../../base/common/collections.js';8import { onUnexpectedError } from '../../../../base/common/errors.js';9import { Event } from '../../../../base/common/event.js';10import { KeyCode, KeyMod } from '../../../../base/common/keyCodes.js';11import { mnemonicButtonLabel } from '../../../../base/common/labels.js';12import { Disposable, DisposableStore, IDisposable, isDisposable } from '../../../../base/common/lifecycle.js';13import { Schemas } from '../../../../base/common/network.js';14import { isNative, isWeb } from '../../../../base/common/platform.js';15import { PolicyCategory } from '../../../../base/common/policy.js';16import { URI, UriComponents } from '../../../../base/common/uri.js';17import { MultiCommand } from '../../../../editor/browser/editorExtensions.js';18import { CopyAction, CutAction, PasteAction } from '../../../../editor/contrib/clipboard/browser/clipboard.js';19import { localize, localize2 } from '../../../../nls.js';20import { Categories } from '../../../../platform/action/common/actionCommonCategories.js';21import { Action2, IAction2Options, IMenuItem, MenuId, MenuRegistry, registerAction2 } from '../../../../platform/actions/common/actions.js';22import { IClipboardService } from '../../../../platform/clipboard/common/clipboardService.js';23import { CommandsRegistry, ICommandService } from '../../../../platform/commands/common/commands.js';24import { Extensions as ConfigurationExtensions, ConfigurationScope, IConfigurationRegistry } from '../../../../platform/configuration/common/configurationRegistry.js';25import { ContextKeyExpr, IContextKeyService, RawContextKey } from '../../../../platform/contextkey/common/contextkey.js';26import { IDialogService, IFileDialogService } from '../../../../platform/dialogs/common/dialogs.js';27import { ExtensionGalleryManifestStatus, ExtensionGalleryResourceType, ExtensionGalleryServiceUrlConfigKey, getExtensionGalleryManifestResourceUri, IExtensionGalleryManifest, IExtensionGalleryManifestService } from '../../../../platform/extensionManagement/common/extensionGalleryManifest.js';28import { EXTENSION_INSTALL_SOURCE_CONTEXT, ExtensionInstallSource, ExtensionRequestsTimeoutConfigKey, ExtensionsLocalizedLabel, FilterType, IExtensionGalleryService, IExtensionManagementService, PreferencesLocalizedLabel, SortBy, VerifyExtensionSignatureConfigKey } from '../../../../platform/extensionManagement/common/extensionManagement.js';29import { areSameExtensions, getIdAndVersion } from '../../../../platform/extensionManagement/common/extensionManagementUtil.js';30import { ExtensionStorageService } from '../../../../platform/extensionManagement/common/extensionStorage.js';31import { IExtensionRecommendationNotificationService } from '../../../../platform/extensionRecommendations/common/extensionRecommendations.js';32import { EXTENSION_CATEGORIES, ExtensionType } from '../../../../platform/extensions/common/extensions.js';33import { SyncDescriptor } from '../../../../platform/instantiation/common/descriptors.js';34import { InstantiationType, registerSingleton } from '../../../../platform/instantiation/common/extensions.js';35import { IInstantiationService, ServicesAccessor } from '../../../../platform/instantiation/common/instantiation.js';36import * as jsonContributionRegistry from '../../../../platform/jsonschemas/common/jsonContributionRegistry.js';37import { INotificationService, Severity } from '../../../../platform/notification/common/notification.js';38import product from '../../../../platform/product/common/product.js';39import { IProductService } from '../../../../platform/product/common/productService.js';40import { ProgressLocation } from '../../../../platform/progress/common/progress.js';41import { Extensions, IQuickAccessRegistry } from '../../../../platform/quickinput/common/quickAccess.js';42import { IQuickInputService } from '../../../../platform/quickinput/common/quickInput.js';43import { Registry } from '../../../../platform/registry/common/platform.js';44import { IStorageService, StorageScope, StorageTarget } from '../../../../platform/storage/common/storage.js';45import { IUriIdentityService } from '../../../../platform/uriIdentity/common/uriIdentity.js';46import { IUserDataProfilesService } from '../../../../platform/userDataProfile/common/userDataProfile.js';47import { EditorPaneDescriptor, IEditorPaneRegistry } from '../../../browser/editor.js';48import { Extensions as ConfigurationMigrationExtensions, IConfigurationMigrationRegistry } from '../../../common/configuration.js';49import { ResourceContextKey, WorkbenchStateContext } from '../../../common/contextkeys.js';50import { IWorkbenchContribution, IWorkbenchContributionsRegistry, registerWorkbenchContribution2, Extensions as WorkbenchExtensions, WorkbenchPhase } from '../../../common/contributions.js';51import { EditorExtensions } from '../../../common/editor.js';52import { IViewContainersRegistry, Extensions as ViewContainerExtensions, ViewContainerLocation } from '../../../common/views.js';53import { DEFAULT_ACCOUNT_SIGN_IN_COMMAND } from '../../../services/accounts/browser/defaultAccount.js';54import { IEditorService } from '../../../services/editor/common/editorService.js';55import { EnablementState, IExtensionManagementServerService, IPublisherInfo, IWorkbenchExtensionEnablementService, IWorkbenchExtensionManagementService } from '../../../services/extensionManagement/common/extensionManagement.js';56import { IExtensionIgnoredRecommendationsService, IExtensionRecommendationsService } from '../../../services/extensionRecommendations/common/extensionRecommendations.js';57import { IWorkspaceExtensionsConfigService } from '../../../services/extensionRecommendations/common/workspaceExtensionsConfig.js';58import { IHostService } from '../../../services/host/browser/host.js';59import { LifecyclePhase } from '../../../services/lifecycle/common/lifecycle.js';60import { IPreferencesService } from '../../../services/preferences/common/preferences.js';61import { CONTEXT_SYNC_ENABLEMENT } from '../../../services/userDataSync/common/userDataSync.js';62import { IViewsService } from '../../../services/views/common/viewsService.js';63import { WORKSPACE_TRUST_EXTENSION_SUPPORT } from '../../../services/workspaces/common/workspaceTrust.js';64import { ILanguageModelToolsService } from '../../chat/common/tools/languageModelToolsService.js';65import { CONTEXT_KEYBINDINGS_EDITOR } from '../../preferences/common/preferences.js';66import { IWebview } from '../../webview/browser/webview.js';67import { Query } from '../common/extensionQuery.js';68import { AutoRestartConfigurationKey, AutoUpdateConfigurationKey, CONTEXT_EXTENSIONS_GALLERY_STATUS, CONTEXT_HAS_GALLERY, DefaultViewsContext, ExtensionEditorTab, ExtensionRuntimeActionType, EXTENSIONS_CATEGORY, extensionsFilterSubMenu, extensionsSearchActionsMenu, HasOutdatedExtensionsContext, IExtensionArg, IExtensionsViewPaneContainer, IExtensionsWorkbenchService, INSTALL_ACTIONS_GROUP, INSTALL_EXTENSION_FROM_VSIX_COMMAND_ID, IWorkspaceRecommendedExtensionsView, LIST_WORKSPACE_UNSUPPORTED_EXTENSIONS_COMMAND_ID, OUTDATED_EXTENSIONS_VIEW_ID, SELECT_INSTALL_VSIX_EXTENSION_COMMAND_ID, THEME_ACTIONS_GROUP, TOGGLE_IGNORE_EXTENSION_ACTION_ID, UPDATE_ACTIONS_GROUP, VIEWLET_ID, WORKSPACE_RECOMMENDATIONS_VIEW_ID } from '../common/extensions.js';69import { ExtensionsConfigurationSchema, ExtensionsConfigurationSchemaId } from '../common/extensionsFileTemplate.js';70import { ExtensionsInput } from '../common/extensionsInput.js';71import { KeymapExtensions } from '../common/extensionsUtils.js';72import { SearchExtensionsTool, SearchExtensionsToolData } from '../common/searchExtensionsTool.js';73import { ShowRuntimeExtensionsAction } from './abstractRuntimeExtensionsEditor.js';74import { ExtensionEditor } from './extensionEditor.js';75import { ExtensionEnablementWorkspaceTrustTransitionParticipant } from './extensionEnablementWorkspaceTrustTransitionParticipant.js';76import { ExtensionRecommendationNotificationService } from './extensionRecommendationNotificationService.js';77import { ExtensionRecommendationsService } from './extensionRecommendationsService.js';78import { ClearLanguageAction, ConfigureWorkspaceFolderRecommendedExtensionsAction, ConfigureWorkspaceRecommendedExtensionsAction, InstallAction, InstallAnotherVersionAction, InstallSpecificVersionOfExtensionAction, SetColorThemeAction, SetFileIconThemeAction, SetProductIconThemeAction, ToggleAutoUpdateForExtensionAction, ToggleAutoUpdatesForPublisherAction, TogglePreReleaseExtensionAction } from './extensionsActions.js';79import { ExtensionActivationProgress } from './extensionsActivationProgress.js';80import { ExtensionsCompletionItemsProvider } from './extensionsCompletionItemsProvider.js';81import { ExtensionDependencyChecker } from './extensionsDependencyChecker.js';82import { clearSearchResultsIcon, configureRecommendedIcon, extensionsViewIcon, filterIcon, installWorkspaceRecommendedIcon, refreshIcon } from './extensionsIcons.js';83import { InstallExtensionQuickAccessProvider, ManageExtensionsQuickAccessProvider } from './extensionsQuickAccess.js';84import { BuiltInExtensionsContext, ExtensionMarketplaceStatusUpdater, ExtensionsSearchValueContext, ExtensionsSortByContext, ExtensionsViewletViewsContribution, ExtensionsViewPaneContainer, MaliciousExtensionChecker, RecommendedExtensionsContext, SearchHasTextContext, SearchMarketplaceExtensionsContext, StatusUpdater } from './extensionsViewlet.js';85import { ExtensionsWorkbenchService } from './extensionsWorkbenchService.js';86import './media/extensionManagement.css';87import { UnsupportedExtensionsMigrationContrib } from './unsupportedExtensionsMigrationContribution.js';8889// Singletons90registerSingleton(IExtensionsWorkbenchService, ExtensionsWorkbenchService, InstantiationType.Eager /* Auto updates extensions */);91registerSingleton(IExtensionRecommendationNotificationService, ExtensionRecommendationNotificationService, InstantiationType.Delayed);92registerSingleton(IExtensionRecommendationsService, ExtensionRecommendationsService, InstantiationType.Eager /* Prompts recommendations in the background */);9394// Quick Access95Registry.as<IQuickAccessRegistry>(Extensions.Quickaccess).registerQuickAccessProvider({96ctor: ManageExtensionsQuickAccessProvider,97prefix: ManageExtensionsQuickAccessProvider.PREFIX,98placeholder: localize('manageExtensionsQuickAccessPlaceholder', "Press Enter to manage extensions."),99helpEntries: [{ description: localize('manageExtensionsHelp', "Manage Extensions") }]100});101102// Editor103Registry.as<IEditorPaneRegistry>(EditorExtensions.EditorPane).registerEditorPane(104EditorPaneDescriptor.create(105ExtensionEditor,106ExtensionEditor.ID,107localize('extension', "Extension")108),109[110new SyncDescriptor(ExtensionsInput)111]);112113export const VIEW_CONTAINER = Registry.as<IViewContainersRegistry>(ViewContainerExtensions.ViewContainersRegistry).registerViewContainer(114{115id: VIEWLET_ID,116title: localize2('extensions', "Extensions"),117openCommandActionDescriptor: {118id: VIEWLET_ID,119mnemonicTitle: localize({ key: 'miViewExtensions', comment: ['&& denotes a mnemonic'] }, "E&&xtensions"),120keybindings: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KeyX },121order: 4,122},123ctorDescriptor: new SyncDescriptor(ExtensionsViewPaneContainer),124icon: extensionsViewIcon,125order: 4,126rejectAddedViews: true,127alwaysUseContainerInfo: true,128}, ViewContainerLocation.Sidebar);129130Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration)131.registerConfiguration({132id: 'extensions',133order: 30,134title: localize('extensionsConfigurationTitle', "Extensions"),135type: 'object',136properties: {137'extensions.autoUpdate': {138enum: [true, 'onlyEnabledExtensions', false,],139enumItemLabels: [140localize('all', "All Extensions"),141localize('enabled', "Only Enabled Extensions"),142localize('none', "None"),143],144enumDescriptions: [145localize('extensions.autoUpdate.true', 'Download and install updates automatically for all extensions.'),146localize('extensions.autoUpdate.enabled', 'Download and install updates automatically only for enabled extensions.'),147localize('extensions.autoUpdate.false', 'Extensions are not automatically updated.'),148],149description: localize('extensions.autoUpdate', "Controls the automatic update behavior of extensions. The updates are fetched from a Microsoft online service."),150default: true,151scope: ConfigurationScope.APPLICATION,152tags: ['usesOnlineServices']153},154'extensions.autoCheckUpdates': {155type: 'boolean',156description: localize('extensionsCheckUpdates', "When enabled, automatically checks extensions for updates. If an extension has an update, it is marked as outdated in the Extensions view. The updates are fetched from a Microsoft online service."),157default: true,158scope: ConfigurationScope.APPLICATION,159tags: ['usesOnlineServices']160},161'extensions.ignoreRecommendations': {162type: 'boolean',163description: localize('extensionsIgnoreRecommendations', "When enabled, the notifications for extension recommendations will not be shown."),164default: false165},166'extensions.showRecommendationsOnlyOnDemand': {167type: 'boolean',168deprecationMessage: localize('extensionsShowRecommendationsOnlyOnDemand_Deprecated', "This setting is deprecated. Use extensions.ignoreRecommendations setting to control recommendation notifications. Use Extensions view's visibility actions to hide Recommended view by default."),169default: false,170tags: ['usesOnlineServices']171},172'extensions.closeExtensionDetailsOnViewChange': {173type: 'boolean',174description: localize('extensionsCloseExtensionDetailsOnViewChange', "When enabled, editors with extension details will be automatically closed upon navigating away from the Extensions View."),175default: false176},177'extensions.confirmedUriHandlerExtensionIds': {178type: 'array',179items: {180type: 'string'181},182description: localize('handleUriConfirmedExtensions', "When an extension is listed here, a confirmation prompt will not be shown when that extension handles a URI."),183default: [],184scope: ConfigurationScope.APPLICATION185},186'extensions.webWorker': {187type: ['boolean', 'string'],188enum: [true, false, 'auto'],189enumDescriptions: [190localize('extensionsWebWorker.true', "The Web Worker Extension Host will always be launched."),191localize('extensionsWebWorker.false', "The Web Worker Extension Host will never be launched."),192localize('extensionsWebWorker.auto', "The Web Worker Extension Host will be launched when a web extension needs it."),193],194description: localize('extensionsWebWorker', "Enable web worker extension host."),195default: 'auto'196},197'extensions.supportVirtualWorkspaces': {198type: 'object',199markdownDescription: localize('extensions.supportVirtualWorkspaces', "Override the virtual workspaces support of an extension."),200patternProperties: {201'([a-z0-9A-Z][a-z0-9-A-Z]*)\\.([a-z0-9A-Z][a-z0-9-A-Z]*)$': {202type: 'boolean',203default: false204}205},206additionalProperties: false,207default: {},208defaultSnippets: [{209'body': {210'pub.name': false211}212}]213},214'extensions.experimental.affinity': {215type: 'object',216markdownDescription: localize('extensions.affinity', "Configure an extension to execute in a different extension host process."),217patternProperties: {218'([a-z0-9A-Z][a-z0-9-A-Z]*)\\.([a-z0-9A-Z][a-z0-9-A-Z]*)$': {219type: 'integer',220default: 1221}222},223additionalProperties: false,224default: {},225defaultSnippets: [{226'body': {227'pub.name': 1228}229}]230},231[WORKSPACE_TRUST_EXTENSION_SUPPORT]: {232type: 'object',233scope: ConfigurationScope.APPLICATION,234markdownDescription: localize('extensions.supportUntrustedWorkspaces', "Override the untrusted workspace support of an extension. Extensions using `true` will always be enabled. Extensions using `limited` will always be enabled, and the extension will hide functionality that requires trust. Extensions using `false` will only be enabled only when the workspace is trusted."),235patternProperties: {236'([a-z0-9A-Z][a-z0-9-A-Z]*)\\.([a-z0-9A-Z][a-z0-9-A-Z]*)$': {237type: 'object',238properties: {239'supported': {240type: ['boolean', 'string'],241enum: [true, false, 'limited'],242enumDescriptions: [243localize('extensions.supportUntrustedWorkspaces.true', "Extension will always be enabled."),244localize('extensions.supportUntrustedWorkspaces.false', "Extension will only be enabled only when the workspace is trusted."),245localize('extensions.supportUntrustedWorkspaces.limited', "Extension will always be enabled, and the extension will hide functionality requiring trust."),246],247description: localize('extensions.supportUntrustedWorkspaces.supported', "Defines the untrusted workspace support setting for the extension."),248},249'version': {250type: 'string',251description: localize('extensions.supportUntrustedWorkspaces.version', "Defines the version of the extension for which the override should be applied. If not specified, the override will be applied independent of the extension version."),252}253}254}255}256},257'extensions.experimental.deferredStartupFinishedActivation': {258type: 'boolean',259description: localize('extensionsDeferredStartupFinishedActivation', "When enabled, extensions which declare the `onStartupFinished` activation event will be activated after a timeout."),260default: false261},262'extensions.experimental.issueQuickAccess': {263type: 'boolean',264description: localize('extensionsInQuickAccess', "When enabled, extensions can be searched for via Quick Access and report issues from there."),265default: true266},267[VerifyExtensionSignatureConfigKey]: {268type: 'boolean',269description: localize('extensions.verifySignature', "When enabled, extensions are verified to be signed before getting installed."),270default: true,271scope: ConfigurationScope.APPLICATION,272included: isNative273},274[AutoRestartConfigurationKey]: {275type: 'boolean',276description: localize('autoRestart', "If activated, extensions will automatically restart following an update if the window is not in focus. There can be a data loss if you have open Notebooks or Custom Editors."),277default: false,278included: product.quality !== 'stable'279},280[ExtensionGalleryServiceUrlConfigKey]: {281type: 'string',282description: localize('extensions.gallery.serviceUrl', "Configure the Marketplace service URL to connect to"),283default: '',284scope: ConfigurationScope.APPLICATION,285tags: ['usesOnlineServices'],286included: false,287policy: {288name: 'ExtensionGalleryServiceUrl',289category: PolicyCategory.Extensions,290minimumVersion: '1.99',291localization: {292description: {293key: 'extensions.gallery.serviceUrl',294value: localize('extensions.gallery.serviceUrl', "Configure the Marketplace service URL to connect to"),295}296}297},298},299'extensions.supportNodeGlobalNavigator': {300type: 'boolean',301description: localize('extensionsSupportNodeGlobalNavigator', "When enabled, Node.js navigator object is exposed on the global scope."),302default: false,303},304[ExtensionRequestsTimeoutConfigKey]: {305type: 'number',306description: localize('extensionsRequestTimeout', "Controls the timeout in milliseconds for HTTP requests made when fetching extensions from the Marketplace"),307default: 60_000,308scope: ConfigurationScope.APPLICATION,309tags: ['advanced', 'usesOnlineServices']310},311}312});313314const jsonRegistry = <jsonContributionRegistry.IJSONContributionRegistry>Registry.as(jsonContributionRegistry.Extensions.JSONContribution);315jsonRegistry.registerSchema(ExtensionsConfigurationSchemaId, ExtensionsConfigurationSchema);316317// Register Commands318CommandsRegistry.registerCommand('_extensions.manage', (accessor: ServicesAccessor, extensionId: string, tab?: ExtensionEditorTab, preserveFocus?: boolean, feature?: string) => {319const extensionService = accessor.get(IExtensionsWorkbenchService);320const extension = extensionService.local.find(e => areSameExtensions(e.identifier, { id: extensionId }));321if (extension) {322extensionService.open(extension, { tab, preserveFocus, feature });323} else {324throw new Error(localize('notFound', "Extension '{0}' not found.", extensionId));325}326});327328CommandsRegistry.registerCommand('extension.open', async (accessor: ServicesAccessor, extensionId: string, tab?: ExtensionEditorTab, preserveFocus?: boolean, feature?: string, sideByside?: boolean) => {329const extensionService = accessor.get(IExtensionsWorkbenchService);330const commandService = accessor.get(ICommandService);331332const [extension] = await extensionService.getExtensions([{ id: extensionId }], CancellationToken.None);333if (extension) {334return extensionService.open(extension, { tab, preserveFocus, feature, sideByside });335}336337return commandService.executeCommand('_extensions.manage', extensionId, tab, preserveFocus, feature);338});339340CommandsRegistry.registerCommand({341id: 'workbench.extensions.installExtension',342metadata: {343description: localize('workbench.extensions.installExtension.description', "Install the given extension"),344args: [345{346name: 'extensionIdOrVSIXUri',347description: localize('workbench.extensions.installExtension.arg.decription', "Extension id or VSIX resource uri"),348constraint: (value: any) => typeof value === 'string' || value instanceof URI,349},350{351name: 'options',352description: '(optional) Options for installing the extension. Object with the following properties: ' +353'`installOnlyNewlyAddedFromExtensionPackVSIX`: When enabled, VS Code installs only newly added extensions from the extension pack VSIX. This option is considered only when installing VSIX. ',354isOptional: true,355schema: {356'type': 'object',357'properties': {358'installOnlyNewlyAddedFromExtensionPackVSIX': {359'type': 'boolean',360'description': localize('workbench.extensions.installExtension.option.installOnlyNewlyAddedFromExtensionPackVSIX', "When enabled, VS Code installs only newly added extensions from the extension pack VSIX. This option is considered only while installing a VSIX."),361default: false362},363'installPreReleaseVersion': {364'type': 'boolean',365'description': localize('workbench.extensions.installExtension.option.installPreReleaseVersion', "When enabled, VS Code installs the pre-release version of the extension if available."),366default: false367},368'donotSync': {369'type': 'boolean',370'description': localize('workbench.extensions.installExtension.option.donotSync', "When enabled, VS Code do not sync this extension when Settings Sync is on."),371default: false372},373'justification': {374'type': ['string', 'object'],375'description': localize('workbench.extensions.installExtension.option.justification', "Justification for installing the extension. This is a string or an object that can be used to pass any information to the installation handlers. i.e. `{reason: 'This extension wants to open a URI', action: 'Open URI'}` will show a message box with the reason and action upon install."),376},377'enable': {378'type': 'boolean',379'description': localize('workbench.extensions.installExtension.option.enable', "When enabled, the extension will be enabled if it is installed but disabled. If the extension is already enabled, this has no effect."),380default: false381},382'context': {383'type': 'object',384'description': localize('workbench.extensions.installExtension.option.context', "Context for the installation. This is a JSON object that can be used to pass any information to the installation handlers. i.e. `{skipWalkthrough: true}` will skip opening the walkthrough upon install."),385}386}387}388}389]390},391handler: async (392accessor,393arg: string | UriComponents,394options?: {395installOnlyNewlyAddedFromExtensionPackVSIX?: boolean;396installPreReleaseVersion?: boolean;397donotSync?: boolean;398justification?: string | { reason: string; action: string };399enable?: boolean;400context?: IStringDictionary<any>;401}) => {402const extensionsWorkbenchService = accessor.get(IExtensionsWorkbenchService);403const extensionManagementService = accessor.get(IWorkbenchExtensionManagementService);404const extensionGalleryService = accessor.get(IExtensionGalleryService);405try {406if (typeof arg === 'string') {407const [id, version] = getIdAndVersion(arg);408const extension = extensionsWorkbenchService.local.find(e => areSameExtensions(e.identifier, { id, uuid: version }));409if (extension?.enablementState === EnablementState.DisabledByExtensionKind) {410const [gallery] = await extensionGalleryService.getExtensions([{ id, preRelease: options?.installPreReleaseVersion }], CancellationToken.None);411if (!gallery) {412throw new Error(localize('notFound', "Extension '{0}' not found.", arg));413}414await extensionManagementService.installFromGallery(gallery, {415isMachineScoped: options?.donotSync ? true : undefined, /* do not allow syncing extensions automatically while installing through the command */416installPreReleaseVersion: options?.installPreReleaseVersion,417installGivenVersion: !!version,418context: { ...options?.context, [EXTENSION_INSTALL_SOURCE_CONTEXT]: ExtensionInstallSource.COMMAND },419});420} else {421await extensionsWorkbenchService.install(id, {422version,423installPreReleaseVersion: options?.installPreReleaseVersion,424context: { ...options?.context, [EXTENSION_INSTALL_SOURCE_CONTEXT]: ExtensionInstallSource.COMMAND },425justification: options?.justification,426enable: options?.enable,427isMachineScoped: options?.donotSync ? true : undefined, /* do not allow syncing extensions automatically while installing through the command */428}, ProgressLocation.Notification);429}430} else {431const vsix = URI.revive(arg);432await extensionsWorkbenchService.install(vsix, { installGivenVersion: true });433}434} catch (e) {435onUnexpectedError(e);436throw e;437}438}439});440441CommandsRegistry.registerCommand({442id: 'workbench.extensions.uninstallExtension',443metadata: {444description: localize('workbench.extensions.uninstallExtension.description', "Uninstall the given extension"),445args: [446{447name: localize('workbench.extensions.uninstallExtension.arg.name', "Id of the extension to uninstall"),448schema: {449'type': 'string'450}451}452]453},454handler: async (accessor, id: string) => {455if (!id) {456throw new Error(localize('id required', "Extension id required."));457}458const extensionManagementService = accessor.get(IExtensionManagementService);459const installed = await extensionManagementService.getInstalled();460const [extensionToUninstall] = installed.filter(e => areSameExtensions(e.identifier, { id }));461if (!extensionToUninstall) {462throw new Error(localize('notInstalled', "Extension '{0}' is not installed. Make sure you use the full extension ID, including the publisher, e.g.: ms-dotnettools.csharp.", id));463}464if (extensionToUninstall.isBuiltin) {465throw new Error(localize('builtin', "Extension '{0}' is a Built-in extension and cannot be uninstalled", id));466}467468try {469await extensionManagementService.uninstall(extensionToUninstall);470} catch (e) {471onUnexpectedError(e);472throw e;473}474}475});476477CommandsRegistry.registerCommand({478id: 'workbench.extensions.search',479metadata: {480description: localize('workbench.extensions.search.description', "Search for a specific extension"),481args: [482{483name: localize('workbench.extensions.search.arg.name', "Query to use in search"),484schema: { 'type': 'string' }485}486]487},488handler: async (accessor, query: string = '') => {489return accessor.get(IExtensionsWorkbenchService).openSearch(query);490}491});492493function overrideActionForActiveExtensionEditorWebview(command: MultiCommand | undefined, f: (webview: IWebview) => void) {494command?.addImplementation(105, 'extensions-editor', (accessor) => {495const editorService = accessor.get(IEditorService);496const editor = editorService.activeEditorPane;497if (editor instanceof ExtensionEditor) {498if (editor.activeWebview?.isFocused) {499f(editor.activeWebview);500return true;501}502}503return false;504});505}506507overrideActionForActiveExtensionEditorWebview(CopyAction, webview => webview.copy());508overrideActionForActiveExtensionEditorWebview(CutAction, webview => webview.cut());509overrideActionForActiveExtensionEditorWebview(PasteAction, webview => webview.paste());510511// Contexts512export const CONTEXT_HAS_LOCAL_SERVER = new RawContextKey<boolean>('hasLocalServer', false);513export const CONTEXT_HAS_REMOTE_SERVER = new RawContextKey<boolean>('hasRemoteServer', false);514export const CONTEXT_HAS_WEB_SERVER = new RawContextKey<boolean>('hasWebServer', false);515const CONTEXT_GALLERY_SORT_CAPABILITIES = new RawContextKey<string>('gallerySortCapabilities', '');516const CONTEXT_GALLERY_FILTER_CAPABILITIES = new RawContextKey<string>('galleryFilterCapabilities', '');517const CONTEXT_GALLERY_ALL_PUBLIC_REPOSITORY_SIGNED = new RawContextKey<boolean>('galleryAllPublicRepositorySigned', false);518const CONTEXT_GALLERY_ALL_PRIVATE_REPOSITORY_SIGNED = new RawContextKey<boolean>('galleryAllPrivateRepositorySigned', false);519const CONTEXT_GALLERY_HAS_EXTENSION_LINK = new RawContextKey<boolean>('galleryHasExtensionLink', false);520521async function runAction(action: IAction): Promise<void> {522try {523await action.run();524} finally {525if (isDisposable(action)) {526action.dispose();527}528}529}530531type IExtensionActionOptions = IAction2Options & {532menuTitles?: { [id: string]: string };533run(accessor: ServicesAccessor, ...args: unknown[]): Promise<any>;534};535536class ExtensionsContributions extends Disposable implements IWorkbenchContribution {537538constructor(539@IExtensionManagementService private readonly extensionManagementService: IExtensionManagementService,540@IExtensionManagementServerService private readonly extensionManagementServerService: IExtensionManagementServerService,541@IExtensionGalleryManifestService private readonly extensionGalleryManifestService: IExtensionGalleryManifestService,542@IContextKeyService private readonly contextKeyService: IContextKeyService,543@IViewsService private readonly viewsService: IViewsService,544@IExtensionsWorkbenchService private readonly extensionsWorkbenchService: IExtensionsWorkbenchService,545@IWorkbenchExtensionEnablementService private readonly extensionEnablementService: IWorkbenchExtensionEnablementService,546@IInstantiationService private readonly instantiationService: IInstantiationService,547@IDialogService private readonly dialogService: IDialogService,548@ICommandService private readonly commandService: ICommandService,549@IProductService private readonly productService: IProductService,550) {551super();552const hasLocalServerContext = CONTEXT_HAS_LOCAL_SERVER.bindTo(contextKeyService);553if (this.extensionManagementServerService.localExtensionManagementServer) {554hasLocalServerContext.set(true);555}556557const hasRemoteServerContext = CONTEXT_HAS_REMOTE_SERVER.bindTo(contextKeyService);558if (this.extensionManagementServerService.remoteExtensionManagementServer) {559hasRemoteServerContext.set(true);560}561562const hasWebServerContext = CONTEXT_HAS_WEB_SERVER.bindTo(contextKeyService);563if (this.extensionManagementServerService.webExtensionManagementServer) {564hasWebServerContext.set(true);565}566567this.updateExtensionGalleryStatusContexts();568this._register(extensionGalleryManifestService.onDidChangeExtensionGalleryManifestStatus(() => this.updateExtensionGalleryStatusContexts()));569extensionGalleryManifestService.getExtensionGalleryManifest()570.then(extensionGalleryManifest => {571this.updateGalleryCapabilitiesContexts(extensionGalleryManifest);572this._register(extensionGalleryManifestService.onDidChangeExtensionGalleryManifest(extensionGalleryManifest => this.updateGalleryCapabilitiesContexts(extensionGalleryManifest)));573});574this.registerGlobalActions();575this.registerContextMenuActions();576this.registerQuickAccessProvider();577}578579private async updateExtensionGalleryStatusContexts(): Promise<void> {580CONTEXT_HAS_GALLERY.bindTo(this.contextKeyService).set(this.extensionGalleryManifestService.extensionGalleryManifestStatus === ExtensionGalleryManifestStatus.Available);581CONTEXT_EXTENSIONS_GALLERY_STATUS.bindTo(this.contextKeyService).set(this.extensionGalleryManifestService.extensionGalleryManifestStatus);582}583584private async updateGalleryCapabilitiesContexts(extensionGalleryManifest: IExtensionGalleryManifest | null): Promise<void> {585CONTEXT_GALLERY_SORT_CAPABILITIES.bindTo(this.contextKeyService).set(`_${extensionGalleryManifest?.capabilities.extensionQuery.sorting?.map(s => s.name)?.join('_')}_UpdateDate_`);586CONTEXT_GALLERY_FILTER_CAPABILITIES.bindTo(this.contextKeyService).set(`_${extensionGalleryManifest?.capabilities.extensionQuery.filtering?.map(s => s.name)?.join('_')}_`);587CONTEXT_GALLERY_ALL_PUBLIC_REPOSITORY_SIGNED.bindTo(this.contextKeyService).set(!!extensionGalleryManifest?.capabilities?.signing?.allPublicRepositorySigned);588CONTEXT_GALLERY_ALL_PRIVATE_REPOSITORY_SIGNED.bindTo(this.contextKeyService).set(!!extensionGalleryManifest?.capabilities?.signing?.allPrivateRepositorySigned);589CONTEXT_GALLERY_HAS_EXTENSION_LINK.bindTo(this.contextKeyService).set(!!(extensionGalleryManifest && getExtensionGalleryManifestResourceUri(extensionGalleryManifest, ExtensionGalleryResourceType.ExtensionDetailsViewUri)));590}591592private registerQuickAccessProvider(): void {593if (this.extensionManagementServerService.localExtensionManagementServer594|| this.extensionManagementServerService.remoteExtensionManagementServer595|| this.extensionManagementServerService.webExtensionManagementServer596) {597Registry.as<IQuickAccessRegistry>(Extensions.Quickaccess).registerQuickAccessProvider({598ctor: InstallExtensionQuickAccessProvider,599prefix: InstallExtensionQuickAccessProvider.PREFIX,600placeholder: localize('installExtensionQuickAccessPlaceholder', "Type the name of an extension to install or search."),601helpEntries: [{ description: localize('installExtensionQuickAccessHelp', "Install or Search Extensions") }]602});603}604}605606// Global actions607private registerGlobalActions(): void {608this._register(MenuRegistry.appendMenuItem(MenuId.MenubarPreferencesMenu, {609command: {610id: VIEWLET_ID,611title: localize({ key: 'miPreferencesExtensions', comment: ['&& denotes a mnemonic'] }, "&&Extensions")612},613group: '2_configuration',614order: 3615}));616this._register(MenuRegistry.appendMenuItem(MenuId.GlobalActivity, {617command: {618id: VIEWLET_ID,619title: localize('showExtensions', "Extensions")620},621group: '2_configuration',622order: 3623}));624625this.registerExtensionAction({626id: 'workbench.extensions.action.focusExtensionsView',627title: localize2('focusExtensions', 'Focus on Extensions View'),628category: ExtensionsLocalizedLabel,629f1: true,630run: async (accessor: ServicesAccessor) => {631await accessor.get(IExtensionsWorkbenchService).openSearch('');632}633});634635this.registerExtensionAction({636id: 'workbench.extensions.action.installExtensions',637title: localize2('installExtensions', 'Install Extensions'),638category: ExtensionsLocalizedLabel,639menu: {640id: MenuId.CommandPalette,641when: ContextKeyExpr.and(CONTEXT_HAS_GALLERY, ContextKeyExpr.or(CONTEXT_HAS_LOCAL_SERVER, CONTEXT_HAS_REMOTE_SERVER, CONTEXT_HAS_WEB_SERVER))642},643run: async (accessor: ServicesAccessor) => {644accessor.get(IViewsService).openViewContainer(VIEWLET_ID, true);645}646});647648this.registerExtensionAction({649id: 'workbench.extensions.action.showRecommendedKeymapExtensions',650title: localize2('showRecommendedKeymapExtensionsShort', 'Keymaps'),651category: PreferencesLocalizedLabel,652menu: [{653id: MenuId.CommandPalette,654when: CONTEXT_HAS_GALLERY655}, {656id: MenuId.EditorTitle,657when: ContextKeyExpr.and(CONTEXT_KEYBINDINGS_EDITOR, CONTEXT_HAS_GALLERY),658group: '2_keyboard_discover_actions'659}],660menuTitles: {661[MenuId.EditorTitle.id]: localize('importKeyboardShortcutsFroms', "Migrate Keyboard Shortcuts from...")662},663run: () => this.extensionsWorkbenchService.openSearch('@recommended:keymaps ')664});665666this.registerExtensionAction({667id: 'workbench.extensions.action.showLanguageExtensions',668title: localize2('showLanguageExtensionsShort', 'Language Extensions'),669category: PreferencesLocalizedLabel,670menu: {671id: MenuId.CommandPalette,672when: CONTEXT_HAS_GALLERY673},674run: () => this.extensionsWorkbenchService.openSearch('@recommended:languages ')675});676677this.registerExtensionAction({678id: 'workbench.extensions.action.checkForUpdates',679title: localize2('checkForUpdates', 'Check for Extension Updates'),680category: ExtensionsLocalizedLabel,681menu: [{682id: MenuId.CommandPalette,683when: ContextKeyExpr.and(CONTEXT_HAS_GALLERY, ContextKeyExpr.or(CONTEXT_HAS_LOCAL_SERVER, CONTEXT_HAS_REMOTE_SERVER, CONTEXT_HAS_WEB_SERVER))684}, {685id: MenuId.ViewContainerTitle,686when: ContextKeyExpr.and(ContextKeyExpr.equals('viewContainer', VIEWLET_ID), CONTEXT_HAS_GALLERY),687group: '1_updates',688order: 1689}],690run: async () => {691await this.extensionsWorkbenchService.checkForUpdates();692const outdated = this.extensionsWorkbenchService.outdated;693if (outdated.length) {694return this.extensionsWorkbenchService.openSearch('@outdated ');695} else {696return this.dialogService.info(localize('noUpdatesAvailable', "All extensions are up to date."));697}698}699});700701const enableAutoUpdateWhenCondition = ContextKeyExpr.equals(`config.${AutoUpdateConfigurationKey}`, false);702this.registerExtensionAction({703id: 'workbench.extensions.action.enableAutoUpdate',704title: localize2('enableAutoUpdate', 'Enable Auto Update for All Extensions'),705category: ExtensionsLocalizedLabel,706precondition: enableAutoUpdateWhenCondition,707menu: [{708id: MenuId.ViewContainerTitle,709order: 5,710group: '1_updates',711when: ContextKeyExpr.and(ContextKeyExpr.equals('viewContainer', VIEWLET_ID), enableAutoUpdateWhenCondition)712}, {713id: MenuId.CommandPalette,714}],715run: (accessor: ServicesAccessor) => accessor.get(IExtensionsWorkbenchService).updateAutoUpdateForAllExtensions(true)716});717718const disableAutoUpdateWhenCondition = ContextKeyExpr.notEquals(`config.${AutoUpdateConfigurationKey}`, false);719this.registerExtensionAction({720id: 'workbench.extensions.action.disableAutoUpdate',721title: localize2('disableAutoUpdate', 'Disable Auto Update for All Extensions'),722precondition: disableAutoUpdateWhenCondition,723category: ExtensionsLocalizedLabel,724menu: [{725id: MenuId.ViewContainerTitle,726order: 5,727group: '1_updates',728when: ContextKeyExpr.and(ContextKeyExpr.equals('viewContainer', VIEWLET_ID), disableAutoUpdateWhenCondition)729}, {730id: MenuId.CommandPalette,731}],732run: (accessor: ServicesAccessor) => accessor.get(IExtensionsWorkbenchService).updateAutoUpdateForAllExtensions(false)733});734735this.registerExtensionAction({736id: 'workbench.extensions.action.updateAllExtensions',737title: localize2('updateAll', 'Update All Extensions'),738category: ExtensionsLocalizedLabel,739precondition: HasOutdatedExtensionsContext,740menu: [741{742id: MenuId.CommandPalette,743when: ContextKeyExpr.and(CONTEXT_HAS_GALLERY, ContextKeyExpr.or(CONTEXT_HAS_LOCAL_SERVER, CONTEXT_HAS_REMOTE_SERVER, CONTEXT_HAS_WEB_SERVER))744}, {745id: MenuId.ViewContainerTitle,746when: ContextKeyExpr.and(ContextKeyExpr.equals('viewContainer', VIEWLET_ID), ContextKeyExpr.or(ContextKeyExpr.has(`config.${AutoUpdateConfigurationKey}`).negate(), ContextKeyExpr.equals(`config.${AutoUpdateConfigurationKey}`, 'onlyEnabledExtensions'))),747group: '1_updates',748order: 2749}, {750id: MenuId.ViewTitle,751when: ContextKeyExpr.equals('view', OUTDATED_EXTENSIONS_VIEW_ID),752group: 'navigation',753order: 1754}755],756icon: installWorkspaceRecommendedIcon,757run: async () => {758await this.extensionsWorkbenchService.updateAll();759}760});761762this.registerExtensionAction({763id: 'workbench.extensions.action.enableAll',764title: localize2('enableAll', 'Enable All Extensions'),765category: ExtensionsLocalizedLabel,766menu: [{767id: MenuId.CommandPalette,768when: ContextKeyExpr.or(CONTEXT_HAS_LOCAL_SERVER, CONTEXT_HAS_REMOTE_SERVER, CONTEXT_HAS_WEB_SERVER)769}, {770id: MenuId.ViewContainerTitle,771when: ContextKeyExpr.equals('viewContainer', VIEWLET_ID),772group: '2_enablement',773order: 1774}],775run: async () => {776const extensionsToEnable = this.extensionsWorkbenchService.local.filter(e => !!e.local && this.extensionEnablementService.canChangeEnablement(e.local) && !this.extensionEnablementService.isEnabled(e.local));777if (extensionsToEnable.length) {778await this.extensionsWorkbenchService.setEnablement(extensionsToEnable, EnablementState.EnabledGlobally);779}780}781});782783this.registerExtensionAction({784id: 'workbench.extensions.action.enableAllWorkspace',785title: localize2('enableAllWorkspace', 'Enable All Extensions for this Workspace'),786category: ExtensionsLocalizedLabel,787menu: {788id: MenuId.CommandPalette,789when: ContextKeyExpr.and(WorkbenchStateContext.notEqualsTo('empty'), ContextKeyExpr.or(CONTEXT_HAS_LOCAL_SERVER, CONTEXT_HAS_REMOTE_SERVER, CONTEXT_HAS_WEB_SERVER))790},791run: async () => {792const extensionsToEnable = this.extensionsWorkbenchService.local.filter(e => !!e.local && this.extensionEnablementService.canChangeEnablement(e.local) && !this.extensionEnablementService.isEnabled(e.local));793if (extensionsToEnable.length) {794await this.extensionsWorkbenchService.setEnablement(extensionsToEnable, EnablementState.EnabledWorkspace);795}796}797});798799this.registerExtensionAction({800id: 'workbench.extensions.action.disableAll',801title: localize2('disableAll', 'Disable All Installed Extensions'),802category: ExtensionsLocalizedLabel,803menu: [{804id: MenuId.CommandPalette,805when: ContextKeyExpr.or(CONTEXT_HAS_LOCAL_SERVER, CONTEXT_HAS_REMOTE_SERVER, CONTEXT_HAS_WEB_SERVER)806}, {807id: MenuId.ViewContainerTitle,808when: ContextKeyExpr.equals('viewContainer', VIEWLET_ID),809group: '2_enablement',810order: 2811}],812run: async () => {813const extensionsToDisable = this.extensionsWorkbenchService.local.filter(e => !e.isBuiltin && !!e.local && this.extensionEnablementService.isEnabled(e.local) && this.extensionEnablementService.canChangeEnablement(e.local));814if (extensionsToDisable.length) {815await this.extensionsWorkbenchService.setEnablement(extensionsToDisable, EnablementState.DisabledGlobally);816}817}818});819820this.registerExtensionAction({821id: 'workbench.extensions.action.disableAllWorkspace',822title: localize2('disableAllWorkspace', 'Disable All Installed Extensions for this Workspace'),823category: ExtensionsLocalizedLabel,824menu: {825id: MenuId.CommandPalette,826when: ContextKeyExpr.and(WorkbenchStateContext.notEqualsTo('empty'), ContextKeyExpr.or(CONTEXT_HAS_LOCAL_SERVER, CONTEXT_HAS_REMOTE_SERVER, CONTEXT_HAS_WEB_SERVER))827},828run: async () => {829const extensionsToDisable = this.extensionsWorkbenchService.local.filter(e => !e.isBuiltin && !!e.local && this.extensionEnablementService.isEnabled(e.local) && this.extensionEnablementService.canChangeEnablement(e.local));830if (extensionsToDisable.length) {831await this.extensionsWorkbenchService.setEnablement(extensionsToDisable, EnablementState.DisabledWorkspace);832}833}834});835836this.registerExtensionAction({837id: SELECT_INSTALL_VSIX_EXTENSION_COMMAND_ID,838title: localize2('InstallFromVSIX', 'Install from VSIX...'),839category: ExtensionsLocalizedLabel,840menu: [{841id: MenuId.CommandPalette,842when: ContextKeyExpr.or(CONTEXT_HAS_LOCAL_SERVER, CONTEXT_HAS_REMOTE_SERVER)843}, {844id: MenuId.ViewContainerTitle,845when: ContextKeyExpr.and(ContextKeyExpr.equals('viewContainer', VIEWLET_ID), ContextKeyExpr.or(CONTEXT_HAS_LOCAL_SERVER, CONTEXT_HAS_REMOTE_SERVER)),846group: '3_install',847order: 1848}],849run: async (accessor: ServicesAccessor) => {850const fileDialogService = accessor.get(IFileDialogService);851const commandService = accessor.get(ICommandService);852const vsixPaths = await fileDialogService.showOpenDialog({853title: localize('installFromVSIX', "Install from VSIX"),854filters: [{ name: 'VSIX Extensions', extensions: ['vsix'] }],855canSelectFiles: true,856canSelectMany: true,857openLabel: mnemonicButtonLabel(localize({ key: 'installButton', comment: ['&& denotes a mnemonic'] }, "&&Install"))858});859if (vsixPaths) {860await commandService.executeCommand(INSTALL_EXTENSION_FROM_VSIX_COMMAND_ID, vsixPaths);861}862}863});864865this.registerExtensionAction({866id: INSTALL_EXTENSION_FROM_VSIX_COMMAND_ID,867title: localize('installVSIX', "Install Extension VSIX"),868menu: [{869id: MenuId.ExplorerContext,870group: 'extensions',871when: ContextKeyExpr.and(ResourceContextKey.Extension.isEqualTo('.vsix'), ContextKeyExpr.or(CONTEXT_HAS_LOCAL_SERVER, CONTEXT_HAS_REMOTE_SERVER)),872}],873run: async (accessor: ServicesAccessor, resources: URI[] | URI) => {874const extensionsWorkbenchService = accessor.get(IExtensionsWorkbenchService);875const hostService = accessor.get(IHostService);876const notificationService = accessor.get(INotificationService);877878const vsixs = Array.isArray(resources) ? resources : [resources];879const result = await Promise.allSettled(vsixs.map(async (vsix) => await extensionsWorkbenchService.install(vsix, { installGivenVersion: true })));880let error: Error | undefined, requireReload = false, requireRestart = false;881for (const r of result) {882if (r.status === 'rejected') {883error = new Error(r.reason);884break;885}886requireReload = requireReload || r.value.runtimeState?.action === ExtensionRuntimeActionType.ReloadWindow;887requireRestart = requireRestart || r.value.runtimeState?.action === ExtensionRuntimeActionType.RestartExtensions;888}889if (error) {890throw error;891}892if (requireReload) {893notificationService.prompt(894Severity.Info,895vsixs.length > 1 ? localize('InstallVSIXs.successReload', "Completed installing extensions. Please reload Visual Studio Code to enable them.")896: localize('InstallVSIXAction.successReload', "Completed installing extension. Please reload Visual Studio Code to enable it."),897[{898label: localize('InstallVSIXAction.reloadNow', "Reload Now"),899run: () => hostService.reload()900}]901);902}903else if (requireRestart) {904notificationService.prompt(905Severity.Info,906vsixs.length > 1 ? localize('InstallVSIXs.successRestart', "Completed installing extensions. Please restart extensions to enable them.")907: localize('InstallVSIXAction.successRestart', "Completed installing extension. Please restart extensions to enable it."),908[{909label: localize('InstallVSIXAction.restartExtensions', "Restart Extensions"),910run: () => extensionsWorkbenchService.updateRunningExtensions()911}]912);913}914else {915notificationService.prompt(916Severity.Info,917vsixs.length > 1 ? localize('InstallVSIXs.successNoReload', "Completed installing extensions.") : localize('InstallVSIXAction.successNoReload', "Completed installing extension."),918[]919);920}921}922});923924this.registerExtensionAction({925id: 'workbench.extensions.action.installExtensionFromLocation',926title: localize2('installExtensionFromLocation', 'Install Extension from Location...'),927category: Categories.Developer,928menu: [{929id: MenuId.CommandPalette,930when: ContextKeyExpr.or(CONTEXT_HAS_WEB_SERVER, CONTEXT_HAS_LOCAL_SERVER)931}],932run: async (accessor: ServicesAccessor) => {933const extensionManagementService = accessor.get(IWorkbenchExtensionManagementService);934if (isWeb) {935return new Promise<void>((c, e) => {936const quickInputService = accessor.get(IQuickInputService);937const disposables = new DisposableStore();938const quickPick = disposables.add(quickInputService.createQuickPick());939quickPick.title = localize('installFromLocation', "Install Extension from Location");940quickPick.customButton = true;941quickPick.customLabel = localize('install button', "Install");942quickPick.placeholder = localize('installFromLocationPlaceHolder', "Location of the web extension");943quickPick.ignoreFocusOut = true;944disposables.add(Event.any(quickPick.onDidAccept, quickPick.onDidCustom)(async () => {945quickPick.hide();946if (quickPick.value) {947try {948await extensionManagementService.installFromLocation(URI.parse(quickPick.value));949} catch (error) {950e(error);951return;952}953}954c();955}));956disposables.add(quickPick.onDidHide(() => disposables.dispose()));957quickPick.show();958});959} else {960const fileDialogService = accessor.get(IFileDialogService);961const extensionLocation = await fileDialogService.showOpenDialog({962canSelectFolders: true,963canSelectFiles: false,964canSelectMany: false,965title: localize('installFromLocation', "Install Extension from Location"),966});967if (extensionLocation?.[0]) {968await extensionManagementService.installFromLocation(extensionLocation[0]);969}970}971}972});973974MenuRegistry.appendMenuItem(extensionsSearchActionsMenu, {975submenu: extensionsFilterSubMenu,976title: localize('filterExtensions', "Filter Extensions..."),977group: 'navigation',978order: 2,979icon: filterIcon,980});981982const showFeaturedExtensionsId = 'extensions.filter.featured';983const featuresExtensionsWhenContext = ContextKeyExpr.and(CONTEXT_HAS_GALLERY, ContextKeyExpr.regex(CONTEXT_GALLERY_FILTER_CAPABILITIES.key, new RegExp(`_${FilterType.Featured}_`)));984this.registerExtensionAction({985id: showFeaturedExtensionsId,986title: localize2('showFeaturedExtensions', 'Show Featured Extensions'),987category: ExtensionsLocalizedLabel,988menu: [{989id: MenuId.CommandPalette,990when: featuresExtensionsWhenContext991}, {992id: extensionsFilterSubMenu,993when: featuresExtensionsWhenContext,994group: '1_predefined',995order: 1,996}],997menuTitles: {998[extensionsFilterSubMenu.id]: localize('featured filter', "Featured")999},1000run: () => this.extensionsWorkbenchService.openSearch('@featured ')1001});10021003this.registerExtensionAction({1004id: 'workbench.extensions.action.showPopularExtensions',1005title: localize2('showPopularExtensions', 'Show Popular Extensions'),1006category: ExtensionsLocalizedLabel,1007menu: [{1008id: MenuId.CommandPalette,1009when: CONTEXT_HAS_GALLERY1010}, {1011id: extensionsFilterSubMenu,1012when: CONTEXT_HAS_GALLERY,1013group: '1_predefined',1014order: 2,1015}],1016menuTitles: {1017[extensionsFilterSubMenu.id]: localize('most popular filter', "Most Popular")1018},1019run: () => this.extensionsWorkbenchService.openSearch('@popular ')1020});10211022this.registerExtensionAction({1023id: 'workbench.extensions.action.showRecommendedExtensions',1024title: localize2('showRecommendedExtensions', 'Show Recommended Extensions'),1025category: ExtensionsLocalizedLabel,1026menu: [{1027id: MenuId.CommandPalette,1028when: CONTEXT_HAS_GALLERY1029}, {1030id: extensionsFilterSubMenu,1031when: CONTEXT_HAS_GALLERY,1032group: '1_predefined',1033order: 2,1034}],1035menuTitles: {1036[extensionsFilterSubMenu.id]: localize('most popular recommended', "Recommended")1037},1038run: () => this.extensionsWorkbenchService.openSearch('@recommended ')1039});10401041this.registerExtensionAction({1042id: 'workbench.extensions.action.recentlyPublishedExtensions',1043title: localize2('recentlyPublishedExtensions', 'Show Recently Published Extensions'),1044category: ExtensionsLocalizedLabel,1045menu: [{1046id: MenuId.CommandPalette,1047when: CONTEXT_HAS_GALLERY1048}, {1049id: extensionsFilterSubMenu,1050when: CONTEXT_HAS_GALLERY,1051group: '1_predefined',1052order: 2,1053}],1054menuTitles: {1055[extensionsFilterSubMenu.id]: localize('recently published filter', "Recently Published")1056},1057run: () => this.extensionsWorkbenchService.openSearch('@recentlyPublished ')1058});10591060const extensionsCategoryFilterSubMenu = new MenuId('extensionsCategoryFilterSubMenu');1061MenuRegistry.appendMenuItem(extensionsFilterSubMenu, {1062submenu: extensionsCategoryFilterSubMenu,1063title: localize('filter by category', "Category"),1064when: ContextKeyExpr.and(CONTEXT_HAS_GALLERY, ContextKeyExpr.regex(CONTEXT_GALLERY_FILTER_CAPABILITIES.key, new RegExp(`_${FilterType.Category}_`))),1065group: '2_categories',1066order: 1,1067});10681069EXTENSION_CATEGORIES.forEach((category, index) => {1070this.registerExtensionAction({1071id: `extensions.actions.searchByCategory.${category}`,1072title: category,1073menu: [{1074id: extensionsCategoryFilterSubMenu,1075when: CONTEXT_HAS_GALLERY,1076order: index,1077}],1078run: () => this.extensionsWorkbenchService.openSearch(`@category:"${category.toLowerCase()}"`)1079});1080});10811082this.registerExtensionAction({1083id: 'workbench.extensions.action.installedExtensions',1084title: localize2('installedExtensions', 'Show Installed Extensions'),1085category: ExtensionsLocalizedLabel,1086f1: true,1087menu: [{1088id: extensionsFilterSubMenu,1089group: '3_installed',1090order: 1,1091}],1092menuTitles: {1093[extensionsFilterSubMenu.id]: localize('installed filter', "Installed")1094},1095run: () => this.extensionsWorkbenchService.openSearch('@installed ')1096});10971098this.registerExtensionAction({1099id: 'workbench.extensions.action.listBuiltInExtensions',1100title: localize2('showBuiltInExtensions', 'Show Built-in Extensions'),1101category: ExtensionsLocalizedLabel,1102menu: [{1103id: MenuId.CommandPalette,1104when: ContextKeyExpr.or(CONTEXT_HAS_LOCAL_SERVER, CONTEXT_HAS_REMOTE_SERVER, CONTEXT_HAS_WEB_SERVER)1105}, {1106id: extensionsFilterSubMenu,1107group: '3_installed',1108order: 3,1109}],1110menuTitles: {1111[extensionsFilterSubMenu.id]: localize('builtin filter', "Built-in")1112},1113run: () => this.extensionsWorkbenchService.openSearch('@builtin ')1114});11151116this.registerExtensionAction({1117id: 'workbench.extensions.action.extensionUpdates',1118title: localize2('extensionUpdates', 'Show Extension Updates'),1119category: ExtensionsLocalizedLabel,1120precondition: CONTEXT_HAS_GALLERY,1121f1: true,1122menu: [{1123id: extensionsFilterSubMenu,1124group: '3_installed',1125when: CONTEXT_HAS_GALLERY,1126order: 2,1127}],1128menuTitles: {1129[extensionsFilterSubMenu.id]: localize('extension updates filter', "Updates")1130},1131run: () => this.extensionsWorkbenchService.openSearch('@updates')1132});11331134this.registerExtensionAction({1135id: LIST_WORKSPACE_UNSUPPORTED_EXTENSIONS_COMMAND_ID,1136title: localize2('showWorkspaceUnsupportedExtensions', 'Show Extensions Unsupported By Workspace'),1137category: ExtensionsLocalizedLabel,1138menu: [{1139id: MenuId.CommandPalette,1140when: ContextKeyExpr.or(CONTEXT_HAS_LOCAL_SERVER, CONTEXT_HAS_REMOTE_SERVER),1141}, {1142id: extensionsFilterSubMenu,1143group: '3_installed',1144order: 6,1145when: ContextKeyExpr.or(CONTEXT_HAS_LOCAL_SERVER, CONTEXT_HAS_REMOTE_SERVER),1146}],1147menuTitles: {1148[extensionsFilterSubMenu.id]: localize('workspace unsupported filter', "Workspace Unsupported")1149},1150run: () => this.extensionsWorkbenchService.openSearch('@workspaceUnsupported')1151});11521153this.registerExtensionAction({1154id: 'workbench.extensions.action.showEnabledExtensions',1155title: localize2('showEnabledExtensions', 'Show Enabled Extensions'),1156category: ExtensionsLocalizedLabel,1157menu: [{1158id: MenuId.CommandPalette,1159when: ContextKeyExpr.or(CONTEXT_HAS_LOCAL_SERVER, CONTEXT_HAS_REMOTE_SERVER, CONTEXT_HAS_WEB_SERVER)1160}, {1161id: extensionsFilterSubMenu,1162group: '3_installed',1163order: 4,1164}],1165menuTitles: {1166[extensionsFilterSubMenu.id]: localize('enabled filter', "Enabled")1167},1168run: () => this.extensionsWorkbenchService.openSearch('@enabled ')1169});11701171this.registerExtensionAction({1172id: 'workbench.extensions.action.showDisabledExtensions',1173title: localize2('showDisabledExtensions', 'Show Disabled Extensions'),1174category: ExtensionsLocalizedLabel,1175menu: [{1176id: MenuId.CommandPalette,1177when: ContextKeyExpr.or(CONTEXT_HAS_LOCAL_SERVER, CONTEXT_HAS_REMOTE_SERVER, CONTEXT_HAS_WEB_SERVER)1178}, {1179id: extensionsFilterSubMenu,1180group: '3_installed',1181order: 5,1182}],1183menuTitles: {1184[extensionsFilterSubMenu.id]: localize('disabled filter', "Disabled")1185},1186run: () => this.extensionsWorkbenchService.openSearch('@disabled ')1187});11881189const extensionsSortSubMenu = new MenuId('extensionsSortSubMenu');1190MenuRegistry.appendMenuItem(extensionsFilterSubMenu, {1191submenu: extensionsSortSubMenu,1192title: localize('sorty by', "Sort By"),1193when: ContextKeyExpr.and(ContextKeyExpr.or(CONTEXT_HAS_GALLERY, DefaultViewsContext)),1194group: '4_sort',1195order: 1,1196});11971198[1199{ id: 'installs', title: localize('sort by installs', "Install Count"), precondition: BuiltInExtensionsContext.negate(), sortCapability: SortBy.InstallCount },1200{ id: 'rating', title: localize('sort by rating', "Rating"), precondition: BuiltInExtensionsContext.negate(), sortCapability: SortBy.WeightedRating },1201{ id: 'name', title: localize('sort by name', "Name"), precondition: BuiltInExtensionsContext.negate(), sortCapability: SortBy.Title },1202{ id: 'publishedDate', title: localize('sort by published date', "Published Date"), precondition: BuiltInExtensionsContext.negate(), sortCapability: SortBy.PublishedDate },1203{ id: 'updateDate', title: localize('sort by update date', "Updated Date"), precondition: ContextKeyExpr.and(SearchMarketplaceExtensionsContext.negate(), RecommendedExtensionsContext.negate(), BuiltInExtensionsContext.negate()), sortCapability: 'UpdateDate' },1204].map(({ id, title, precondition, sortCapability }, index) => {1205const sortCapabilityContext = ContextKeyExpr.regex(CONTEXT_GALLERY_SORT_CAPABILITIES.key, new RegExp(`_${sortCapability}_`));1206this.registerExtensionAction({1207id: `extensions.sort.${id}`,1208title,1209precondition: ContextKeyExpr.and(precondition, ContextKeyExpr.regex(ExtensionsSearchValueContext.key, /^@contribute:/).negate(), sortCapabilityContext),1210menu: [{1211id: extensionsSortSubMenu,1212when: ContextKeyExpr.and(ContextKeyExpr.or(CONTEXT_HAS_GALLERY, DefaultViewsContext), sortCapabilityContext),1213order: index,1214}],1215toggled: ExtensionsSortByContext.isEqualTo(id),1216run: async () => {1217const extensionsViewPaneContainer = ((await this.viewsService.openViewContainer(VIEWLET_ID, true))?.getViewPaneContainer()) as IExtensionsViewPaneContainer | undefined;1218const currentQuery = Query.parse(extensionsViewPaneContainer?.searchValue ?? '');1219extensionsViewPaneContainer?.search(new Query(currentQuery.value, id).toString());1220extensionsViewPaneContainer?.focus();1221}1222});1223});12241225this.registerExtensionAction({1226id: 'workbench.extensions.action.clearExtensionsSearchResults',1227title: localize2('clearExtensionsSearchResults', 'Clear Extensions Search Results'),1228category: ExtensionsLocalizedLabel,1229icon: clearSearchResultsIcon,1230f1: true,1231precondition: SearchHasTextContext,1232menu: {1233id: extensionsSearchActionsMenu,1234group: 'navigation',1235order: 1,1236},1237run: async (accessor: ServicesAccessor) => {1238const viewPaneContainer = accessor.get(IViewsService).getActiveViewPaneContainerWithId(VIEWLET_ID);1239if (viewPaneContainer) {1240const extensionsViewPaneContainer = viewPaneContainer as IExtensionsViewPaneContainer;1241extensionsViewPaneContainer.search('');1242extensionsViewPaneContainer.focus();1243}1244}1245});12461247this.registerExtensionAction({1248id: 'workbench.extensions.action.refreshExtension',1249title: localize2('refreshExtension', 'Refresh'),1250category: ExtensionsLocalizedLabel,1251icon: refreshIcon,1252f1: true,1253menu: {1254id: MenuId.ViewContainerTitle,1255when: ContextKeyExpr.equals('viewContainer', VIEWLET_ID),1256group: 'navigation',1257order: 21258},1259run: async (accessor: ServicesAccessor) => {1260const viewPaneContainer = accessor.get(IViewsService).getActiveViewPaneContainerWithId(VIEWLET_ID);1261if (viewPaneContainer) {1262await (viewPaneContainer as IExtensionsViewPaneContainer).refresh();1263}1264}1265});12661267this.registerExtensionAction({1268id: 'workbench.extensions.action.installWorkspaceRecommendedExtensions',1269title: localize('installWorkspaceRecommendedExtensions', "Install Workspace Recommended Extensions"),1270icon: installWorkspaceRecommendedIcon,1271menu: {1272id: MenuId.ViewTitle,1273when: ContextKeyExpr.equals('view', WORKSPACE_RECOMMENDATIONS_VIEW_ID),1274group: 'navigation',1275order: 11276},1277run: async (accessor: ServicesAccessor) => {1278const view = accessor.get(IViewsService).getActiveViewWithId(WORKSPACE_RECOMMENDATIONS_VIEW_ID) as IWorkspaceRecommendedExtensionsView;1279return view.installWorkspaceRecommendations();1280}1281});12821283this.registerExtensionAction({1284id: ConfigureWorkspaceFolderRecommendedExtensionsAction.ID,1285title: ConfigureWorkspaceFolderRecommendedExtensionsAction.LABEL,1286icon: configureRecommendedIcon,1287menu: [{1288id: MenuId.CommandPalette,1289when: WorkbenchStateContext.notEqualsTo('empty'),1290}, {1291id: MenuId.ViewTitle,1292when: ContextKeyExpr.equals('view', WORKSPACE_RECOMMENDATIONS_VIEW_ID),1293group: 'navigation',1294order: 21295}],1296run: () => runAction(this.instantiationService.createInstance(ConfigureWorkspaceFolderRecommendedExtensionsAction, ConfigureWorkspaceFolderRecommendedExtensionsAction.ID, ConfigureWorkspaceFolderRecommendedExtensionsAction.LABEL))1297});12981299this.registerExtensionAction({1300id: InstallSpecificVersionOfExtensionAction.ID,1301title: { value: InstallSpecificVersionOfExtensionAction.LABEL, original: 'Install Specific Version of Extension...' },1302category: ExtensionsLocalizedLabel,1303menu: {1304id: MenuId.CommandPalette,1305when: ContextKeyExpr.and(CONTEXT_HAS_GALLERY, ContextKeyExpr.or(CONTEXT_HAS_LOCAL_SERVER, CONTEXT_HAS_REMOTE_SERVER, CONTEXT_HAS_WEB_SERVER))1306},1307run: () => runAction(this.instantiationService.createInstance(InstallSpecificVersionOfExtensionAction, InstallSpecificVersionOfExtensionAction.ID, InstallSpecificVersionOfExtensionAction.LABEL))1308});1309}13101311// Extension Context Menu1312private registerContextMenuActions(): void {13131314this.registerExtensionAction({1315id: SetColorThemeAction.ID,1316title: SetColorThemeAction.TITLE,1317menu: {1318id: MenuId.ExtensionContext,1319group: THEME_ACTIONS_GROUP,1320order: 0,1321when: ContextKeyExpr.and(ContextKeyExpr.not('inExtensionEditor'), ContextKeyExpr.equals('extensionStatus', 'installed'), ContextKeyExpr.has('extensionHasColorThemes'))1322},1323run: async (accessor: ServicesAccessor, extensionId: string) => {1324const extensionWorkbenchService = accessor.get(IExtensionsWorkbenchService);1325const instantiationService = accessor.get(IInstantiationService);1326const extension = extensionWorkbenchService.local.find(e => areSameExtensions(e.identifier, { id: extensionId }));1327if (extension) {1328const action = instantiationService.createInstance(SetColorThemeAction);1329action.extension = extension;1330return action.run();1331}1332}1333});13341335this.registerExtensionAction({1336id: SetFileIconThemeAction.ID,1337title: SetFileIconThemeAction.TITLE,1338menu: {1339id: MenuId.ExtensionContext,1340group: THEME_ACTIONS_GROUP,1341order: 0,1342when: ContextKeyExpr.and(ContextKeyExpr.not('inExtensionEditor'), ContextKeyExpr.equals('extensionStatus', 'installed'), ContextKeyExpr.has('extensionHasFileIconThemes'))1343},1344run: async (accessor: ServicesAccessor, extensionId: string) => {1345const extensionWorkbenchService = accessor.get(IExtensionsWorkbenchService);1346const instantiationService = accessor.get(IInstantiationService);1347const extension = extensionWorkbenchService.local.find(e => areSameExtensions(e.identifier, { id: extensionId }));1348if (extension) {1349const action = instantiationService.createInstance(SetFileIconThemeAction);1350action.extension = extension;1351return action.run();1352}1353}1354});13551356this.registerExtensionAction({1357id: SetProductIconThemeAction.ID,1358title: SetProductIconThemeAction.TITLE,1359menu: {1360id: MenuId.ExtensionContext,1361group: THEME_ACTIONS_GROUP,1362order: 0,1363when: ContextKeyExpr.and(ContextKeyExpr.not('inExtensionEditor'), ContextKeyExpr.equals('extensionStatus', 'installed'), ContextKeyExpr.has('extensionHasProductIconThemes'))1364},1365run: async (accessor: ServicesAccessor, extensionId: string) => {1366const extensionWorkbenchService = accessor.get(IExtensionsWorkbenchService);1367const instantiationService = accessor.get(IInstantiationService);1368const extension = extensionWorkbenchService.local.find(e => areSameExtensions(e.identifier, { id: extensionId }));1369if (extension) {1370const action = instantiationService.createInstance(SetProductIconThemeAction);1371action.extension = extension;1372return action.run();1373}1374}1375});13761377this.registerExtensionAction({1378id: 'workbench.extensions.action.showPreReleaseVersion',1379title: localize2('show pre-release version', 'Show Pre-Release Version'),1380menu: {1381id: MenuId.ExtensionContext,1382group: INSTALL_ACTIONS_GROUP,1383order: 0,1384when: ContextKeyExpr.and(ContextKeyExpr.has('inExtensionEditor'), ContextKeyExpr.has('galleryExtensionHasPreReleaseVersion'), ContextKeyExpr.has('isPreReleaseExtensionAllowed'), ContextKeyExpr.not('showPreReleaseVersion'), ContextKeyExpr.not('isBuiltinExtension'))1385},1386run: async (accessor: ServicesAccessor, extensionId: string) => {1387const extensionWorkbenchService = accessor.get(IExtensionsWorkbenchService);1388const extension = (await extensionWorkbenchService.getExtensions([{ id: extensionId }], CancellationToken.None))[0];1389extensionWorkbenchService.open(extension, { showPreReleaseVersion: true });1390}1391});13921393this.registerExtensionAction({1394id: 'workbench.extensions.action.showReleasedVersion',1395title: localize2('show released version', 'Show Release Version'),1396menu: {1397id: MenuId.ExtensionContext,1398group: INSTALL_ACTIONS_GROUP,1399order: 1,1400when: ContextKeyExpr.and(ContextKeyExpr.has('inExtensionEditor'), ContextKeyExpr.has('galleryExtensionHasPreReleaseVersion'), ContextKeyExpr.has('extensionHasReleaseVersion'), ContextKeyExpr.has('showPreReleaseVersion'), ContextKeyExpr.not('isBuiltinExtension'))1401},1402run: async (accessor: ServicesAccessor, extensionId: string) => {1403const extensionWorkbenchService = accessor.get(IExtensionsWorkbenchService);1404const extension = (await extensionWorkbenchService.getExtensions([{ id: extensionId }], CancellationToken.None))[0];1405extensionWorkbenchService.open(extension, { showPreReleaseVersion: false });1406}1407});14081409this.registerExtensionAction({1410id: ToggleAutoUpdateForExtensionAction.ID,1411title: ToggleAutoUpdateForExtensionAction.LABEL,1412category: ExtensionsLocalizedLabel,1413precondition: ContextKeyExpr.and(ContextKeyExpr.or(ContextKeyExpr.notEquals(`config.${AutoUpdateConfigurationKey}`, 'onlyEnabledExtensions'), ContextKeyExpr.equals('isExtensionEnabled', true)), ContextKeyExpr.not('extensionDisallowInstall'), ContextKeyExpr.has('isExtensionAllowed')),1414menu: {1415id: MenuId.ExtensionContext,1416group: UPDATE_ACTIONS_GROUP,1417order: 1,1418when: ContextKeyExpr.and(1419ContextKeyExpr.not('inExtensionEditor'),1420ContextKeyExpr.equals('extensionStatus', 'installed'),1421ContextKeyExpr.not('isBuiltinExtension'),1422)1423},1424run: async (accessor: ServicesAccessor, id: string) => {1425const instantiationService = accessor.get(IInstantiationService);1426const extensionWorkbenchService = accessor.get(IExtensionsWorkbenchService);1427const extension = extensionWorkbenchService.local.find(e => areSameExtensions(e.identifier, { id }));1428if (extension) {1429const action = instantiationService.createInstance(ToggleAutoUpdateForExtensionAction);1430action.extension = extension;1431return action.run();1432}1433}1434});14351436this.registerExtensionAction({1437id: ToggleAutoUpdatesForPublisherAction.ID,1438title: { value: ToggleAutoUpdatesForPublisherAction.LABEL, original: 'Auto Update (Publisher)' },1439category: ExtensionsLocalizedLabel,1440precondition: ContextKeyExpr.equals(`config.${AutoUpdateConfigurationKey}`, false),1441menu: {1442id: MenuId.ExtensionContext,1443group: UPDATE_ACTIONS_GROUP,1444order: 2,1445when: ContextKeyExpr.and(ContextKeyExpr.equals('extensionStatus', 'installed'), ContextKeyExpr.not('isBuiltinExtension'))1446},1447run: async (accessor: ServicesAccessor, id: string) => {1448const instantiationService = accessor.get(IInstantiationService);1449const extensionWorkbenchService = accessor.get(IExtensionsWorkbenchService);1450const extension = extensionWorkbenchService.local.find(e => areSameExtensions(e.identifier, { id }));1451if (extension) {1452const action = instantiationService.createInstance(ToggleAutoUpdatesForPublisherAction);1453action.extension = extension;1454return action.run();1455}1456}1457});14581459this.registerExtensionAction({1460id: 'workbench.extensions.action.switchToPreRlease',1461title: localize('enablePreRleaseLabel', "Switch to Pre-Release Version"),1462category: ExtensionsLocalizedLabel,1463menu: {1464id: MenuId.ExtensionContext,1465group: INSTALL_ACTIONS_GROUP,1466order: 2,1467when: ContextKeyExpr.and(CONTEXT_HAS_GALLERY, ContextKeyExpr.has('galleryExtensionHasPreReleaseVersion'), ContextKeyExpr.has('isPreReleaseExtensionAllowed'), ContextKeyExpr.not('installedExtensionIsOptedToPreRelease'), ContextKeyExpr.not('inExtensionEditor'), ContextKeyExpr.equals('extensionStatus', 'installed'), ContextKeyExpr.not('isBuiltinExtension'))1468},1469run: async (accessor: ServicesAccessor, id: string) => {1470const instantiationService = accessor.get(IInstantiationService);1471const extensionWorkbenchService = accessor.get(IExtensionsWorkbenchService);1472const extension = extensionWorkbenchService.local.find(e => areSameExtensions(e.identifier, { id }));1473if (extension) {1474const action = instantiationService.createInstance(TogglePreReleaseExtensionAction);1475action.extension = extension;1476return action.run();1477}1478}1479});14801481this.registerExtensionAction({1482id: 'workbench.extensions.action.switchToRelease',1483title: localize('disablePreRleaseLabel', "Switch to Release Version"),1484category: ExtensionsLocalizedLabel,1485menu: {1486id: MenuId.ExtensionContext,1487group: INSTALL_ACTIONS_GROUP,1488order: 2,1489when: ContextKeyExpr.and(CONTEXT_HAS_GALLERY, ContextKeyExpr.has('galleryExtensionHasPreReleaseVersion'), ContextKeyExpr.has('isExtensionAllowed'), ContextKeyExpr.has('installedExtensionIsOptedToPreRelease'), ContextKeyExpr.not('inExtensionEditor'), ContextKeyExpr.equals('extensionStatus', 'installed'), ContextKeyExpr.not('isBuiltinExtension'))1490},1491run: async (accessor: ServicesAccessor, id: string) => {1492const instantiationService = accessor.get(IInstantiationService);1493const extensionWorkbenchService = accessor.get(IExtensionsWorkbenchService);1494const extension = extensionWorkbenchService.local.find(e => areSameExtensions(e.identifier, { id }));1495if (extension) {1496const action = instantiationService.createInstance(TogglePreReleaseExtensionAction);1497action.extension = extension;1498return action.run();1499}1500}1501});15021503this.registerExtensionAction({1504id: ClearLanguageAction.ID,1505title: ClearLanguageAction.TITLE,1506menu: {1507id: MenuId.ExtensionContext,1508group: INSTALL_ACTIONS_GROUP,1509order: 0,1510when: ContextKeyExpr.and(ContextKeyExpr.not('inExtensionEditor'), ContextKeyExpr.has('canSetLanguage'), ContextKeyExpr.has('isActiveLanguagePackExtension'))1511},1512run: async (accessor: ServicesAccessor, extensionId: string) => {1513const instantiationService = accessor.get(IInstantiationService);1514const extensionsWorkbenchService = accessor.get(IExtensionsWorkbenchService);1515const extension = (await extensionsWorkbenchService.getExtensions([{ id: extensionId }], CancellationToken.None))[0];1516const action = instantiationService.createInstance(ClearLanguageAction);1517action.extension = extension;1518return action.run();1519}1520});15211522this.registerExtensionAction({1523id: 'workbench.extensions.action.installUnsigned',1524title: localize('install', "Install"),1525menu: {1526id: MenuId.ExtensionContext,1527group: '0_install',1528when: ContextKeyExpr.and(ContextKeyExpr.equals('extensionStatus', 'uninstalled'), ContextKeyExpr.has('isGalleryExtension'), ContextKeyExpr.not('extensionDisallowInstall'), ContextKeyExpr.has('extensionIsUnsigned'),1529ContextKeyExpr.or(ContextKeyExpr.and(CONTEXT_GALLERY_ALL_PUBLIC_REPOSITORY_SIGNED, ContextKeyExpr.not('extensionIsPrivate')), ContextKeyExpr.and(CONTEXT_GALLERY_ALL_PRIVATE_REPOSITORY_SIGNED, ContextKeyExpr.has('extensionIsPrivate')))),1530order: 11531},1532run: async (accessor: ServicesAccessor, extensionId: string) => {1533const instantiationService = accessor.get(IInstantiationService);1534const extension = this.extensionsWorkbenchService.local.filter(e => areSameExtensions(e.identifier, { id: extensionId }))[0]1535|| (await this.extensionsWorkbenchService.getExtensions([{ id: extensionId }], CancellationToken.None))[0];1536if (extension) {1537const action = instantiationService.createInstance(InstallAction, { installPreReleaseVersion: this.extensionManagementService.preferPreReleases });1538action.extension = extension;1539return action.run();1540}1541}1542});15431544this.registerExtensionAction({1545id: 'workbench.extensions.action.installAndDonotSync',1546title: localize('install installAndDonotSync', "Install (Do not Sync)"),1547menu: {1548id: MenuId.ExtensionContext,1549group: '0_install',1550when: ContextKeyExpr.and(ContextKeyExpr.equals('extensionStatus', 'uninstalled'), ContextKeyExpr.has('isGalleryExtension'), ContextKeyExpr.has('isExtensionAllowed'), ContextKeyExpr.not('extensionDisallowInstall'), CONTEXT_SYNC_ENABLEMENT),1551order: 11552},1553run: async (accessor: ServicesAccessor, extensionId: string) => {1554const instantiationService = accessor.get(IInstantiationService);1555const extension = this.extensionsWorkbenchService.local.filter(e => areSameExtensions(e.identifier, { id: extensionId }))[0]1556|| (await this.extensionsWorkbenchService.getExtensions([{ id: extensionId }], CancellationToken.None))[0];1557if (extension) {1558const action = instantiationService.createInstance(InstallAction, {1559installPreReleaseVersion: this.extensionManagementService.preferPreReleases,1560isMachineScoped: true,1561});1562action.extension = extension;1563return action.run();1564}1565}1566});15671568this.registerExtensionAction({1569id: 'workbench.extensions.action.installPrereleaseAndDonotSync',1570title: localize('installPrereleaseAndDonotSync', "Install Pre-Release (Do not Sync)"),1571menu: {1572id: MenuId.ExtensionContext,1573group: '0_install',1574when: ContextKeyExpr.and(ContextKeyExpr.equals('extensionStatus', 'uninstalled'), ContextKeyExpr.has('isGalleryExtension'), ContextKeyExpr.has('extensionHasPreReleaseVersion'), ContextKeyExpr.has('isPreReleaseExtensionAllowed'), ContextKeyExpr.not('extensionDisallowInstall'), CONTEXT_SYNC_ENABLEMENT),1575order: 21576},1577run: async (accessor: ServicesAccessor, extensionId: string) => {1578const instantiationService = accessor.get(IInstantiationService);1579const extension = this.extensionsWorkbenchService.local.filter(e => areSameExtensions(e.identifier, { id: extensionId }))[0]1580|| (await this.extensionsWorkbenchService.getExtensions([{ id: extensionId }], CancellationToken.None))[0];1581if (extension) {1582const action = instantiationService.createInstance(InstallAction, {1583isMachineScoped: true,1584preRelease: true1585});1586action.extension = extension;1587return action.run();1588}1589}1590});15911592this.registerExtensionAction({1593id: InstallAnotherVersionAction.ID,1594title: InstallAnotherVersionAction.LABEL,1595menu: {1596id: MenuId.ExtensionContext,1597group: '0_install',1598when: ContextKeyExpr.and(ContextKeyExpr.equals('extensionStatus', 'uninstalled'), ContextKeyExpr.has('isGalleryExtension'), ContextKeyExpr.has('isExtensionAllowed'), ContextKeyExpr.not('extensionDisallowInstall')),1599order: 31600},1601run: async (accessor: ServicesAccessor, extensionId: string) => {1602const instantiationService = accessor.get(IInstantiationService);1603const extension = this.extensionsWorkbenchService.local.filter(e => areSameExtensions(e.identifier, { id: extensionId }))[0]1604|| (await this.extensionsWorkbenchService.getExtensions([{ id: extensionId }], CancellationToken.None))[0];1605if (extension) {1606return instantiationService.createInstance(InstallAnotherVersionAction, extension, false).run();1607}1608}1609});16101611this.registerExtensionAction({1612id: 'workbench.extensions.action.copyExtension',1613title: localize2('workbench.extensions.action.copyExtension', 'Copy'),1614menu: {1615id: MenuId.ExtensionContext,1616group: '1_copy'1617},1618run: async (accessor: ServicesAccessor, extensionId: string) => {1619const clipboardService = accessor.get(IClipboardService);1620const extension = this.extensionsWorkbenchService.local.filter(e => areSameExtensions(e.identifier, { id: extensionId }))[0]1621|| (await this.extensionsWorkbenchService.getExtensions([{ id: extensionId }], CancellationToken.None))[0];1622if (extension) {1623const name = localize('extensionInfoName', 'Name: {0}', extension.displayName);1624const id = localize('extensionInfoId', 'Id: {0}', extensionId);1625const description = localize('extensionInfoDescription', 'Description: {0}', extension.description);1626const verision = localize('extensionInfoVersion', 'Version: {0}', extension.version);1627const publisher = localize('extensionInfoPublisher', 'Publisher: {0}', extension.publisherDisplayName);1628const link = extension.url ? localize('extensionInfoVSMarketplaceLink', 'VS Marketplace Link: {0}', `${extension.url}`) : null;1629const clipboardStr = `${name}\n${id}\n${description}\n${verision}\n${publisher}${link ? '\n' + link : ''}`;1630await clipboardService.writeText(clipboardStr);1631}1632}1633});16341635this.registerExtensionAction({1636id: 'workbench.extensions.action.copyExtensionId',1637title: localize2('workbench.extensions.action.copyExtensionId', 'Copy Extension ID'),1638menu: {1639id: MenuId.ExtensionContext,1640group: '1_copy'1641},1642run: async (accessor: ServicesAccessor, id: string) => accessor.get(IClipboardService).writeText(id)1643});16441645this.registerExtensionAction({1646id: 'workbench.extensions.action.copyLink',1647title: localize2('workbench.extensions.action.copyLink', 'Copy Link'),1648menu: {1649id: MenuId.ExtensionContext,1650group: '1_copy',1651when: ContextKeyExpr.and(ContextKeyExpr.has('isGalleryExtension'), CONTEXT_GALLERY_HAS_EXTENSION_LINK),1652},1653run: async (accessor: ServicesAccessor, _, extension: IExtensionArg) => {1654const clipboardService = accessor.get(IClipboardService);1655if (extension.galleryLink) {1656await clipboardService.writeText(extension.galleryLink);1657}1658}1659});16601661this.registerExtensionAction({1662id: 'workbench.extensions.action.configure',1663title: localize2('workbench.extensions.action.configure', 'Settings'),1664menu: {1665id: MenuId.ExtensionContext,1666group: '2_configure',1667when: ContextKeyExpr.and(ContextKeyExpr.equals('extensionStatus', 'installed'), ContextKeyExpr.has('extensionHasConfiguration')),1668order: 11669},1670run: async (accessor: ServicesAccessor, id: string) => accessor.get(IPreferencesService).openSettings({ jsonEditor: false, query: `@ext:${id}` })1671});16721673this.registerExtensionAction({1674id: 'workbench.extensions.action.download',1675title: localize('download VSIX', "Download VSIX"),1676menu: {1677id: MenuId.ExtensionContext,1678when: ContextKeyExpr.and(ContextKeyExpr.not('extensionDisallowInstall'), ContextKeyExpr.has('isGalleryExtension')),1679order: this.productService.quality === 'stable' ? 0 : 11680},1681run: async (accessor: ServicesAccessor, extensionId: string) => {1682accessor.get(IExtensionsWorkbenchService).downloadVSIX(extensionId, 'release');1683}1684});16851686this.registerExtensionAction({1687id: 'workbench.extensions.action.downloadPreRelease',1688title: localize('download pre-release', "Download Pre-Release VSIX"),1689menu: {1690id: MenuId.ExtensionContext,1691when: ContextKeyExpr.and(ContextKeyExpr.not('extensionDisallowInstall'), ContextKeyExpr.has('isGalleryExtension'), ContextKeyExpr.has('extensionHasPreReleaseVersion')),1692order: this.productService.quality === 'stable' ? 1 : 01693},1694run: async (accessor: ServicesAccessor, extensionId: string) => {1695accessor.get(IExtensionsWorkbenchService).downloadVSIX(extensionId, 'prerelease');1696}1697});16981699this.registerExtensionAction({1700id: 'workbench.extensions.action.downloadSpecificVersion',1701title: localize('download specific version', "Download Specific Version VSIX..."),1702menu: {1703id: MenuId.ExtensionContext,1704when: ContextKeyExpr.and(ContextKeyExpr.not('extensionDisallowInstall'), ContextKeyExpr.has('isGalleryExtension')),1705order: 21706},1707run: async (accessor: ServicesAccessor, extensionId: string) => {1708accessor.get(IExtensionsWorkbenchService).downloadVSIX(extensionId, 'any');1709}1710});17111712this.registerExtensionAction({1713id: 'workbench.extensions.action.manageAccountPreferences',1714title: localize2('workbench.extensions.action.changeAccountPreference', "Account Preferences"),1715menu: {1716id: MenuId.ExtensionContext,1717group: '2_configure',1718when: ContextKeyExpr.and(ContextKeyExpr.equals('extensionStatus', 'installed'), ContextKeyExpr.has('extensionHasAccountPreferences')),1719order: 2,1720},1721run: (accessor: ServicesAccessor, id: string) => accessor.get(ICommandService).executeCommand('_manageAccountPreferencesForExtension', id)1722});17231724this.registerExtensionAction({1725id: 'workbench.extensions.action.configureKeybindings',1726title: localize2('workbench.extensions.action.configureKeybindings', 'Keyboard Shortcuts'),1727menu: {1728id: MenuId.ExtensionContext,1729group: '2_configure',1730when: ContextKeyExpr.and(ContextKeyExpr.equals('extensionStatus', 'installed'), ContextKeyExpr.has('extensionHasKeybindings')),1731order: 21732},1733run: async (accessor: ServicesAccessor, id: string) => accessor.get(IPreferencesService).openGlobalKeybindingSettings(false, { query: `@ext:${id}` })1734});17351736this.registerExtensionAction({1737id: 'workbench.extensions.action.toggleApplyToAllProfiles',1738title: localize2('workbench.extensions.action.toggleApplyToAllProfiles', "Apply Extension to all Profiles"),1739toggled: ContextKeyExpr.has('isApplicationScopedExtension'),1740menu: {1741id: MenuId.ExtensionContext,1742group: '2_configure',1743when: ContextKeyExpr.and(ContextKeyExpr.equals('extensionStatus', 'installed'), ContextKeyExpr.has('isDefaultApplicationScopedExtension').negate(), ContextKeyExpr.has('isBuiltinExtension').negate(), ContextKeyExpr.equals('isWorkspaceScopedExtension', false)),1744order: 31745},1746run: async (accessor: ServicesAccessor, _: string, extensionArg: IExtensionArg) => {1747const uriIdentityService = accessor.get(IUriIdentityService);1748const extension = extensionArg.location ? this.extensionsWorkbenchService.installed.find(e => uriIdentityService.extUri.isEqual(e.local?.location, extensionArg.location)) : undefined;1749if (extension) {1750return this.extensionsWorkbenchService.toggleApplyExtensionToAllProfiles(extension);1751}1752}1753});17541755this.registerExtensionAction({1756id: TOGGLE_IGNORE_EXTENSION_ACTION_ID,1757title: localize2('workbench.extensions.action.toggleIgnoreExtension', "Sync This Extension"),1758menu: {1759id: MenuId.ExtensionContext,1760group: '2_configure',1761when: ContextKeyExpr.and(ContextKeyExpr.equals('extensionStatus', 'installed'), CONTEXT_SYNC_ENABLEMENT, ContextKeyExpr.equals('isWorkspaceScopedExtension', false)),1762order: 41763},1764run: async (accessor: ServicesAccessor, id: string) => {1765const extension = this.extensionsWorkbenchService.local.find(e => areSameExtensions({ id }, e.identifier));1766if (extension) {1767return this.extensionsWorkbenchService.toggleExtensionIgnoredToSync(extension);1768}1769}1770});17711772this.registerExtensionAction({1773id: 'workbench.extensions.action.ignoreRecommendation',1774title: localize2('workbench.extensions.action.ignoreRecommendation', "Ignore Recommendation"),1775menu: {1776id: MenuId.ExtensionContext,1777group: '3_recommendations',1778when: ContextKeyExpr.has('isExtensionRecommended'),1779order: 11780},1781run: async (accessor: ServicesAccessor, id: string) => accessor.get(IExtensionIgnoredRecommendationsService).toggleGlobalIgnoredRecommendation(id, true)1782});17831784this.registerExtensionAction({1785id: 'workbench.extensions.action.undoIgnoredRecommendation',1786title: localize2('workbench.extensions.action.undoIgnoredRecommendation', "Undo Ignored Recommendation"),1787menu: {1788id: MenuId.ExtensionContext,1789group: '3_recommendations',1790when: ContextKeyExpr.has('isUserIgnoredRecommendation'),1791order: 11792},1793run: async (accessor: ServicesAccessor, id: string) => accessor.get(IExtensionIgnoredRecommendationsService).toggleGlobalIgnoredRecommendation(id, false)1794});17951796this.registerExtensionAction({1797id: 'workbench.extensions.action.addExtensionToWorkspaceRecommendations',1798title: localize2('workbench.extensions.action.addExtensionToWorkspaceRecommendations', "Add to Workspace Recommendations"),1799menu: {1800id: MenuId.ExtensionContext,1801group: '3_recommendations',1802when: ContextKeyExpr.and(WorkbenchStateContext.notEqualsTo('empty'), ContextKeyExpr.has('isBuiltinExtension').negate(), ContextKeyExpr.has('isExtensionWorkspaceRecommended').negate(), ContextKeyExpr.has('isUserIgnoredRecommendation').negate(), ContextKeyExpr.notEquals('extensionSource', 'resource')),1803order: 21804},1805run: (accessor: ServicesAccessor, id: string) => accessor.get(IWorkspaceExtensionsConfigService).toggleRecommendation(id)1806});18071808this.registerExtensionAction({1809id: 'workbench.extensions.action.removeExtensionFromWorkspaceRecommendations',1810title: localize2('workbench.extensions.action.removeExtensionFromWorkspaceRecommendations', "Remove from Workspace Recommendations"),1811menu: {1812id: MenuId.ExtensionContext,1813group: '3_recommendations',1814when: ContextKeyExpr.and(WorkbenchStateContext.notEqualsTo('empty'), ContextKeyExpr.has('isBuiltinExtension').negate(), ContextKeyExpr.has('isExtensionWorkspaceRecommended')),1815order: 21816},1817run: (accessor: ServicesAccessor, id: string) => accessor.get(IWorkspaceExtensionsConfigService).toggleRecommendation(id)1818});18191820this.registerExtensionAction({1821id: 'workbench.extensions.action.addToWorkspaceRecommendations',1822title: localize2('workbench.extensions.action.addToWorkspaceRecommendations', "Add Extension to Workspace Recommendations"),1823category: EXTENSIONS_CATEGORY,1824menu: {1825id: MenuId.CommandPalette,1826when: ContextKeyExpr.and(WorkbenchStateContext.isEqualTo('workspace'), ContextKeyExpr.equals('resourceScheme', Schemas.extension)),1827},1828async run(accessor: ServicesAccessor): Promise<any> {1829const editorService = accessor.get(IEditorService);1830const workspaceExtensionsConfigService = accessor.get(IWorkspaceExtensionsConfigService);1831if (!(editorService.activeEditor instanceof ExtensionsInput)) {1832return;1833}1834const extensionId = editorService.activeEditor.extension.identifier.id.toLowerCase();1835const recommendations = await workspaceExtensionsConfigService.getRecommendations();1836if (recommendations.includes(extensionId)) {1837return;1838}1839await workspaceExtensionsConfigService.toggleRecommendation(extensionId);1840}1841});18421843this.registerExtensionAction({1844id: 'workbench.extensions.action.addToWorkspaceFolderRecommendations',1845title: localize2('workbench.extensions.action.addToWorkspaceFolderRecommendations', "Add Extension to Workspace Folder Recommendations"),1846category: EXTENSIONS_CATEGORY,1847menu: {1848id: MenuId.CommandPalette,1849when: ContextKeyExpr.and(WorkbenchStateContext.isEqualTo('folder'), ContextKeyExpr.equals('resourceScheme', Schemas.extension)),1850},1851run: () => this.commandService.executeCommand('workbench.extensions.action.addToWorkspaceRecommendations')1852});18531854this.registerExtensionAction({1855id: 'workbench.extensions.action.addToWorkspaceIgnoredRecommendations',1856title: localize2('workbench.extensions.action.addToWorkspaceIgnoredRecommendations', "Add Extension to Workspace Ignored Recommendations"),1857category: EXTENSIONS_CATEGORY,1858menu: {1859id: MenuId.CommandPalette,1860when: ContextKeyExpr.and(WorkbenchStateContext.isEqualTo('workspace'), ContextKeyExpr.equals('resourceScheme', Schemas.extension)),1861},1862async run(accessor: ServicesAccessor): Promise<any> {1863const editorService = accessor.get(IEditorService);1864const workspaceExtensionsConfigService = accessor.get(IWorkspaceExtensionsConfigService);1865if (!(editorService.activeEditor instanceof ExtensionsInput)) {1866return;1867}1868const extensionId = editorService.activeEditor.extension.identifier.id.toLowerCase();1869const unwantedRecommendations = await workspaceExtensionsConfigService.getUnwantedRecommendations();1870if (unwantedRecommendations.includes(extensionId)) {1871return;1872}1873await workspaceExtensionsConfigService.toggleUnwantedRecommendation(extensionId);1874}1875});18761877this.registerExtensionAction({1878id: 'workbench.extensions.action.addToWorkspaceFolderIgnoredRecommendations',1879title: localize2('workbench.extensions.action.addToWorkspaceFolderIgnoredRecommendations', "Add Extension to Workspace Folder Ignored Recommendations"),1880category: EXTENSIONS_CATEGORY,1881menu: {1882id: MenuId.CommandPalette,1883when: ContextKeyExpr.and(WorkbenchStateContext.isEqualTo('folder'), ContextKeyExpr.equals('resourceScheme', Schemas.extension)),1884},1885run: () => this.commandService.executeCommand('workbench.extensions.action.addToWorkspaceIgnoredRecommendations')1886});18871888this.registerExtensionAction({1889id: ConfigureWorkspaceRecommendedExtensionsAction.ID,1890title: { value: ConfigureWorkspaceRecommendedExtensionsAction.LABEL, original: 'Configure Recommended Extensions (Workspace)' },1891category: EXTENSIONS_CATEGORY,1892menu: {1893id: MenuId.CommandPalette,1894when: WorkbenchStateContext.isEqualTo('workspace'),1895},1896run: () => runAction(this.instantiationService.createInstance(ConfigureWorkspaceRecommendedExtensionsAction, ConfigureWorkspaceRecommendedExtensionsAction.ID, ConfigureWorkspaceRecommendedExtensionsAction.LABEL))1897});18981899this.registerExtensionAction({1900id: 'workbench.extensions.action.manageTrustedPublishers',1901title: localize2('workbench.extensions.action.manageTrustedPublishers', "Manage Trusted Extension Publishers"),1902category: EXTENSIONS_CATEGORY,1903f1: true,1904run: async (accessor: ServicesAccessor) => {1905const quickInputService = accessor.get(IQuickInputService);1906const extensionManagementService = accessor.get(IWorkbenchExtensionManagementService);1907const trustedPublishers = extensionManagementService.getTrustedPublishers();1908const trustedPublisherItems = trustedPublishers.map(publisher => ({1909id: publisher.publisher,1910label: publisher.publisherDisplayName,1911description: publisher.publisher,1912picked: true,1913})).sort((a, b) => a.label.localeCompare(b.label));1914const result = await quickInputService.pick(trustedPublisherItems, {1915canPickMany: true,1916title: localize('trustedPublishers', "Manage Trusted Extension Publishers"),1917placeHolder: localize('trustedPublishersPlaceholder', "Choose which publishers to trust"),1918});1919if (result) {1920const untrustedPublishers = [];1921for (const { publisher } of trustedPublishers) {1922if (!result.some(r => r.id === publisher)) {1923untrustedPublishers.push(publisher);1924}1925}1926trustedPublishers.filter(publisher => !result.some(r => r.id === publisher.publisher));1927extensionManagementService.untrustPublishers(...untrustedPublishers);1928}1929}1930});19311932}19331934private registerExtensionAction(extensionActionOptions: IExtensionActionOptions): IDisposable {1935const menus = extensionActionOptions.menu ? Array.isArray(extensionActionOptions.menu) ? extensionActionOptions.menu : [extensionActionOptions.menu] : [];1936let menusWithOutTitles: ({ id: MenuId } & Omit<IMenuItem, 'command'>)[] = [];1937const menusWithTitles: { id: MenuId; item: IMenuItem }[] = [];1938if (extensionActionOptions.menuTitles) {1939for (let index = 0; index < menus.length; index++) {1940const menu = menus[index];1941const menuTitle = extensionActionOptions.menuTitles[menu.id.id];1942if (menuTitle) {1943menusWithTitles.push({ id: menu.id, item: { ...menu, command: { id: extensionActionOptions.id, title: menuTitle } } });1944} else {1945menusWithOutTitles.push(menu);1946}1947}1948} else {1949menusWithOutTitles = menus;1950}1951const disposables = new DisposableStore();1952disposables.add(registerAction2(class extends Action2 {1953constructor() {1954super({1955...extensionActionOptions,1956menu: menusWithOutTitles1957});1958}1959run(accessor: ServicesAccessor, ...args: unknown[]): Promise<any> {1960return extensionActionOptions.run(accessor, ...args);1961}1962}));1963if (menusWithTitles.length) {1964disposables.add(MenuRegistry.appendMenuItems(menusWithTitles));1965}1966return disposables;1967}19681969}19701971class ExtensionStorageCleaner implements IWorkbenchContribution {19721973constructor(1974@IExtensionManagementService extensionManagementService: IExtensionManagementService,1975@IStorageService storageService: IStorageService,1976) {1977ExtensionStorageService.removeOutdatedExtensionVersions(extensionManagementService, storageService);1978}1979}19801981class TrustedPublishersInitializer implements IWorkbenchContribution {1982constructor(1983@IWorkbenchExtensionManagementService extensionManagementService: IWorkbenchExtensionManagementService,1984@IUserDataProfilesService userDataProfilesService: IUserDataProfilesService,1985@IProductService productService: IProductService,1986@IStorageService storageService: IStorageService,1987) {1988const trustedPublishersInitStatusKey = 'trusted-publishers-init-migration';1989if (!storageService.get(trustedPublishersInitStatusKey, StorageScope.APPLICATION)) {1990for (const profile of userDataProfilesService.profiles) {1991extensionManagementService.getInstalled(ExtensionType.User, profile.extensionsResource)1992.then(async extensions => {1993const trustedPublishers = new Map<string, IPublisherInfo>();1994for (const extension of extensions) {1995if (!extension.publisherDisplayName) {1996continue;1997}1998const publisher = extension.manifest.publisher.toLowerCase();1999if (productService.trustedExtensionPublishers?.includes(publisher)2000|| (extension.publisherDisplayName && productService.trustedExtensionPublishers?.includes(extension.publisherDisplayName.toLowerCase()))) {2001continue;2002}2003trustedPublishers.set(publisher, { publisher, publisherDisplayName: extension.publisherDisplayName });2004}2005if (trustedPublishers.size) {2006extensionManagementService.trustPublishers(...trustedPublishers.values());2007}2008storageService.store(trustedPublishersInitStatusKey, 'true', StorageScope.APPLICATION, StorageTarget.MACHINE);2009});2010}2011}2012}2013}20142015class ExtensionToolsContribution extends Disposable implements IWorkbenchContribution {20162017static readonly ID = 'extensions.chat.toolsContribution';20182019constructor(2020@ILanguageModelToolsService toolsService: ILanguageModelToolsService,2021@IInstantiationService instantiationService: IInstantiationService,2022) {2023super();2024const searchExtensionsTool = instantiationService.createInstance(SearchExtensionsTool);2025this._register(toolsService.registerTool(SearchExtensionsToolData, searchExtensionsTool));2026this._register(toolsService.vscodeToolSet.addTool(SearchExtensionsToolData));2027}2028}20292030const workbenchRegistry = Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench);2031workbenchRegistry.registerWorkbenchContribution(ExtensionsContributions, LifecyclePhase.Restored);2032workbenchRegistry.registerWorkbenchContribution(StatusUpdater, LifecyclePhase.Eventually);2033workbenchRegistry.registerWorkbenchContribution(MaliciousExtensionChecker, LifecyclePhase.Eventually);2034workbenchRegistry.registerWorkbenchContribution(KeymapExtensions, LifecyclePhase.Restored);2035workbenchRegistry.registerWorkbenchContribution(ExtensionsViewletViewsContribution, LifecyclePhase.Restored);2036workbenchRegistry.registerWorkbenchContribution(ExtensionActivationProgress, LifecyclePhase.Eventually);2037workbenchRegistry.registerWorkbenchContribution(ExtensionDependencyChecker, LifecyclePhase.Eventually);2038workbenchRegistry.registerWorkbenchContribution(ExtensionEnablementWorkspaceTrustTransitionParticipant, LifecyclePhase.Restored);2039workbenchRegistry.registerWorkbenchContribution(ExtensionsCompletionItemsProvider, LifecyclePhase.Restored);2040workbenchRegistry.registerWorkbenchContribution(UnsupportedExtensionsMigrationContrib, LifecyclePhase.Eventually);2041workbenchRegistry.registerWorkbenchContribution(TrustedPublishersInitializer, LifecyclePhase.Eventually);2042workbenchRegistry.registerWorkbenchContribution(ExtensionMarketplaceStatusUpdater, LifecyclePhase.Eventually);2043if (isWeb) {2044workbenchRegistry.registerWorkbenchContribution(ExtensionStorageCleaner, LifecyclePhase.Eventually);2045}20462047registerWorkbenchContribution2(ExtensionToolsContribution.ID, ExtensionToolsContribution, WorkbenchPhase.AfterRestored);204820492050// Running Extensions2051registerAction2(ShowRuntimeExtensionsAction);20522053registerAction2(class ExtensionsGallerySignInAction extends Action2 {2054constructor() {2055super({2056id: 'workbench.extensions.actions.gallery.signIn',2057title: localize2('signInToMarketplace', 'Sign in to access Extensions Marketplace'),2058menu: {2059id: MenuId.AccountsContext,2060when: CONTEXT_EXTENSIONS_GALLERY_STATUS.isEqualTo(ExtensionGalleryManifestStatus.RequiresSignIn)2061},2062});2063}2064run(accessor: ServicesAccessor): Promise<void> {2065return accessor.get(ICommandService).executeCommand(DEFAULT_ACCOUNT_SIGN_IN_COMMAND);2066}2067});20682069Registry.as<IConfigurationMigrationRegistry>(ConfigurationMigrationExtensions.ConfigurationMigration)2070.registerConfigurationMigrations([{2071key: AutoUpdateConfigurationKey,2072migrateFn: (value, accessor) => {2073if (value === 'onlySelectedExtensions') {2074return { value: false };2075}2076return [];2077}2078}]);207920802081