Extension management - refactoring workspace trust signal (#116118)
This commit is contained in:
parent
c86be3bb57
commit
e146dd28e1
3 changed files with 56 additions and 50 deletions
|
@ -41,7 +41,6 @@ import { FileAccess } from 'vs/base/common/network';
|
|||
import { IIgnoredExtensionsManagementService } from 'vs/platform/userDataSync/common/ignoredExtensions';
|
||||
import { IUserDataAutoSyncService } from 'vs/platform/userDataSync/common/userDataSync';
|
||||
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IWorkspaceTrustService, WorkspaceTrustState } from 'vs/platform/workspace/common/workspaceTrust';
|
||||
|
||||
interface IExtensionStateProvider<T> {
|
||||
(extension: Extension): T;
|
||||
|
@ -525,8 +524,7 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension
|
|||
@IIgnoredExtensionsManagementService private readonly extensionsSyncManagementService: IIgnoredExtensionsManagementService,
|
||||
@IUserDataAutoSyncService private readonly userDataAutoSyncService: IUserDataAutoSyncService,
|
||||
@IProductService private readonly productService: IProductService,
|
||||
@IContextKeyService contextKeyService: IContextKeyService,
|
||||
@IWorkspaceTrustService private readonly workspaceTrustService: IWorkspaceTrustService
|
||||
@IContextKeyService contextKeyService: IContextKeyService
|
||||
) {
|
||||
super();
|
||||
this.hasOutdatedExtensionsContextKey = HasOutdatedExtensionsContext.bindTo(contextKeyService);
|
||||
|
@ -1033,54 +1031,33 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension
|
|||
|
||||
private async installFromVSIX(vsix: URI): Promise<IExtension> {
|
||||
const manifest = await this.extensionManagementService.getManifest(vsix);
|
||||
return this.promptForTrustIfNeededAndInstall(manifest, async () => {
|
||||
const existingExtension = this.local.find(local => areSameExtensions(local.identifier, { id: getGalleryExtensionId(manifest.publisher, manifest.name) }));
|
||||
const { identifier } = await this.extensionManagementService.install(vsix);
|
||||
const existingExtension = this.local.find(local => areSameExtensions(local.identifier, { id: getGalleryExtensionId(manifest.publisher, manifest.name) }));
|
||||
const { identifier } = await this.extensionManagementService.install(vsix);
|
||||
|
||||
if (existingExtension && existingExtension.latestVersion !== manifest.version) {
|
||||
this.ignoreAutoUpdate(new ExtensionIdentifierWithVersion(identifier, manifest.version));
|
||||
}
|
||||
if (existingExtension && existingExtension.latestVersion !== manifest.version) {
|
||||
this.ignoreAutoUpdate(new ExtensionIdentifierWithVersion(identifier, manifest.version));
|
||||
}
|
||||
|
||||
return this.local.filter(local => areSameExtensions(local.identifier, identifier))[0];
|
||||
});
|
||||
return this.local.filter(local => areSameExtensions(local.identifier, identifier))[0];
|
||||
}
|
||||
|
||||
private async installFromGallery(extension: IExtension, gallery: IGalleryExtension, installOptions?: InstallOptions): Promise<IExtension> {
|
||||
const manifest = await extension.getManifest(CancellationToken.None);
|
||||
|
||||
if (manifest) {
|
||||
this.promptForTrustIfNeededAndInstall(manifest, async () => {
|
||||
this.installing.push(extension);
|
||||
this._onChange.fire(extension);
|
||||
try {
|
||||
if (extension.state === ExtensionState.Installed && extension.local) {
|
||||
await this.extensionManagementService.updateFromGallery(gallery, extension.local);
|
||||
} else {
|
||||
await this.extensionManagementService.installFromGallery(gallery, installOptions);
|
||||
}
|
||||
const ids: string[] | undefined = extension.identifier.uuid ? [extension.identifier.uuid] : undefined;
|
||||
const names: string[] | undefined = extension.identifier.uuid ? undefined : [extension.identifier.id];
|
||||
this.queryGallery({ names, ids, pageSize: 1 }, CancellationToken.None);
|
||||
return this.local.filter(local => areSameExtensions(local.identifier, gallery.identifier))[0];
|
||||
} finally {
|
||||
this.installing = this.installing.filter(e => e !== extension);
|
||||
this._onChange.fire(this.local.filter(e => areSameExtensions(e.identifier, extension.identifier))[0]);
|
||||
}
|
||||
});
|
||||
this.installing.push(extension);
|
||||
this._onChange.fire(extension);
|
||||
try {
|
||||
if (extension.state === ExtensionState.Installed && extension.local) {
|
||||
await this.extensionManagementService.updateFromGallery(gallery, extension.local);
|
||||
} else {
|
||||
await this.extensionManagementService.installFromGallery(gallery, installOptions);
|
||||
}
|
||||
const ids: string[] | undefined = extension.identifier.uuid ? [extension.identifier.uuid] : undefined;
|
||||
const names: string[] | undefined = extension.identifier.uuid ? undefined : [extension.identifier.id];
|
||||
this.queryGallery({ names, ids, pageSize: 1 }, CancellationToken.None);
|
||||
return this.local.filter(local => areSameExtensions(local.identifier, gallery.identifier))[0];
|
||||
} finally {
|
||||
this.installing = this.installing.filter(e => e !== extension);
|
||||
this._onChange.fire(this.local.filter(e => areSameExtensions(e.identifier, extension.identifier))[0]);
|
||||
}
|
||||
return Promise.reject();
|
||||
}
|
||||
|
||||
private async promptForTrustIfNeededAndInstall<T>(manifest: IExtensionManifest, installTask: () => Promise<T>): Promise<T> {
|
||||
if (manifest.requiresWorkspaceTrust === 'onStart') {
|
||||
const trustState = await this.workspaceTrustService.requireWorkspaceTrust(
|
||||
{
|
||||
immediate: true,
|
||||
message: 'Installing this extension requires you to trust the contents of this workspace.'
|
||||
});
|
||||
return trustState === WorkspaceTrustState.Trusted ? installTask() : Promise.reject();
|
||||
}
|
||||
return installTask();
|
||||
}
|
||||
|
||||
private promptAndSetEnablement(extensions: IExtension[], enablementState: EnablementState): Promise<any> {
|
||||
|
|
|
@ -25,6 +25,7 @@ import Severity from 'vs/base/common/severity';
|
|||
import { canceled } from 'vs/base/common/errors';
|
||||
import { IUserDataAutoSyncEnablementService, IUserDataSyncResourceEnablementService, SyncResource } from 'vs/platform/userDataSync/common/userDataSync';
|
||||
import { Promises } from 'vs/base/common/async';
|
||||
import { IWorkspaceTrustService, WorkspaceTrustState } from 'vs/platform/workspace/common/workspaceTrust';
|
||||
|
||||
export class ExtensionManagementService extends Disposable implements IWorkbenchExtensioManagementService {
|
||||
|
||||
|
@ -46,6 +47,7 @@ export class ExtensionManagementService extends Disposable implements IWorkbench
|
|||
@IUserDataAutoSyncEnablementService private readonly userDataAutoSyncEnablementService: IUserDataAutoSyncEnablementService,
|
||||
@IUserDataSyncResourceEnablementService private readonly userDataSyncResourceEnablementService: IUserDataSyncResourceEnablementService,
|
||||
@IDialogService private readonly dialogService: IDialogService,
|
||||
@IWorkspaceTrustService private readonly workspaceTrustService: IWorkspaceTrustService
|
||||
) {
|
||||
super();
|
||||
if (this.extensionManagementServerService.localExtensionManagementServer) {
|
||||
|
@ -128,9 +130,10 @@ export class ExtensionManagementService extends Disposable implements IWorkbench
|
|||
|
||||
}
|
||||
|
||||
reinstallFromGallery(extension: ILocalExtension): Promise<void> {
|
||||
async reinstallFromGallery(extension: ILocalExtension): Promise<void> {
|
||||
const server = this.getServer(extension);
|
||||
if (server) {
|
||||
await this.checkForWorkspaceTrust(extension.manifest);
|
||||
return server.extensionManagementService.reinstallFromGallery(extension);
|
||||
}
|
||||
return Promise.reject(`Invalid location ${extension.location.toString()}`);
|
||||
|
@ -191,8 +194,13 @@ export class ExtensionManagementService extends Disposable implements IWorkbench
|
|||
return Promise.reject('No Servers to Install');
|
||||
}
|
||||
|
||||
protected installVSIX(vsix: URI, server: IExtensionManagementServer): Promise<ILocalExtension> {
|
||||
return server.extensionManagementService.install(vsix);
|
||||
protected async installVSIX(vsix: URI, server: IExtensionManagementServer): Promise<ILocalExtension> {
|
||||
const manifest = await this.getManifest(vsix);
|
||||
if (manifest) {
|
||||
await this.checkForWorkspaceTrust(manifest);
|
||||
return server.extensionManagementService.install(vsix);
|
||||
}
|
||||
return Promise.reject('Unable to get the extension manifest.');
|
||||
}
|
||||
|
||||
getManifest(vsix: URI): Promise<IExtensionManifest> {
|
||||
|
@ -269,6 +277,7 @@ export class ExtensionManagementService extends Disposable implements IWorkbench
|
|||
servers.push(this.extensionManagementServerService.localExtensionManagementServer);
|
||||
}
|
||||
}
|
||||
await this.checkForWorkspaceTrust(manifest);
|
||||
return Promises.settled(servers.map(server => server.extensionManagementService.installFromGallery(gallery, installOptions))).then(([local]) => local);
|
||||
}
|
||||
|
||||
|
@ -346,4 +355,16 @@ export class ExtensionManagementService extends Disposable implements IWorkbench
|
|||
private getServer(extension: ILocalExtension): IExtensionManagementServer | null {
|
||||
return this.extensionManagementServerService.getExtensionManagementServer(extension);
|
||||
}
|
||||
|
||||
protected async checkForWorkspaceTrust(manifest: IExtensionManifest): Promise<void> {
|
||||
if (manifest.requiresWorkspaceTrust === 'onStart') {
|
||||
const trustState = await this.workspaceTrustService.requireWorkspaceTrust(
|
||||
{
|
||||
immediate: true,
|
||||
message: 'Installing this extension requires you to trust the contents of this workspace.'
|
||||
});
|
||||
return trustState === WorkspaceTrustState.Trusted ? Promise.resolve() : Promise.reject(canceled());
|
||||
}
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ import { INativeWorkbenchEnvironmentService } from 'vs/workbench/services/enviro
|
|||
import { joinPath } from 'vs/base/common/resources';
|
||||
import { IUserDataAutoSyncEnablementService, IUserDataSyncResourceEnablementService } from 'vs/platform/userDataSync/common/userDataSync';
|
||||
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
|
||||
import { IWorkspaceTrustService } from 'vs/platform/workspace/common/workspaceTrust';
|
||||
|
||||
export class ExtensionManagementService extends BaseExtensionManagementService {
|
||||
|
||||
|
@ -30,8 +31,9 @@ export class ExtensionManagementService extends BaseExtensionManagementService {
|
|||
@IUserDataAutoSyncEnablementService userDataAutoSyncEnablementService: IUserDataAutoSyncEnablementService,
|
||||
@IUserDataSyncResourceEnablementService userDataSyncResourceEnablementService: IUserDataSyncResourceEnablementService,
|
||||
@IDialogService dialogService: IDialogService,
|
||||
@IWorkspaceTrustService workspaceTrustService: IWorkspaceTrustService
|
||||
) {
|
||||
super(extensionManagementServerService, extensionGalleryService, configurationService, productService, downloadService, userDataAutoSyncEnablementService, userDataSyncResourceEnablementService, dialogService);
|
||||
super(extensionManagementServerService, extensionGalleryService, configurationService, productService, downloadService, userDataAutoSyncEnablementService, userDataSyncResourceEnablementService, dialogService, workspaceTrustService);
|
||||
}
|
||||
|
||||
protected async installVSIX(vsix: URI, server: IExtensionManagementServer): Promise<ILocalExtension> {
|
||||
|
@ -40,7 +42,13 @@ export class ExtensionManagementService extends BaseExtensionManagementService {
|
|||
await this.downloadService.download(vsix, downloadedLocation);
|
||||
vsix = downloadedLocation;
|
||||
}
|
||||
return server.extensionManagementService.install(vsix);
|
||||
const manifest = await this.getManifest(vsix);
|
||||
if (manifest) {
|
||||
await this.checkForWorkspaceTrust(manifest);
|
||||
return server.extensionManagementService.install(vsix);
|
||||
}
|
||||
|
||||
return Promise.reject('Unable to get the extension manifest.');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue