Skip to content

Commit

Permalink
#136424 Initialize remote with user synced extensions
Browse files Browse the repository at this point in the history
  • Loading branch information
sandy081 committed Nov 12, 2021
1 parent a341134 commit 9b1d819
Show file tree
Hide file tree
Showing 7 changed files with 143 additions and 11 deletions.
1 change: 1 addition & 0 deletions src/vs/platform/remote/common/remoteAuthorityResolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export interface ResolvedAuthority {
export interface ResolvedOptions {
readonly extensionHostEnv?: { [key: string]: string | null };
readonly isTrusted?: boolean;
readonly initializeUsingAccount?: { providerId: string, sessionId: string };
}

export interface TunnelDescription {
Expand Down
9 changes: 2 additions & 7 deletions src/vs/platform/userDataSync/common/abstractSynchronizer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { localize } from 'vs/nls';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { FileChangesEvent, FileOperationError, FileOperationResult, IFileContent, IFileService } from 'vs/platform/files/common/files';
import { ILogService } from 'vs/platform/log/common/log';
import { getServiceMachineId } from 'vs/platform/serviceMachineId/common/serviceMachineId';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
Expand Down Expand Up @@ -835,7 +836,7 @@ export abstract class AbstractInitializer implements IUserDataInitializer {
constructor(
readonly resource: SyncResource,
@IEnvironmentService protected readonly environmentService: IEnvironmentService,
@IUserDataSyncLogService protected readonly logService: IUserDataSyncLogService,
@ILogService protected readonly logService: ILogService,
@IFileService protected readonly fileService: IFileService,
@IUriIdentityService uriIdentityService: IUriIdentityService,
) {
Expand All @@ -854,12 +855,6 @@ export abstract class AbstractInitializer implements IUserDataInitializer {
return;
}

const isPreviouslySynced = await this.fileService.exists(this.lastSyncResource);
if (isPreviouslySynced) {
this.logService.info('Remote content does not exist.', this.resource);
return;
}

try {
await this.doInitialize({ ref, syncData });
} catch (error) {
Expand Down
3 changes: 2 additions & 1 deletion src/vs/platform/userDataSync/common/extensionsSync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { IExtensionGalleryService, IExtensionManagementService, IGlobalExtension
import { areSameExtensions, getExtensionId, getGalleryExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
import { ExtensionType, IExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import { IFileService } from 'vs/platform/files/common/files';
import { ILogService } from 'vs/platform/log/common/log';
import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity';
Expand Down Expand Up @@ -506,7 +507,7 @@ export abstract class AbstractExtensionsInitializer extends AbstractInitializer
@IIgnoredExtensionsManagementService private readonly ignoredExtensionsManagementService: IIgnoredExtensionsManagementService,
@IFileService fileService: IFileService,
@IEnvironmentService environmentService: IEnvironmentService,
@IUserDataSyncLogService logService: IUserDataSyncLogService,
@ILogService logService: ILogService,
@IUriIdentityService uriIdentityService: IUriIdentityService,
) {
super(SyncResource.Extensions, environmentService, logService, fileService, uriIdentityService);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { IExtensionRecommendationNotificationService } from 'vs/platform/extensi
import { ISharedProcessService } from 'vs/platform/ipc/electron-sandbox/services';
import { ExtensionRecommendationNotificationServiceChannel } from 'vs/platform/extensionRecommendations/electron-sandbox/extensionRecommendationsIpc';
import { Codicon } from 'vs/base/common/codicons';
import { RemoteExtensionsInitializerContribution } from 'vs/workbench/contrib/extensions/electron-sandbox/remoteExtensionsInit';

// Running Extensions Editor
Registry.as<IEditorPaneRegistry>(EditorExtensions.EditorPane).registerEditorPane(
Expand Down Expand Up @@ -60,6 +61,7 @@ class ExtensionsContributions implements IWorkbenchContribution {

const workbenchRegistry = Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench);
workbenchRegistry.registerWorkbenchContribution(ExtensionsContributions, LifecyclePhase.Starting);
workbenchRegistry.registerWorkbenchContribution(RemoteExtensionsInitializerContribution, LifecyclePhase.Restored);

// Register Commands

Expand Down
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);
}
}));
}
}
}
3 changes: 3 additions & 0 deletions src/vs/workbench/workbench.common.main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,10 @@ import { OpenerService } from 'vs/editor/browser/services/openerService';
import { IOpenerService } from 'vs/platform/opener/common/opener';
import { IgnoredExtensionsManagementService, IIgnoredExtensionsManagementService } from 'vs/platform/userDataSync/common/ignoredExtensions';
import { ExtensionsStorageSyncService, IExtensionsStorageSyncService } from 'vs/platform/userDataSync/common/extensionsStorageSync';
import { IUserDataSyncLogService } from 'vs/platform/userDataSync/common/userDataSync';
import { UserDataSyncLogService } from 'vs/platform/userDataSync/common/userDataSyncLog';

registerSingleton(IUserDataSyncLogService, UserDataSyncLogService);
registerSingleton(IIgnoredExtensionsManagementService, IgnoredExtensionsManagementService);
registerSingleton(IGlobalExtensionEnablementService, GlobalExtensionEnablementService);
registerSingleton(IExtensionsStorageSyncService, ExtensionsStorageSyncService);
Expand Down
4 changes: 1 addition & 3 deletions src/vs/workbench/workbench.web.main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,7 @@ import { ExtensionManagementService } from 'vs/workbench/services/extensionManag
import { ILoggerService } from 'vs/platform/log/common/log';
import { FileLoggerService } from 'vs/platform/log/common/fileLog';
import { UserDataSyncMachinesService, IUserDataSyncMachinesService } from 'vs/platform/userDataSync/common/userDataSyncMachines';
import { IUserDataSyncStoreService, IUserDataSyncService, IUserDataSyncLogService, IUserDataAutoSyncService, IUserDataSyncBackupStoreService } from 'vs/platform/userDataSync/common/userDataSync';
import { UserDataSyncLogService } from 'vs/platform/userDataSync/common/userDataSyncLog';
import { IUserDataSyncStoreService, IUserDataSyncService, IUserDataAutoSyncService, IUserDataSyncBackupStoreService } from 'vs/platform/userDataSync/common/userDataSync';
import { UserDataSyncStoreService } from 'vs/platform/userDataSync/common/userDataSyncStoreService';
import { UserDataSyncBackupStoreService } from 'vs/platform/userDataSync/common/userDataSyncBackupStoreService';
import { UserDataSyncService } from 'vs/platform/userDataSync/common/userDataSyncService';
Expand All @@ -94,7 +93,6 @@ registerSingleton(IWorkbenchExtensionManagementService, ExtensionManagementServi
registerSingleton(IAccessibilityService, AccessibilityService, true);
registerSingleton(IContextMenuService, ContextMenuService);
registerSingleton(ILoggerService, FileLoggerService);
registerSingleton(IUserDataSyncLogService, UserDataSyncLogService);
registerSingleton(IUserDataSyncStoreService, UserDataSyncStoreService);
registerSingleton(IUserDataSyncMachinesService, UserDataSyncMachinesService);
registerSingleton(IUserDataSyncBackupStoreService, UserDataSyncBackupStoreService);
Expand Down

0 comments on commit 9b1d819

Please sign in to comment.