Skip to content

Commit 1fc4a6b

Browse files
authored
support hosted web extension (microsoft#183375)
1 parent 3c161fd commit 1fc4a6b

File tree

2 files changed

+49
-7
lines changed

2 files changed

+49
-7
lines changed

src/vs/workbench/browser/web.api.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ export interface IWorkbenchConstructionOptions {
220220
* - an extension in the Marketplace
221221
* - location of the extension where it is hosted.
222222
*/
223-
readonly additionalBuiltinExtensions?: readonly (MarketplaceExtension | UriComponents)[];
223+
readonly additionalBuiltinExtensions?: readonly (MarketplaceExtension | UriComponents | HostedExtension)[];
224224

225225
/**
226226
* List of extensions to be enabled if they are installed.
@@ -373,6 +373,14 @@ export interface IResourceUriProvider {
373373
export type ExtensionId = string;
374374

375375
export type MarketplaceExtension = ExtensionId | { readonly id: ExtensionId; preRelease?: boolean; migrateStorageFrom?: ExtensionId };
376+
export interface HostedExtension {
377+
readonly location: UriComponents;
378+
readonly preRelease?: boolean;
379+
readonly packageNLSUris?: Map<string, UriComponents>;
380+
readonly fallbackPackageNLSUri?: UriComponents;
381+
readonly readmeUri?: UriComponents;
382+
readonly changelogUri?: UriComponents;
383+
}
376384

377385
export interface ICommonTelemetryPropertiesResolver {
378386
(): { [key: string]: any };

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

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,14 @@ import { IUserDataProfilesService } from 'vs/platform/userDataProfile/common/use
4545
import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity';
4646

4747
type GalleryExtensionInfo = { readonly id: string; preRelease?: boolean; migrateStorageFrom?: string };
48+
interface HostedExtensionInfo {
49+
readonly location: UriComponents;
50+
readonly preRelease?: boolean;
51+
readonly packageNLSUris?: Map<string, UriComponents>;
52+
readonly fallbackPackageNLSUri?: UriComponents;
53+
readonly readmeUri?: UriComponents;
54+
readonly changelogUri?: UriComponents;
55+
}
4856
type ExtensionInfo = { readonly id: string; preRelease: boolean };
4957

5058
function isGalleryExtensionInfo(obj: unknown): obj is GalleryExtensionInfo {
@@ -54,6 +62,23 @@ function isGalleryExtensionInfo(obj: unknown): obj is GalleryExtensionInfo {
5462
&& (galleryExtensionInfo.migrateStorageFrom === undefined || typeof galleryExtensionInfo.migrateStorageFrom === 'string');
5563
}
5664

65+
function isHostedExtensionInfo(obj: unknown): obj is HostedExtensionInfo {
66+
const hostedExtensionInfo = obj as HostedExtensionInfo | undefined;
67+
return isUriComponents(hostedExtensionInfo?.location)
68+
&& (hostedExtensionInfo?.preRelease === undefined || typeof hostedExtensionInfo.preRelease === 'boolean')
69+
&& (hostedExtensionInfo?.fallbackPackageNLSUri === undefined || isUriComponents(hostedExtensionInfo?.fallbackPackageNLSUri))
70+
&& (hostedExtensionInfo?.changelogUri === undefined || isUriComponents(hostedExtensionInfo?.changelogUri))
71+
&& (hostedExtensionInfo?.readmeUri === undefined || isUriComponents(hostedExtensionInfo?.readmeUri));
72+
}
73+
74+
function isUriComponents(thing: unknown): thing is UriComponents {
75+
if (!thing) {
76+
return false;
77+
}
78+
return isString((<any>thing).path) &&
79+
isString((<any>thing).scheme);
80+
}
81+
5782
interface IStoredWebExtension {
5883
readonly identifier: IExtensionIdentifier;
5984
readonly version: string;
@@ -117,12 +142,12 @@ export class WebExtensionsScannerService extends Disposable implements IWebExten
117142
}
118143
}
119144

120-
private _customBuiltinExtensionsInfoPromise: Promise<{ extensions: ExtensionInfo[]; extensionsToMigrate: [string, string][]; extensionLocations: URI[] }> | undefined;
121-
private readCustomBuiltinExtensionsInfoFromEnv(): Promise<{ extensions: ExtensionInfo[]; extensionsToMigrate: [string, string][]; extensionLocations: URI[] }> {
145+
private _customBuiltinExtensionsInfoPromise: Promise<{ extensions: ExtensionInfo[]; extensionsToMigrate: [string, string][]; extensionLocations: HostedExtensionInfo[] }> | undefined;
146+
private readCustomBuiltinExtensionsInfoFromEnv(): Promise<{ extensions: ExtensionInfo[]; extensionsToMigrate: [string, string][]; extensionLocations: HostedExtensionInfo[] }> {
122147
if (!this._customBuiltinExtensionsInfoPromise) {
123148
this._customBuiltinExtensionsInfoPromise = (async () => {
124149
let extensions: ExtensionInfo[] = [];
125-
const extensionLocations: URI[] = [];
150+
const extensionLocations: HostedExtensionInfo[] = [];
126151
const extensionsToMigrate: [string, string][] = [];
127152
const customBuiltinExtensionsInfo = this.environmentService.options && Array.isArray(this.environmentService.options.additionalBuiltinExtensions)
128153
? this.environmentService.options.additionalBuiltinExtensions.map(additionalBuiltinExtension => isString(additionalBuiltinExtension) ? { id: additionalBuiltinExtension } : additionalBuiltinExtension)
@@ -134,7 +159,11 @@ export class WebExtensionsScannerService extends Disposable implements IWebExten
134159
extensionsToMigrate.push([e.migrateStorageFrom, e.id]);
135160
}
136161
} else {
137-
extensionLocations.push(URI.revive(e));
162+
if (isHostedExtensionInfo(e)) {
163+
extensionLocations.push(e);
164+
} else {
165+
extensionLocations.push({ location: e });
166+
}
138167
}
139168
}
140169
if (extensions.length) {
@@ -212,9 +241,14 @@ export class WebExtensionsScannerService extends Disposable implements IWebExten
212241
return [];
213242
}
214243
const result: IScannedExtension[] = [];
215-
await Promise.allSettled(extensionLocations.map(async location => {
244+
await Promise.allSettled(extensionLocations.map(async ({ location, preRelease, packageNLSUris, fallbackPackageNLSUri, readmeUri, changelogUri }) => {
216245
try {
217-
const webExtension = await this.toWebExtension(location);
246+
const webExtension = await this.toWebExtension(URI.revive(location), undefined,
247+
packageNLSUris ? [...packageNLSUris.entries()].reduce((result, [key, value]) => { result.set(key, URI.revive(value)); return result; }, new Map<string, URI>()) : undefined,
248+
URI.revive(fallbackPackageNLSUri),
249+
URI.revive(readmeUri),
250+
URI.revive(changelogUri),
251+
{ preRelease });
218252
const extension = await this.toScannedExtension(webExtension, true);
219253
if (extension.isValid || !scanOptions?.skipInvalidExtensions) {
220254
result.push(extension);

0 commit comments

Comments
 (0)