@codingame/monaco-vscode-extension-gallery-service-override 2.2.2 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (17) hide show
  1. package/extensionGallery.js +23 -8
  2. package/package.json +9 -9
  3. package/vscode/src/vs/platform/extensionManagement/common/abstractExtensionManagementService.js +123 -163
  4. package/vscode/src/vs/platform/extensionManagement/common/extensionGalleryService.js +1 -1
  5. package/vscode/src/vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor.js +42 -7
  6. package/vscode/src/vs/workbench/contrib/extensions/browser/extensionEditor.js +43 -827
  7. package/vscode/src/vs/workbench/contrib/extensions/browser/extensionFeaturesTab.js +542 -0
  8. package/vscode/src/vs/workbench/contrib/extensions/browser/extensions.contribution.js +63 -54
  9. package/vscode/src/vs/workbench/contrib/extensions/browser/extensionsList.js +0 -1
  10. package/vscode/src/vs/workbench/contrib/extensions/browser/extensionsViewlet.js +10 -13
  11. package/vscode/src/vs/workbench/contrib/extensions/browser/extensionsViews.js +36 -8
  12. package/vscode/src/vs/workbench/contrib/extensions/browser/extensionsWidgets.js +2 -2
  13. package/vscode/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.js +1 -5
  14. package/vscode/src/vs/workbench/contrib/extensions/browser/media/extension.css.js +1 -1
  15. package/vscode/src/vs/workbench/contrib/extensions/browser/media/extensionEditor.css.js +1 -1
  16. package/vscode/src/vs/workbench/services/extensionManagement/common/extensionFeaturesManagemetService.js +234 -0
  17. package/vscode/src/vs/workbench/services/extensionManagement/common/webExtensionManagementService.js +2 -2
@@ -21,30 +21,44 @@ import { ExtensionTipsService } from './vscode/src/vs/platform/extensionManageme
21
21
  import { ExtensionManagementService } from './vscode/src/vs/workbench/services/extensionManagement/common/extensionManagementService.js';
22
22
  import { IRemoteUserDataProfilesService, RemoteUserDataProfilesService } from 'vscode/vscode/vs/workbench/services/userDataProfile/common/remoteUserDataProfiles';
23
23
  import { ExtensionEnablementService } from './vscode/src/vs/workbench/services/extensionManagement/browser/extensionEnablementService.js';
24
- import './vscode/src/vs/workbench/contrib/extensions/browser/extensions.contribution.js';
25
- import './vscode/src/vs/workbench/contrib/extensions/browser/extensions.web.contribution.js';
26
24
  import { IExtensionUrlHandler, ExtensionUrlHandler } from 'vscode/vscode/vs/workbench/services/extensions/browser/extensionUrlHandler';
27
25
  import { IRemoteAgentService } from 'vscode/vscode/vs/workbench/services/remote/common/remoteAgentService';
28
26
  import { IInstantiationService } from 'vscode/vscode/vs/platform/instantiation/common/instantiation';
29
27
  import { ILabelService } from 'vscode/vscode/vs/platform/label/common/label';
28
+ import { IExtensionFeaturesManagementService } from 'vscode/vscode/vs/workbench/services/extensionManagement/common/extensionFeatures';
29
+ import { ExtensionFeaturesManagementService } from './vscode/src/vs/workbench/services/extensionManagement/common/extensionFeaturesManagemetService.js';
30
30
  import { registerAssets } from 'vscode/assets';
31
31
  import { getExtensionManifests } from 'vscode/extensions';
32
+ import './vscode/src/vs/workbench/contrib/extensions/browser/extensions.contribution.js';
33
+ import './vscode/src/vs/workbench/contrib/extensions/browser/extensions.web.contribution.js';
32
34
 
33
35
  registerAssets({
34
36
  'vs/workbench/services/extensionManagement/common/media/defaultIcon.png': ( new URL('./assets/defaultIcon.png', import.meta.url).toString()),
35
37
  'vs/workbench/contrib/extensions/browser/media/theme-icon.png': new URL('./assets/theme-icon.png', import.meta.url).href,
36
38
  'vs/workbench/contrib/extensions/browser/media/language-icon.svg': new URL('./assets/theme-icon.png', import.meta.url).href
37
39
  });
40
+ class EmptyRemoteAgentService {
41
+ constructor() {
42
+ this.getConnection = () => null;
43
+ this.getEnvironment = async () => null;
44
+ this.getRawEnvironment = async () => null;
45
+ this.getExtensionHostExitInfo = async () => null;
46
+ this.getRoundTripTime = async () => undefined;
47
+ this.whenExtensionsReady = async () => undefined;
48
+ this.scanExtensions = async () => [];
49
+ this.scanSingleExtension = async () => null;
50
+ this.getDiagnosticInfo = async () => undefined;
51
+ this.updateTelemetryLevel = async () => undefined;
52
+ this.logTelemetry = async () => undefined;
53
+ this.flushTelemetry = async () => undefined;
54
+ }
55
+ }
38
56
  let ExtensionManagementServerServiceOverride = class ExtensionManagementServerServiceOverride extends ExtensionManagementServerService {
39
57
  constructor(isWebOnly, remoteAgentService, labelService, instantiationService) {
40
- super(remoteAgentService, labelService, instantiationService);
41
- this.isWebOnly = isWebOnly;
58
+ super(isWebOnly ? new EmptyRemoteAgentService() : remoteAgentService, labelService, instantiationService);
42
59
  this.remoteAgentService = remoteAgentService;
43
60
  this.labelService = labelService;
44
61
  this.instantiationService = instantiationService;
45
- if (this.isWebOnly) {
46
- this.remoteExtensionManagementServer = null;
47
- }
48
62
  }
49
63
  };
50
64
  ExtensionManagementServerServiceOverride = __decorate([
@@ -75,7 +89,8 @@ function getServiceOverride(options = { webOnly: false }) {
75
89
  [( IExtensionTipsService.toString())]: new SyncDescriptor(ExtensionTipsService, [], true),
76
90
  [( IRemoteUserDataProfilesService.toString())]: new SyncDescriptor(RemoteUserDataProfilesService, [], true),
77
91
  [( IWorkbenchExtensionEnablementService.toString())]: new SyncDescriptor(ExtensionEnablementService, [], true),
78
- [( IExtensionUrlHandler.toString())]: new SyncDescriptor(ExtensionUrlHandler, [], true)
92
+ [( IExtensionUrlHandler.toString())]: new SyncDescriptor(ExtensionUrlHandler, [], true),
93
+ [( IExtensionFeaturesManagementService.toString())]: new SyncDescriptor(ExtensionFeaturesManagementService, [], true)
79
94
  };
80
95
  }
81
96
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codingame/monaco-vscode-extension-gallery-service-override",
3
- "version": "2.2.2",
3
+ "version": "3.1.0",
4
4
  "keywords": [],
5
5
  "author": {
6
6
  "name": "CodinGame",
@@ -18,15 +18,15 @@
18
18
  "module": "index.js",
19
19
  "types": "index.d.ts",
20
20
  "dependencies": {
21
- "vscode": "npm:@codingame/monaco-vscode-api@2.2.2",
21
+ "vscode": "npm:@codingame/monaco-vscode-api@3.1.0",
22
22
  "vscode-marked": "npm:marked@=3.0.2",
23
23
  "vscode-semver": "npm:semver@=5.5.0",
24
- "@codingame/monaco-vscode-files-service-override": "2.2.2",
25
- "@codingame/monaco-vscode-quickaccess-service-override": "2.2.2",
26
- "@codingame/monaco-vscode-extensions-service-override": "2.2.2",
27
- "@codingame/monaco-vscode-environment-service-override": "2.2.2",
28
- "@codingame/monaco-vscode-layout-service-override": "2.2.2",
29
- "@codingame/monaco-vscode-host-service-override": "2.2.2",
30
- "@codingame/monaco-vscode-base-service-override": "2.2.2"
24
+ "@codingame/monaco-vscode-files-service-override": "3.1.0",
25
+ "@codingame/monaco-vscode-quickaccess-service-override": "3.1.0",
26
+ "@codingame/monaco-vscode-extensions-service-override": "3.1.0",
27
+ "@codingame/monaco-vscode-environment-service-override": "3.1.0",
28
+ "@codingame/monaco-vscode-layout-service-override": "3.1.0",
29
+ "@codingame/monaco-vscode-host-service-override": "3.1.0",
30
+ "@codingame/monaco-vscode-base-service-override": "3.1.0"
31
31
  }
32
32
  }
@@ -10,7 +10,7 @@ import { isDefined } from 'vscode/vscode/vs/base/common/types';
10
10
  import { URI } from 'vscode/vscode/vs/base/common/uri';
11
11
  import { localizeWithPath } from 'vscode/vscode/vs/nls';
12
12
  import { isTargetPlatformCompatible, ExtensionManagementError, ExtensionManagementErrorCode, EXTENSION_INSTALL_DEP_PACK_CONTEXT, TargetPlatformToString, IExtensionGalleryService, ExtensionGalleryError } from 'vscode/vscode/vs/platform/extensionManagement/common/extensionManagement';
13
- import { areSameExtensions, getGalleryExtensionTelemetryData, adoptToGalleryExtensionId, getGalleryExtensionId, ExtensionKey, getLocalExtensionTelemetryData } from 'vscode/vscode/vs/platform/extensionManagement/common/extensionManagementUtil';
13
+ import { areSameExtensions, getGalleryExtensionTelemetryData, ExtensionKey, getLocalExtensionTelemetryData } from 'vscode/vscode/vs/platform/extensionManagement/common/extensionManagementUtil';
14
14
  import { isApplicationScopedExtension } from 'vscode/vscode/vs/platform/extensions/common/extensions';
15
15
  import { ILogService } from 'vscode/vscode/vs/platform/log/common/log';
16
16
  import { IProductService } from 'vscode/vscode/vs/platform/product/common/productService';
@@ -145,191 +145,153 @@ let AbstractExtensionManagementService = class AbstractExtensionManagementServic
145
145
  }
146
146
  async installExtensions(extensions) {
147
147
  const results = [];
148
- await Promise.allSettled(( extensions.map(async (e) => {
149
- try {
150
- const result = await this.installExtension(e, (taskToWait, taskToWaitFor) => {
151
- if (( extensions.some(
152
- e => adoptToGalleryExtensionId(taskToWaitFor.identifier.id) === getGalleryExtensionId(e.manifest.publisher, e.manifest.name)
153
- ))) {
154
- return false;
155
- }
156
- return this.canWaitForTask(taskToWait, taskToWaitFor);
157
- });
158
- results.push(...result);
159
- }
160
- catch (error) {
161
- results.push({ identifier: { id: getGalleryExtensionId(e.manifest.publisher, e.manifest.name) }, operation: 2 , source: e.extension, error });
148
+ const installingExtensionsMap = ( new Map());
149
+ const alreadyRequestedInstallations = [];
150
+ const successResults = [];
151
+ const getInstallExtensionTaskKey = (extension, profileLocation) => `${( ExtensionKey.create(extension).toString())}-${( profileLocation.toString())}`;
152
+ const createInstallExtensionTask = (manifest, extension, options) => {
153
+ const installExtensionTask = this.createInstallExtensionTask(manifest, extension, options);
154
+ const key = URI.isUri(extension) ? extension.path : `${extension.identifier.id.toLowerCase()}-${( options.profileLocation.toString())}`;
155
+ installingExtensionsMap.set(key, { task: installExtensionTask, manifest });
156
+ this._onInstallExtension.fire({ identifier: installExtensionTask.identifier, source: extension, profileLocation: options.profileLocation });
157
+ this.logService.info('Installing extension:', installExtensionTask.identifier.id);
158
+ if (!URI.isUri(extension)) {
159
+ this.installingExtensions.set(getInstallExtensionTaskKey(extension, options.profileLocation), { task: installExtensionTask, waitingTasks: [] });
162
160
  }
163
- })));
164
- this._onDidInstallExtensions.fire(results);
165
- return results;
166
- }
167
- async installExtension({ manifest, extension, options }, shouldWait) {
168
- const isApplicationScoped = options.isApplicationScoped || options.isBuiltin || isApplicationScopedExtension(manifest);
169
- const installExtensionTaskOptions = {
170
- ...options,
171
- installOnlyNewlyAddedFromExtensionPack: URI.isUri(extension) ? options.installOnlyNewlyAddedFromExtensionPack : true,
172
- isApplicationScoped,
173
- profileLocation: isApplicationScoped ? this.userDataProfilesService.defaultProfile.extensionsResource : options.profileLocation ?? this.getCurrentExtensionsManifestLocation()
174
161
  };
175
- const getInstallExtensionTaskKey = (extension) => `${( ExtensionKey.create(extension).toString())}${installExtensionTaskOptions.profileLocation ? `-${( installExtensionTaskOptions.profileLocation.toString())}` : ''}`;
176
- if (!URI.isUri(extension)) {
177
- const installingExtension = this.installingExtensions.get(getInstallExtensionTaskKey(extension));
178
- if (installingExtension) {
179
- this.logService.info('Extensions is already requested to install', extension.identifier.id);
180
- await installingExtension.task.waitUntilTaskIsFinished();
181
- return [];
182
- }
183
- }
184
- const allInstallExtensionTasks = [];
185
- const alreadyRequestedInstallations = [];
186
- const installResults = [];
187
- const installExtensionTask = this.createInstallExtensionTask(manifest, extension, installExtensionTaskOptions);
188
- if (!URI.isUri(extension)) {
189
- this.installingExtensions.set(getInstallExtensionTaskKey(extension), { task: installExtensionTask, waitingTasks: [] });
190
- }
191
- this._onInstallExtension.fire({ identifier: installExtensionTask.identifier, source: extension, profileLocation: installExtensionTaskOptions.profileLocation });
192
- this.logService.info('Installing extension:', installExtensionTask.identifier.id);
193
- allInstallExtensionTasks.push({ task: installExtensionTask, manifest });
194
- let installExtensionHasDependents = false;
195
162
  try {
196
- if (installExtensionTaskOptions.donotIncludePackAndDependencies) {
197
- this.logService.info('Installing the extension without checking dependencies and pack', installExtensionTask.identifier.id);
198
- }
199
- else {
200
- try {
201
- const allDepsAndPackExtensionsToInstall = await this.getAllDepsAndPackExtensions(installExtensionTask.identifier, manifest, !!installExtensionTaskOptions.installOnlyNewlyAddedFromExtensionPack, !!installExtensionTaskOptions.installPreReleaseVersion, installExtensionTaskOptions.profileLocation);
202
- const installed = await this.getInstalled(undefined, installExtensionTaskOptions.profileLocation);
203
- const options = { ...installExtensionTaskOptions, donotIncludePackAndDependencies: true, context: { ...installExtensionTaskOptions.context, [EXTENSION_INSTALL_DEP_PACK_CONTEXT]: true } };
204
- for (const { gallery, manifest } of distinct(allDepsAndPackExtensionsToInstall, ({ gallery }) => gallery.identifier.id)) {
205
- installExtensionHasDependents = installExtensionHasDependents || !!manifest.extensionDependencies?.some(id => areSameExtensions({ id }, installExtensionTask.identifier));
206
- const key = getInstallExtensionTaskKey(gallery);
207
- const existingInstallingExtension = this.installingExtensions.get(key);
208
- if (existingInstallingExtension) {
209
- if (shouldWait(installExtensionTask, existingInstallingExtension.task)) {
210
- const identifier = existingInstallingExtension.task.identifier;
211
- this.logService.info('Waiting for already requested installing extension', identifier.id, installExtensionTask.identifier.id);
212
- existingInstallingExtension.waitingTasks.push(installExtensionTask);
213
- alreadyRequestedInstallations.push(Event.toPromise(Event.filter(this.onDidInstallExtensions, results => ( results.some(result => areSameExtensions(result.identifier, identifier))))).then(results => {
214
- this.logService.info('Finished waiting for already requested installing extension', identifier.id, installExtensionTask.identifier.id);
215
- const result = results.find(result => areSameExtensions(result.identifier, identifier));
216
- if (!result?.local) {
217
- throw new Error(`Extension ${identifier.id} is not installed`);
218
- }
219
- }));
220
- }
221
- }
222
- else if (!( installed.some(({ identifier }) => areSameExtensions(identifier, gallery.identifier)))) {
223
- const task = this.createInstallExtensionTask(manifest, gallery, options);
224
- this.installingExtensions.set(key, { task, waitingTasks: [installExtensionTask] });
225
- this._onInstallExtension.fire({ identifier: task.identifier, source: gallery, profileLocation: installExtensionTaskOptions.profileLocation });
226
- this.logService.info('Installing extension:', task.identifier.id, installExtensionTask.identifier.id);
227
- allInstallExtensionTasks.push({ task, manifest });
228
- }
229
- }
163
+ for (const { manifest, extension, options } of extensions) {
164
+ const isApplicationScoped = options.isApplicationScoped || options.isBuiltin || isApplicationScopedExtension(manifest);
165
+ const installExtensionTaskOptions = {
166
+ ...options,
167
+ installOnlyNewlyAddedFromExtensionPack: URI.isUri(extension) ? options.installOnlyNewlyAddedFromExtensionPack : true,
168
+ isApplicationScoped,
169
+ profileLocation: isApplicationScoped ? this.userDataProfilesService.defaultProfile.extensionsResource : options.profileLocation ?? this.getCurrentExtensionsManifestLocation()
170
+ };
171
+ const existingInstallExtensionTask = !URI.isUri(extension) ? this.installingExtensions.get(getInstallExtensionTaskKey(extension, installExtensionTaskOptions.profileLocation)) : undefined;
172
+ if (existingInstallExtensionTask) {
173
+ this.logService.info('Extension is already requested to install', existingInstallExtensionTask.task.identifier.id);
174
+ alreadyRequestedInstallations.push(existingInstallExtensionTask.task.waitUntilTaskIsFinished());
230
175
  }
231
- catch (error) {
232
- if (URI.isUri(installExtensionTask.source)) {
233
- if (isNonEmptyArray(manifest.extensionDependencies)) {
234
- this.logService.warn(`Cannot install dependencies of extension:`, installExtensionTask.identifier.id, error.message);
235
- }
236
- if (isNonEmptyArray(manifest.extensionPack)) {
237
- this.logService.warn(`Cannot install packed extensions of extension:`, installExtensionTask.identifier.id, error.message);
238
- }
239
- }
240
- else {
241
- this.logService.error('Error while preparing to install dependencies and extension packs of the extension:', installExtensionTask.identifier.id);
242
- throw error;
243
- }
176
+ else {
177
+ createInstallExtensionTask(manifest, extension, installExtensionTaskOptions);
244
178
  }
245
179
  }
246
- const extensionsToInstallMap = allInstallExtensionTasks.reduce((result, { task, manifest }) => {
247
- result.set(task.identifier.id.toLowerCase(), { task, manifest });
248
- return result;
249
- }, ( new Map()));
250
- while (extensionsToInstallMap.size) {
251
- let extensionsToInstall;
252
- const extensionsWithoutDepsToInstall = [...( extensionsToInstallMap.values())].filter(({ manifest }) => !manifest.extensionDependencies?.some(id => ( extensionsToInstallMap.has(id.toLowerCase()))));
253
- if (extensionsWithoutDepsToInstall.length) {
254
- extensionsToInstall = extensionsToInstallMap.size === 1 ? extensionsWithoutDepsToInstall
255
- : extensionsWithoutDepsToInstall.filter(({ task }) => !(task === installExtensionTask && !installExtensionHasDependents));
180
+ await Promise.all(( [...( installingExtensionsMap.values())].map(async ({ task, manifest }) => {
181
+ if (task.options.donotIncludePackAndDependencies) {
182
+ this.logService.info('Installing the extension without checking dependencies and pack', task.identifier.id);
256
183
  }
257
184
  else {
258
- this.logService.info('Found extensions with circular dependencies', ( extensionsWithoutDepsToInstall.map(({ task }) => task.identifier.id)));
259
- extensionsToInstall = [...( extensionsToInstallMap.values())];
260
- }
261
- await this.joinAllSettled(( extensionsToInstall.map(async ({ task }) => {
262
- const startTime = ( new Date()).getTime();
263
185
  try {
264
- const local = await task.run();
265
- await this.joinAllSettled(( this.participants.map(
266
- participant => participant.postInstall(local, task.source, installExtensionTaskOptions, CancellationToken.None)
267
- )));
268
- if (!URI.isUri(task.source)) {
269
- const isUpdate = task.operation === 3 ;
270
- const durationSinceUpdate = isUpdate ? undefined : (( new Date()).getTime() - task.source.lastUpdated) / 1000;
271
- reportTelemetry(this.telemetryService, isUpdate ? 'extensionGallery:update' : 'extensionGallery:install', {
272
- extensionData: getGalleryExtensionTelemetryData(task.source),
273
- verificationStatus: task.verificationStatus,
274
- duration: ( new Date()).getTime() - startTime,
275
- durationSinceUpdate
276
- });
277
- if (isWeb && task.operation !== 3 ) {
278
- try {
279
- await this.galleryService.reportStatistic(local.manifest.publisher, local.manifest.name, local.manifest.version, "install" );
186
+ const allDepsAndPackExtensionsToInstall = await this.getAllDepsAndPackExtensions(task.identifier, manifest, !!task.options.installOnlyNewlyAddedFromExtensionPack, !!task.options.installPreReleaseVersion, task.options.profileLocation);
187
+ const installed = await this.getInstalled(undefined, task.options.profileLocation);
188
+ const options = { ...task.options, donotIncludePackAndDependencies: true, context: { ...task.options.context, [EXTENSION_INSTALL_DEP_PACK_CONTEXT]: true } };
189
+ for (const { gallery, manifest } of distinct(allDepsAndPackExtensionsToInstall, ({ gallery }) => gallery.identifier.id)) {
190
+ if (( installingExtensionsMap.has(`${gallery.identifier.id.toLowerCase()}-${( options.profileLocation.toString())}`))) {
191
+ continue;
192
+ }
193
+ const existingInstallingExtension = this.installingExtensions.get(getInstallExtensionTaskKey(gallery, options.profileLocation));
194
+ if (existingInstallingExtension) {
195
+ if (this.canWaitForTask(task, existingInstallingExtension.task)) {
196
+ const identifier = existingInstallingExtension.task.identifier;
197
+ this.logService.info('Waiting for already requested installing extension', identifier.id, task.identifier.id);
198
+ existingInstallingExtension.waitingTasks.push(task);
199
+ alreadyRequestedInstallations.push(Event.toPromise(Event.filter(this.onDidInstallExtensions, results => ( results.some(result => areSameExtensions(result.identifier, identifier))))).then(results => {
200
+ this.logService.info('Finished waiting for already requested installing extension', identifier.id, task.identifier.id);
201
+ const result = results.find(result => areSameExtensions(result.identifier, identifier));
202
+ if (!result?.local) {
203
+ throw new Error(`Extension ${identifier.id} is not installed`);
204
+ }
205
+ }));
280
206
  }
281
- catch (error) { }
207
+ }
208
+ else if (!( installed.some(({ identifier }) => areSameExtensions(identifier, gallery.identifier)))) {
209
+ createInstallExtensionTask(manifest, gallery, options);
282
210
  }
283
211
  }
284
- installResults.push({ local, identifier: task.identifier, operation: task.operation, source: task.source, context: task.options.context, profileLocation: task.profileLocation, applicationScoped: local.isApplicationScoped });
285
212
  }
286
213
  catch (error) {
287
- this.logService.error('Error while installing the extension', task.identifier.id, getErrorMessage(error));
288
- throw error;
289
- }
290
- finally {
291
- extensionsToInstallMap.delete(task.identifier.id.toLowerCase());
214
+ if (URI.isUri(task.source)) {
215
+ if (isNonEmptyArray(manifest.extensionDependencies)) {
216
+ this.logService.warn(`Cannot install dependencies of extension:`, task.identifier.id, error.message);
217
+ }
218
+ if (isNonEmptyArray(manifest.extensionPack)) {
219
+ this.logService.warn(`Cannot install packed extensions of extension:`, task.identifier.id, error.message);
220
+ }
221
+ }
222
+ else {
223
+ this.logService.error('Error while preparing to install dependencies and extension packs of the extension:', task.identifier.id);
224
+ throw error;
225
+ }
292
226
  }
293
- })));
294
- }
295
- if (alreadyRequestedInstallations.length) {
296
- await this.joinAllSettled(alreadyRequestedInstallations);
297
- }
298
- installResults.forEach(({ identifier }) => this.logService.info(`Extension installed successfully:`, identifier.id));
299
- return installResults;
300
- }
301
- catch (error) {
302
- allInstallExtensionTasks.forEach(({ task }) => task.cancel());
303
- if (installResults.length) {
227
+ }
228
+ })));
229
+ await this.joinAllSettled(( [...( installingExtensionsMap.values())].map(async ({ task }) => {
230
+ const startTime = ( new Date()).getTime();
304
231
  try {
305
- const result = await Promise.allSettled(( installResults.map(
306
- ({ local }) => this.createUninstallExtensionTask(local, { versionOnly: true, profileLocation: installExtensionTaskOptions.profileLocation }).run()
232
+ const local = await task.run();
233
+ await this.joinAllSettled(( this.participants.map(
234
+ participant => participant.postInstall(local, task.source, task.options, CancellationToken.None)
307
235
  )));
308
- for (let index = 0; index < result.length; index++) {
309
- const r = result[index];
310
- const { identifier } = installResults[index];
311
- if (r.status === 'fulfilled') {
312
- this.logService.info('Rollback: Uninstalled extension', identifier.id);
313
- }
314
- else {
315
- this.logService.warn('Rollback: Error while uninstalling extension', identifier.id, getErrorMessage(r.reason));
236
+ if (!URI.isUri(task.source)) {
237
+ const isUpdate = task.operation === 3 ;
238
+ const durationSinceUpdate = isUpdate ? undefined : (( new Date()).getTime() - task.source.lastUpdated) / 1000;
239
+ reportTelemetry(this.telemetryService, isUpdate ? 'extensionGallery:update' : 'extensionGallery:install', {
240
+ extensionData: getGalleryExtensionTelemetryData(task.source),
241
+ verificationStatus: task.verificationStatus,
242
+ duration: ( new Date()).getTime() - startTime,
243
+ durationSinceUpdate
244
+ });
245
+ if (isWeb && task.operation !== 3 ) {
246
+ try {
247
+ await this.galleryService.reportStatistic(local.manifest.publisher, local.manifest.name, local.manifest.version, "install" );
248
+ }
249
+ catch (error) { }
316
250
  }
317
251
  }
252
+ successResults.push({ local, identifier: task.identifier, operation: task.operation, source: task.source, context: task.options.context, profileLocation: task.profileLocation, applicationScoped: local.isApplicationScoped });
318
253
  }
319
254
  catch (error) {
320
- this.logService.warn('Error while rolling back extensions', getErrorMessage(error), ( installResults.map(({ identifier }) => identifier.id)));
255
+ this.logService.error('Error while installing the extension', task.identifier.id, getErrorMessage(error));
256
+ throw error;
321
257
  }
258
+ })));
259
+ if (alreadyRequestedInstallations.length) {
260
+ await this.joinAllSettled(alreadyRequestedInstallations);
322
261
  }
323
- return ( allInstallExtensionTasks.map(
324
- ({ task }) => ({ identifier: task.identifier, operation: 2 , source: task.source, context: installExtensionTaskOptions.context, profileLocation: installExtensionTaskOptions.profileLocation, error })
325
- ));
262
+ for (const result of successResults) {
263
+ this.logService.info(`Extension installed successfully:`, result.identifier.id);
264
+ results.push(result);
265
+ }
266
+ return results;
267
+ }
268
+ catch (error) {
269
+ if (successResults.length) {
270
+ await Promise.allSettled(( successResults.map(async ({ local, profileLocation }) => {
271
+ try {
272
+ await this.createUninstallExtensionTask(local, { versionOnly: true, profileLocation }).run();
273
+ this.logService.info('Rollback: Uninstalled extension', local.identifier.id);
274
+ }
275
+ catch (error) {
276
+ this.logService.warn('Rollback: Error while uninstalling extension', local.identifier.id, getErrorMessage(error));
277
+ }
278
+ })));
279
+ }
280
+ for (const { task } of ( installingExtensionsMap.values())) {
281
+ task.cancel();
282
+ results.push({ identifier: task.identifier, operation: 2 , source: task.source, context: task.options.context, profileLocation: task.profileLocation, error });
283
+ }
284
+ throw error;
326
285
  }
327
286
  finally {
328
- for (const { task } of allInstallExtensionTasks) {
287
+ for (const { task } of ( installingExtensionsMap.values())) {
329
288
  if (task.source && !URI.isUri(task.source)) {
330
- this.installingExtensions.delete(getInstallExtensionTaskKey(task.source));
289
+ this.installingExtensions.delete(getInstallExtensionTaskKey(task.source, task.profileLocation));
331
290
  }
332
291
  }
292
+ if (results.length) {
293
+ this._onDidInstallExtensions.fire(results);
294
+ }
333
295
  }
334
296
  }
335
297
  canWaitForTask(taskToWait, taskToWaitFor) {
@@ -682,13 +644,11 @@ let AbstractExtensionManagementService = class AbstractExtensionManagementServic
682
644
  }
683
645
  async updateControlCache() {
684
646
  try {
685
- this.logService.trace('ExtensionManagementService.refreshReportedCache');
686
- const manifest = await this.galleryService.getExtensionsControlManifest();
687
- this.logService.trace(`ExtensionManagementService.refreshControlCache`, manifest);
688
- return manifest;
647
+ this.logService.trace('ExtensionManagementService.updateControlCache');
648
+ return await this.galleryService.getExtensionsControlManifest();
689
649
  }
690
650
  catch (err) {
691
- this.logService.trace('ExtensionManagementService.refreshControlCache - failed to get extension control manifest');
651
+ this.logService.trace('ExtensionManagementService.refreshControlCache - failed to get extension control manifest', getErrorMessage(err));
692
652
  return { malicious: [], deprecated: {}, search: [] };
693
653
  }
694
654
  }
@@ -269,7 +269,7 @@ function toExtension(galleryExtension, version, allTargetPlatforms, queryContext
269
269
  publisherDisplayName: galleryExtension.publisher.displayName,
270
270
  publisherDomain: galleryExtension.publisher.domain ? { link: galleryExtension.publisher.domain, verified: !!galleryExtension.publisher.isDomainVerified } : undefined,
271
271
  publisherSponsorLink: getSponsorLink(latestVersion),
272
- description: galleryExtension.shortDescription || '',
272
+ description: galleryExtension.shortDescription ?? '',
273
273
  installCount: getStatistic(galleryExtension.statistics, 'install'),
274
274
  rating: getStatistic(galleryExtension.statistics, 'averagerating'),
275
275
  ratingCount: getStatistic(galleryExtension.statistics, 'ratingcount'),
@@ -5,11 +5,12 @@ import { renderLabelWithIcons } from 'vscode/vscode/vs/base/browser/ui/iconLabel
5
5
  import { Action, Separator } from 'vscode/vscode/vs/base/common/actions';
6
6
  import { isNonEmptyArray } from 'vscode/vscode/vs/base/common/arrays';
7
7
  import { RunOnceScheduler } from 'vscode/vscode/vs/base/common/async';
8
+ import { fromNow } from 'vscode/vscode/vs/base/common/date';
8
9
  import { memoize } from 'vscode/vscode/vs/base/common/decorators';
9
10
  import { dispose } from 'vscode/vscode/vs/base/common/lifecycle';
10
11
  import { Schemas } from 'vscode/vscode/vs/base/common/network';
11
12
  import './media/runtimeExtensionsEditor.css.js';
12
- import { localizeWithPath } from 'vscode/vscode/vs/nls';
13
+ import { localizeWithPath, localize2WithPath } from 'vscode/vscode/vs/nls';
13
14
  import { Categories } from 'vscode/vscode/vs/platform/action/common/actionCommonCategories';
14
15
  import { Action2, MenuId } from 'vscode/vscode/vs/platform/actions/common/actions';
15
16
  import { IClipboardService } from 'vscode/vscode/vs/platform/clipboard/common/clipboardService';
@@ -19,16 +20,19 @@ import { ExtensionIdentifierMap } from 'vscode/vscode/vs/platform/extensions/com
19
20
  import { IInstantiationService } from 'vscode/vscode/vs/platform/instantiation/common/instantiation';
20
21
  import { ILabelService } from 'vscode/vscode/vs/platform/label/common/label';
21
22
  import { WorkbenchList } from 'vscode/vscode/vs/platform/list/browser/listService';
22
- import { INotificationService } from 'vscode/vscode/vs/platform/notification/common/notification';
23
+ import { Severity, INotificationService } from 'vscode/vscode/vs/platform/notification/common/notification';
24
+ import { Registry } from 'vscode/vscode/vs/platform/registry/common/platform';
23
25
  import { IStorageService } from 'vscode/vscode/vs/platform/storage/common/storage';
24
26
  import { ITelemetryService } from 'vscode/vscode/vs/platform/telemetry/common/telemetry';
25
27
  import { editorBackground } from 'vscode/vscode/vs/platform/theme/common/colorRegistry';
26
28
  import { IThemeService } from 'vscode/vscode/vs/platform/theme/common/themeService';
27
29
  import { EditorPane } from 'vscode/vscode/vs/workbench/browser/parts/editor/editorPane';
30
+ import { errorIcon, warningIcon } from 'vscode/vscode/vs/workbench/contrib/extensions/browser/extensionsIcons';
28
31
  import { IExtensionsWorkbenchService } from 'vscode/vscode/vs/workbench/contrib/extensions/common/extensions';
29
32
  import { RuntimeExtensionsInput } from '../common/runtimeExtensionsInput.js';
30
33
  import { IEditorService } from 'vscode/vscode/vs/workbench/services/editor/common/editorService';
31
34
  import { IWorkbenchEnvironmentService } from 'vscode/vscode/vs/workbench/services/environment/common/environmentService';
35
+ import { Extensions, IExtensionFeaturesManagementService } from 'vscode/vscode/vs/workbench/services/extensionManagement/common/extensionFeatures';
32
36
  import { getDefaultIconPath } from 'vscode/vscode/vs/workbench/services/extensionManagement/common/extensionManagement';
33
37
  import { LocalWebWorkerRunningLocation } from 'vscode/vscode/vs/workbench/services/extensions/common/extensionRunningLocation';
34
38
  import { IExtensionService } from 'vscode/vscode/vs/workbench/services/extensions/common/extensions';
@@ -37,7 +41,7 @@ var AbstractRuntimeExtensionsEditor_1;
37
41
  let AbstractRuntimeExtensionsEditor = class AbstractRuntimeExtensionsEditor extends EditorPane {
38
42
  static { AbstractRuntimeExtensionsEditor_1 = this; }
39
43
  static { this.ID = 'workbench.editor.runtimeExtensions'; }
40
- constructor(telemetryService, themeService, contextKeyService, _extensionsWorkbenchService, _extensionService, _notificationService, _contextMenuService, _instantiationService, storageService, _labelService, _environmentService, _clipboardService) {
44
+ constructor(telemetryService, themeService, contextKeyService, _extensionsWorkbenchService, _extensionService, _notificationService, _contextMenuService, _instantiationService, storageService, _labelService, _environmentService, _clipboardService, _extensionFeaturesManagementService) {
41
45
  super(AbstractRuntimeExtensionsEditor_1.ID, telemetryService, themeService, storageService);
42
46
  this._extensionsWorkbenchService = _extensionsWorkbenchService;
43
47
  this._extensionService = _extensionService;
@@ -47,10 +51,12 @@ let AbstractRuntimeExtensionsEditor = class AbstractRuntimeExtensionsEditor exte
47
51
  this._labelService = _labelService;
48
52
  this._environmentService = _environmentService;
49
53
  this._clipboardService = _clipboardService;
54
+ this._extensionFeaturesManagementService = _extensionFeaturesManagementService;
50
55
  this._list = null;
51
56
  this._elements = null;
52
57
  this._updateSoon = this._register(( new RunOnceScheduler(() => this._updateExtensions(), 200)));
53
58
  this._register(this._extensionService.onDidChangeExtensionsStatus(() => this._updateSoon.schedule()));
59
+ this._register(this._extensionFeaturesManagementService.onDidChangeAccessData(() => this._updateSoon.schedule()));
54
60
  this._updateExtensions();
55
61
  }
56
62
  async _updateExtensions() {
@@ -153,7 +159,7 @@ let AbstractRuntimeExtensionsEditor = class AbstractRuntimeExtensionsEditor exte
153
159
  const name = append(header, $('div.name'));
154
160
  const version = append(header, $('span.version'));
155
161
  const msgContainer = append(desc, $('div.msg'));
156
- const actionbar = ( new ActionBar(desc, { animated: false }));
162
+ const actionbar = ( new ActionBar(desc));
157
163
  actionbar.onDidRun(({ error }) => error && this._notificationService.error(error));
158
164
  const timeContainer = append(element, $('.time'));
159
165
  const activationTime = append(timeContainer, $('div.activation-time'));
@@ -364,6 +370,34 @@ let AbstractRuntimeExtensionsEditor = class AbstractRuntimeExtensionsEditor exte
364
370
  const el = $('span', undefined, ...renderLabelWithIcons(extraLabel));
365
371
  data.msgContainer.appendChild(el);
366
372
  }
373
+ const features = ( Registry.as(Extensions.ExtensionFeaturesRegistry)).getExtensionFeatures();
374
+ for (const feature of features) {
375
+ const accessData = this._extensionFeaturesManagementService.getAccessData(element.description.identifier, feature.id);
376
+ if (accessData) {
377
+ const status = accessData?.current?.status;
378
+ if (status) {
379
+ data.msgContainer.appendChild($('span', undefined, `${feature.label}: `));
380
+ data.msgContainer.appendChild($('span', undefined, ...renderLabelWithIcons(`$(${status.severity === Severity.Error ? errorIcon.id : warningIcon.id}) ${status.message}`)));
381
+ }
382
+ if (accessData?.current) {
383
+ const element = $('span', undefined, ( localizeWithPath(
384
+ 'vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor',
385
+ 'requests count',
386
+ "{0} Requests: {1} (Session)",
387
+ feature.label,
388
+ accessData.current.count
389
+ )));
390
+ element.title = ( localizeWithPath(
391
+ 'vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor',
392
+ 'requests count title',
393
+ "Last request was {0}. Overall Requests: {1}",
394
+ fromNow(accessData.current.lastAccessed, true, true),
395
+ accessData.totalCount
396
+ ));
397
+ data.msgContainer.appendChild(element);
398
+ }
399
+ }
400
+ }
367
401
  if (element.profileInfo) {
368
402
  data.profileTime.textContent = `Profile: ${(element.profileInfo.totalTime / 1000).toFixed(2)}ms`;
369
403
  }
@@ -463,17 +497,18 @@ AbstractRuntimeExtensionsEditor = AbstractRuntimeExtensionsEditor_1 = ( __decora
463
497
  ( __param(8, IStorageService)),
464
498
  ( __param(9, ILabelService)),
465
499
  ( __param(10, IWorkbenchEnvironmentService)),
466
- ( __param(11, IClipboardService))
500
+ ( __param(11, IClipboardService)),
501
+ ( __param(12, IExtensionFeaturesManagementService))
467
502
  ], AbstractRuntimeExtensionsEditor));
468
503
  class ShowRuntimeExtensionsAction extends Action2 {
469
504
  constructor() {
470
505
  super({
471
506
  id: 'workbench.action.showRuntimeExtensions',
472
- title: { value: ( localizeWithPath(
507
+ title: ( localize2WithPath(
473
508
  'vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor',
474
509
  'showRuntimeExtensions',
475
510
  "Show Running Extensions"
476
- )), original: 'Show Running Extensions' },
511
+ )),
477
512
  category: Categories.Developer,
478
513
  f1: true,
479
514
  menu: {