Skip to content

Commit 61a9d72

Browse files
committed
trigger extensions change when profile changed
1 parent 7f8fdb3 commit 61a9d72

File tree

3 files changed

+35
-13
lines changed

3 files changed

+35
-13
lines changed

src/vs/workbench/services/extensionManagement/browser/webExtensionsScannerService.ts

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6-
import { IBuiltinExtensionsScannerService, ExtensionType, IExtensionIdentifier, IExtension, IExtensionManifest, TargetPlatform } from 'vs/platform/extensions/common/extensions';
6+
import { IBuiltinExtensionsScannerService, ExtensionType, IExtensionIdentifier, IExtension, IExtensionManifest, TargetPlatform, ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
77
import { IBrowserWorkbenchEnvironmentService } from 'vs/workbench/services/environment/browser/environmentService';
88
import { IScannedExtension, IWebExtensionsScannerService, ScanOptions } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
99
import { isWeb, Language } from 'vs/base/common/platform';
@@ -33,15 +33,17 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic
3333
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
3434
import { basename } from 'vs/base/common/path';
3535
import { IExtensionStorageService } from 'vs/platform/extensionManagement/common/extensionStorage';
36-
import { isNonEmptyArray } from 'vs/base/common/arrays';
36+
import { delta, isNonEmptyArray } from 'vs/base/common/arrays';
3737
import { ILifecycleService, LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle';
3838
import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
3939
import { IProductService } from 'vs/platform/product/common/productService';
4040
import { validateExtensionManifest } from 'vs/platform/extensions/common/extensionValidator';
4141
import Severity from 'vs/base/common/severity';
4242
import { IStringDictionary } from 'vs/base/common/collections';
43-
import { IUserDataProfileService } from 'vs/workbench/services/userDataProfile/common/userDataProfile';
43+
import { DidChangeUserDataProfileEvent, IUserDataProfileService } from 'vs/workbench/services/userDataProfile/common/userDataProfile';
4444
import { IUserDataProfile, IUserDataProfilesService } from 'vs/platform/userDataProfile/common/userDataProfile';
45+
import { Emitter } from 'vs/base/common/event';
46+
import { compare } from 'vs/base/common/strings';
4547

4648
type GalleryExtensionInfo = { readonly id: string; preRelease?: boolean; migrateStorageFrom?: string };
4749
type ExtensionInfo = { readonly id: string; preRelease: boolean };
@@ -87,6 +89,9 @@ export class WebExtensionsScannerService extends Disposable implements IWebExten
8789
private readonly customBuiltinExtensionsCacheResource: URI | undefined = undefined;
8890
private readonly resourcesAccessQueueMap = new ResourceMap<Queue<IWebExtension[]>>();
8991

92+
private readonly _onDidChangeProfileExtensions = this._register(new Emitter<{ readonly added: IScannedExtension[]; readonly removed: IScannedExtension[] }>());
93+
readonly onDidChangeProfileExtensions = this._onDidChangeProfileExtensions.event;
94+
9095
constructor(
9196
@IBrowserWorkbenchEnvironmentService private readonly environmentService: IBrowserWorkbenchEnvironmentService,
9297
@IBuiltinExtensionsScannerService private readonly builtinExtensionsScannerService: IBuiltinExtensionsScannerService,
@@ -110,6 +115,7 @@ export class WebExtensionsScannerService extends Disposable implements IWebExten
110115

111116
// Eventually update caches
112117
lifecycleService.when(LifecyclePhase.Eventually).then(() => this.updateCaches());
118+
this._register(userDataProfileService.onDidChangeCurrentProfile(e => e.join(this.whenProfileChanged(e))));
113119
}
114120
}
115121

@@ -381,7 +387,7 @@ export class WebExtensionsScannerService extends Disposable implements IWebExten
381387
}
382388

383389
// User Installed extensions
384-
const installedExtensions = await this.scanInstalledExtensions(scanOptions);
390+
const installedExtensions = await this.scanInstalledExtensions(this.userDataProfileService.currentProfile, scanOptions);
385391
for (const extension of installedExtensions) {
386392
extensions.set(extension.identifier.id.toLowerCase(), extension);
387393
}
@@ -480,30 +486,30 @@ export class WebExtensionsScannerService extends Disposable implements IWebExten
480486
const installedExtensions = await this.readInstalledExtensions(profile);
481487
// Also add to installed extensions if it is installed to update its version
482488
if (installedExtensions.some(e => areSameExtensions(e.identifier, webExtension.identifier))) {
483-
await this.addToInstalledExtensions(webExtension, profile);
489+
await this.addToInstalledExtensions([webExtension], profile);
484490
}
485491
return extension;
486492
}
487493

488494
// Add to installed extensions
489-
await this.addToInstalledExtensions(webExtension, profile);
495+
await this.addToInstalledExtensions([webExtension], profile);
490496
return extension;
491497
}
492498

493-
private async addToInstalledExtensions(webExtension: IWebExtension, profile: IUserDataProfile): Promise<void> {
499+
private async addToInstalledExtensions(webExtensions: IWebExtension[], profile: IUserDataProfile): Promise<void> {
494500
await this.writeInstalledExtensions(profile, installedExtensions => {
495501
// Remove the existing extension to avoid duplicates
496-
installedExtensions = installedExtensions.filter(e => !areSameExtensions(e.identifier, webExtension.identifier));
497-
installedExtensions.push(webExtension);
502+
installedExtensions = installedExtensions.filter(installedExtension => webExtensions.some(extension => !areSameExtensions(installedExtension.identifier, extension.identifier)));
503+
installedExtensions.push(...webExtensions);
498504
return installedExtensions;
499505
});
500506
}
501507

502-
private async scanInstalledExtensions(scanOptions?: ScanOptions): Promise<IScannedExtension[]> {
503-
let installedExtensions = await this.readInstalledExtensions(this.userDataProfileService.currentProfile);
508+
private async scanInstalledExtensions(profile: IUserDataProfile, scanOptions?: ScanOptions): Promise<IScannedExtension[]> {
509+
let installedExtensions = await this.readInstalledExtensions(profile);
504510

505511
// If current profile is not a default profile, then add the application extensions to the list
506-
if (!this.userDataProfileService.currentProfile.isDefault) {
512+
if (!profile.isDefault) {
507513
// Remove application extensions from the non default profile
508514
installedExtensions = installedExtensions.filter(i => !i.metadata?.isApplicationScoped);
509515
// Add application extensions from the default profile to the list
@@ -830,6 +836,19 @@ export class WebExtensionsScannerService extends Disposable implements IWebExten
830836
}));
831837
}
832838

839+
private async whenProfileChanged(e: DidChangeUserDataProfileEvent): Promise<void> {
840+
if (e.preserveData) {
841+
const extensions = (await this.readInstalledExtensions(e.previous)).filter(e => !e.metadata?.isApplicationScoped); /* remove application scoped extensions */
842+
await this.addToInstalledExtensions(extensions, e.profile);
843+
} else {
844+
const oldExtensions = await this.scanInstalledExtensions(e.previous);
845+
const newExtensions = await this.scanInstalledExtensions(e.profile);
846+
const { added, removed } = delta(oldExtensions, newExtensions, (a, b) => compare(`${ExtensionIdentifier.toKey(a.identifier.id)}@${a.manifest.version}`, `${ExtensionIdentifier.toKey(b.identifier.id)}@${b.manifest.version}`));
847+
if (added.length || removed.length) {
848+
this._onDidChangeProfileExtensions.fire({ added, removed });
849+
}
850+
}
851+
}
833852
}
834853

835854
registerSingleton(IWebExtensionsScannerService, WebExtensionsScannerService);

src/vs/workbench/services/extensionManagement/common/extensionManagement.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,8 @@ export const IWebExtensionsScannerService = createDecorator<IWebExtensionsScanne
157157
export interface IWebExtensionsScannerService {
158158
readonly _serviceBrand: undefined;
159159

160+
readonly onDidChangeProfileExtensions: Event<{ readonly added: IScannedExtension[]; readonly removed: IScannedExtension[] }>;
161+
160162
scanSystemExtensions(): Promise<IExtension[]>;
161163
scanUserExtensions(options?: ScanOptions): Promise<IScannedExtension[]>;
162164
scanExtensionsUnderDevelopment(): Promise<IExtension[]>;

src/vs/workbench/services/extensionManagement/common/webExtensionManagementService.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export class WebExtensionManagementService extends AbstractExtensionManagementSe
2121

2222
declare readonly _serviceBrand: undefined;
2323

24-
readonly onDidChangeProfileExtensions = Event.None;
24+
readonly onDidChangeProfileExtensions: Event<{ readonly added: ILocalExtension[]; readonly removed: ILocalExtension[] }>;
2525

2626
constructor(
2727
@IExtensionGalleryService extensionGalleryService: IExtensionGalleryService,
@@ -32,6 +32,7 @@ export class WebExtensionManagementService extends AbstractExtensionManagementSe
3232
@IProductService productService: IProductService,
3333
) {
3434
super(extensionGalleryService, telemetryService, logService, productService);
35+
this.onDidChangeProfileExtensions = Event.map(this.webExtensionsScannerService.onDidChangeProfileExtensions, e => ({ added: e.added.map(a => toLocalExtension(a)), removed: e.removed.map(a => toLocalExtension(a)) }));
3536
}
3637

3738
async getTargetPlatform(): Promise<TargetPlatform> {

0 commit comments

Comments
 (0)