@@ -18,10 +18,12 @@ import {
18
18
} from 'vs/platform/extensionManagement/common/extensionManagement' ;
19
19
import { areSameExtensions , ExtensionKey , getGalleryExtensionTelemetryData , getLocalExtensionTelemetryData , getMaliciousExtensionsSet } from 'vs/platform/extensionManagement/common/extensionManagementUtil' ;
20
20
import { IExtensionsProfileScannerService } from 'vs/platform/extensionManagement/common/extensionsProfileScannerService' ;
21
- import { ExtensionType , IExtensionManifest , TargetPlatform } from 'vs/platform/extensions/common/extensions' ;
21
+ import { ExtensionType , IExtensionManifest , isApplicationScopedExtension , TargetPlatform } from 'vs/platform/extensions/common/extensions' ;
22
22
import { ILogService } from 'vs/platform/log/common/log' ;
23
23
import { IProductService } from 'vs/platform/product/common/productService' ;
24
24
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry' ;
25
+ import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity' ;
26
+ import { IUserDataProfilesService } from 'vs/platform/userDataProfile/common/userDataProfile' ;
25
27
26
28
export interface IInstallExtensionTask {
27
29
readonly identifier : IExtensionIdentifier ;
@@ -65,6 +67,8 @@ export abstract class AbstractExtensionManagementService extends Disposable impl
65
67
private readonly participants : IExtensionManagementParticipant [ ] = [ ] ;
66
68
67
69
constructor (
70
+ @IUserDataProfilesService private readonly userDataProfilesService : IUserDataProfilesService ,
71
+ @IUriIdentityService private readonly uriIdenityService : IUriIdentityService ,
68
72
@IExtensionGalleryService protected readonly galleryService : IExtensionGalleryService ,
69
73
@IExtensionsProfileScannerService protected readonly extensionsProfileScannerService : IExtensionsProfileScannerService ,
70
74
@ITelemetryService protected readonly telemetryService : ITelemetryService ,
@@ -142,18 +146,16 @@ export abstract class AbstractExtensionManagementService extends Disposable impl
142
146
const installExtensionTask = this . installingExtensions . get ( ExtensionKey . create ( extension ) . toString ( ) ) ;
143
147
if ( installExtensionTask ) {
144
148
this . logService . info ( 'Extensions is already requested to install' , extension . identifier . id ) ;
145
- const { local, metadata } = await installExtensionTask . waitUntilTaskIsFinished ( ) ;
146
- if ( options . profileLocation ) {
147
- await this . extensionsProfileScannerService . addExtensionsToProfile ( [ [ local , metadata ] ] , options . profileLocation ) ;
148
- }
149
+ const waitUntilTaskIsFinishedTask = this . createWaitUntilInstallExtensionTaskIsFinishedTask ( installExtensionTask , options ) ;
150
+ const { local } = await waitUntilTaskIsFinishedTask . waitUntilTaskIsFinished ( ) ;
149
151
return local ;
150
152
}
151
153
options = { ...options , installOnlyNewlyAddedFromExtensionPack : true /* always true for gallery extensions */ } ;
152
154
}
153
155
154
156
const allInstallExtensionTasks : { task : IInstallExtensionTask ; manifest : IExtensionManifest } [ ] = [ ] ;
155
157
const installResults : ( InstallExtensionResult & { local : ILocalExtension } ) [ ] = [ ] ;
156
- const installExtensionTask = this . createDefaultInstallExtensionTask ( manifest , extension , options ) ;
158
+ const installExtensionTask = this . createInstallExtensionTask ( manifest , extension , options ) ;
157
159
if ( ! URI . isUri ( extension ) ) {
158
160
this . installingExtensions . set ( ExtensionKey . create ( extension ) . toString ( ) , installExtensionTask ) ;
159
161
}
@@ -174,7 +176,7 @@ export abstract class AbstractExtensionManagementService extends Disposable impl
174
176
if ( this . installingExtensions . has ( key ) ) {
175
177
this . logService . info ( 'Extension is already requested to install' , gallery . identifier . id ) ;
176
178
} else {
177
- const task = this . createDefaultInstallExtensionTask ( manifest , gallery , { ...options , donotIncludePackAndDependencies : true } ) ;
179
+ const task = this . createInstallExtensionTask ( manifest , gallery , { ...options , donotIncludePackAndDependencies : true } ) ;
178
180
this . installingExtensions . set ( key , task ) ;
179
181
this . _onInstallExtension . fire ( { identifier : task . identifier , source : gallery } ) ;
180
182
this . logService . info ( 'Installing extension:' , task . identifier . id ) ;
@@ -219,10 +221,7 @@ export abstract class AbstractExtensionManagementService extends Disposable impl
219
221
await this . joinAllSettled ( extensionsToInstall . map ( async ( { task } ) => {
220
222
const startTime = new Date ( ) . getTime ( ) ;
221
223
try {
222
- const { local, metadata } = await task . run ( ) ;
223
- if ( options . profileLocation ) {
224
- await this . extensionsProfileScannerService . addExtensionsToProfile ( [ [ local , metadata ] ] , options . profileLocation ) ;
225
- }
224
+ const { local } = await task . run ( ) ;
226
225
await this . joinAllSettled ( this . participants . map ( participant => participant . postInstall ( local , task . source , options , CancellationToken . None ) ) ) ;
227
226
if ( ! URI . isUri ( task . source ) ) {
228
227
const isUpdate = task . operation === InstallOperation . Update ;
@@ -593,8 +592,23 @@ export abstract class AbstractExtensionManagementService extends Disposable impl
593
592
}
594
593
}
595
594
595
+ private createInstallExtensionTask ( manifest : IExtensionManifest , extension : URI | IGalleryExtension , options : ServerInstallOptions & ServerInstallVSIXOptions ) : IInstallExtensionTask {
596
+ const installTask = this . createDefaultInstallExtensionTask ( manifest , extension , options ) ;
597
+ return options . profileLocation && this . userDataProfilesService . defaultProfile . extensionsResource ? new InstallExtensionInProfileTask ( installTask , options . profileLocation , this . userDataProfilesService . defaultProfile . extensionsResource , this . extensionsProfileScannerService ) : installTask ;
598
+ }
599
+
600
+ private createWaitUntilInstallExtensionTaskIsFinishedTask ( installTask : IInstallExtensionTask , options : ServerInstallOptions & ServerInstallVSIXOptions ) : IInstallExtensionTask {
601
+ if ( ! options . profileLocation || ! this . userDataProfilesService . defaultProfile . extensionsResource ) {
602
+ return installTask ;
603
+ }
604
+ if ( installTask instanceof InstallExtensionInProfileTask && this . uriIdenityService . extUri . isEqual ( installTask . profileLocation , options . profileLocation ) ) {
605
+ return installTask ;
606
+ }
607
+ return new InstallExtensionInProfileTask ( installTask , options . profileLocation , this . userDataProfilesService . defaultProfile . extensionsResource , this . extensionsProfileScannerService ) ;
608
+ }
609
+
596
610
private createUninstallExtensionTask ( extension : ILocalExtension , options : UninstallExtensionTaskOptions , profile ?: URI ) : IUninstallExtensionTask {
597
- return profile ? new UninstallExtensionFromProfileTask ( extension , profile , this . extensionsProfileScannerService ) : this . createDefaultUninstallExtensionTask ( extension , options ) ;
611
+ return profile && this . userDataProfilesService . defaultProfile . extensionsResource ? new UninstallExtensionFromProfileTask ( extension , profile , this . userDataProfilesService , this . extensionsProfileScannerService ) : this . createDefaultUninstallExtensionTask ( extension , options ) ;
598
612
}
599
613
600
614
abstract getTargetPlatform ( ) : Promise < TargetPlatform > ;
@@ -707,18 +721,66 @@ export abstract class AbstractExtensionTask<T> {
707
721
protected abstract doRun ( token : CancellationToken ) : Promise < T > ;
708
722
}
709
723
710
- export class UninstallExtensionFromProfileTask extends AbstractExtensionTask < void > implements IUninstallExtensionTask {
724
+ class InstallExtensionInProfileTask implements IInstallExtensionTask {
725
+
726
+ readonly identifier = this . task . identifier ;
727
+ readonly source = this . task . source ;
728
+ readonly operation = this . task . operation ;
729
+
730
+ private readonly promise : Promise < { local : ILocalExtension ; metadata : Metadata } > ;
731
+
732
+ constructor (
733
+ private readonly task : IInstallExtensionTask ,
734
+ readonly profileLocation : URI ,
735
+ private readonly defaultProfileLocation : URI ,
736
+ private readonly extensionsProfileScannerService : IExtensionsProfileScannerService ,
737
+ ) {
738
+ this . promise = this . waitAndAddExtensionToProfile ( ) ;
739
+ }
740
+
741
+ private async waitAndAddExtensionToProfile ( ) : Promise < { local : ILocalExtension ; metadata : Metadata } > {
742
+ const result = await this . task . waitUntilTaskIsFinished ( ) ;
743
+ let profileLocation = this . profileLocation ;
744
+ if ( isApplicationScopedExtension ( result . local . manifest ) ) {
745
+ profileLocation = this . defaultProfileLocation ;
746
+ result . metadata = { ...result . metadata , isApplicationScoped : true } ;
747
+ }
748
+ await this . extensionsProfileScannerService . addExtensionsToProfile ( [ [ result . local , result . metadata ] ] , profileLocation ) ;
749
+ return result ;
750
+ }
751
+
752
+ async run ( ) : Promise < { local : ILocalExtension ; metadata : Metadata } > {
753
+ await this . task . run ( ) ;
754
+ return this . promise ;
755
+ }
756
+
757
+ waitUntilTaskIsFinished ( ) : Promise < { local : ILocalExtension ; metadata : Metadata } > {
758
+ return this . promise ;
759
+ }
760
+
761
+ cancel ( ) : void {
762
+ return this . task . cancel ( ) ;
763
+ }
764
+ }
765
+
766
+ class UninstallExtensionFromProfileTask extends AbstractExtensionTask < void > implements IUninstallExtensionTask {
711
767
712
768
constructor (
713
769
readonly extension : ILocalExtension ,
714
770
private readonly profileLocation : URI ,
771
+ private readonly userDataProfilesService : IUserDataProfilesService ,
715
772
private readonly extensionsProfileScannerService : IExtensionsProfileScannerService ,
716
773
) {
717
774
super ( ) ;
718
775
}
719
776
720
777
protected async doRun ( token : CancellationToken ) : Promise < void > {
721
- await this . extensionsProfileScannerService . removeExtensionFromProfile ( this . extension . identifier , this . profileLocation ) ;
778
+ const promises : Promise < any > [ ] = [ ] ;
779
+ promises . push ( this . extensionsProfileScannerService . removeExtensionFromProfile ( this . extension . identifier , this . profileLocation ) ) ;
780
+ if ( isApplicationScopedExtension ( this . extension . manifest ) && this . userDataProfilesService . defaultProfile . extensionsResource ) {
781
+ promises . push ( this . extensionsProfileScannerService . removeExtensionFromProfile ( this . extension . identifier , this . userDataProfilesService . defaultProfile . extensionsResource ) ) ;
782
+ }
783
+ await Promise . all ( promises ) ;
722
784
}
723
785
724
786
}
0 commit comments