Path: blob/main/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts
3296 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 { URI, UriComponents } from '../../../../base/common/uri.js';16import { MultiCommand } from '../../../../editor/browser/editorExtensions.js';17import { CopyAction, CutAction, PasteAction } from '../../../../editor/contrib/clipboard/browser/clipboard.js';18import { localize, localize2 } from '../../../../nls.js';19import { Categories } from '../../../../platform/action/common/actionCommonCategories.js';20import { Action2, IAction2Options, IMenuItem, MenuId, MenuRegistry, registerAction2 } from '../../../../platform/actions/common/actions.js';21import { IClipboardService } from '../../../../platform/clipboard/common/clipboardService.js';22import { CommandsRegistry, ICommandService } from '../../../../platform/commands/common/commands.js';23import { Extensions as ConfigurationExtensions, ConfigurationScope, IConfigurationRegistry } from '../../../../platform/configuration/common/configurationRegistry.js';24import { ContextKeyExpr, IContextKeyService, RawContextKey } from '../../../../platform/contextkey/common/contextkey.js';25import { IDialogService, IFileDialogService } from '../../../../platform/dialogs/common/dialogs.js';26import { ExtensionGalleryManifestStatus, ExtensionGalleryResourceType, ExtensionGalleryServiceUrlConfigKey, getExtensionGalleryManifestResourceUri, IExtensionGalleryManifest, IExtensionGalleryManifestService } from '../../../../platform/extensionManagement/common/extensionGalleryManifest.js';27import { EXTENSION_INSTALL_SOURCE_CONTEXT, ExtensionInstallSource, ExtensionsLocalizedLabel, FilterType, IExtensionGalleryService, IExtensionManagementService, PreferencesLocalizedLabel, SortBy, VerifyExtensionSignatureConfigKey } from '../../../../platform/extensionManagement/common/extensionManagement.js';28import { areSameExtensions, getIdAndVersion } from '../../../../platform/extensionManagement/common/extensionManagementUtil.js';29import { ExtensionStorageService } from '../../../../platform/extensionManagement/common/extensionStorage.js';30import { IExtensionRecommendationNotificationService } from '../../../../platform/extensionRecommendations/common/extensionRecommendations.js';31import { EXTENSION_CATEGORIES, ExtensionType } from '../../../../platform/extensions/common/extensions.js';32import { SyncDescriptor } from '../../../../platform/instantiation/common/descriptors.js';33import { InstantiationType, registerSingleton } from '../../../../platform/instantiation/common/extensions.js';34import { IInstantiationService, ServicesAccessor } from '../../../../platform/instantiation/common/instantiation.js';35import * as jsonContributionRegistry from '../../../../platform/jsonschemas/common/jsonContributionRegistry.js';36import { INotificationService, Severity } from '../../../../platform/notification/common/notification.js';37import product from '../../../../platform/product/common/product.js';38import { IProductService } from '../../../../platform/product/common/productService.js';39import { ProgressLocation } from '../../../../platform/progress/common/progress.js';40import { Extensions, IQuickAccessRegistry } from '../../../../platform/quickinput/common/quickAccess.js';41import { IQuickInputService } from '../../../../platform/quickinput/common/quickInput.js';42import { Registry } from '../../../../platform/registry/common/platform.js';43import { IStorageService, StorageScope, StorageTarget } from '../../../../platform/storage/common/storage.js';44import { IUriIdentityService } from '../../../../platform/uriIdentity/common/uriIdentity.js';45import { IUserDataProfilesService } from '../../../../platform/userDataProfile/common/userDataProfile.js';46import { EditorPaneDescriptor, IEditorPaneRegistry } from '../../../browser/editor.js';47import { Extensions as ConfigurationMigrationExtensions, IConfigurationMigrationRegistry } from '../../../common/configuration.js';48import { ResourceContextKey, WorkbenchStateContext } from '../../../common/contextkeys.js';49import { IWorkbenchContribution, IWorkbenchContributionsRegistry, registerWorkbenchContribution2, Extensions as WorkbenchExtensions, WorkbenchPhase } from '../../../common/contributions.js';50import { EditorExtensions } from '../../../common/editor.js';51import { IViewContainersRegistry, Extensions as ViewContainerExtensions, ViewContainerLocation } from '../../../common/views.js';52import { DEFAULT_ACCOUNT_SIGN_IN_COMMAND } from '../../../services/accounts/common/defaultAccount.js';53import { IEditorService } from '../../../services/editor/common/editorService.js';54import { EnablementState, IExtensionManagementServerService, IPublisherInfo, IWorkbenchExtensionEnablementService, IWorkbenchExtensionManagementService } from '../../../services/extensionManagement/common/extensionManagement.js';55import { IExtensionIgnoredRecommendationsService, IExtensionRecommendationsService } from '../../../services/extensionRecommendations/common/extensionRecommendations.js';56import { IWorkspaceExtensionsConfigService } from '../../../services/extensionRecommendations/common/workspaceExtensionsConfig.js';57import { IHostService } from '../../../services/host/browser/host.js';58import { LifecyclePhase } from '../../../services/lifecycle/common/lifecycle.js';59import { IPreferencesService } from '../../../services/preferences/common/preferences.js';60import { CONTEXT_SYNC_ENABLEMENT } from '../../../services/userDataSync/common/userDataSync.js';61import { IViewsService } from '../../../services/views/common/viewsService.js';62import { WORKSPACE_TRUST_EXTENSION_SUPPORT } from '../../../services/workspaces/common/workspaceTrust.js';63import { ILanguageModelToolsService } from '../../chat/common/languageModelToolsService.js';64import { CONTEXT_KEYBINDINGS_EDITOR } from '../../preferences/common/preferences.js';65import { IWebview } from '../../webview/browser/webview.js';66import { Query } from '../common/extensionQuery.js';67import { 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';68import { ExtensionsConfigurationSchema, ExtensionsConfigurationSchemaId } from '../common/extensionsFileTemplate.js';69import { ExtensionsInput } from '../common/extensionsInput.js';70import { KeymapExtensions } from '../common/extensionsUtils.js';71import { SearchExtensionsTool, SearchExtensionsToolData } from '../common/searchExtensionsTool.js';72import { ShowRuntimeExtensionsAction } from './abstractRuntimeExtensionsEditor.js';73import { ExtensionEditor } from './extensionEditor.js';74import { ExtensionEnablementWorkspaceTrustTransitionParticipant } from './extensionEnablementWorkspaceTrustTransitionParticipant.js';75import { ExtensionRecommendationNotificationService } from './extensionRecommendationNotificationService.js';76import { ExtensionRecommendationsService } from './extensionRecommendationsService.js';77import { ClearLanguageAction, ConfigureWorkspaceFolderRecommendedExtensionsAction, ConfigureWorkspaceRecommendedExtensionsAction, InstallAction, InstallAnotherVersionAction, InstallSpecificVersionOfExtensionAction, SetColorThemeAction, SetFileIconThemeAction, SetProductIconThemeAction, ToggleAutoUpdateForExtensionAction, ToggleAutoUpdatesForPublisherAction, TogglePreReleaseExtensionAction } from './extensionsActions.js';78import { ExtensionActivationProgress } from './extensionsActivationProgress.js';79import { ExtensionsCompletionItemsProvider } from './extensionsCompletionItemsProvider.js';80import { ExtensionDependencyChecker } from './extensionsDependencyChecker.js';81import { clearSearchResultsIcon, configureRecommendedIcon, extensionsViewIcon, filterIcon, installWorkspaceRecommendedIcon, refreshIcon } from './extensionsIcons.js';82import { InstallExtensionQuickAccessProvider, ManageExtensionsQuickAccessProvider } from './extensionsQuickAccess.js';83import { BuiltInExtensionsContext, ExtensionMarketplaceStatusUpdater, ExtensionsSearchValueContext, ExtensionsSortByContext, ExtensionsViewletViewsContribution, ExtensionsViewPaneContainer, MaliciousExtensionChecker, RecommendedExtensionsContext, SearchHasTextContext, SearchMarketplaceExtensionsContext, StatusUpdater } from './extensionsViewlet.js';84import { ExtensionsWorkbenchService } from './extensionsWorkbenchService.js';85import './media/extensionManagement.css';86import { UnsupportedExtensionsMigrationContrib } from './unsupportedExtensionsMigrationContribution.js';8788// Singletons89registerSingleton(IExtensionsWorkbenchService, ExtensionsWorkbenchService, InstantiationType.Eager /* Auto updates extensions */);90registerSingleton(IExtensionRecommendationNotificationService, ExtensionRecommendationNotificationService, InstantiationType.Delayed);91registerSingleton(IExtensionRecommendationsService, ExtensionRecommendationsService, InstantiationType.Eager /* Prompts recommendations in the background */);9293// Quick Access94Registry.as<IQuickAccessRegistry>(Extensions.Quickaccess).registerQuickAccessProvider({95ctor: ManageExtensionsQuickAccessProvider,96prefix: ManageExtensionsQuickAccessProvider.PREFIX,97placeholder: localize('manageExtensionsQuickAccessPlaceholder', "Press Enter to manage extensions."),98helpEntries: [{ description: localize('manageExtensionsHelp', "Manage Extensions") }]99});100101// Editor102Registry.as<IEditorPaneRegistry>(EditorExtensions.EditorPane).registerEditorPane(103EditorPaneDescriptor.create(104ExtensionEditor,105ExtensionEditor.ID,106localize('extension', "Extension")107),108[109new SyncDescriptor(ExtensionsInput)110]);111112export const VIEW_CONTAINER = Registry.as<IViewContainersRegistry>(ViewContainerExtensions.ViewContainersRegistry).registerViewContainer(113{114id: VIEWLET_ID,115title: localize2('extensions', "Extensions"),116openCommandActionDescriptor: {117id: VIEWLET_ID,118mnemonicTitle: localize({ key: 'miViewExtensions', comment: ['&& denotes a mnemonic'] }, "E&&xtensions"),119keybindings: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KeyX },120order: 4,121},122ctorDescriptor: new SyncDescriptor(ExtensionsViewPaneContainer),123icon: extensionsViewIcon,124order: 4,125rejectAddedViews: true,126alwaysUseContainerInfo: true,127}, ViewContainerLocation.Sidebar);128129Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration)130.registerConfiguration({131id: 'extensions',132order: 30,133title: localize('extensionsConfigurationTitle', "Extensions"),134type: 'object',135properties: {136'extensions.autoUpdate': {137enum: [true, 'onlyEnabledExtensions', false,],138enumItemLabels: [139localize('all', "All Extensions"),140localize('enabled', "Only Enabled Extensions"),141localize('none', "None"),142],143enumDescriptions: [144localize('extensions.autoUpdate.true', 'Download and install updates automatically for all extensions.'),145localize('extensions.autoUpdate.enabled', 'Download and install updates automatically only for enabled extensions.'),146localize('extensions.autoUpdate.false', 'Extensions are not automatically updated.'),147],148description: localize('extensions.autoUpdate', "Controls the automatic update behavior of extensions. The updates are fetched from a Microsoft online service."),149default: true,150scope: ConfigurationScope.APPLICATION,151tags: ['usesOnlineServices']152},153'extensions.autoCheckUpdates': {154type: 'boolean',155description: 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."),156default: true,157scope: ConfigurationScope.APPLICATION,158tags: ['usesOnlineServices']159},160'extensions.ignoreRecommendations': {161type: 'boolean',162description: localize('extensionsIgnoreRecommendations', "When enabled, the notifications for extension recommendations will not be shown."),163default: false164},165'extensions.showRecommendationsOnlyOnDemand': {166type: 'boolean',167deprecationMessage: 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."),168default: false,169tags: ['usesOnlineServices']170},171'extensions.closeExtensionDetailsOnViewChange': {172type: 'boolean',173description: localize('extensionsCloseExtensionDetailsOnViewChange', "When enabled, editors with extension details will be automatically closed upon navigating away from the Extensions View."),174default: false175},176'extensions.confirmedUriHandlerExtensionIds': {177type: 'array',178items: {179type: 'string'180},181description: localize('handleUriConfirmedExtensions', "When an extension is listed here, a confirmation prompt will not be shown when that extension handles a URI."),182default: [],183scope: ConfigurationScope.APPLICATION184},185'extensions.webWorker': {186type: ['boolean', 'string'],187enum: [true, false, 'auto'],188enumDescriptions: [189localize('extensionsWebWorker.true', "The Web Worker Extension Host will always be launched."),190localize('extensionsWebWorker.false', "The Web Worker Extension Host will never be launched."),191localize('extensionsWebWorker.auto', "The Web Worker Extension Host will be launched when a web extension needs it."),192],193description: localize('extensionsWebWorker', "Enable web worker extension host."),194default: 'auto'195},196'extensions.supportVirtualWorkspaces': {197type: 'object',198markdownDescription: localize('extensions.supportVirtualWorkspaces', "Override the virtual workspaces support of an extension."),199patternProperties: {200'([a-z0-9A-Z][a-z0-9-A-Z]*)\\.([a-z0-9A-Z][a-z0-9-A-Z]*)$': {201type: 'boolean',202default: false203}204},205additionalProperties: false,206default: {},207defaultSnippets: [{208'body': {209'pub.name': false210}211}]212},213'extensions.experimental.affinity': {214type: 'object',215markdownDescription: localize('extensions.affinity', "Configure an extension to execute in a different extension host process."),216patternProperties: {217'([a-z0-9A-Z][a-z0-9-A-Z]*)\\.([a-z0-9A-Z][a-z0-9-A-Z]*)$': {218type: 'integer',219default: 1220}221},222additionalProperties: false,223default: {},224defaultSnippets: [{225'body': {226'pub.name': 1227}228}]229},230[WORKSPACE_TRUST_EXTENSION_SUPPORT]: {231type: 'object',232scope: ConfigurationScope.APPLICATION,233markdownDescription: 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."),234patternProperties: {235'([a-z0-9A-Z][a-z0-9-A-Z]*)\\.([a-z0-9A-Z][a-z0-9-A-Z]*)$': {236type: 'object',237properties: {238'supported': {239type: ['boolean', 'string'],240enum: [true, false, 'limited'],241enumDescriptions: [242localize('extensions.supportUntrustedWorkspaces.true', "Extension will always be enabled."),243localize('extensions.supportUntrustedWorkspaces.false', "Extension will only be enabled only when the workspace is trusted."),244localize('extensions.supportUntrustedWorkspaces.limited', "Extension will always be enabled, and the extension will hide functionality requiring trust."),245],246description: localize('extensions.supportUntrustedWorkspaces.supported', "Defines the untrusted workspace support setting for the extension."),247},248'version': {249type: 'string',250description: 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."),251}252}253}254}255},256'extensions.experimental.deferredStartupFinishedActivation': {257type: 'boolean',258description: localize('extensionsDeferredStartupFinishedActivation', "When enabled, extensions which declare the `onStartupFinished` activation event will be activated after a timeout."),259default: false260},261'extensions.experimental.issueQuickAccess': {262type: 'boolean',263description: localize('extensionsInQuickAccess', "When enabled, extensions can be searched for via Quick Access and report issues from there."),264default: true265},266[VerifyExtensionSignatureConfigKey]: {267type: 'boolean',268description: localize('extensions.verifySignature', "When enabled, extensions are verified to be signed before getting installed."),269default: true,270scope: ConfigurationScope.APPLICATION,271included: isNative272},273[AutoRestartConfigurationKey]: {274type: 'boolean',275description: 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."),276default: false,277included: product.quality !== 'stable'278},279[ExtensionGalleryServiceUrlConfigKey]: {280type: 'string',281description: localize('extensions.gallery.serviceUrl', "Configure the Marketplace service URL to connect to"),282default: '',283scope: ConfigurationScope.APPLICATION,284tags: ['usesOnlineServices'],285included: false,286policy: {287name: 'ExtensionGalleryServiceUrl',288minimumVersion: '1.99',289},290},291'extensions.supportNodeGlobalNavigator': {292type: 'boolean',293description: localize('extensionsSupportNodeGlobalNavigator', "When enabled, Node.js navigator object is exposed on the global scope."),294default: false,295},296}297});298299const jsonRegistry = <jsonContributionRegistry.IJSONContributionRegistry>Registry.as(jsonContributionRegistry.Extensions.JSONContribution);300jsonRegistry.registerSchema(ExtensionsConfigurationSchemaId, ExtensionsConfigurationSchema);301302// Register Commands303CommandsRegistry.registerCommand('_extensions.manage', (accessor: ServicesAccessor, extensionId: string, tab?: ExtensionEditorTab, preserveFocus?: boolean, feature?: string) => {304const extensionService = accessor.get(IExtensionsWorkbenchService);305const extension = extensionService.local.find(e => areSameExtensions(e.identifier, { id: extensionId }));306if (extension) {307extensionService.open(extension, { tab, preserveFocus, feature });308} else {309throw new Error(localize('notFound', "Extension '{0}' not found.", extensionId));310}311});312313CommandsRegistry.registerCommand('extension.open', async (accessor: ServicesAccessor, extensionId: string, tab?: ExtensionEditorTab, preserveFocus?: boolean, feature?: string, sideByside?: boolean) => {314const extensionService = accessor.get(IExtensionsWorkbenchService);315const commandService = accessor.get(ICommandService);316317const [extension] = await extensionService.getExtensions([{ id: extensionId }], CancellationToken.None);318if (extension) {319return extensionService.open(extension, { tab, preserveFocus, feature, sideByside });320}321322return commandService.executeCommand('_extensions.manage', extensionId, tab, preserveFocus, feature);323});324325CommandsRegistry.registerCommand({326id: 'workbench.extensions.installExtension',327metadata: {328description: localize('workbench.extensions.installExtension.description', "Install the given extension"),329args: [330{331name: 'extensionIdOrVSIXUri',332description: localize('workbench.extensions.installExtension.arg.decription', "Extension id or VSIX resource uri"),333constraint: (value: any) => typeof value === 'string' || value instanceof URI,334},335{336name: 'options',337description: '(optional) Options for installing the extension. Object with the following properties: ' +338'`installOnlyNewlyAddedFromExtensionPackVSIX`: When enabled, VS Code installs only newly added extensions from the extension pack VSIX. This option is considered only when installing VSIX. ',339isOptional: true,340schema: {341'type': 'object',342'properties': {343'installOnlyNewlyAddedFromExtensionPackVSIX': {344'type': 'boolean',345'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."),346default: false347},348'installPreReleaseVersion': {349'type': 'boolean',350'description': localize('workbench.extensions.installExtension.option.installPreReleaseVersion', "When enabled, VS Code installs the pre-release version of the extension if available."),351default: false352},353'donotSync': {354'type': 'boolean',355'description': localize('workbench.extensions.installExtension.option.donotSync', "When enabled, VS Code do not sync this extension when Settings Sync is on."),356default: false357},358'justification': {359'type': ['string', 'object'],360'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."),361},362'enable': {363'type': 'boolean',364'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."),365default: false366},367'context': {368'type': 'object',369'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."),370}371}372}373}374]375},376handler: async (377accessor,378arg: string | UriComponents,379options?: {380installOnlyNewlyAddedFromExtensionPackVSIX?: boolean;381installPreReleaseVersion?: boolean;382donotSync?: boolean;383justification?: string | { reason: string; action: string };384enable?: boolean;385context?: IStringDictionary<any>;386}) => {387const extensionsWorkbenchService = accessor.get(IExtensionsWorkbenchService);388const extensionManagementService = accessor.get(IWorkbenchExtensionManagementService);389const extensionGalleryService = accessor.get(IExtensionGalleryService);390try {391if (typeof arg === 'string') {392const [id, version] = getIdAndVersion(arg);393const extension = extensionsWorkbenchService.local.find(e => areSameExtensions(e.identifier, { id, uuid: version }));394if (extension?.enablementState === EnablementState.DisabledByExtensionKind) {395const [gallery] = await extensionGalleryService.getExtensions([{ id, preRelease: options?.installPreReleaseVersion }], CancellationToken.None);396if (!gallery) {397throw new Error(localize('notFound', "Extension '{0}' not found.", arg));398}399await extensionManagementService.installFromGallery(gallery, {400isMachineScoped: options?.donotSync ? true : undefined, /* do not allow syncing extensions automatically while installing through the command */401installPreReleaseVersion: options?.installPreReleaseVersion,402installGivenVersion: !!version,403context: { ...options?.context, [EXTENSION_INSTALL_SOURCE_CONTEXT]: ExtensionInstallSource.COMMAND },404});405} else {406await extensionsWorkbenchService.install(arg, {407version,408installPreReleaseVersion: options?.installPreReleaseVersion,409context: { ...options?.context, [EXTENSION_INSTALL_SOURCE_CONTEXT]: ExtensionInstallSource.COMMAND },410justification: options?.justification,411enable: options?.enable,412isMachineScoped: options?.donotSync ? true : undefined, /* do not allow syncing extensions automatically while installing through the command */413}, ProgressLocation.Notification);414}415} else {416const vsix = URI.revive(arg);417await extensionsWorkbenchService.install(vsix, { installGivenVersion: true });418}419} catch (e) {420onUnexpectedError(e);421throw e;422}423}424});425426CommandsRegistry.registerCommand({427id: 'workbench.extensions.uninstallExtension',428metadata: {429description: localize('workbench.extensions.uninstallExtension.description', "Uninstall the given extension"),430args: [431{432name: localize('workbench.extensions.uninstallExtension.arg.name', "Id of the extension to uninstall"),433schema: {434'type': 'string'435}436}437]438},439handler: async (accessor, id: string) => {440if (!id) {441throw new Error(localize('id required', "Extension id required."));442}443const extensionManagementService = accessor.get(IExtensionManagementService);444const installed = await extensionManagementService.getInstalled();445const [extensionToUninstall] = installed.filter(e => areSameExtensions(e.identifier, { id }));446if (!extensionToUninstall) {447throw 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));448}449if (extensionToUninstall.isBuiltin) {450throw new Error(localize('builtin', "Extension '{0}' is a Built-in extension and cannot be uninstalled", id));451}452453try {454await extensionManagementService.uninstall(extensionToUninstall);455} catch (e) {456onUnexpectedError(e);457throw e;458}459}460});461462CommandsRegistry.registerCommand({463id: 'workbench.extensions.search',464metadata: {465description: localize('workbench.extensions.search.description', "Search for a specific extension"),466args: [467{468name: localize('workbench.extensions.search.arg.name', "Query to use in search"),469schema: { 'type': 'string' }470}471]472},473handler: async (accessor, query: string = '') => {474return accessor.get(IExtensionsWorkbenchService).openSearch(query);475}476});477478function overrideActionForActiveExtensionEditorWebview(command: MultiCommand | undefined, f: (webview: IWebview) => void) {479command?.addImplementation(105, 'extensions-editor', (accessor) => {480const editorService = accessor.get(IEditorService);481const editor = editorService.activeEditorPane;482if (editor instanceof ExtensionEditor) {483if (editor.activeWebview?.isFocused) {484f(editor.activeWebview);485return true;486}487}488return false;489});490}491492overrideActionForActiveExtensionEditorWebview(CopyAction, webview => webview.copy());493overrideActionForActiveExtensionEditorWebview(CutAction, webview => webview.cut());494overrideActionForActiveExtensionEditorWebview(PasteAction, webview => webview.paste());495496// Contexts497export const CONTEXT_HAS_LOCAL_SERVER = new RawContextKey<boolean>('hasLocalServer', false);498export const CONTEXT_HAS_REMOTE_SERVER = new RawContextKey<boolean>('hasRemoteServer', false);499export const CONTEXT_HAS_WEB_SERVER = new RawContextKey<boolean>('hasWebServer', false);500const CONTEXT_GALLERY_SORT_CAPABILITIES = new RawContextKey<string>('gallerySortCapabilities', '');501const CONTEXT_GALLERY_FILTER_CAPABILITIES = new RawContextKey<string>('galleryFilterCapabilities', '');502const CONTEXT_GALLERY_ALL_PUBLIC_REPOSITORY_SIGNED = new RawContextKey<boolean>('galleryAllPublicRepositorySigned', false);503const CONTEXT_GALLERY_ALL_PRIVATE_REPOSITORY_SIGNED = new RawContextKey<boolean>('galleryAllPrivateRepositorySigned', false);504const CONTEXT_GALLERY_HAS_EXTENSION_LINK = new RawContextKey<boolean>('galleryHasExtensionLink', false);505506async function runAction(action: IAction): Promise<void> {507try {508await action.run();509} finally {510if (isDisposable(action)) {511action.dispose();512}513}514}515516type IExtensionActionOptions = IAction2Options & {517menuTitles?: { [id: string]: string };518run(accessor: ServicesAccessor, ...args: any[]): Promise<any>;519};520521class ExtensionsContributions extends Disposable implements IWorkbenchContribution {522523constructor(524@IExtensionManagementService private readonly extensionManagementService: IExtensionManagementService,525@IExtensionManagementServerService private readonly extensionManagementServerService: IExtensionManagementServerService,526@IExtensionGalleryManifestService private readonly extensionGalleryManifestService: IExtensionGalleryManifestService,527@IContextKeyService private readonly contextKeyService: IContextKeyService,528@IViewsService private readonly viewsService: IViewsService,529@IExtensionsWorkbenchService private readonly extensionsWorkbenchService: IExtensionsWorkbenchService,530@IWorkbenchExtensionEnablementService private readonly extensionEnablementService: IWorkbenchExtensionEnablementService,531@IInstantiationService private readonly instantiationService: IInstantiationService,532@IDialogService private readonly dialogService: IDialogService,533@ICommandService private readonly commandService: ICommandService,534@IProductService private readonly productService: IProductService,535) {536super();537const hasLocalServerContext = CONTEXT_HAS_LOCAL_SERVER.bindTo(contextKeyService);538if (this.extensionManagementServerService.localExtensionManagementServer) {539hasLocalServerContext.set(true);540}541542const hasRemoteServerContext = CONTEXT_HAS_REMOTE_SERVER.bindTo(contextKeyService);543if (this.extensionManagementServerService.remoteExtensionManagementServer) {544hasRemoteServerContext.set(true);545}546547const hasWebServerContext = CONTEXT_HAS_WEB_SERVER.bindTo(contextKeyService);548if (this.extensionManagementServerService.webExtensionManagementServer) {549hasWebServerContext.set(true);550}551552this.updateExtensionGalleryStatusContexts();553this._register(extensionGalleryManifestService.onDidChangeExtensionGalleryManifestStatus(() => this.updateExtensionGalleryStatusContexts()));554extensionGalleryManifestService.getExtensionGalleryManifest()555.then(extensionGalleryManifest => {556this.updateGalleryCapabilitiesContexts(extensionGalleryManifest);557this._register(extensionGalleryManifestService.onDidChangeExtensionGalleryManifest(extensionGalleryManifest => this.updateGalleryCapabilitiesContexts(extensionGalleryManifest)));558});559this.registerGlobalActions();560this.registerContextMenuActions();561this.registerQuickAccessProvider();562}563564private async updateExtensionGalleryStatusContexts(): Promise<void> {565CONTEXT_HAS_GALLERY.bindTo(this.contextKeyService).set(this.extensionGalleryManifestService.extensionGalleryManifestStatus === ExtensionGalleryManifestStatus.Available);566CONTEXT_EXTENSIONS_GALLERY_STATUS.bindTo(this.contextKeyService).set(this.extensionGalleryManifestService.extensionGalleryManifestStatus);567}568569private async updateGalleryCapabilitiesContexts(extensionGalleryManifest: IExtensionGalleryManifest | null): Promise<void> {570CONTEXT_GALLERY_SORT_CAPABILITIES.bindTo(this.contextKeyService).set(`_${extensionGalleryManifest?.capabilities.extensionQuery.sorting?.map(s => s.name)?.join('_')}_UpdateDate_`);571CONTEXT_GALLERY_FILTER_CAPABILITIES.bindTo(this.contextKeyService).set(`_${extensionGalleryManifest?.capabilities.extensionQuery.filtering?.map(s => s.name)?.join('_')}_`);572CONTEXT_GALLERY_ALL_PUBLIC_REPOSITORY_SIGNED.bindTo(this.contextKeyService).set(!!extensionGalleryManifest?.capabilities?.signing?.allPublicRepositorySigned);573CONTEXT_GALLERY_ALL_PRIVATE_REPOSITORY_SIGNED.bindTo(this.contextKeyService).set(!!extensionGalleryManifest?.capabilities?.signing?.allPrivateRepositorySigned);574CONTEXT_GALLERY_HAS_EXTENSION_LINK.bindTo(this.contextKeyService).set(!!(extensionGalleryManifest && getExtensionGalleryManifestResourceUri(extensionGalleryManifest, ExtensionGalleryResourceType.ExtensionDetailsViewUri)));575}576577private registerQuickAccessProvider(): void {578if (this.extensionManagementServerService.localExtensionManagementServer579|| this.extensionManagementServerService.remoteExtensionManagementServer580|| this.extensionManagementServerService.webExtensionManagementServer581) {582Registry.as<IQuickAccessRegistry>(Extensions.Quickaccess).registerQuickAccessProvider({583ctor: InstallExtensionQuickAccessProvider,584prefix: InstallExtensionQuickAccessProvider.PREFIX,585placeholder: localize('installExtensionQuickAccessPlaceholder', "Type the name of an extension to install or search."),586helpEntries: [{ description: localize('installExtensionQuickAccessHelp', "Install or Search Extensions") }]587});588}589}590591// Global actions592private registerGlobalActions(): void {593this._register(MenuRegistry.appendMenuItem(MenuId.MenubarPreferencesMenu, {594command: {595id: VIEWLET_ID,596title: localize({ key: 'miPreferencesExtensions', comment: ['&& denotes a mnemonic'] }, "&&Extensions")597},598group: '2_configuration',599order: 3600}));601this._register(MenuRegistry.appendMenuItem(MenuId.GlobalActivity, {602command: {603id: VIEWLET_ID,604title: localize('showExtensions', "Extensions")605},606group: '2_configuration',607order: 3608}));609610this.registerExtensionAction({611id: 'workbench.extensions.action.focusExtensionsView',612title: localize2('focusExtensions', 'Focus on Extensions View'),613category: ExtensionsLocalizedLabel,614f1: true,615run: async (accessor: ServicesAccessor) => {616await accessor.get(IExtensionsWorkbenchService).openSearch('');617}618});619620this.registerExtensionAction({621id: 'workbench.extensions.action.installExtensions',622title: localize2('installExtensions', 'Install Extensions'),623category: ExtensionsLocalizedLabel,624menu: {625id: MenuId.CommandPalette,626when: ContextKeyExpr.and(CONTEXT_HAS_GALLERY, ContextKeyExpr.or(CONTEXT_HAS_LOCAL_SERVER, CONTEXT_HAS_REMOTE_SERVER, CONTEXT_HAS_WEB_SERVER))627},628run: async (accessor: ServicesAccessor) => {629accessor.get(IViewsService).openViewContainer(VIEWLET_ID, true);630}631});632633this.registerExtensionAction({634id: 'workbench.extensions.action.showRecommendedKeymapExtensions',635title: localize2('showRecommendedKeymapExtensionsShort', 'Keymaps'),636category: PreferencesLocalizedLabel,637menu: [{638id: MenuId.CommandPalette,639when: CONTEXT_HAS_GALLERY640}, {641id: MenuId.EditorTitle,642when: ContextKeyExpr.and(CONTEXT_KEYBINDINGS_EDITOR, CONTEXT_HAS_GALLERY),643group: '2_keyboard_discover_actions'644}],645menuTitles: {646[MenuId.EditorTitle.id]: localize('importKeyboardShortcutsFroms', "Migrate Keyboard Shortcuts from...")647},648run: () => this.extensionsWorkbenchService.openSearch('@recommended:keymaps ')649});650651this.registerExtensionAction({652id: 'workbench.extensions.action.showLanguageExtensions',653title: localize2('showLanguageExtensionsShort', 'Language Extensions'),654category: PreferencesLocalizedLabel,655menu: {656id: MenuId.CommandPalette,657when: CONTEXT_HAS_GALLERY658},659run: () => this.extensionsWorkbenchService.openSearch('@recommended:languages ')660});661662this.registerExtensionAction({663id: 'workbench.extensions.action.checkForUpdates',664title: localize2('checkForUpdates', 'Check for Extension Updates'),665category: ExtensionsLocalizedLabel,666menu: [{667id: MenuId.CommandPalette,668when: ContextKeyExpr.and(CONTEXT_HAS_GALLERY, ContextKeyExpr.or(CONTEXT_HAS_LOCAL_SERVER, CONTEXT_HAS_REMOTE_SERVER, CONTEXT_HAS_WEB_SERVER))669}, {670id: MenuId.ViewContainerTitle,671when: ContextKeyExpr.and(ContextKeyExpr.equals('viewContainer', VIEWLET_ID), CONTEXT_HAS_GALLERY),672group: '1_updates',673order: 1674}],675run: async () => {676await this.extensionsWorkbenchService.checkForUpdates();677const outdated = this.extensionsWorkbenchService.outdated;678if (outdated.length) {679return this.extensionsWorkbenchService.openSearch('@outdated ');680} else {681return this.dialogService.info(localize('noUpdatesAvailable', "All extensions are up to date."));682}683}684});685686const enableAutoUpdateWhenCondition = ContextKeyExpr.equals(`config.${AutoUpdateConfigurationKey}`, false);687this.registerExtensionAction({688id: 'workbench.extensions.action.enableAutoUpdate',689title: localize2('enableAutoUpdate', 'Enable Auto Update for All Extensions'),690category: ExtensionsLocalizedLabel,691precondition: enableAutoUpdateWhenCondition,692menu: [{693id: MenuId.ViewContainerTitle,694order: 5,695group: '1_updates',696when: ContextKeyExpr.and(ContextKeyExpr.equals('viewContainer', VIEWLET_ID), enableAutoUpdateWhenCondition)697}, {698id: MenuId.CommandPalette,699}],700run: (accessor: ServicesAccessor) => accessor.get(IExtensionsWorkbenchService).updateAutoUpdateForAllExtensions(true)701});702703const disableAutoUpdateWhenCondition = ContextKeyExpr.notEquals(`config.${AutoUpdateConfigurationKey}`, false);704this.registerExtensionAction({705id: 'workbench.extensions.action.disableAutoUpdate',706title: localize2('disableAutoUpdate', 'Disable Auto Update for All Extensions'),707precondition: disableAutoUpdateWhenCondition,708category: ExtensionsLocalizedLabel,709menu: [{710id: MenuId.ViewContainerTitle,711order: 5,712group: '1_updates',713when: ContextKeyExpr.and(ContextKeyExpr.equals('viewContainer', VIEWLET_ID), disableAutoUpdateWhenCondition)714}, {715id: MenuId.CommandPalette,716}],717run: (accessor: ServicesAccessor) => accessor.get(IExtensionsWorkbenchService).updateAutoUpdateForAllExtensions(false)718});719720this.registerExtensionAction({721id: 'workbench.extensions.action.updateAllExtensions',722title: localize2('updateAll', 'Update All Extensions'),723category: ExtensionsLocalizedLabel,724precondition: HasOutdatedExtensionsContext,725menu: [726{727id: MenuId.CommandPalette,728when: ContextKeyExpr.and(CONTEXT_HAS_GALLERY, ContextKeyExpr.or(CONTEXT_HAS_LOCAL_SERVER, CONTEXT_HAS_REMOTE_SERVER, CONTEXT_HAS_WEB_SERVER))729}, {730id: MenuId.ViewContainerTitle,731when: ContextKeyExpr.and(ContextKeyExpr.equals('viewContainer', VIEWLET_ID), ContextKeyExpr.or(ContextKeyExpr.has(`config.${AutoUpdateConfigurationKey}`).negate(), ContextKeyExpr.equals(`config.${AutoUpdateConfigurationKey}`, 'onlyEnabledExtensions'))),732group: '1_updates',733order: 2734}, {735id: MenuId.ViewTitle,736when: ContextKeyExpr.equals('view', OUTDATED_EXTENSIONS_VIEW_ID),737group: 'navigation',738order: 1739}740],741icon: installWorkspaceRecommendedIcon,742run: async () => {743await this.extensionsWorkbenchService.updateAll();744}745});746747this.registerExtensionAction({748id: 'workbench.extensions.action.enableAll',749title: localize2('enableAll', 'Enable All Extensions'),750category: ExtensionsLocalizedLabel,751menu: [{752id: MenuId.CommandPalette,753when: ContextKeyExpr.or(CONTEXT_HAS_LOCAL_SERVER, CONTEXT_HAS_REMOTE_SERVER, CONTEXT_HAS_WEB_SERVER)754}, {755id: MenuId.ViewContainerTitle,756when: ContextKeyExpr.equals('viewContainer', VIEWLET_ID),757group: '2_enablement',758order: 1759}],760run: async () => {761const extensionsToEnable = this.extensionsWorkbenchService.local.filter(e => !!e.local && this.extensionEnablementService.canChangeEnablement(e.local) && !this.extensionEnablementService.isEnabled(e.local));762if (extensionsToEnable.length) {763await this.extensionsWorkbenchService.setEnablement(extensionsToEnable, EnablementState.EnabledGlobally);764}765}766});767768this.registerExtensionAction({769id: 'workbench.extensions.action.enableAllWorkspace',770title: localize2('enableAllWorkspace', 'Enable All Extensions for this Workspace'),771category: ExtensionsLocalizedLabel,772menu: {773id: MenuId.CommandPalette,774when: ContextKeyExpr.and(WorkbenchStateContext.notEqualsTo('empty'), ContextKeyExpr.or(CONTEXT_HAS_LOCAL_SERVER, CONTEXT_HAS_REMOTE_SERVER, CONTEXT_HAS_WEB_SERVER))775},776run: async () => {777const extensionsToEnable = this.extensionsWorkbenchService.local.filter(e => !!e.local && this.extensionEnablementService.canChangeEnablement(e.local) && !this.extensionEnablementService.isEnabled(e.local));778if (extensionsToEnable.length) {779await this.extensionsWorkbenchService.setEnablement(extensionsToEnable, EnablementState.EnabledWorkspace);780}781}782});783784this.registerExtensionAction({785id: 'workbench.extensions.action.disableAll',786title: localize2('disableAll', 'Disable All Installed Extensions'),787category: ExtensionsLocalizedLabel,788menu: [{789id: MenuId.CommandPalette,790when: ContextKeyExpr.or(CONTEXT_HAS_LOCAL_SERVER, CONTEXT_HAS_REMOTE_SERVER, CONTEXT_HAS_WEB_SERVER)791}, {792id: MenuId.ViewContainerTitle,793when: ContextKeyExpr.equals('viewContainer', VIEWLET_ID),794group: '2_enablement',795order: 2796}],797run: async () => {798const extensionsToDisable = this.extensionsWorkbenchService.local.filter(e => !e.isBuiltin && !!e.local && this.extensionEnablementService.isEnabled(e.local) && this.extensionEnablementService.canChangeEnablement(e.local));799if (extensionsToDisable.length) {800await this.extensionsWorkbenchService.setEnablement(extensionsToDisable, EnablementState.DisabledGlobally);801}802}803});804805this.registerExtensionAction({806id: 'workbench.extensions.action.disableAllWorkspace',807title: localize2('disableAllWorkspace', 'Disable All Installed Extensions for this Workspace'),808category: ExtensionsLocalizedLabel,809menu: {810id: MenuId.CommandPalette,811when: ContextKeyExpr.and(WorkbenchStateContext.notEqualsTo('empty'), ContextKeyExpr.or(CONTEXT_HAS_LOCAL_SERVER, CONTEXT_HAS_REMOTE_SERVER, CONTEXT_HAS_WEB_SERVER))812},813run: async () => {814const extensionsToDisable = this.extensionsWorkbenchService.local.filter(e => !e.isBuiltin && !!e.local && this.extensionEnablementService.isEnabled(e.local) && this.extensionEnablementService.canChangeEnablement(e.local));815if (extensionsToDisable.length) {816await this.extensionsWorkbenchService.setEnablement(extensionsToDisable, EnablementState.DisabledWorkspace);817}818}819});820821this.registerExtensionAction({822id: SELECT_INSTALL_VSIX_EXTENSION_COMMAND_ID,823title: localize2('InstallFromVSIX', 'Install from VSIX...'),824category: ExtensionsLocalizedLabel,825menu: [{826id: MenuId.CommandPalette,827when: ContextKeyExpr.or(CONTEXT_HAS_LOCAL_SERVER, CONTEXT_HAS_REMOTE_SERVER)828}, {829id: MenuId.ViewContainerTitle,830when: ContextKeyExpr.and(ContextKeyExpr.equals('viewContainer', VIEWLET_ID), ContextKeyExpr.or(CONTEXT_HAS_LOCAL_SERVER, CONTEXT_HAS_REMOTE_SERVER)),831group: '3_install',832order: 1833}],834run: async (accessor: ServicesAccessor) => {835const fileDialogService = accessor.get(IFileDialogService);836const commandService = accessor.get(ICommandService);837const vsixPaths = await fileDialogService.showOpenDialog({838title: localize('installFromVSIX', "Install from VSIX"),839filters: [{ name: 'VSIX Extensions', extensions: ['vsix'] }],840canSelectFiles: true,841canSelectMany: true,842openLabel: mnemonicButtonLabel(localize({ key: 'installButton', comment: ['&& denotes a mnemonic'] }, "&&Install"))843});844if (vsixPaths) {845await commandService.executeCommand(INSTALL_EXTENSION_FROM_VSIX_COMMAND_ID, vsixPaths);846}847}848});849850this.registerExtensionAction({851id: INSTALL_EXTENSION_FROM_VSIX_COMMAND_ID,852title: localize('installVSIX', "Install Extension VSIX"),853menu: [{854id: MenuId.ExplorerContext,855group: 'extensions',856when: ContextKeyExpr.and(ResourceContextKey.Extension.isEqualTo('.vsix'), ContextKeyExpr.or(CONTEXT_HAS_LOCAL_SERVER, CONTEXT_HAS_REMOTE_SERVER)),857}],858run: async (accessor: ServicesAccessor, resources: URI[] | URI) => {859const extensionsWorkbenchService = accessor.get(IExtensionsWorkbenchService);860const hostService = accessor.get(IHostService);861const notificationService = accessor.get(INotificationService);862863const vsixs = Array.isArray(resources) ? resources : [resources];864const result = await Promise.allSettled(vsixs.map(async (vsix) => await extensionsWorkbenchService.install(vsix, { installGivenVersion: true })));865let error: Error | undefined, requireReload = false, requireRestart = false;866for (const r of result) {867if (r.status === 'rejected') {868error = new Error(r.reason);869break;870}871requireReload = requireReload || r.value.runtimeState?.action === ExtensionRuntimeActionType.ReloadWindow;872requireRestart = requireRestart || r.value.runtimeState?.action === ExtensionRuntimeActionType.RestartExtensions;873}874if (error) {875throw error;876}877if (requireReload) {878notificationService.prompt(879Severity.Info,880vsixs.length > 1 ? localize('InstallVSIXs.successReload', "Completed installing extensions. Please reload Visual Studio Code to enable them.")881: localize('InstallVSIXAction.successReload', "Completed installing extension. Please reload Visual Studio Code to enable it."),882[{883label: localize('InstallVSIXAction.reloadNow', "Reload Now"),884run: () => hostService.reload()885}]886);887}888else if (requireRestart) {889notificationService.prompt(890Severity.Info,891vsixs.length > 1 ? localize('InstallVSIXs.successRestart', "Completed installing extensions. Please restart extensions to enable them.")892: localize('InstallVSIXAction.successRestart', "Completed installing extension. Please restart extensions to enable it."),893[{894label: localize('InstallVSIXAction.restartExtensions', "Restart Extensions"),895run: () => extensionsWorkbenchService.updateRunningExtensions()896}]897);898}899else {900notificationService.prompt(901Severity.Info,902vsixs.length > 1 ? localize('InstallVSIXs.successNoReload', "Completed installing extensions.") : localize('InstallVSIXAction.successNoReload', "Completed installing extension."),903[]904);905}906}907});908909this.registerExtensionAction({910id: 'workbench.extensions.action.installExtensionFromLocation',911title: localize2('installExtensionFromLocation', 'Install Extension from Location...'),912category: Categories.Developer,913menu: [{914id: MenuId.CommandPalette,915when: ContextKeyExpr.or(CONTEXT_HAS_WEB_SERVER, CONTEXT_HAS_LOCAL_SERVER)916}],917run: async (accessor: ServicesAccessor) => {918const extensionManagementService = accessor.get(IWorkbenchExtensionManagementService);919if (isWeb) {920return new Promise<void>((c, e) => {921const quickInputService = accessor.get(IQuickInputService);922const disposables = new DisposableStore();923const quickPick = disposables.add(quickInputService.createQuickPick());924quickPick.title = localize('installFromLocation', "Install Extension from Location");925quickPick.customButton = true;926quickPick.customLabel = localize('install button', "Install");927quickPick.placeholder = localize('installFromLocationPlaceHolder', "Location of the web extension");928quickPick.ignoreFocusOut = true;929disposables.add(Event.any(quickPick.onDidAccept, quickPick.onDidCustom)(async () => {930quickPick.hide();931if (quickPick.value) {932try {933await extensionManagementService.installFromLocation(URI.parse(quickPick.value));934} catch (error) {935e(error);936return;937}938}939c();940}));941disposables.add(quickPick.onDidHide(() => disposables.dispose()));942quickPick.show();943});944} else {945const fileDialogService = accessor.get(IFileDialogService);946const extensionLocation = await fileDialogService.showOpenDialog({947canSelectFolders: true,948canSelectFiles: false,949canSelectMany: false,950title: localize('installFromLocation', "Install Extension from Location"),951});952if (extensionLocation?.[0]) {953await extensionManagementService.installFromLocation(extensionLocation[0]);954}955}956}957});958959MenuRegistry.appendMenuItem(extensionsSearchActionsMenu, {960submenu: extensionsFilterSubMenu,961title: localize('filterExtensions', "Filter Extensions..."),962group: 'navigation',963order: 2,964icon: filterIcon,965});966967const showFeaturedExtensionsId = 'extensions.filter.featured';968const featuresExtensionsWhenContext = ContextKeyExpr.and(CONTEXT_HAS_GALLERY, ContextKeyExpr.regex(CONTEXT_GALLERY_FILTER_CAPABILITIES.key, new RegExp(`_${FilterType.Featured}_`)));969this.registerExtensionAction({970id: showFeaturedExtensionsId,971title: localize2('showFeaturedExtensions', 'Show Featured Extensions'),972category: ExtensionsLocalizedLabel,973menu: [{974id: MenuId.CommandPalette,975when: featuresExtensionsWhenContext976}, {977id: extensionsFilterSubMenu,978when: featuresExtensionsWhenContext,979group: '1_predefined',980order: 1,981}],982menuTitles: {983[extensionsFilterSubMenu.id]: localize('featured filter', "Featured")984},985run: () => this.extensionsWorkbenchService.openSearch('@featured ')986});987988this.registerExtensionAction({989id: 'workbench.extensions.action.showPopularExtensions',990title: localize2('showPopularExtensions', 'Show Popular Extensions'),991category: ExtensionsLocalizedLabel,992menu: [{993id: MenuId.CommandPalette,994when: CONTEXT_HAS_GALLERY995}, {996id: extensionsFilterSubMenu,997when: CONTEXT_HAS_GALLERY,998group: '1_predefined',999order: 2,1000}],1001menuTitles: {1002[extensionsFilterSubMenu.id]: localize('most popular filter', "Most Popular")1003},1004run: () => this.extensionsWorkbenchService.openSearch('@popular ')1005});10061007this.registerExtensionAction({1008id: 'workbench.extensions.action.showRecommendedExtensions',1009title: localize2('showRecommendedExtensions', 'Show Recommended Extensions'),1010category: ExtensionsLocalizedLabel,1011menu: [{1012id: MenuId.CommandPalette,1013when: CONTEXT_HAS_GALLERY1014}, {1015id: extensionsFilterSubMenu,1016when: CONTEXT_HAS_GALLERY,1017group: '1_predefined',1018order: 2,1019}],1020menuTitles: {1021[extensionsFilterSubMenu.id]: localize('most popular recommended', "Recommended")1022},1023run: () => this.extensionsWorkbenchService.openSearch('@recommended ')1024});10251026this.registerExtensionAction({1027id: 'workbench.extensions.action.recentlyPublishedExtensions',1028title: localize2('recentlyPublishedExtensions', 'Show Recently Published Extensions'),1029category: ExtensionsLocalizedLabel,1030menu: [{1031id: MenuId.CommandPalette,1032when: CONTEXT_HAS_GALLERY1033}, {1034id: extensionsFilterSubMenu,1035when: CONTEXT_HAS_GALLERY,1036group: '1_predefined',1037order: 2,1038}],1039menuTitles: {1040[extensionsFilterSubMenu.id]: localize('recently published filter', "Recently Published")1041},1042run: () => this.extensionsWorkbenchService.openSearch('@recentlyPublished ')1043});10441045const extensionsCategoryFilterSubMenu = new MenuId('extensionsCategoryFilterSubMenu');1046MenuRegistry.appendMenuItem(extensionsFilterSubMenu, {1047submenu: extensionsCategoryFilterSubMenu,1048title: localize('filter by category', "Category"),1049when: ContextKeyExpr.and(CONTEXT_HAS_GALLERY, ContextKeyExpr.regex(CONTEXT_GALLERY_FILTER_CAPABILITIES.key, new RegExp(`_${FilterType.Category}_`))),1050group: '2_categories',1051order: 1,1052});10531054EXTENSION_CATEGORIES.forEach((category, index) => {1055this.registerExtensionAction({1056id: `extensions.actions.searchByCategory.${category}`,1057title: category,1058menu: [{1059id: extensionsCategoryFilterSubMenu,1060when: CONTEXT_HAS_GALLERY,1061order: index,1062}],1063run: () => this.extensionsWorkbenchService.openSearch(`@category:"${category.toLowerCase()}"`)1064});1065});10661067this.registerExtensionAction({1068id: 'workbench.extensions.action.installedExtensions',1069title: localize2('installedExtensions', 'Show Installed Extensions'),1070category: ExtensionsLocalizedLabel,1071f1: true,1072menu: [{1073id: extensionsFilterSubMenu,1074group: '3_installed',1075order: 1,1076}],1077menuTitles: {1078[extensionsFilterSubMenu.id]: localize('installed filter', "Installed")1079},1080run: () => this.extensionsWorkbenchService.openSearch('@installed ')1081});10821083this.registerExtensionAction({1084id: 'workbench.extensions.action.listBuiltInExtensions',1085title: localize2('showBuiltInExtensions', 'Show Built-in Extensions'),1086category: ExtensionsLocalizedLabel,1087menu: [{1088id: MenuId.CommandPalette,1089when: ContextKeyExpr.or(CONTEXT_HAS_LOCAL_SERVER, CONTEXT_HAS_REMOTE_SERVER, CONTEXT_HAS_WEB_SERVER)1090}, {1091id: extensionsFilterSubMenu,1092group: '3_installed',1093order: 3,1094}],1095menuTitles: {1096[extensionsFilterSubMenu.id]: localize('builtin filter', "Built-in")1097},1098run: () => this.extensionsWorkbenchService.openSearch('@builtin ')1099});11001101this.registerExtensionAction({1102id: 'workbench.extensions.action.extensionUpdates',1103title: localize2('extensionUpdates', 'Show Extension Updates'),1104category: ExtensionsLocalizedLabel,1105precondition: CONTEXT_HAS_GALLERY,1106f1: true,1107menu: [{1108id: extensionsFilterSubMenu,1109group: '3_installed',1110when: CONTEXT_HAS_GALLERY,1111order: 2,1112}],1113menuTitles: {1114[extensionsFilterSubMenu.id]: localize('extension updates filter', "Updates")1115},1116run: () => this.extensionsWorkbenchService.openSearch('@updates')1117});11181119this.registerExtensionAction({1120id: LIST_WORKSPACE_UNSUPPORTED_EXTENSIONS_COMMAND_ID,1121title: localize2('showWorkspaceUnsupportedExtensions', 'Show Extensions Unsupported By Workspace'),1122category: ExtensionsLocalizedLabel,1123menu: [{1124id: MenuId.CommandPalette,1125when: ContextKeyExpr.or(CONTEXT_HAS_LOCAL_SERVER, CONTEXT_HAS_REMOTE_SERVER),1126}, {1127id: extensionsFilterSubMenu,1128group: '3_installed',1129order: 6,1130when: ContextKeyExpr.or(CONTEXT_HAS_LOCAL_SERVER, CONTEXT_HAS_REMOTE_SERVER),1131}],1132menuTitles: {1133[extensionsFilterSubMenu.id]: localize('workspace unsupported filter', "Workspace Unsupported")1134},1135run: () => this.extensionsWorkbenchService.openSearch('@workspaceUnsupported')1136});11371138this.registerExtensionAction({1139id: 'workbench.extensions.action.showEnabledExtensions',1140title: localize2('showEnabledExtensions', 'Show Enabled Extensions'),1141category: ExtensionsLocalizedLabel,1142menu: [{1143id: MenuId.CommandPalette,1144when: ContextKeyExpr.or(CONTEXT_HAS_LOCAL_SERVER, CONTEXT_HAS_REMOTE_SERVER, CONTEXT_HAS_WEB_SERVER)1145}, {1146id: extensionsFilterSubMenu,1147group: '3_installed',1148order: 4,1149}],1150menuTitles: {1151[extensionsFilterSubMenu.id]: localize('enabled filter', "Enabled")1152},1153run: () => this.extensionsWorkbenchService.openSearch('@enabled ')1154});11551156this.registerExtensionAction({1157id: 'workbench.extensions.action.showDisabledExtensions',1158title: localize2('showDisabledExtensions', 'Show Disabled Extensions'),1159category: ExtensionsLocalizedLabel,1160menu: [{1161id: MenuId.CommandPalette,1162when: ContextKeyExpr.or(CONTEXT_HAS_LOCAL_SERVER, CONTEXT_HAS_REMOTE_SERVER, CONTEXT_HAS_WEB_SERVER)1163}, {1164id: extensionsFilterSubMenu,1165group: '3_installed',1166order: 5,1167}],1168menuTitles: {1169[extensionsFilterSubMenu.id]: localize('disabled filter', "Disabled")1170},1171run: () => this.extensionsWorkbenchService.openSearch('@disabled ')1172});11731174const extensionsSortSubMenu = new MenuId('extensionsSortSubMenu');1175MenuRegistry.appendMenuItem(extensionsFilterSubMenu, {1176submenu: extensionsSortSubMenu,1177title: localize('sorty by', "Sort By"),1178when: ContextKeyExpr.and(ContextKeyExpr.or(CONTEXT_HAS_GALLERY, DefaultViewsContext)),1179group: '4_sort',1180order: 1,1181});11821183[1184{ id: 'installs', title: localize('sort by installs', "Install Count"), precondition: BuiltInExtensionsContext.negate(), sortCapability: SortBy.InstallCount },1185{ id: 'rating', title: localize('sort by rating', "Rating"), precondition: BuiltInExtensionsContext.negate(), sortCapability: SortBy.WeightedRating },1186{ id: 'name', title: localize('sort by name', "Name"), precondition: BuiltInExtensionsContext.negate(), sortCapability: SortBy.Title },1187{ id: 'publishedDate', title: localize('sort by published date', "Published Date"), precondition: BuiltInExtensionsContext.negate(), sortCapability: SortBy.PublishedDate },1188{ id: 'updateDate', title: localize('sort by update date', "Updated Date"), precondition: ContextKeyExpr.and(SearchMarketplaceExtensionsContext.negate(), RecommendedExtensionsContext.negate(), BuiltInExtensionsContext.negate()), sortCapability: 'UpdateDate' },1189].map(({ id, title, precondition, sortCapability }, index) => {1190const sortCapabilityContext = ContextKeyExpr.regex(CONTEXT_GALLERY_SORT_CAPABILITIES.key, new RegExp(`_${sortCapability}_`));1191this.registerExtensionAction({1192id: `extensions.sort.${id}`,1193title,1194precondition: ContextKeyExpr.and(precondition, ContextKeyExpr.regex(ExtensionsSearchValueContext.key, /^@feature:/).negate(), sortCapabilityContext),1195menu: [{1196id: extensionsSortSubMenu,1197when: ContextKeyExpr.and(ContextKeyExpr.or(CONTEXT_HAS_GALLERY, DefaultViewsContext), sortCapabilityContext),1198order: index,1199}],1200toggled: ExtensionsSortByContext.isEqualTo(id),1201run: async () => {1202const extensionsViewPaneContainer = ((await this.viewsService.openViewContainer(VIEWLET_ID, true))?.getViewPaneContainer()) as IExtensionsViewPaneContainer | undefined;1203const currentQuery = Query.parse(extensionsViewPaneContainer?.searchValue ?? '');1204extensionsViewPaneContainer?.search(new Query(currentQuery.value, id).toString());1205extensionsViewPaneContainer?.focus();1206}1207});1208});12091210this.registerExtensionAction({1211id: 'workbench.extensions.action.clearExtensionsSearchResults',1212title: localize2('clearExtensionsSearchResults', 'Clear Extensions Search Results'),1213category: ExtensionsLocalizedLabel,1214icon: clearSearchResultsIcon,1215f1: true,1216precondition: SearchHasTextContext,1217menu: {1218id: extensionsSearchActionsMenu,1219group: 'navigation',1220order: 1,1221},1222run: async (accessor: ServicesAccessor) => {1223const viewPaneContainer = accessor.get(IViewsService).getActiveViewPaneContainerWithId(VIEWLET_ID);1224if (viewPaneContainer) {1225const extensionsViewPaneContainer = viewPaneContainer as IExtensionsViewPaneContainer;1226extensionsViewPaneContainer.search('');1227extensionsViewPaneContainer.focus();1228}1229}1230});12311232this.registerExtensionAction({1233id: 'workbench.extensions.action.refreshExtension',1234title: localize2('refreshExtension', 'Refresh'),1235category: ExtensionsLocalizedLabel,1236icon: refreshIcon,1237f1: true,1238menu: {1239id: MenuId.ViewContainerTitle,1240when: ContextKeyExpr.equals('viewContainer', VIEWLET_ID),1241group: 'navigation',1242order: 21243},1244run: async (accessor: ServicesAccessor) => {1245const viewPaneContainer = accessor.get(IViewsService).getActiveViewPaneContainerWithId(VIEWLET_ID);1246if (viewPaneContainer) {1247await (viewPaneContainer as IExtensionsViewPaneContainer).refresh();1248}1249}1250});12511252this.registerExtensionAction({1253id: 'workbench.extensions.action.installWorkspaceRecommendedExtensions',1254title: localize('installWorkspaceRecommendedExtensions', "Install Workspace Recommended Extensions"),1255icon: installWorkspaceRecommendedIcon,1256menu: {1257id: MenuId.ViewTitle,1258when: ContextKeyExpr.equals('view', WORKSPACE_RECOMMENDATIONS_VIEW_ID),1259group: 'navigation',1260order: 11261},1262run: async (accessor: ServicesAccessor) => {1263const view = accessor.get(IViewsService).getActiveViewWithId(WORKSPACE_RECOMMENDATIONS_VIEW_ID) as IWorkspaceRecommendedExtensionsView;1264return view.installWorkspaceRecommendations();1265}1266});12671268this.registerExtensionAction({1269id: ConfigureWorkspaceFolderRecommendedExtensionsAction.ID,1270title: ConfigureWorkspaceFolderRecommendedExtensionsAction.LABEL,1271icon: configureRecommendedIcon,1272menu: [{1273id: MenuId.CommandPalette,1274when: WorkbenchStateContext.notEqualsTo('empty'),1275}, {1276id: MenuId.ViewTitle,1277when: ContextKeyExpr.equals('view', WORKSPACE_RECOMMENDATIONS_VIEW_ID),1278group: 'navigation',1279order: 21280}],1281run: () => runAction(this.instantiationService.createInstance(ConfigureWorkspaceFolderRecommendedExtensionsAction, ConfigureWorkspaceFolderRecommendedExtensionsAction.ID, ConfigureWorkspaceFolderRecommendedExtensionsAction.LABEL))1282});12831284this.registerExtensionAction({1285id: InstallSpecificVersionOfExtensionAction.ID,1286title: { value: InstallSpecificVersionOfExtensionAction.LABEL, original: 'Install Specific Version of Extension...' },1287category: ExtensionsLocalizedLabel,1288menu: {1289id: MenuId.CommandPalette,1290when: ContextKeyExpr.and(CONTEXT_HAS_GALLERY, ContextKeyExpr.or(CONTEXT_HAS_LOCAL_SERVER, CONTEXT_HAS_REMOTE_SERVER, CONTEXT_HAS_WEB_SERVER))1291},1292run: () => runAction(this.instantiationService.createInstance(InstallSpecificVersionOfExtensionAction, InstallSpecificVersionOfExtensionAction.ID, InstallSpecificVersionOfExtensionAction.LABEL))1293});1294}12951296// Extension Context Menu1297private registerContextMenuActions(): void {12981299this.registerExtensionAction({1300id: SetColorThemeAction.ID,1301title: SetColorThemeAction.TITLE,1302menu: {1303id: MenuId.ExtensionContext,1304group: THEME_ACTIONS_GROUP,1305order: 0,1306when: ContextKeyExpr.and(ContextKeyExpr.not('inExtensionEditor'), ContextKeyExpr.equals('extensionStatus', 'installed'), ContextKeyExpr.has('extensionHasColorThemes'))1307},1308run: async (accessor: ServicesAccessor, extensionId: string) => {1309const extensionWorkbenchService = accessor.get(IExtensionsWorkbenchService);1310const instantiationService = accessor.get(IInstantiationService);1311const extension = extensionWorkbenchService.local.find(e => areSameExtensions(e.identifier, { id: extensionId }));1312if (extension) {1313const action = instantiationService.createInstance(SetColorThemeAction);1314action.extension = extension;1315return action.run();1316}1317}1318});13191320this.registerExtensionAction({1321id: SetFileIconThemeAction.ID,1322title: SetFileIconThemeAction.TITLE,1323menu: {1324id: MenuId.ExtensionContext,1325group: THEME_ACTIONS_GROUP,1326order: 0,1327when: ContextKeyExpr.and(ContextKeyExpr.not('inExtensionEditor'), ContextKeyExpr.equals('extensionStatus', 'installed'), ContextKeyExpr.has('extensionHasFileIconThemes'))1328},1329run: async (accessor: ServicesAccessor, extensionId: string) => {1330const extensionWorkbenchService = accessor.get(IExtensionsWorkbenchService);1331const instantiationService = accessor.get(IInstantiationService);1332const extension = extensionWorkbenchService.local.find(e => areSameExtensions(e.identifier, { id: extensionId }));1333if (extension) {1334const action = instantiationService.createInstance(SetFileIconThemeAction);1335action.extension = extension;1336return action.run();1337}1338}1339});13401341this.registerExtensionAction({1342id: SetProductIconThemeAction.ID,1343title: SetProductIconThemeAction.TITLE,1344menu: {1345id: MenuId.ExtensionContext,1346group: THEME_ACTIONS_GROUP,1347order: 0,1348when: ContextKeyExpr.and(ContextKeyExpr.not('inExtensionEditor'), ContextKeyExpr.equals('extensionStatus', 'installed'), ContextKeyExpr.has('extensionHasProductIconThemes'))1349},1350run: async (accessor: ServicesAccessor, extensionId: string) => {1351const extensionWorkbenchService = accessor.get(IExtensionsWorkbenchService);1352const instantiationService = accessor.get(IInstantiationService);1353const extension = extensionWorkbenchService.local.find(e => areSameExtensions(e.identifier, { id: extensionId }));1354if (extension) {1355const action = instantiationService.createInstance(SetProductIconThemeAction);1356action.extension = extension;1357return action.run();1358}1359}1360});13611362this.registerExtensionAction({1363id: 'workbench.extensions.action.showPreReleaseVersion',1364title: localize2('show pre-release version', 'Show Pre-Release Version'),1365menu: {1366id: MenuId.ExtensionContext,1367group: INSTALL_ACTIONS_GROUP,1368order: 0,1369when: ContextKeyExpr.and(ContextKeyExpr.has('inExtensionEditor'), ContextKeyExpr.has('galleryExtensionHasPreReleaseVersion'), ContextKeyExpr.has('isPreReleaseExtensionAllowed'), ContextKeyExpr.not('showPreReleaseVersion'), ContextKeyExpr.not('isBuiltinExtension'))1370},1371run: async (accessor: ServicesAccessor, extensionId: string) => {1372const extensionWorkbenchService = accessor.get(IExtensionsWorkbenchService);1373const extension = (await extensionWorkbenchService.getExtensions([{ id: extensionId }], CancellationToken.None))[0];1374extensionWorkbenchService.open(extension, { showPreReleaseVersion: true });1375}1376});13771378this.registerExtensionAction({1379id: 'workbench.extensions.action.showReleasedVersion',1380title: localize2('show released version', 'Show Release Version'),1381menu: {1382id: MenuId.ExtensionContext,1383group: INSTALL_ACTIONS_GROUP,1384order: 1,1385when: ContextKeyExpr.and(ContextKeyExpr.has('inExtensionEditor'), ContextKeyExpr.has('galleryExtensionHasPreReleaseVersion'), ContextKeyExpr.has('extensionHasReleaseVersion'), ContextKeyExpr.has('showPreReleaseVersion'), ContextKeyExpr.not('isBuiltinExtension'))1386},1387run: async (accessor: ServicesAccessor, extensionId: string) => {1388const extensionWorkbenchService = accessor.get(IExtensionsWorkbenchService);1389const extension = (await extensionWorkbenchService.getExtensions([{ id: extensionId }], CancellationToken.None))[0];1390extensionWorkbenchService.open(extension, { showPreReleaseVersion: false });1391}1392});13931394this.registerExtensionAction({1395id: ToggleAutoUpdateForExtensionAction.ID,1396title: ToggleAutoUpdateForExtensionAction.LABEL,1397category: ExtensionsLocalizedLabel,1398precondition: ContextKeyExpr.and(ContextKeyExpr.or(ContextKeyExpr.notEquals(`config.${AutoUpdateConfigurationKey}`, 'onlyEnabledExtensions'), ContextKeyExpr.equals('isExtensionEnabled', true)), ContextKeyExpr.not('extensionDisallowInstall'), ContextKeyExpr.has('isExtensionAllowed')),1399menu: {1400id: MenuId.ExtensionContext,1401group: UPDATE_ACTIONS_GROUP,1402order: 1,1403when: ContextKeyExpr.and(1404ContextKeyExpr.not('inExtensionEditor'),1405ContextKeyExpr.equals('extensionStatus', 'installed'),1406ContextKeyExpr.not('isBuiltinExtension'),1407)1408},1409run: async (accessor: ServicesAccessor, id: string) => {1410const instantiationService = accessor.get(IInstantiationService);1411const extensionWorkbenchService = accessor.get(IExtensionsWorkbenchService);1412const extension = extensionWorkbenchService.local.find(e => areSameExtensions(e.identifier, { id }));1413if (extension) {1414const action = instantiationService.createInstance(ToggleAutoUpdateForExtensionAction);1415action.extension = extension;1416return action.run();1417}1418}1419});14201421this.registerExtensionAction({1422id: ToggleAutoUpdatesForPublisherAction.ID,1423title: { value: ToggleAutoUpdatesForPublisherAction.LABEL, original: 'Auto Update (Publisher)' },1424category: ExtensionsLocalizedLabel,1425precondition: ContextKeyExpr.equals(`config.${AutoUpdateConfigurationKey}`, false),1426menu: {1427id: MenuId.ExtensionContext,1428group: UPDATE_ACTIONS_GROUP,1429order: 2,1430when: ContextKeyExpr.and(ContextKeyExpr.equals('extensionStatus', 'installed'), ContextKeyExpr.not('isBuiltinExtension'))1431},1432run: async (accessor: ServicesAccessor, id: string) => {1433const instantiationService = accessor.get(IInstantiationService);1434const extensionWorkbenchService = accessor.get(IExtensionsWorkbenchService);1435const extension = extensionWorkbenchService.local.find(e => areSameExtensions(e.identifier, { id }));1436if (extension) {1437const action = instantiationService.createInstance(ToggleAutoUpdatesForPublisherAction);1438action.extension = extension;1439return action.run();1440}1441}1442});14431444this.registerExtensionAction({1445id: 'workbench.extensions.action.switchToPreRlease',1446title: localize('enablePreRleaseLabel', "Switch to Pre-Release Version"),1447category: ExtensionsLocalizedLabel,1448menu: {1449id: MenuId.ExtensionContext,1450group: INSTALL_ACTIONS_GROUP,1451order: 2,1452when: ContextKeyExpr.and(CONTEXT_HAS_GALLERY, ContextKeyExpr.has('galleryExtensionHasPreReleaseVersion'), ContextKeyExpr.has('isPreReleaseExtensionAllowed'), ContextKeyExpr.not('installedExtensionIsOptedToPreRelease'), ContextKeyExpr.not('inExtensionEditor'), ContextKeyExpr.equals('extensionStatus', 'installed'), ContextKeyExpr.not('isBuiltinExtension'))1453},1454run: async (accessor: ServicesAccessor, id: string) => {1455const instantiationService = accessor.get(IInstantiationService);1456const extensionWorkbenchService = accessor.get(IExtensionsWorkbenchService);1457const extension = extensionWorkbenchService.local.find(e => areSameExtensions(e.identifier, { id }));1458if (extension) {1459const action = instantiationService.createInstance(TogglePreReleaseExtensionAction);1460action.extension = extension;1461return action.run();1462}1463}1464});14651466this.registerExtensionAction({1467id: 'workbench.extensions.action.switchToRelease',1468title: localize('disablePreRleaseLabel', "Switch to Release Version"),1469category: ExtensionsLocalizedLabel,1470menu: {1471id: MenuId.ExtensionContext,1472group: INSTALL_ACTIONS_GROUP,1473order: 2,1474when: ContextKeyExpr.and(CONTEXT_HAS_GALLERY, ContextKeyExpr.has('galleryExtensionHasPreReleaseVersion'), ContextKeyExpr.has('isExtensionAllowed'), ContextKeyExpr.has('installedExtensionIsOptedToPreRelease'), ContextKeyExpr.not('inExtensionEditor'), ContextKeyExpr.equals('extensionStatus', 'installed'), ContextKeyExpr.not('isBuiltinExtension'))1475},1476run: async (accessor: ServicesAccessor, id: string) => {1477const instantiationService = accessor.get(IInstantiationService);1478const extensionWorkbenchService = accessor.get(IExtensionsWorkbenchService);1479const extension = extensionWorkbenchService.local.find(e => areSameExtensions(e.identifier, { id }));1480if (extension) {1481const action = instantiationService.createInstance(TogglePreReleaseExtensionAction);1482action.extension = extension;1483return action.run();1484}1485}1486});14871488this.registerExtensionAction({1489id: ClearLanguageAction.ID,1490title: ClearLanguageAction.TITLE,1491menu: {1492id: MenuId.ExtensionContext,1493group: INSTALL_ACTIONS_GROUP,1494order: 0,1495when: ContextKeyExpr.and(ContextKeyExpr.not('inExtensionEditor'), ContextKeyExpr.has('canSetLanguage'), ContextKeyExpr.has('isActiveLanguagePackExtension'))1496},1497run: async (accessor: ServicesAccessor, extensionId: string) => {1498const instantiationService = accessor.get(IInstantiationService);1499const extensionsWorkbenchService = accessor.get(IExtensionsWorkbenchService);1500const extension = (await extensionsWorkbenchService.getExtensions([{ id: extensionId }], CancellationToken.None))[0];1501const action = instantiationService.createInstance(ClearLanguageAction);1502action.extension = extension;1503return action.run();1504}1505});15061507this.registerExtensionAction({1508id: 'workbench.extensions.action.installUnsigned',1509title: localize('install', "Install"),1510menu: {1511id: MenuId.ExtensionContext,1512group: '0_install',1513when: ContextKeyExpr.and(ContextKeyExpr.equals('extensionStatus', 'uninstalled'), ContextKeyExpr.has('isGalleryExtension'), ContextKeyExpr.not('extensionDisallowInstall'), ContextKeyExpr.has('extensionIsUnsigned'),1514ContextKeyExpr.or(ContextKeyExpr.and(CONTEXT_GALLERY_ALL_PUBLIC_REPOSITORY_SIGNED, ContextKeyExpr.not('extensionIsPrivate')), ContextKeyExpr.and(CONTEXT_GALLERY_ALL_PRIVATE_REPOSITORY_SIGNED, ContextKeyExpr.has('extensionIsPrivate')))),1515order: 11516},1517run: async (accessor: ServicesAccessor, extensionId: string) => {1518const instantiationService = accessor.get(IInstantiationService);1519const extension = this.extensionsWorkbenchService.local.filter(e => areSameExtensions(e.identifier, { id: extensionId }))[0]1520|| (await this.extensionsWorkbenchService.getExtensions([{ id: extensionId }], CancellationToken.None))[0];1521if (extension) {1522const action = instantiationService.createInstance(InstallAction, { installPreReleaseVersion: this.extensionManagementService.preferPreReleases });1523action.extension = extension;1524return action.run();1525}1526}1527});15281529this.registerExtensionAction({1530id: 'workbench.extensions.action.installAndDonotSync',1531title: localize('install installAndDonotSync', "Install (Do not Sync)"),1532menu: {1533id: MenuId.ExtensionContext,1534group: '0_install',1535when: ContextKeyExpr.and(ContextKeyExpr.equals('extensionStatus', 'uninstalled'), ContextKeyExpr.has('isGalleryExtension'), ContextKeyExpr.has('isExtensionAllowed'), ContextKeyExpr.not('extensionDisallowInstall'), CONTEXT_SYNC_ENABLEMENT),1536order: 11537},1538run: async (accessor: ServicesAccessor, extensionId: string) => {1539const instantiationService = accessor.get(IInstantiationService);1540const extension = this.extensionsWorkbenchService.local.filter(e => areSameExtensions(e.identifier, { id: extensionId }))[0]1541|| (await this.extensionsWorkbenchService.getExtensions([{ id: extensionId }], CancellationToken.None))[0];1542if (extension) {1543const action = instantiationService.createInstance(InstallAction, {1544installPreReleaseVersion: this.extensionManagementService.preferPreReleases,1545isMachineScoped: true,1546});1547action.extension = extension;1548return action.run();1549}1550}1551});15521553this.registerExtensionAction({1554id: 'workbench.extensions.action.installPrereleaseAndDonotSync',1555title: localize('installPrereleaseAndDonotSync', "Install Pre-Release (Do not Sync)"),1556menu: {1557id: MenuId.ExtensionContext,1558group: '0_install',1559when: ContextKeyExpr.and(ContextKeyExpr.equals('extensionStatus', 'uninstalled'), ContextKeyExpr.has('isGalleryExtension'), ContextKeyExpr.has('extensionHasPreReleaseVersion'), ContextKeyExpr.has('isPreReleaseExtensionAllowed'), ContextKeyExpr.not('extensionDisallowInstall'), CONTEXT_SYNC_ENABLEMENT),1560order: 21561},1562run: async (accessor: ServicesAccessor, extensionId: string) => {1563const instantiationService = accessor.get(IInstantiationService);1564const extension = this.extensionsWorkbenchService.local.filter(e => areSameExtensions(e.identifier, { id: extensionId }))[0]1565|| (await this.extensionsWorkbenchService.getExtensions([{ id: extensionId }], CancellationToken.None))[0];1566if (extension) {1567const action = instantiationService.createInstance(InstallAction, {1568isMachineScoped: true,1569preRelease: true1570});1571action.extension = extension;1572return action.run();1573}1574}1575});15761577this.registerExtensionAction({1578id: InstallAnotherVersionAction.ID,1579title: InstallAnotherVersionAction.LABEL,1580menu: {1581id: MenuId.ExtensionContext,1582group: '0_install',1583when: ContextKeyExpr.and(ContextKeyExpr.equals('extensionStatus', 'uninstalled'), ContextKeyExpr.has('isGalleryExtension'), ContextKeyExpr.has('isExtensionAllowed'), ContextKeyExpr.not('extensionDisallowInstall')),1584order: 31585},1586run: async (accessor: ServicesAccessor, extensionId: string) => {1587const instantiationService = accessor.get(IInstantiationService);1588const extension = this.extensionsWorkbenchService.local.filter(e => areSameExtensions(e.identifier, { id: extensionId }))[0]1589|| (await this.extensionsWorkbenchService.getExtensions([{ id: extensionId }], CancellationToken.None))[0];1590if (extension) {1591return instantiationService.createInstance(InstallAnotherVersionAction, extension, false).run();1592}1593}1594});15951596this.registerExtensionAction({1597id: 'workbench.extensions.action.copyExtension',1598title: localize2('workbench.extensions.action.copyExtension', 'Copy'),1599menu: {1600id: MenuId.ExtensionContext,1601group: '1_copy'1602},1603run: async (accessor: ServicesAccessor, extensionId: string) => {1604const clipboardService = accessor.get(IClipboardService);1605const extension = this.extensionsWorkbenchService.local.filter(e => areSameExtensions(e.identifier, { id: extensionId }))[0]1606|| (await this.extensionsWorkbenchService.getExtensions([{ id: extensionId }], CancellationToken.None))[0];1607if (extension) {1608const name = localize('extensionInfoName', 'Name: {0}', extension.displayName);1609const id = localize('extensionInfoId', 'Id: {0}', extensionId);1610const description = localize('extensionInfoDescription', 'Description: {0}', extension.description);1611const verision = localize('extensionInfoVersion', 'Version: {0}', extension.version);1612const publisher = localize('extensionInfoPublisher', 'Publisher: {0}', extension.publisherDisplayName);1613const link = extension.url ? localize('extensionInfoVSMarketplaceLink', 'VS Marketplace Link: {0}', `${extension.url}`) : null;1614const clipboardStr = `${name}\n${id}\n${description}\n${verision}\n${publisher}${link ? '\n' + link : ''}`;1615await clipboardService.writeText(clipboardStr);1616}1617}1618});16191620this.registerExtensionAction({1621id: 'workbench.extensions.action.copyExtensionId',1622title: localize2('workbench.extensions.action.copyExtensionId', 'Copy Extension ID'),1623menu: {1624id: MenuId.ExtensionContext,1625group: '1_copy'1626},1627run: async (accessor: ServicesAccessor, id: string) => accessor.get(IClipboardService).writeText(id)1628});16291630this.registerExtensionAction({1631id: 'workbench.extensions.action.copyLink',1632title: localize2('workbench.extensions.action.copyLink', 'Copy Link'),1633menu: {1634id: MenuId.ExtensionContext,1635group: '1_copy',1636when: ContextKeyExpr.and(ContextKeyExpr.has('isGalleryExtension'), CONTEXT_GALLERY_HAS_EXTENSION_LINK),1637},1638run: async (accessor: ServicesAccessor, _, extension: IExtensionArg) => {1639const clipboardService = accessor.get(IClipboardService);1640if (extension.galleryLink) {1641await clipboardService.writeText(extension.galleryLink);1642}1643}1644});16451646this.registerExtensionAction({1647id: 'workbench.extensions.action.configure',1648title: localize2('workbench.extensions.action.configure', 'Settings'),1649menu: {1650id: MenuId.ExtensionContext,1651group: '2_configure',1652when: ContextKeyExpr.and(ContextKeyExpr.equals('extensionStatus', 'installed'), ContextKeyExpr.has('extensionHasConfiguration')),1653order: 11654},1655run: async (accessor: ServicesAccessor, id: string) => accessor.get(IPreferencesService).openSettings({ jsonEditor: false, query: `@ext:${id}` })1656});16571658this.registerExtensionAction({1659id: 'workbench.extensions.action.download',1660title: localize('download VSIX', "Download VSIX"),1661menu: {1662id: MenuId.ExtensionContext,1663when: ContextKeyExpr.and(ContextKeyExpr.not('extensionDisallowInstall'), ContextKeyExpr.has('isGalleryExtension')),1664order: this.productService.quality === 'stable' ? 0 : 11665},1666run: async (accessor: ServicesAccessor, extensionId: string) => {1667accessor.get(IExtensionsWorkbenchService).downloadVSIX(extensionId, 'release');1668}1669});16701671this.registerExtensionAction({1672id: 'workbench.extensions.action.downloadPreRelease',1673title: localize('download pre-release', "Download Pre-Release VSIX"),1674menu: {1675id: MenuId.ExtensionContext,1676when: ContextKeyExpr.and(ContextKeyExpr.not('extensionDisallowInstall'), ContextKeyExpr.has('isGalleryExtension'), ContextKeyExpr.has('extensionHasPreReleaseVersion')),1677order: this.productService.quality === 'stable' ? 1 : 01678},1679run: async (accessor: ServicesAccessor, extensionId: string) => {1680accessor.get(IExtensionsWorkbenchService).downloadVSIX(extensionId, 'prerelease');1681}1682});16831684this.registerExtensionAction({1685id: 'workbench.extensions.action.downloadSpecificVersion',1686title: localize('download specific version', "Download Specific Version VSIX..."),1687menu: {1688id: MenuId.ExtensionContext,1689when: ContextKeyExpr.and(ContextKeyExpr.not('extensionDisallowInstall'), ContextKeyExpr.has('isGalleryExtension')),1690order: 21691},1692run: async (accessor: ServicesAccessor, extensionId: string) => {1693accessor.get(IExtensionsWorkbenchService).downloadVSIX(extensionId, 'any');1694}1695});16961697this.registerExtensionAction({1698id: 'workbench.extensions.action.manageAccountPreferences',1699title: localize2('workbench.extensions.action.changeAccountPreference', "Account Preferences"),1700menu: {1701id: MenuId.ExtensionContext,1702group: '2_configure',1703when: ContextKeyExpr.and(ContextKeyExpr.equals('extensionStatus', 'installed'), ContextKeyExpr.has('extensionHasAccountPreferences')),1704order: 2,1705},1706run: (accessor: ServicesAccessor, id: string) => accessor.get(ICommandService).executeCommand('_manageAccountPreferencesForExtension', id)1707});17081709this.registerExtensionAction({1710id: 'workbench.extensions.action.configureKeybindings',1711title: localize2('workbench.extensions.action.configureKeybindings', 'Keyboard Shortcuts'),1712menu: {1713id: MenuId.ExtensionContext,1714group: '2_configure',1715when: ContextKeyExpr.and(ContextKeyExpr.equals('extensionStatus', 'installed'), ContextKeyExpr.has('extensionHasKeybindings')),1716order: 21717},1718run: async (accessor: ServicesAccessor, id: string) => accessor.get(IPreferencesService).openGlobalKeybindingSettings(false, { query: `@ext:${id}` })1719});17201721this.registerExtensionAction({1722id: 'workbench.extensions.action.toggleApplyToAllProfiles',1723title: localize2('workbench.extensions.action.toggleApplyToAllProfiles', "Apply Extension to all Profiles"),1724toggled: ContextKeyExpr.has('isApplicationScopedExtension'),1725menu: {1726id: MenuId.ExtensionContext,1727group: '2_configure',1728when: ContextKeyExpr.and(ContextKeyExpr.equals('extensionStatus', 'installed'), ContextKeyExpr.has('isDefaultApplicationScopedExtension').negate(), ContextKeyExpr.has('isBuiltinExtension').negate(), ContextKeyExpr.equals('isWorkspaceScopedExtension', false)),1729order: 31730},1731run: async (accessor: ServicesAccessor, _: string, extensionArg: IExtensionArg) => {1732const uriIdentityService = accessor.get(IUriIdentityService);1733const extension = extensionArg.location ? this.extensionsWorkbenchService.installed.find(e => uriIdentityService.extUri.isEqual(e.local?.location, extensionArg.location)) : undefined;1734if (extension) {1735return this.extensionsWorkbenchService.toggleApplyExtensionToAllProfiles(extension);1736}1737}1738});17391740this.registerExtensionAction({1741id: TOGGLE_IGNORE_EXTENSION_ACTION_ID,1742title: localize2('workbench.extensions.action.toggleIgnoreExtension', "Sync This Extension"),1743menu: {1744id: MenuId.ExtensionContext,1745group: '2_configure',1746when: ContextKeyExpr.and(ContextKeyExpr.equals('extensionStatus', 'installed'), CONTEXT_SYNC_ENABLEMENT, ContextKeyExpr.equals('isWorkspaceScopedExtension', false)),1747order: 41748},1749run: async (accessor: ServicesAccessor, id: string) => {1750const extension = this.extensionsWorkbenchService.local.find(e => areSameExtensions({ id }, e.identifier));1751if (extension) {1752return this.extensionsWorkbenchService.toggleExtensionIgnoredToSync(extension);1753}1754}1755});17561757this.registerExtensionAction({1758id: 'workbench.extensions.action.ignoreRecommendation',1759title: localize2('workbench.extensions.action.ignoreRecommendation', "Ignore Recommendation"),1760menu: {1761id: MenuId.ExtensionContext,1762group: '3_recommendations',1763when: ContextKeyExpr.has('isExtensionRecommended'),1764order: 11765},1766run: async (accessor: ServicesAccessor, id: string) => accessor.get(IExtensionIgnoredRecommendationsService).toggleGlobalIgnoredRecommendation(id, true)1767});17681769this.registerExtensionAction({1770id: 'workbench.extensions.action.undoIgnoredRecommendation',1771title: localize2('workbench.extensions.action.undoIgnoredRecommendation', "Undo Ignored Recommendation"),1772menu: {1773id: MenuId.ExtensionContext,1774group: '3_recommendations',1775when: ContextKeyExpr.has('isUserIgnoredRecommendation'),1776order: 11777},1778run: async (accessor: ServicesAccessor, id: string) => accessor.get(IExtensionIgnoredRecommendationsService).toggleGlobalIgnoredRecommendation(id, false)1779});17801781this.registerExtensionAction({1782id: 'workbench.extensions.action.addExtensionToWorkspaceRecommendations',1783title: localize2('workbench.extensions.action.addExtensionToWorkspaceRecommendations', "Add to Workspace Recommendations"),1784menu: {1785id: MenuId.ExtensionContext,1786group: '3_recommendations',1787when: ContextKeyExpr.and(WorkbenchStateContext.notEqualsTo('empty'), ContextKeyExpr.has('isBuiltinExtension').negate(), ContextKeyExpr.has('isExtensionWorkspaceRecommended').negate(), ContextKeyExpr.has('isUserIgnoredRecommendation').negate(), ContextKeyExpr.notEquals('extensionSource', 'resource')),1788order: 21789},1790run: (accessor: ServicesAccessor, id: string) => accessor.get(IWorkspaceExtensionsConfigService).toggleRecommendation(id)1791});17921793this.registerExtensionAction({1794id: 'workbench.extensions.action.removeExtensionFromWorkspaceRecommendations',1795title: localize2('workbench.extensions.action.removeExtensionFromWorkspaceRecommendations', "Remove from Workspace Recommendations"),1796menu: {1797id: MenuId.ExtensionContext,1798group: '3_recommendations',1799when: ContextKeyExpr.and(WorkbenchStateContext.notEqualsTo('empty'), ContextKeyExpr.has('isBuiltinExtension').negate(), ContextKeyExpr.has('isExtensionWorkspaceRecommended')),1800order: 21801},1802run: (accessor: ServicesAccessor, id: string) => accessor.get(IWorkspaceExtensionsConfigService).toggleRecommendation(id)1803});18041805this.registerExtensionAction({1806id: 'workbench.extensions.action.addToWorkspaceRecommendations',1807title: localize2('workbench.extensions.action.addToWorkspaceRecommendations', "Add Extension to Workspace Recommendations"),1808category: EXTENSIONS_CATEGORY,1809menu: {1810id: MenuId.CommandPalette,1811when: ContextKeyExpr.and(WorkbenchStateContext.isEqualTo('workspace'), ContextKeyExpr.equals('resourceScheme', Schemas.extension)),1812},1813async run(accessor: ServicesAccessor): Promise<any> {1814const editorService = accessor.get(IEditorService);1815const workspaceExtensionsConfigService = accessor.get(IWorkspaceExtensionsConfigService);1816if (!(editorService.activeEditor instanceof ExtensionsInput)) {1817return;1818}1819const extensionId = editorService.activeEditor.extension.identifier.id.toLowerCase();1820const recommendations = await workspaceExtensionsConfigService.getRecommendations();1821if (recommendations.includes(extensionId)) {1822return;1823}1824await workspaceExtensionsConfigService.toggleRecommendation(extensionId);1825}1826});18271828this.registerExtensionAction({1829id: 'workbench.extensions.action.addToWorkspaceFolderRecommendations',1830title: localize2('workbench.extensions.action.addToWorkspaceFolderRecommendations', "Add Extension to Workspace Folder Recommendations"),1831category: EXTENSIONS_CATEGORY,1832menu: {1833id: MenuId.CommandPalette,1834when: ContextKeyExpr.and(WorkbenchStateContext.isEqualTo('folder'), ContextKeyExpr.equals('resourceScheme', Schemas.extension)),1835},1836run: () => this.commandService.executeCommand('workbench.extensions.action.addToWorkspaceRecommendations')1837});18381839this.registerExtensionAction({1840id: 'workbench.extensions.action.addToWorkspaceIgnoredRecommendations',1841title: localize2('workbench.extensions.action.addToWorkspaceIgnoredRecommendations', "Add Extension to Workspace Ignored Recommendations"),1842category: EXTENSIONS_CATEGORY,1843menu: {1844id: MenuId.CommandPalette,1845when: ContextKeyExpr.and(WorkbenchStateContext.isEqualTo('workspace'), ContextKeyExpr.equals('resourceScheme', Schemas.extension)),1846},1847async run(accessor: ServicesAccessor): Promise<any> {1848const editorService = accessor.get(IEditorService);1849const workspaceExtensionsConfigService = accessor.get(IWorkspaceExtensionsConfigService);1850if (!(editorService.activeEditor instanceof ExtensionsInput)) {1851return;1852}1853const extensionId = editorService.activeEditor.extension.identifier.id.toLowerCase();1854const unwantedRecommendations = await workspaceExtensionsConfigService.getUnwantedRecommendations();1855if (unwantedRecommendations.includes(extensionId)) {1856return;1857}1858await workspaceExtensionsConfigService.toggleUnwantedRecommendation(extensionId);1859}1860});18611862this.registerExtensionAction({1863id: 'workbench.extensions.action.addToWorkspaceFolderIgnoredRecommendations',1864title: localize2('workbench.extensions.action.addToWorkspaceFolderIgnoredRecommendations', "Add Extension to Workspace Folder Ignored Recommendations"),1865category: EXTENSIONS_CATEGORY,1866menu: {1867id: MenuId.CommandPalette,1868when: ContextKeyExpr.and(WorkbenchStateContext.isEqualTo('folder'), ContextKeyExpr.equals('resourceScheme', Schemas.extension)),1869},1870run: () => this.commandService.executeCommand('workbench.extensions.action.addToWorkspaceIgnoredRecommendations')1871});18721873this.registerExtensionAction({1874id: ConfigureWorkspaceRecommendedExtensionsAction.ID,1875title: { value: ConfigureWorkspaceRecommendedExtensionsAction.LABEL, original: 'Configure Recommended Extensions (Workspace)' },1876category: EXTENSIONS_CATEGORY,1877menu: {1878id: MenuId.CommandPalette,1879when: WorkbenchStateContext.isEqualTo('workspace'),1880},1881run: () => runAction(this.instantiationService.createInstance(ConfigureWorkspaceRecommendedExtensionsAction, ConfigureWorkspaceRecommendedExtensionsAction.ID, ConfigureWorkspaceRecommendedExtensionsAction.LABEL))1882});18831884this.registerExtensionAction({1885id: 'workbench.extensions.action.manageTrustedPublishers',1886title: localize2('workbench.extensions.action.manageTrustedPublishers', "Manage Trusted Extension Publishers"),1887category: EXTENSIONS_CATEGORY,1888f1: true,1889run: async (accessor: ServicesAccessor) => {1890const quickInputService = accessor.get(IQuickInputService);1891const extensionManagementService = accessor.get(IWorkbenchExtensionManagementService);1892const trustedPublishers = extensionManagementService.getTrustedPublishers();1893const trustedPublisherItems = trustedPublishers.map(publisher => ({1894id: publisher.publisher,1895label: publisher.publisherDisplayName,1896description: publisher.publisher,1897picked: true,1898})).sort((a, b) => a.label.localeCompare(b.label));1899const result = await quickInputService.pick(trustedPublisherItems, {1900canPickMany: true,1901title: localize('trustedPublishers', "Manage Trusted Extension Publishers"),1902placeHolder: localize('trustedPublishersPlaceholder', "Choose which publishers to trust"),1903});1904if (result) {1905const untrustedPublishers = [];1906for (const { publisher } of trustedPublishers) {1907if (!result.some(r => r.id === publisher)) {1908untrustedPublishers.push(publisher);1909}1910}1911trustedPublishers.filter(publisher => !result.some(r => r.id === publisher.publisher));1912extensionManagementService.untrustPublishers(...untrustedPublishers);1913}1914}1915});19161917}19181919private registerExtensionAction(extensionActionOptions: IExtensionActionOptions): IDisposable {1920const menus = extensionActionOptions.menu ? Array.isArray(extensionActionOptions.menu) ? extensionActionOptions.menu : [extensionActionOptions.menu] : [];1921let menusWithOutTitles: ({ id: MenuId } & Omit<IMenuItem, 'command'>)[] = [];1922const menusWithTitles: { id: MenuId; item: IMenuItem }[] = [];1923if (extensionActionOptions.menuTitles) {1924for (let index = 0; index < menus.length; index++) {1925const menu = menus[index];1926const menuTitle = extensionActionOptions.menuTitles[menu.id.id];1927if (menuTitle) {1928menusWithTitles.push({ id: menu.id, item: { ...menu, command: { id: extensionActionOptions.id, title: menuTitle } } });1929} else {1930menusWithOutTitles.push(menu);1931}1932}1933} else {1934menusWithOutTitles = menus;1935}1936const disposables = new DisposableStore();1937disposables.add(registerAction2(class extends Action2 {1938constructor() {1939super({1940...extensionActionOptions,1941menu: menusWithOutTitles1942});1943}1944run(accessor: ServicesAccessor, ...args: any[]): Promise<any> {1945return extensionActionOptions.run(accessor, ...args);1946}1947}));1948if (menusWithTitles.length) {1949disposables.add(MenuRegistry.appendMenuItems(menusWithTitles));1950}1951return disposables;1952}19531954}19551956class ExtensionStorageCleaner implements IWorkbenchContribution {19571958constructor(1959@IExtensionManagementService extensionManagementService: IExtensionManagementService,1960@IStorageService storageService: IStorageService,1961) {1962ExtensionStorageService.removeOutdatedExtensionVersions(extensionManagementService, storageService);1963}1964}19651966class TrustedPublishersInitializer implements IWorkbenchContribution {1967constructor(1968@IWorkbenchExtensionManagementService extensionManagementService: IWorkbenchExtensionManagementService,1969@IUserDataProfilesService userDataProfilesService: IUserDataProfilesService,1970@IProductService productService: IProductService,1971@IStorageService storageService: IStorageService,1972) {1973const trustedPublishersInitStatusKey = 'trusted-publishers-init-migration';1974if (!storageService.get(trustedPublishersInitStatusKey, StorageScope.APPLICATION)) {1975for (const profile of userDataProfilesService.profiles) {1976extensionManagementService.getInstalled(ExtensionType.User, profile.extensionsResource)1977.then(async extensions => {1978const trustedPublishers = new Map<string, IPublisherInfo>();1979for (const extension of extensions) {1980if (!extension.publisherDisplayName) {1981continue;1982}1983const publisher = extension.manifest.publisher.toLowerCase();1984if (productService.trustedExtensionPublishers?.includes(publisher)1985|| (extension.publisherDisplayName && productService.trustedExtensionPublishers?.includes(extension.publisherDisplayName.toLowerCase()))) {1986continue;1987}1988trustedPublishers.set(publisher, { publisher, publisherDisplayName: extension.publisherDisplayName });1989}1990if (trustedPublishers.size) {1991extensionManagementService.trustPublishers(...trustedPublishers.values());1992}1993storageService.store(trustedPublishersInitStatusKey, 'true', StorageScope.APPLICATION, StorageTarget.MACHINE);1994});1995}1996}1997}1998}19992000class ExtensionToolsContribution extends Disposable implements IWorkbenchContribution {20012002static readonly ID = 'extensions.chat.toolsContribution';20032004constructor(2005@ILanguageModelToolsService toolsService: ILanguageModelToolsService,2006@IInstantiationService instantiationService: IInstantiationService,2007) {2008super();2009const searchExtensionsTool = instantiationService.createInstance(SearchExtensionsTool);2010this._register(toolsService.registerTool(SearchExtensionsToolData, searchExtensionsTool));2011}2012}20132014const workbenchRegistry = Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench);2015workbenchRegistry.registerWorkbenchContribution(ExtensionsContributions, LifecyclePhase.Restored);2016workbenchRegistry.registerWorkbenchContribution(StatusUpdater, LifecyclePhase.Eventually);2017workbenchRegistry.registerWorkbenchContribution(MaliciousExtensionChecker, LifecyclePhase.Eventually);2018workbenchRegistry.registerWorkbenchContribution(KeymapExtensions, LifecyclePhase.Restored);2019workbenchRegistry.registerWorkbenchContribution(ExtensionsViewletViewsContribution, LifecyclePhase.Restored);2020workbenchRegistry.registerWorkbenchContribution(ExtensionActivationProgress, LifecyclePhase.Eventually);2021workbenchRegistry.registerWorkbenchContribution(ExtensionDependencyChecker, LifecyclePhase.Eventually);2022workbenchRegistry.registerWorkbenchContribution(ExtensionEnablementWorkspaceTrustTransitionParticipant, LifecyclePhase.Restored);2023workbenchRegistry.registerWorkbenchContribution(ExtensionsCompletionItemsProvider, LifecyclePhase.Restored);2024workbenchRegistry.registerWorkbenchContribution(UnsupportedExtensionsMigrationContrib, LifecyclePhase.Eventually);2025workbenchRegistry.registerWorkbenchContribution(TrustedPublishersInitializer, LifecyclePhase.Eventually);2026workbenchRegistry.registerWorkbenchContribution(ExtensionMarketplaceStatusUpdater, LifecyclePhase.Eventually);2027if (isWeb) {2028workbenchRegistry.registerWorkbenchContribution(ExtensionStorageCleaner, LifecyclePhase.Eventually);2029}20302031registerWorkbenchContribution2(ExtensionToolsContribution.ID, ExtensionToolsContribution, WorkbenchPhase.AfterRestored);203220332034// Running Extensions2035registerAction2(ShowRuntimeExtensionsAction);20362037registerAction2(class ExtensionsGallerySignInAction extends Action2 {2038constructor() {2039super({2040id: 'workbench.extensions.actions.gallery.signIn',2041title: localize2('signInToMarketplace', 'Sign in to access Extensions Marketplace'),2042menu: {2043id: MenuId.AccountsContext,2044when: CONTEXT_EXTENSIONS_GALLERY_STATUS.isEqualTo(ExtensionGalleryManifestStatus.RequiresSignIn)2045},2046});2047}2048run(accessor: ServicesAccessor): Promise<void> {2049return accessor.get(ICommandService).executeCommand(DEFAULT_ACCOUNT_SIGN_IN_COMMAND);2050}2051});20522053Registry.as<IConfigurationMigrationRegistry>(ConfigurationMigrationExtensions.ConfigurationMigration)2054.registerConfigurationMigrations([{2055key: AutoUpdateConfigurationKey,2056migrateFn: (value, accessor) => {2057if (value === 'onlySelectedExtensions') {2058return { value: false };2059}2060return [];2061}2062}]);206320642065