src/vs/workbench/services/extensions/common/extensionManifestPropertiesService.ts

423 LOC · 332 covered · 91 uncovered · 96 ranges · 54 concepts · 36 introducers · 38 tests

File neighbourhood

The centred file is linked to every concept that introduces one of its ranges, every test that runs code from the file, and the gray connector concepts standing between those tests and the file's own introducer concepts. Undirected links join concepts to every file where they introduce source and concepts to the tests they introduce; arrows show specialization between the displayed concepts and bridge only concepts omitted from this view. Concept colors match the source ranges below; connector concepts have no source color and are shown in gray.

Focused file, its introducer and connector concepts, their introduced files, and tests that run code from the file

In the embedded map, ordinary wheel input scrolls the page; use the visible controls to zoom and drag to pan. Open the full-screen map for canvas navigation: wheel pans, Ctrl/Command plus wheel zooms, and arrow keys pan when this region is focused. On touch screens, open the full-screen map to pan or pinch. If JavaScript or WebGL is unavailable, use the related-file, concept, and source links on this page.

Graph controls are ready.

Interactive rendering requires JavaScript and WebGL. Use the related-file, concept, and source links on this page while the interactive map is unavailable.

1 > /*--------------------------------------------------------------------------------------------- extensionManifestPropertiesService.ts ×23
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 { IConfigurationService } from '../../../../platform/configuration/common/configuration.js';
7 > import { IExtensionManifest, ExtensionUntrustedWorkspaceSupportType, ExtensionVirtualWorkspaceSupportType, IExtensionIdentifier, ALL_EXTENSION_KINDS, ExtensionIdentifierMap, IExtensionContributions } from '../../../../platform/extensions/common/extensions.js';
8 > import { ExtensionKind } from '../../../../platform/environment/common/environment.js';
9 > import { ExtensionsRegistry } from './extensionsRegistry.js';
10 > import { getGalleryExtensionId } from '../../../../platform/extensionManagement/common/extensionManagementUtil.js';
11 > import { isNonEmptyArray } from '../../../../base/common/arrays.js';
12 > import { IProductService } from '../../../../platform/product/common/productService.js';
13 > import { createDecorator } from '../../../../platform/instantiation/common/instantiation.js';
14 > import { InstantiationType, registerSingleton } from '../../../../platform/instantiation/common/extensions.js';
15 > import { ExtensionUntrustedWorkspaceSupport } from '../../../../base/common/product.js';
16 > import { Disposable } from '../../../../base/common/lifecycle.js';
17 > import { WORKSPACE_TRUST_EXTENSION_SUPPORT } from '../../workspaces/common/workspaceTrust.js';
18 > import { isBoolean } from '../../../../base/common/types.js';
19 > import { IWorkspaceTrustEnablementService } from '../../../../platform/workspace/common/workspaceTrust.js';
20 > import { ILogService } from '../../../../platform/log/common/log.js';
21 > import { isWeb } from '../../../../base/common/platform.js';
22 >
23 > export const IExtensionManifestPropertiesService = createDecorator<IExtensionManifestPropertiesService>('extensionManifestPropertiesService');
24 >
25 > export const EXTENSIONS_SUPPORT_AGENTS_WINDOW = 'extensions.supportAgentsWindow';
26 >
27 > const SESSIONS_WINDOW_ALLOWED_CONTRIBUTION_POINTS: ReadonlySet<keyof IExtensionContributions> = new Set([
28 > 'themes',
29 > 'iconThemes',
30 > 'productIconThemes',
31 > 'colors',
32 > 'keybindings',
33 > 'jsonValidation',
34 > 'jsonValidationRegistry',
35 > 'localizations',
36 > 'grammars',
37 > 'languages',
38 > ]);
39 >
40 > export interface IExtensionManifestPropertiesService {
41 > readonly _serviceBrand: undefined;
42 >
43 > prefersExecuteOnUI(manifest: IExtensionManifest): boolean;
44 > prefersExecuteOnWorkspace(manifest: IExtensionManifest): boolean;
45 > prefersExecuteOnWeb(manifest: IExtensionManifest): boolean;
46 >
47 > canExecuteOnUI(manifest: IExtensionManifest): boolean;
48 > canExecuteOnWorkspace(manifest: IExtensionManifest): boolean;
49 > canExecuteOnWeb(manifest: IExtensionManifest): boolean;
50 > canExecuteOnSessionsWindow(manifest: IExtensionManifest): boolean;
51 >
52 > getExtensionKind(manifest: IExtensionManifest): ExtensionKind[];
53 > getUserConfiguredExtensionKind(extensionIdentifier: IExtensionIdentifier): ExtensionKind[] | undefined;
54 > getExtensionUntrustedWorkspaceSupportType(manifest: IExtensionManifest): ExtensionUntrustedWorkspaceSupportType;
55 > getExtensionVirtualWorkspaceSupportType(manifest: IExtensionManifest): ExtensionVirtualWorkspaceSupportType;
56 > }
57 >
58 > export class ExtensionManifestPropertiesService extends Disposable implements IExtensionManifestPropertiesService {
59 >
60 > readonly _serviceBrand: undefined;
61 >
62 > private _extensionPointExtensionKindsMap: Map<string, ExtensionKind[]> | null = null;
63 > private _productExtensionKindsMap: ExtensionIdentifierMap<ExtensionKind[]> | null = null;
64 > private _configuredExtensionKindsMap: ExtensionIdentifierMap<ExtensionKind | ExtensionKind[]> | null = null;
65 >
66 > private _productVirtualWorkspaceSupportMap: ExtensionIdentifierMap<{ default?: boolean; override?: boolean }> | null = null;
67 > private _configuredVirtualWorkspaceSupportMap: ExtensionIdentifierMap<boolean> | null = null;
68 > private _configuredSessionsWindowSupportMap: ExtensionIdentifierMap<boolean> | null = null;
69 >
70 > private readonly _configuredExtensionWorkspaceTrustRequestMap: ExtensionIdentifierMap<{ supported: ExtensionUntrustedWorkspaceSupportType; version?: string }>;
71 > private readonly _productExtensionWorkspaceTrustRequestMap: Map<string, ExtensionUntrustedWorkspaceSupport>;
72 >
73 > constructor(
74 > @IProductService private readonly productService: IProductService, extensionManifestPropertiesService.ts ×3
75 > @IConfigurationService private readonly configurationService: IConfigurationService,
76 > @IWorkspaceTrustEnablementService private readonly workspaceTrustEnablementService: IWorkspaceTrustEnablementService,
77 > @ILogService private readonly logService: ILogService,
78 > ) {
79 > super();
80 >
81 > // Workspace trust request type (settings.json)
82 > this._configuredExtensionWorkspaceTrustRequestMap = new ExtensionIdentifierMap<{ supported: ExtensionUntrustedWorkspaceSupportType; version?: string }>();
83 > const configuredExtensionWorkspaceTrustRequests = configurationService.inspect<{ [key: string]: { supported: ExtensionUntrustedWorkspaceSupportType; version?: string } }>(WORKSPACE_TRUST_EXTENSION_SUPPORT).userValue || {};
84 > for (const id of Object.keys(configuredExtensionWorkspaceTrustRequests)) {
85 > this._configuredExtensionWorkspaceTrustRequestMap.set(id, configuredExtensionWorkspaceTrustRequests[id]); extensionManifestPropertiesService.ts ×1
86 > }
88 > // Workspace trust request type (product.json)
89 > this._productExtensionWorkspaceTrustRequestMap = new Map<string, ExtensionUntrustedWorkspaceSupport>();
90 > if (productService.extensionUntrustedWorkspaceSupport) {
91 > for (const id of Object.keys(productService.extensionUntrustedWorkspaceSupport)) { extensionManifestPropertiesService.ts ×1
92 > this._productExtensionWorkspaceTrustRequestMap.set(id, productService.extensionUntrustedWorkspaceSupport[id]);
93 > }
94 > }
97 > canExecuteOnSessionsWindow(manifest: IExtensionManifest): boolean {
98 > const configuredSessionsWindowSupport = this.getConfiguredSessionsWindowSupport(manifest); extensionManifestPropertiesService.ts ×5
99 > if (configuredSessionsWindowSupport !== undefined) {
100 > return configuredSessionsWindowSupport; extensionManifestPropertiesService.ts ×2
101 > }
103 > // In the sessions window only extensions that have no code are currently allowed to run
104 > if (manifest.main || manifest.browser) { extensionManifestPropertiesService.ts ×5
106 > }
107 >
108 > // Only allow extensions that contribute to themes and other declarative, non-executing contribution points
109 > const contributionPoints = Object.keys(manifest.contributes || {}) as Array<keyof IExtensionContributions>; extensionManifestPropertiesService.ts ×5
110 > return contributionPoints.every(point => SESSIONS_WINDOW_ALLOWED_CONTRIBUTION_POINTS.has(point));
111 > }
113 > prefersExecuteOnUI(manifest: IExtensionManifest): boolean {
114 const extensionKind = this.getExtensionKind(manifest);
115 return (extensionKind.length > 0 && extensionKind[0] === 'ui');
116 }
118 > prefersExecuteOnWorkspace(manifest: IExtensionManifest): boolean {
119 const extensionKind = this.getExtensionKind(manifest);
120 return (extensionKind.length > 0 && extensionKind[0] === 'workspace');
121 }
123 > prefersExecuteOnWeb(manifest: IExtensionManifest): boolean {
124 const extensionKind = this.getExtensionKind(manifest);
125 return (extensionKind.length > 0 && extensionKind[0] === 'web');
126 }
128 > canExecuteOnUI(manifest: IExtensionManifest): boolean {
129 const extensionKind = this.getExtensionKind(manifest);
130 return extensionKind.some(kind => kind === 'ui');
131 }
133 > canExecuteOnWorkspace(manifest: IExtensionManifest): boolean {
134 const extensionKind = this.getExtensionKind(manifest);
135 return extensionKind.some(kind => kind === 'workspace');
136 }
138 > canExecuteOnWeb(manifest: IExtensionManifest): boolean {
139 const extensionKind = this.getExtensionKind(manifest);
140 return extensionKind.some(kind => kind === 'web');
141 }
143 > getExtensionKind(manifest: IExtensionManifest): ExtensionKind[] {
144 > const deducedExtensionKind = this.deduceExtensionKind(manifest); extensionManifestPropertiesService.ts ×9
145 > const configuredExtensionKind = this.getConfiguredExtensionKind(manifest);
146 >
147 > if (configuredExtensionKind && configuredExtensionKind.length > 0) {
148 > const result: ExtensionKind[] = []; extensionManifestPropertiesService.ts ×4
149 > for (const extensionKind of configuredExtensionKind) {
150 > if (extensionKind !== '-web') {
151 > result.push(extensionKind); extensionManifestPropertiesService.ts ×1
152 > }
154 >
155 > // If opted out from web without specifying other extension kinds then default to ui, workspace
156 > if (configuredExtensionKind.includes('-web') && !result.length) {
158 > result.push('workspace');
159 > }
161 > // Add web kind if not opted out from web and can run in web
162 > if (isWeb && !configuredExtensionKind.includes('-web') && !configuredExtensionKind.includes('web') && deducedExtensionKind.includes('web')) {
163 result.push('web');
164 }
166 > return result;
167 > }
169 > return deducedExtensionKind;
172 > getUserConfiguredExtensionKind(extensionIdentifier: IExtensionIdentifier): ExtensionKind[] | undefined {
173 > if (this._configuredExtensionKindsMap === null) { extensionManifestPropertiesService.ts ×9
174 > const configuredExtensionKindsMap = new ExtensionIdentifierMap<ExtensionKind | ExtensionKind[]>();
175 > const configuredExtensionKinds = this.configurationService.getValue<{ [key: string]: ExtensionKind | ExtensionKind[] }>('remote.extensionKind') || {};
176 > for (const id of Object.keys(configuredExtensionKinds)) {
177 > configuredExtensionKindsMap.set(id, configuredExtensionKinds[id]); extensionManifestPropertiesService.ts ×2
178 > }
179 > this._configuredExtensionKindsMap = configuredExtensionKindsMap; extensionManifestPropertiesService.ts ×9
180 > }
181 >
182 > const userConfiguredExtensionKind = this._configuredExtensionKindsMap.get(extensionIdentifier.id);
183 > return userConfiguredExtensionKind ? this.toArray(userConfiguredExtensionKind) : undefined;
184 > }
186 > getExtensionUntrustedWorkspaceSupportType(manifest: IExtensionManifest): ExtensionUntrustedWorkspaceSupportType {
187 > // Workspace trust feature is disabled, or extension has no entry point extensionManifestPropertiesService.ts ×5
188 > if (!this.workspaceTrustEnablementService.isWorkspaceTrustEnabled() || !manifest.main) {
190 > }
192 > // Get extension workspace trust requirements from settings.json
193 > const configuredWorkspaceTrustRequest = this.getConfiguredExtensionWorkspaceTrustRequest(manifest);
194 >
195 > // Get extension workspace trust requirements from product.json
196 > const productWorkspaceTrustRequest = this.getProductExtensionWorkspaceTrustRequest(manifest);
197 >
198 > // Use settings.json override value if it exists
199 > if (configuredWorkspaceTrustRequest !== undefined) {
200 > return configuredWorkspaceTrustRequest; extensionManifestPropertiesService.ts ×2
201 > }
203 > // Use product.json override value if it exists
204 > if (productWorkspaceTrustRequest?.override !== undefined) { extensionManifestPropertiesService.ts ×5
205 > return productWorkspaceTrustRequest.override; extensionManifestPropertiesService.ts ×1
206 > }
208 > // Use extension manifest value if it exists
209 > if (manifest.capabilities?.untrustedWorkspaces?.supported !== undefined) { extensionManifestPropertiesService.ts ×5
210 > return manifest.capabilities.untrustedWorkspaces.supported; extensionManifestPropertiesService.ts ×1
211 > }
213 > // Use product.json default value if it exists
214 > if (productWorkspaceTrustRequest?.default !== undefined) { extensionManifestPropertiesService.ts ×5
215 > return productWorkspaceTrustRequest.default; extensionManifestPropertiesService.ts ×1
216 > }
218 > return false;
221 > getExtensionVirtualWorkspaceSupportType(manifest: IExtensionManifest): ExtensionVirtualWorkspaceSupportType {
222 // check user configured
223 const userConfiguredVirtualWorkspaceSupport = this.getConfiguredVirtualWorkspaceSupport(manifest);
224 if (userConfiguredVirtualWorkspaceSupport !== undefined) {
225 return userConfiguredVirtualWorkspaceSupport;
226 }
227
228 const productConfiguredWorkspaceSchemes = this.getProductVirtualWorkspaceSupport(manifest);
229
230 // check override from product
231 if (productConfiguredWorkspaceSchemes?.override !== undefined) {
232 return productConfiguredWorkspaceSchemes.override;
233 }
234
235 // check the manifest
236 const virtualWorkspaces = manifest.capabilities?.virtualWorkspaces;
237 if (isBoolean(virtualWorkspaces)) {
238 return virtualWorkspaces;
239 } else if (virtualWorkspaces) {
240 const supported = virtualWorkspaces.supported;
241 if (isBoolean(supported) || supported === 'limited') {
242 return supported;
243 }
244 }
245
246 // check default from product
247 if (productConfiguredWorkspaceSchemes?.default !== undefined) {
248 return productConfiguredWorkspaceSchemes.default;
249 }
250
251 // Default - supports virtual workspace
252 return true;
253 }
255 > private deduceExtensionKind(manifest: IExtensionManifest): ExtensionKind[] {
256 > // Not an UI extension if it has main extensionManifestPropertiesService.ts ×9
257 > if (manifest.main) {
258 > if (manifest.browser) { extensionManifestPropertiesService.ts ×1
259 > return isWeb ? ['workspace', 'web'] : ['workspace']; extensionManifestPropertiesService.ts ×1
260 > }
261 > return ['workspace']; extensionManifestPropertiesService.ts ×1
262 > }
264 > if (manifest.browser) {
266 > }
268 > let result = [...ALL_EXTENSION_KINDS];
269 >
270 > if (isNonEmptyArray(manifest.extensionPack) || isNonEmptyArray(manifest.extensionDependencies)) { extensionManifestPropertiesService.ts ×9
271 > // Extension pack defaults to [workspace, web] in web and only [workspace] in desktop extensionManifestPropertiesService.ts ×1
272 > result = isWeb ? ['workspace', 'web'] : ['workspace'];
273 > }
275 > if (manifest.contributes) {
276 > for (const contribution of Object.keys(manifest.contributes)) { extensionManifestPropertiesService.ts ×4
277 > const supportedExtensionKinds = this.getSupportedExtensionKindsForExtensionPoint(contribution);
278 > if (supportedExtensionKinds.length) {
279 > result = result.filter(extensionKind => supportedExtensionKinds.includes(extensionKind));
280 > }
281 > }
282 > }
284 > if (!result.length) {
285 this.logService.warn('Cannot deduce extensionKind for extension', getGalleryExtensionId(manifest.publisher, manifest.name));
286 }
288 > return result;
291 > private getSupportedExtensionKindsForExtensionPoint(extensionPoint: string): ExtensionKind[] {
292 > if (this._extensionPointExtensionKindsMap === null) { extensionManifestPropertiesService.ts ×4
293 > const extensionPointExtensionKindsMap = new Map<string, ExtensionKind[]>();
294 > ExtensionsRegistry.getExtensionPoints().forEach(e => extensionPointExtensionKindsMap.set(e.name, e.defaultExtensionKind || [] /* supports all */));
295 > this._extensionPointExtensionKindsMap = extensionPointExtensionKindsMap;
296 > }
297 >
298 > let extensionPointExtensionKind = this._extensionPointExtensionKindsMap.get(extensionPoint);
299 > if (extensionPointExtensionKind) {
300 return extensionPointExtensionKind;
301 }
303 > extensionPointExtensionKind = this.productService.extensionPointExtensionKind ? this.productService.extensionPointExtensionKind[extensionPoint] : undefined;
304 > if (extensionPointExtensionKind) {
305 return extensionPointExtensionKind;
306 }
308 > /* Unknown extension point */
309 > return isWeb ? ['workspace', 'web'] : ['workspace'];
310 > }
312 > private getConfiguredExtensionKind(manifest: IExtensionManifest): (ExtensionKind | '-web')[] | null {
313 > const extensionIdentifier = { id: getGalleryExtensionId(manifest.publisher, manifest.name) }; extensionManifestPropertiesService.ts ×9
314 >
315 > // check in config
316 > let result: ExtensionKind | ExtensionKind[] | undefined = this.getUserConfiguredExtensionKind(extensionIdentifier);
317 > if (typeof result !== 'undefined') {
318 > return this.toArray(result); extensionManifestPropertiesService.ts ×2
319 > }
321 > // check product.json
322 > result = this.getProductExtensionKind(manifest);
323 > if (typeof result !== 'undefined') {
324 return result;
325 }
327 > // check the manifest itself
328 > result = manifest.extensionKind;
329 > if (typeof result !== 'undefined') {
330 > result = this.toArray(result); extensionManifestPropertiesService.ts ×1
331 > return result.filter(r => ['ui', 'workspace'].includes(r));
332 > }
334 > return null;
337 > private getProductExtensionKind(manifest: IExtensionManifest): ExtensionKind[] | undefined {
338 > if (this._productExtensionKindsMap === null) { extensionManifestPropertiesService.ts ×4
339 > const productExtensionKindsMap = new ExtensionIdentifierMap<ExtensionKind[]>();
340 > if (this.productService.extensionKind) {
341 for (const id of Object.keys(this.productService.extensionKind)) {
342 productExtensionKindsMap.set(id, this.productService.extensionKind[id]);
343 }
344 }
345 > this._productExtensionKindsMap = productExtensionKindsMap; extensionManifestPropertiesService.ts ×4
346 > }
347 >
348 > const extensionId = getGalleryExtensionId(manifest.publisher, manifest.name);
349 > return this._productExtensionKindsMap.get(extensionId);
350 > }
352 > private getProductVirtualWorkspaceSupport(manifest: IExtensionManifest): { default?: boolean; override?: boolean } | undefined {
353 if (this._productVirtualWorkspaceSupportMap === null) {
354 const productWorkspaceSchemesMap = new ExtensionIdentifierMap<{ default?: boolean; override?: boolean }>();
355 if (this.productService.extensionVirtualWorkspacesSupport) {
356 for (const id of Object.keys(this.productService.extensionVirtualWorkspacesSupport)) {
357 productWorkspaceSchemesMap.set(id, this.productService.extensionVirtualWorkspacesSupport[id]);
358 }
359 }
360 this._productVirtualWorkspaceSupportMap = productWorkspaceSchemesMap;
361 }
362
363 const extensionId = getGalleryExtensionId(manifest.publisher, manifest.name);
364 return this._productVirtualWorkspaceSupportMap.get(extensionId);
365 }
367 > private getConfiguredVirtualWorkspaceSupport(manifest: IExtensionManifest): boolean | undefined {
368 if (this._configuredVirtualWorkspaceSupportMap === null) {
369 const configuredWorkspaceSchemesMap = new ExtensionIdentifierMap<boolean>();
370 const configuredWorkspaceSchemes = this.configurationService.getValue<{ [key: string]: boolean }>('extensions.supportVirtualWorkspaces') || {};
371 for (const id of Object.keys(configuredWorkspaceSchemes)) {
372 if (configuredWorkspaceSchemes[id] !== undefined) {
373 configuredWorkspaceSchemesMap.set(id, configuredWorkspaceSchemes[id]);
374 }
375 }
376 this._configuredVirtualWorkspaceSupportMap = configuredWorkspaceSchemesMap;
377 }
378
379 const extensionId = getGalleryExtensionId(manifest.publisher, manifest.name);
380 return this._configuredVirtualWorkspaceSupportMap.get(extensionId);
381 }
383 > private getConfiguredSessionsWindowSupport(manifest: IExtensionManifest): boolean | undefined {
384 > if (this._configuredSessionsWindowSupportMap === null) { extensionManifestPropertiesService.ts ×5
385 > const configuredSessionsWindowSupportMap = new ExtensionIdentifierMap<boolean>();
386 > const configuredSessionsWindowSupport = this.configurationService.getValue<{ [key: string]: boolean }>(EXTENSIONS_SUPPORT_AGENTS_WINDOW) || {};
387 > for (const id of Object.keys(configuredSessionsWindowSupport)) {
388 > if (configuredSessionsWindowSupport[id] !== undefined) { extensionManifestPropertiesService.ts ×2
389 > configuredSessionsWindowSupportMap.set(id, configuredSessionsWindowSupport[id]);
390 > }
391 > }
392 > this._configuredSessionsWindowSupportMap = configuredSessionsWindowSupportMap; extensionManifestPropertiesService.ts ×5
393 > }
394 >
395 > const extensionId = getGalleryExtensionId(manifest.publisher, manifest.name);
396 > return this._configuredSessionsWindowSupportMap.get(extensionId);
397 > }
399 > private getConfiguredExtensionWorkspaceTrustRequest(manifest: IExtensionManifest): ExtensionUntrustedWorkspaceSupportType | undefined {
400 > const extensionId = getGalleryExtensionId(manifest.publisher, manifest.name); extensionManifestPropertiesService.ts ×4
401 > const extensionWorkspaceTrustRequest = this._configuredExtensionWorkspaceTrustRequestMap.get(extensionId);
402 >
403 > if (extensionWorkspaceTrustRequest && (extensionWorkspaceTrustRequest.version === undefined || extensionWorkspaceTrustRequest.version === manifest.version)) {
404 > return extensionWorkspaceTrustRequest.supported; extensionManifestPropertiesService.ts ×2
405 > }
407 > return undefined;
410 > private getProductExtensionWorkspaceTrustRequest(manifest: IExtensionManifest): ExtensionUntrustedWorkspaceSupport | undefined {
411 > const extensionId = getGalleryExtensionId(manifest.publisher, manifest.name); extensionManifestPropertiesService.ts ×4
412 > return this._productExtensionWorkspaceTrustRequestMap.get(extensionId);
413 > }
415 > private toArray(extensionKind: ExtensionKind | ExtensionKind[]): ExtensionKind[] {
416 > if (Array.isArray(extensionKind)) { extensionManifestPropertiesService.ts ×1
417 > return extensionKind;
418 > }
419 > return extensionKind === 'ui' ? ['ui', 'workspace'] : [extensionKind];
420 > }
422 >
423 > registerSingleton(IExtensionManifestPropertiesService, ExtensionManifestPropertiesService, InstantiationType.Delayed);