diff --git a/src/vs/workbench/contrib/extensions/electron-sandbox/extensions.contribution.ts b/src/vs/workbench/contrib/extensions/electron-sandbox/extensions.contribution.ts index 9f793d53124e7..d7ab04b698f4b 100644 --- a/src/vs/workbench/contrib/extensions/electron-sandbox/extensions.contribution.ts +++ b/src/vs/workbench/contrib/extensions/electron-sandbox/extensions.contribution.ts @@ -23,8 +23,7 @@ import { DebugExtensionHostAction, DebugExtensionsContribution } from './debugEx import { ExtensionHostProfileService } from './extensionProfileService.js'; import { CleanUpExtensionsFolderAction, OpenExtensionsFolderAction } from './extensionsActions.js'; import { ExtensionsAutoProfiler } from './extensionsAutoProfiler.js'; -import { InstallFailedExtensions } from './installFailedExtensions.js'; -import { RemoteExtensionsInitializerContribution } from './remoteExtensionsInit.js'; +import { InstallFailedRemoteExtensionsContribution, RemoteExtensionsInitializerContribution } from './remoteExtensionsInit.js'; import { IExtensionHostProfileService, OpenExtensionHostProfileACtion, RuntimeExtensionsEditor, SaveExtensionHostProfileAction, StartExtensionHostProfileAction, StopExtensionHostProfileAction } from './runtimeExtensionsEditor.js'; // Singletons @@ -72,8 +71,8 @@ const workbenchRegistry = Registry.as(Workbench workbenchRegistry.registerWorkbenchContribution(ExtensionsContributions, LifecyclePhase.Restored); workbenchRegistry.registerWorkbenchContribution(ExtensionsAutoProfiler, LifecyclePhase.Eventually); workbenchRegistry.registerWorkbenchContribution(RemoteExtensionsInitializerContribution, LifecyclePhase.Restored); +workbenchRegistry.registerWorkbenchContribution(InstallFailedRemoteExtensionsContribution, LifecyclePhase.Restored); workbenchRegistry.registerWorkbenchContribution(DebugExtensionsContribution, LifecyclePhase.Restored); -workbenchRegistry.registerWorkbenchContribution(InstallFailedExtensions, LifecyclePhase.Restored); // Register Commands @@ -82,4 +81,3 @@ registerAction2(StartExtensionHostProfileAction); registerAction2(StopExtensionHostProfileAction); registerAction2(SaveExtensionHostProfileAction); registerAction2(OpenExtensionHostProfileACtion); - diff --git a/src/vs/workbench/contrib/extensions/electron-sandbox/installFailedExtensions.ts b/src/vs/workbench/contrib/extensions/electron-sandbox/installFailedExtensions.ts deleted file mode 100644 index 3f602213b23d0..0000000000000 --- a/src/vs/workbench/contrib/extensions/electron-sandbox/installFailedExtensions.ts +++ /dev/null @@ -1,62 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { CancellationToken } from '../../../../base/common/cancellation.js'; -import { Disposable } from '../../../../base/common/lifecycle.js'; -import { IExtensionGalleryService, InstallExtensionInfo } from '../../../../platform/extensionManagement/common/extensionManagement.js'; -import { ILogService } from '../../../../platform/log/common/log.js'; -import { IRemoteExtensionsScannerService } from '../../../../platform/remote/common/remoteExtensionsScanner.js'; -import { IWorkbenchContribution } from '../../../common/contributions.js'; -import { areSameExtensions } from '../../../../platform/extensionManagement/common/extensionManagementUtil.js'; -import { IExtensionManagementServerService } from '../../../services/extensionManagement/common/extensionManagement.js'; -/** - * Checks and attempts to install extensions that remote server has 'relayed' to workbench. - * The server would 'relay' an extension for installation if it was unable to install it by itself. - */ -export class InstallFailedExtensions extends Disposable implements IWorkbenchContribution { - constructor( - @IRemoteExtensionsScannerService remoteExtensionsScannerService: IRemoteExtensionsScannerService, - @IExtensionGalleryService private readonly _extensionGalleryService: IExtensionGalleryService, - @IExtensionManagementServerService private readonly _extensionManagementServerService: IExtensionManagementServerService, - @ILogService logService: ILogService - ) { - super(); - logService.info('Checking for extensions relayed from server'); - remoteExtensionsScannerService.whenExtensionsReady() - .then(async ({ failed }) => { - if (failed.length === 0) { - logService.trace('No extensions relayed from server'); - return; - } - - if (!this._extensionManagementServerService.remoteExtensionManagementServer) { - logService.error('No remote extension management server available'); - return; - } - - logService.trace(`Retrieved gallery information for '${failed.length}' extensions relayed from server`); - const extensionManagementService = this._extensionManagementServerService.remoteExtensionManagementServer.extensionManagementService; - const galleryExtensions = await this._extensionGalleryService.getExtensions(failed, CancellationToken.None); - // Join back with its installOptions - const installExtensionInfo: InstallExtensionInfo[] = galleryExtensions.map(ext => { - return { - extension: ext, - options: failed.find(f => areSameExtensions(f, ext.identifier))?.installOptions || {} - }; - }); - - logService.trace(`Retrieved gallery information for '${installExtensionInfo.length}' extensions relayed from server`); - const settled = await Promise.allSettled( - installExtensionInfo.map(info => extensionManagementService.installFromGallery(info.extension, info.options)) - ); - - const installedCount = settled.filter(result => result.status === 'fulfilled').length; - logService.info(`Installed '${installedCount}' of '${failed.length}' extensions relayed from server`); - }).catch(e => { - logService.error('Unexpected failure installing extensions relayed from server'); - logService.error(e); - }); - } -} diff --git a/src/vs/workbench/contrib/extensions/electron-sandbox/remoteExtensionsInit.ts b/src/vs/workbench/contrib/extensions/electron-sandbox/remoteExtensionsInit.ts index 203212373a6e5..88e2f38ec668a 100644 --- a/src/vs/workbench/contrib/extensions/electron-sandbox/remoteExtensionsInit.ts +++ b/src/vs/workbench/contrib/extensions/electron-sandbox/remoteExtensionsInit.ts @@ -5,13 +5,14 @@ import { CancellationToken } from '../../../../base/common/cancellation.js'; import { IEnvironmentService } from '../../../../platform/environment/common/environment.js'; -import { IExtensionGalleryService, IExtensionManagementService } from '../../../../platform/extensionManagement/common/extensionManagement.js'; +import { IExtensionGalleryService, IExtensionManagementService, InstallExtensionInfo } from '../../../../platform/extensionManagement/common/extensionManagement.js'; import { areSameExtensions } from '../../../../platform/extensionManagement/common/extensionManagementUtil.js'; import { IFileService } from '../../../../platform/files/common/files.js'; import { IInstantiationService } from '../../../../platform/instantiation/common/instantiation.js'; import { ServiceCollection } from '../../../../platform/instantiation/common/serviceCollection.js'; import { ILogService } from '../../../../platform/log/common/log.js'; import { IRemoteAuthorityResolverService } from '../../../../platform/remote/common/remoteAuthorityResolver.js'; +import { IRemoteExtensionsScannerService } from '../../../../platform/remote/common/remoteExtensionsScanner.js'; import { IStorageService, IS_NEW_KEY, StorageScope, StorageTarget } from '../../../../platform/storage/common/storage.js'; import { IUriIdentityService } from '../../../../platform/uriIdentity/common/uriIdentity.js'; import { IUserDataProfilesService } from '../../../../platform/userDataProfile/common/userDataProfile.js'; @@ -25,6 +26,51 @@ import { IExtensionManagementServerService } from '../../../services/extensionMa import { IExtensionManifestPropertiesService } from '../../../services/extensions/common/extensionManifestPropertiesService.js'; import { IRemoteAgentService } from '../../../services/remote/common/remoteAgentService.js'; +export class InstallFailedRemoteExtensionsContribution implements IWorkbenchContribution { + constructor( + @IRemoteAgentService private readonly remoteAgentService: IRemoteAgentService, + @IRemoteExtensionsScannerService private readonly remoteExtensionsScannerService: IRemoteExtensionsScannerService, + @IExtensionGalleryService private readonly extensionGalleryService: IExtensionGalleryService, + @IExtensionManagementServerService private readonly extensionManagementServerService: IExtensionManagementServerService, + @ILogService private readonly logService: ILogService + ) { + this.installFailedRemoteExtensions(); + } + + private async installFailedRemoteExtensions(): Promise { + if (!this.remoteAgentService.getConnection()) { + return; + } + + const { failed } = await this.remoteExtensionsScannerService.whenExtensionsReady(); + if (failed.length === 0) { + this.logService.trace('No extensions relayed from server'); + return; + } + + if (!this.extensionManagementServerService.remoteExtensionManagementServer) { + this.logService.error('No remote extension management server available'); + return; + } + + this.logService.info(`Installing '${failed.length}' extensions relayed from server`); + const galleryExtensions = await this.extensionGalleryService.getExtensions(failed.map(({ id }) => ({ id })), CancellationToken.None); + const installExtensionInfo: InstallExtensionInfo[] = []; + for (const { id, installOptions } of failed) { + const extension = galleryExtensions.find(e => areSameExtensions(e.identifier, { id })); + if (extension) { + installExtensionInfo.push({ extension, options: installOptions }); + } else { + this.logService.warn(`Relayed failed extension '${id}' from server is not found in the gallery`); + } + } + + if (installExtensionInfo.length) { + await this.extensionManagementServerService.remoteExtensionManagementServer.extensionManagementService.installGalleryExtensions(installExtensionInfo); + } + } +} + export class RemoteExtensionsInitializerContribution implements IWorkbenchContribution { constructor( @IExtensionManagementServerService private readonly extensionManagementServerService: IExtensionManagementServerService,