Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/workbench/contrib/externalUriOpener/common/contributedOpeners.ts
4780 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { Disposable } from '../../../../base/common/lifecycle.js';
7
import { IStorageService, StorageScope, StorageTarget } from '../../../../platform/storage/common/storage.js';
8
import { Memento } from '../../../common/memento.js';
9
import { updateContributedOpeners } from './configuration.js';
10
import { IExtensionService } from '../../../services/extensions/common/extensions.js';
11
12
interface RegisteredExternalOpener {
13
readonly extensionId: string;
14
15
isCurrentlyRegistered: boolean;
16
}
17
18
interface OpenersMemento {
19
[id: string]: RegisteredExternalOpener | undefined;
20
}
21
22
export class ContributedExternalUriOpenersStore extends Disposable {
23
24
private static readonly STORAGE_ID = 'externalUriOpeners';
25
26
private readonly _openers = new Map<string, RegisteredExternalOpener>();
27
private readonly _memento: Memento<OpenersMemento>;
28
private _mementoObject: OpenersMemento;
29
30
constructor(
31
@IStorageService storageService: IStorageService,
32
@IExtensionService private readonly _extensionService: IExtensionService
33
) {
34
super();
35
36
this._memento = new Memento(ContributedExternalUriOpenersStore.STORAGE_ID, storageService);
37
this._mementoObject = this._memento.getMemento(StorageScope.PROFILE, StorageTarget.MACHINE);
38
for (const [id, value] of Object.entries(this._mementoObject || {})) {
39
if (value) {
40
this.add(id, value.extensionId, { isCurrentlyRegistered: false });
41
}
42
}
43
44
this.invalidateOpenersOnExtensionsChanged();
45
46
this._register(this._extensionService.onDidChangeExtensions(() => this.invalidateOpenersOnExtensionsChanged()));
47
this._register(this._extensionService.onDidChangeExtensionsStatus(() => this.invalidateOpenersOnExtensionsChanged()));
48
}
49
50
public didRegisterOpener(id: string, extensionId: string): void {
51
this.add(id, extensionId, {
52
isCurrentlyRegistered: true
53
});
54
}
55
56
private add(id: string, extensionId: string, options: { isCurrentlyRegistered: boolean }): void {
57
const existing = this._openers.get(id);
58
if (existing) {
59
existing.isCurrentlyRegistered = existing.isCurrentlyRegistered || options.isCurrentlyRegistered;
60
return;
61
}
62
63
const entry = {
64
extensionId,
65
isCurrentlyRegistered: options.isCurrentlyRegistered
66
};
67
this._openers.set(id, entry);
68
69
this._mementoObject[id] = entry;
70
this._memento.saveMemento();
71
72
this.updateSchema();
73
}
74
75
public delete(id: string): void {
76
this._openers.delete(id);
77
78
delete this._mementoObject[id];
79
this._memento.saveMemento();
80
81
this.updateSchema();
82
}
83
84
private async invalidateOpenersOnExtensionsChanged() {
85
await this._extensionService.whenInstalledExtensionsRegistered();
86
const registeredExtensions = this._extensionService.extensions;
87
88
for (const [id, entry] of this._openers) {
89
const extension = registeredExtensions.find(r => r.identifier.value === entry.extensionId);
90
if (extension) {
91
if (!this._extensionService.canRemoveExtension(extension)) {
92
// The extension is running. We should have registered openers at this point
93
if (!entry.isCurrentlyRegistered) {
94
this.delete(id);
95
}
96
}
97
} else {
98
// The opener came from an extension that is no longer enabled/installed
99
this.delete(id);
100
}
101
}
102
}
103
104
private updateSchema() {
105
const ids: string[] = [];
106
const descriptions: string[] = [];
107
108
for (const [id, entry] of this._openers) {
109
ids.push(id);
110
descriptions.push(entry.extensionId);
111
}
112
113
updateContributedOpeners(ids, descriptions);
114
}
115
}
116
117