-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
#136424 Initialize remote with user synced extensions
- Loading branch information
Showing
7 changed files
with
143 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
132 changes: 132 additions & 0 deletions
132
src/vs/workbench/contrib/extensions/electron-sandbox/remoteExtensionsInit.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
/*--------------------------------------------------------------------------------------------- | ||
* 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 'vs/base/common/cancellation'; | ||
import { IEnvironmentService } from 'vs/platform/environment/common/environment'; | ||
import { IExtensionGalleryService, IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement'; | ||
import { IFileService } from 'vs/platform/files/common/files'; | ||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; | ||
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; | ||
import { ILogService } from 'vs/platform/log/common/log'; | ||
import { IRemoteAuthorityResolverService } from 'vs/platform/remote/common/remoteAuthorityResolver'; | ||
import { IStorageService, IS_NEW_KEY, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; | ||
import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity'; | ||
import { AbstractExtensionsInitializer } from 'vs/platform/userDataSync/common/extensionsSync'; | ||
import { IIgnoredExtensionsManagementService } from 'vs/platform/userDataSync/common/ignoredExtensions'; | ||
import { IRemoteUserData, IUserDataSyncStoreManagementService, SyncResource } from 'vs/platform/userDataSync/common/userDataSync'; | ||
import { UserDataSyncStoreClient } from 'vs/platform/userDataSync/common/userDataSyncStoreService'; | ||
import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; | ||
import { IAuthenticationService } from 'vs/workbench/services/authentication/browser/authenticationService'; | ||
import { IExtensionManagementServerService } from 'vs/workbench/services/extensionManagement/common/extensionManagement'; | ||
import { IExtensionManifestPropertiesService } from 'vs/workbench/services/extensions/common/extensionManifestPropertiesService'; | ||
import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService'; | ||
|
||
export class RemoteExtensionsInitializerContribution implements IWorkbenchContribution { | ||
constructor( | ||
@IExtensionManagementServerService private readonly extensionManagementServerService: IExtensionManagementServerService, | ||
@IStorageService private readonly storageService: IStorageService, | ||
@IRemoteAgentService private readonly remoteAgentService: IRemoteAgentService, | ||
@IUserDataSyncStoreManagementService private readonly userDataSyncStoreManagementService: IUserDataSyncStoreManagementService, | ||
@IInstantiationService private readonly instantiationService: IInstantiationService, | ||
@ILogService private readonly logService: ILogService, | ||
@IAuthenticationService private readonly authenticationService: IAuthenticationService, | ||
@IRemoteAuthorityResolverService private readonly remoteAuthorityResolverService: IRemoteAuthorityResolverService, | ||
) { | ||
this.initializeRemoteExtensions(); | ||
} | ||
|
||
private async initializeRemoteExtensions(): Promise<void> { | ||
const connection = this.remoteAgentService.getConnection(); | ||
const localExtensionManagementServer = this.extensionManagementServerService.localExtensionManagementServer; | ||
const remoteExtensionManagementServer = this.extensionManagementServerService.remoteExtensionManagementServer; | ||
// Skip: Not a remote window | ||
if (!connection || !remoteExtensionManagementServer) { | ||
return; | ||
} | ||
// Skip: Not a native window | ||
if (!localExtensionManagementServer) { | ||
return; | ||
} | ||
// Skip: No UserdataSyncStore is configured | ||
if (!this.userDataSyncStoreManagementService.userDataSyncStore) { | ||
return; | ||
} | ||
const newRemoteConnectionKey = `${IS_NEW_KEY}.${connection.remoteAuthority}`; | ||
// Skip: Not a new remote connection | ||
if (!this.storageService.getBoolean(newRemoteConnectionKey, StorageScope.GLOBAL, true)) { | ||
this.logService.trace(`Skipping initializing remote extensions because the window with this remote authority was opened before.`); | ||
return; | ||
} | ||
this.storageService.store(newRemoteConnectionKey, false, StorageScope.GLOBAL, StorageTarget.MACHINE); | ||
// Skip: Not a new workspace | ||
if (!this.storageService.isNew(StorageScope.WORKSPACE)) { | ||
this.logService.trace(`Skipping initializing remote extensions because this workspace was opened before.`); | ||
return; | ||
} | ||
// Skip: No account is provided to initialize | ||
const resolvedAuthority = await this.remoteAuthorityResolverService.resolveAuthority(connection.remoteAuthority); | ||
if (!resolvedAuthority.options?.initializeUsingAccount) { | ||
return; | ||
} | ||
|
||
const sessions = await this.authenticationService.getSessions(resolvedAuthority.options?.initializeUsingAccount.providerId); | ||
const session = sessions.find(s => s.id === resolvedAuthority.options?.initializeUsingAccount?.sessionId); | ||
// Skip: Session is not found | ||
if (!session) { | ||
this.logService.info('Skipping initializing remote extensions because the account with given session id is not found', resolvedAuthority.options.initializeUsingAccount.sessionId); | ||
return; | ||
} | ||
|
||
const userDataSyncStoreClient = this.instantiationService.createInstance(UserDataSyncStoreClient, this.userDataSyncStoreManagementService.userDataSyncStore.url); | ||
userDataSyncStoreClient.setAuthToken(session.accessToken, resolvedAuthority.options.initializeUsingAccount.providerId); | ||
const userData = await userDataSyncStoreClient.read(SyncResource.Extensions, null); | ||
|
||
const serviceCollection = new ServiceCollection(); | ||
serviceCollection.set(IExtensionManagementService, remoteExtensionManagementServer.extensionManagementService); | ||
const instantiationService = this.instantiationService.createChild(serviceCollection); | ||
const extensionsToInstallInitializer = instantiationService.createInstance(RemoteExtensionsInitializer); | ||
|
||
await extensionsToInstallInitializer.initialize(userData); | ||
} | ||
} | ||
|
||
class RemoteExtensionsInitializer extends AbstractExtensionsInitializer { | ||
|
||
constructor( | ||
@IExtensionManagementService extensionManagementService: IExtensionManagementService, | ||
@IIgnoredExtensionsManagementService ignoredExtensionsManagementService: IIgnoredExtensionsManagementService, | ||
@IFileService fileService: IFileService, | ||
@IEnvironmentService environmentService: IEnvironmentService, | ||
@ILogService logService: ILogService, | ||
@IUriIdentityService uriIdentityService: IUriIdentityService, | ||
@IExtensionGalleryService private readonly extensionGalleryService: IExtensionGalleryService, | ||
@IExtensionManifestPropertiesService private readonly extensionManifestPropertiesService: IExtensionManifestPropertiesService, | ||
) { | ||
super(extensionManagementService, ignoredExtensionsManagementService, fileService, environmentService, logService, uriIdentityService); | ||
} | ||
|
||
protected override async doInitialize(remoteUserData: IRemoteUserData): Promise<void> { | ||
const remoteExtensions = await this.parseExtensions(remoteUserData); | ||
if (!remoteExtensions) { | ||
this.logService.info('No synced extensions exist while initializing remote extensions.'); | ||
return; | ||
} | ||
const installedExtensions = await this.extensionManagementService.getInstalled(); | ||
const { newExtensions } = this.generatePreview(remoteExtensions, installedExtensions); | ||
if (!newExtensions.length) { | ||
this.logService.trace('No new remote extensions to install.'); | ||
return; | ||
} | ||
const extensionsToInstall = await this.extensionGalleryService.getExtensions(newExtensions, CancellationToken.None); | ||
if (extensionsToInstall.length) { | ||
await Promise.allSettled(extensionsToInstall.map(async e => { | ||
const manifest = await this.extensionGalleryService.getManifest(e, CancellationToken.None); | ||
if (manifest && this.extensionManifestPropertiesService.canExecuteOnWorkspace(manifest)) { | ||
await this.extensionManagementService.installFromGallery(e); | ||
} | ||
})); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters