From a4dd9113c99ee75cd24021269aa7af9c68c5c259 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Thu, 10 Jan 2019 10:02:04 +0100 Subject: [PATCH] Use uris for changelog and readme of extension and transform them. --- src/vs/base/common/uriIpc.ts | 82 ++++++++++++++++++- .../sharedProcess/sharedProcessMain.ts | 3 +- .../common/extensionManagement.ts | 4 +- .../node/extensionManagementIpc.ts | 68 ++++++++------- .../node/extensionManagementService.ts | 4 +- .../node/extensionsWorkbenchService.ts | 30 +++---- .../services/extensions/node/rpcProtocol.ts | 73 +---------------- 7 files changed, 136 insertions(+), 128 deletions(-) diff --git a/src/vs/base/common/uriIpc.ts b/src/vs/base/common/uriIpc.ts index 374ffd99055..10e24307da0 100644 --- a/src/vs/base/common/uriIpc.ts +++ b/src/vs/base/common/uriIpc.ts @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { URI, UriComponents } from 'vs/base/common/uri'; +import { MarshalledObject } from 'vs/base/common/marshalling'; export interface IURITransformer { transformIncoming(uri: UriComponents): UriComponents; @@ -21,4 +22,83 @@ export const DefaultURITransformer: IURITransformer = new class { transformOutgoing(uri: URI | UriComponents): URI | UriComponents { return uri; } -}; \ No newline at end of file +}; + +function _transformOutgoingURIs(obj: any, transformer: IURITransformer, depth: number): any { + + if (!obj || depth > 200) { + return null; + } + + if (typeof obj === 'object') { + if (obj instanceof URI) { + return transformer.transformOutgoing(obj); + } + + // walk object (or array) + for (let key in obj) { + if (Object.hasOwnProperty.call(obj, key)) { + const r = _transformOutgoingURIs(obj[key], transformer, depth + 1); + if (r !== null) { + obj[key] = r; + } + } + } + } + + return null; +} + +export function transformOutgoingURIs(obj: T, transformer: IURITransformer): T { + const result = _transformOutgoingURIs(obj, transformer, 0); + if (result === null) { + // no change + return obj; + } + return result; +} + + +function _transformIncomingURIs(obj: any, transformer: IURITransformer, revive: boolean, depth: number): any { + + if (!obj || depth > 200) { + return null; + } + + if (typeof obj === 'object') { + + if ((obj).$mid === 1) { + return revive ? URI.revive(transformer.transformIncoming(obj)) : transformer.transformIncoming(obj); + } + + // walk object (or array) + for (let key in obj) { + if (Object.hasOwnProperty.call(obj, key)) { + const r = _transformIncomingURIs(obj[key], transformer, revive, depth + 1); + if (r !== null) { + obj[key] = r; + } + } + } + } + + return null; +} + +export function transformIncomingURIs(obj: T, transformer: IURITransformer): T { + const result = _transformIncomingURIs(obj, transformer, false, 0); + if (result === null) { + // no change + return obj; + } + return result; +} + +export function transformAndReviveIncomingURIs(obj: T, transformer: IURITransformer): T { + const result = _transformIncomingURIs(obj, transformer, true, 0); + if (result === null) { + // no change + return obj; + } + return result; +} \ No newline at end of file diff --git a/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts b/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts index fb0305ca329..7c52379bc9b 100644 --- a/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts +++ b/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts @@ -43,7 +43,6 @@ import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { DownloadService } from 'vs/platform/download/node/downloadService'; import { IDownloadService } from 'vs/platform/download/common/download'; import { StaticRouter } from 'vs/base/parts/ipc/node/ipc'; -import { DefaultURITransformer } from 'vs/base/common/uriIpc'; export interface ISharedProcessConfiguration { readonly machineId: string; @@ -133,7 +132,7 @@ function main(server: Server, initData: ISharedProcessInitData, configuration: I instantiationService2.invokeFunction(accessor => { const extensionManagementService = accessor.get(IExtensionManagementService); - const channel = new ExtensionManagementChannel(extensionManagementService, () => DefaultURITransformer); + const channel = new ExtensionManagementChannel(extensionManagementService, () => null); server.registerChannel('extensions', channel); // clean up deprecated extensions diff --git a/src/vs/platform/extensionManagement/common/extensionManagement.ts b/src/vs/platform/extensionManagement/common/extensionManagement.ts index a6bdb826346..ff5a8cfff1b 100644 --- a/src/vs/platform/extensionManagement/common/extensionManagement.ts +++ b/src/vs/platform/extensionManagement/common/extensionManagement.ts @@ -223,8 +223,8 @@ export interface ILocalExtension { manifest: IExtensionManifest; metadata: IGalleryMetadata; location: URI; - readmeUrl: string; - changelogUrl: string; + readmeUrl: URI | null; + changelogUrl: URI | null; } export const IExtensionManagementService = createDecorator('extensionManagementService'); diff --git a/src/vs/platform/extensionManagement/node/extensionManagementIpc.ts b/src/vs/platform/extensionManagement/node/extensionManagementIpc.ts index a1f0d010abf..07fabbbe8f4 100644 --- a/src/vs/platform/extensionManagement/node/extensionManagementIpc.ts +++ b/src/vs/platform/extensionManagement/node/extensionManagementIpc.ts @@ -6,8 +6,30 @@ import { IChannel, IServerChannel } from 'vs/base/parts/ipc/node/ipc'; import { IExtensionManagementService, ILocalExtension, InstallExtensionEvent, DidInstallExtensionEvent, IGalleryExtension, LocalExtensionType, DidUninstallExtensionEvent, IExtensionIdentifier, IGalleryMetadata, IReportedExtension } from '../common/extensionManagement'; import { Event } from 'vs/base/common/event'; -import { URI } from 'vs/base/common/uri'; -import { IURITransformer } from 'vs/base/common/uriIpc'; +import { URI, UriComponents } from 'vs/base/common/uri'; +import { IURITransformer, DefaultURITransformer, transformAndReviveIncomingURIs } from 'vs/base/common/uriIpc'; +import { cloneAndChange } from 'vs/base/common/objects'; + +function transformIncomingURI(uri: UriComponents, transformer: IURITransformer | null): URI { + return URI.revive(transformer ? transformer.transformIncoming(uri) : uri); +} + +function transformOutgoingURI(uri: URI, transformer: IURITransformer | null): URI { + return transformer ? transformer.transformOutgoing(uri) : uri; +} + +function transformIncomingExtension(extension: ILocalExtension, transformer: IURITransformer | null): ILocalExtension { + transformer = transformer ? transformer : DefaultURITransformer; + const manfiest = extension.manifest; + extension.manifest = undefined; + extension = transformAndReviveIncomingURIs(extension, transformer); + extension.manifest = manfiest; + return extension; +} + +function transformOutgoingExtension(extension: ILocalExtension, transformer: IURITransformer | null): ILocalExtension { + return transformer ? cloneAndChange(extension, value => value instanceof URI ? transformer.transformOutgoing(value) : undefined) : extension; +} export class ExtensionManagementChannel implements IServerChannel { @@ -16,7 +38,7 @@ export class ExtensionManagementChannel implements IServerChannel { onUninstallExtension: Event; onDidUninstallExtension: Event; - constructor(private service: IExtensionManagementService, private getUriTransformer: (requestContext: any) => IURITransformer) { + constructor(private service: IExtensionManagementService, private getUriTransformer: (requestContext: any) => IURITransformer | null) { this.onInstallExtension = Event.buffer(service.onInstallExtension, true); this.onDidInstallExtension = Event.buffer(service.onDidInstallExtension, true); this.onUninstallExtension = Event.buffer(service.onUninstallExtension, true); @@ -27,7 +49,7 @@ export class ExtensionManagementChannel implements IServerChannel { const uriTransformer = this.getUriTransformer(context); switch (event) { case 'onInstallExtension': return this.onInstallExtension; - case 'onDidInstallExtension': return Event.map(this.onDidInstallExtension, i => ({ ...i, local: this._transformOutgoing(i.local, uriTransformer) })); + case 'onDidInstallExtension': return Event.map(this.onDidInstallExtension, i => ({ ...i, local: transformOutgoingExtension(i.local, uriTransformer) })); case 'onUninstallExtension': return this.onUninstallExtension; case 'onDidUninstallExtension': return this.onDidUninstallExtension; } @@ -36,31 +58,21 @@ export class ExtensionManagementChannel implements IServerChannel { } call(context, command: string, args?: any): Promise { - const uriTransformer = this.getUriTransformer(context); + const uriTransformer: IURITransformer | null = this.getUriTransformer(context); switch (command) { - case 'zip': return this.service.zip(this._transformIncoming(args[0], uriTransformer)).then(uri => uriTransformer.transformOutgoing(uri)); - case 'unzip': return this.service.unzip(URI.revive(uriTransformer.transformIncoming(args[0])), args[1]); - case 'install': return this.service.install(URI.revive(uriTransformer.transformIncoming(args[0]))); + case 'zip': return this.service.zip(transformIncomingExtension(args[0], uriTransformer)).then(uri => transformOutgoingURI(uri, uriTransformer)); + case 'unzip': return this.service.unzip(transformIncomingURI(args[0], uriTransformer), args[1]); + case 'install': return this.service.install(transformIncomingURI(args[0], uriTransformer)); case 'installFromGallery': return this.service.installFromGallery(args[0]); - case 'uninstall': return this.service.uninstall(this._transformIncoming(args[0], uriTransformer), args[1]); - case 'reinstallFromGallery': return this.service.reinstallFromGallery(this._transformIncoming(args[0], uriTransformer)); - case 'getInstalled': return this.service.getInstalled(args[0]).then(extensions => extensions.map(e => this._transformOutgoing(e, uriTransformer))); - case 'updateMetadata': return this.service.updateMetadata(this._transformIncoming(args[0], uriTransformer), args[1]).then(e => this._transformOutgoing(e, uriTransformer)); + case 'uninstall': return this.service.uninstall(transformIncomingExtension(args[0], uriTransformer), args[1]); + case 'reinstallFromGallery': return this.service.reinstallFromGallery(transformIncomingExtension(args[0], uriTransformer)); + case 'getInstalled': return this.service.getInstalled(args[0]).then(extensions => extensions.map(e => transformOutgoingExtension(e, uriTransformer))); + case 'updateMetadata': return this.service.updateMetadata(transformIncomingExtension(args[0], uriTransformer), args[1]).then(e => transformOutgoingExtension(e, uriTransformer)); case 'getExtensionsReport': return this.service.getExtensionsReport(); } throw new Error('Invalid call'); } - - private _transformIncoming(extension: ILocalExtension, uriTransformer: IURITransformer): ILocalExtension { - return extension ? { ...extension, ...{ location: URI.revive(uriTransformer.transformIncoming(extension.location)) } } : extension; - } - - private _transformOutgoing(extension: ILocalExtension, uriTransformer: IURITransformer): ILocalExtension; - private _transformOutgoing(extension: ILocalExtension | undefined, uriTransformer: IURITransformer): ILocalExtension | undefined; - private _transformOutgoing(extension: ILocalExtension | undefined, uriTransformer: IURITransformer): ILocalExtension | undefined { - return extension ? { ...extension, ...{ location: uriTransformer.transformOutgoing(extension.location) } } : extension; - } } export class ExtensionManagementChannelClient implements IExtensionManagementService { @@ -70,7 +82,7 @@ export class ExtensionManagementChannelClient implements IExtensionManagementSer constructor(private channel: IChannel) { } get onInstallExtension(): Event { return this.channel.listen('onInstallExtension'); } - get onDidInstallExtension(): Event { return Event.map(this.channel.listen('onDidInstallExtension'), i => ({ ...i, local: this._transformIncoming(i.local) })); } + get onDidInstallExtension(): Event { return Event.map(this.channel.listen('onDidInstallExtension'), i => ({ ...i, local: transformIncomingExtension(i.local, null) })); } get onUninstallExtension(): Event { return this.channel.listen('onUninstallExtension'); } get onDidUninstallExtension(): Event { return this.channel.listen('onDidUninstallExtension'); } @@ -100,21 +112,15 @@ export class ExtensionManagementChannelClient implements IExtensionManagementSer getInstalled(type: LocalExtensionType | null = null): Promise { return Promise.resolve(this.channel.call('getInstalled', [type])) - .then(extensions => extensions.map(extension => this._transformIncoming(extension))); + .then(extensions => extensions.map(extension => transformIncomingExtension(extension, null))); } updateMetadata(local: ILocalExtension, metadata: IGalleryMetadata): Promise { return Promise.resolve(this.channel.call('updateMetadata', [local, metadata])) - .then(extension => this._transformIncoming(extension)); + .then(extension => transformIncomingExtension(extension, null)); } getExtensionsReport(): Promise { return Promise.resolve(this.channel.call('getExtensionsReport')); } - - private _transformIncoming(extension: ILocalExtension): ILocalExtension; - private _transformIncoming(extension: ILocalExtension | undefined): ILocalExtension | undefined; - private _transformIncoming(extension: ILocalExtension | undefined): ILocalExtension | undefined { - return extension ? { ...extension, ...{ location: URI.revive(extension.location) } } : extension; - } } \ No newline at end of file diff --git a/src/vs/platform/extensionManagement/node/extensionManagementService.ts b/src/vs/platform/extensionManagement/node/extensionManagementService.ts index b2b55c6f524..69e32ce2152 100644 --- a/src/vs/platform/extensionManagement/node/extensionManagementService.ts +++ b/src/vs/platform/extensionManagement/node/extensionManagementService.ts @@ -776,9 +776,9 @@ export class ExtensionManagementService extends Disposable implements IExtension .then(children => readManifest(extensionPath) .then(({ manifest, metadata }) => { const readme = children.filter(child => /^readme(\.txt|\.md|)$/i.test(child))[0]; - const readmeUrl = readme ? URI.file(path.join(extensionPath, readme)).toString() : null; + const readmeUrl = readme ? URI.file(path.join(extensionPath, readme)) : null; const changelog = children.filter(child => /^changelog(\.txt|\.md|)$/i.test(child))[0]; - const changelogUrl = changelog ? URI.file(path.join(extensionPath, changelog)).toString() : null; + const changelogUrl = changelog ? URI.file(path.join(extensionPath, changelog)) : null; if (manifest.extensionDependencies) { manifest.extensionDependencies = manifest.extensionDependencies.map(id => adoptToGalleryExtensionId(id)); } diff --git a/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.ts b/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.ts index ba095c6890a..fd01f0e7dd1 100644 --- a/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.ts +++ b/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.ts @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ import * as nls from 'vs/nls'; -import { readFile } from 'vs/base/node/pfs'; import * as semver from 'semver'; import { Event, Emitter } from 'vs/base/common/event'; import { index, distinct } from 'vs/base/common/arrays'; @@ -37,6 +36,7 @@ import { Schemas } from 'vs/base/common/network'; import * as resources from 'vs/base/common/resources'; import { CancellationToken } from 'vs/base/common/cancellation'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; +import { IFileService } from 'vs/platform/files/common/files'; interface IExtensionStateProvider { (extension: Extension): T; @@ -53,7 +53,8 @@ class Extension implements IExtension { public locals: ILocalExtension[], public gallery: IGalleryExtension | undefined, private telemetryService: ITelemetryService, - private logService: ILogService + private logService: ILogService, + private fileService: IFileService ) { } get type(): LocalExtensionType | undefined { @@ -237,8 +238,7 @@ class Extension implements IExtension { } if (this.local && this.local.readmeUrl) { - const uri = URI.parse(this.local.readmeUrl); - return readFile(uri.fsPath, 'utf8'); + return this.fileService.resolveContent(this.local.readmeUrl, { encoding: 'utf8' }).then(content => content.value); } if (this.type === LocalExtensionType.System) { @@ -258,8 +258,7 @@ ${this.description} } if (this.local && this.local.changelogUrl) { - const uri = URI.parse(this.local.changelogUrl); - return uri.scheme === 'file'; + return true; } return this.type === LocalExtensionType.System; @@ -280,13 +279,7 @@ ${this.description} return Promise.reject(new Error('not available')); } - const uri = URI.parse(changelogUrl); - - if (uri.scheme === 'file') { - return readFile(uri.fsPath, 'utf8'); - } - - return Promise.reject(new Error('not available')); + return this.fileService.resolveContent(changelogUrl, { encoding: 'utf8' }).then(content => content.value); } get dependencies(): string[] { @@ -391,7 +384,8 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService, @IProgressService2 private readonly progressService: IProgressService2, @IExtensionService private readonly runtimeExtensionService: IExtensionService, @IExtensionManagementServerService private readonly extensionManagementServerService: IExtensionManagementServerService, - @IStorageService private readonly storageService: IStorageService + @IStorageService private readonly storageService: IStorageService, + @IFileService private readonly fileService: IFileService ) { this.stateProvider = ext => this.getExtensionState(ext); @@ -443,7 +437,7 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService, const locals = groupById[getGalleryExtensionIdFromLocal(local)]; locals.splice(locals.indexOf(local), 1); locals.splice(0, 0, local); - const extension = installedById[local.identifier.id] || new Extension(this.galleryService, this.stateProvider, locals, undefined, this.telemetryService, this.logService); + const extension = installedById[local.identifier.id] || new Extension(this.galleryService, this.stateProvider, locals, undefined, this.telemetryService, this.logService, this.fileService); extension.locals = locals; extension.enablementState = this.extensionEnablementService.getEnablementState(local); return extension; @@ -561,7 +555,7 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService, this.syncLocalWithGalleryExtension(result, gallery); } } else { - result = new Extension(this.galleryService, this.stateProvider, [], gallery, this.telemetryService, this.logService); + result = new Extension(this.galleryService, this.stateProvider, [], gallery, this.telemetryService, this.logService, this.fileService); } if (maliciousExtensionSet.has(result.identifier.id)) { @@ -920,7 +914,7 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService, let extension = this.installed.filter(e => areSameExtensions(e.identifier, gallery.identifier))[0]; if (!extension) { - extension = new Extension(this.galleryService, this.stateProvider, [], gallery, this.telemetryService, this.logService); + extension = new Extension(this.galleryService, this.stateProvider, [], gallery, this.telemetryService, this.logService, this.fileService); } this.installing.push(extension); @@ -931,7 +925,7 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService, private onDidInstallExtension(event: DidInstallExtensionEvent): void { const { local, zipPath, error, gallery } = event; const installingExtension = gallery ? this.installing.filter(e => areSameExtensions(e.identifier, gallery.identifier))[0] : null; - let extension: Extension | undefined = installingExtension ? installingExtension : zipPath ? new Extension(this.galleryService, this.stateProvider, local ? [local] : [], undefined, this.telemetryService, this.logService) : undefined; + let extension: Extension | undefined = installingExtension ? installingExtension : zipPath ? new Extension(this.galleryService, this.stateProvider, local ? [local] : [], undefined, this.telemetryService, this.logService, this.fileService) : undefined; if (extension) { this.installing = installingExtension ? this.installing.filter(e => e !== installingExtension) : this.installing; if (local) { diff --git a/src/vs/workbench/services/extensions/node/rpcProtocol.ts b/src/vs/workbench/services/extensions/node/rpcProtocol.ts index 33e6b81c70d..4d75df47757 100644 --- a/src/vs/workbench/services/extensions/node/rpcProtocol.ts +++ b/src/vs/workbench/services/extensions/node/rpcProtocol.ts @@ -9,9 +9,7 @@ import { CharCode } from 'vs/base/common/charCode'; import * as errors from 'vs/base/common/errors'; import { Emitter, Event } from 'vs/base/common/event'; import { Disposable } from 'vs/base/common/lifecycle'; -import { MarshalledObject } from 'vs/base/common/marshalling'; -import { URI } from 'vs/base/common/uri'; -import { IURITransformer } from 'vs/base/common/uriIpc'; +import { IURITransformer, transformIncomingURIs } from 'vs/base/common/uriIpc'; import { IMessagePassingProtocol } from 'vs/base/parts/ipc/node/ipc'; import { LazyPromise } from 'vs/workbench/services/extensions/node/lazyPromise'; import { IRPCProtocol, ProxyIdentifier, getStringIdentifierForProxy } from 'vs/workbench/services/extensions/node/proxyIdentifier'; @@ -40,75 +38,6 @@ function createURIReplacer(transformer: IURITransformer | null): JSONStringifyRe }; } -function _transformOutgoingURIs(obj: any, transformer: IURITransformer, depth: number): any { - - if (!obj || depth > 200) { - return null; - } - - if (typeof obj === 'object') { - if (obj instanceof URI) { - return transformer.transformOutgoing(obj); - } - - // walk object (or array) - for (let key in obj) { - if (Object.hasOwnProperty.call(obj, key)) { - const r = _transformOutgoingURIs(obj[key], transformer, depth + 1); - if (r !== null) { - obj[key] = r; - } - } - } - } - - return null; -} - -export function transformOutgoingURIs(obj: T, transformer: IURITransformer): T { - const result = _transformOutgoingURIs(obj, transformer, 0); - if (result === null) { - // no change - return obj; - } - return result; -} - -function _transformIncomingURIs(obj: any, transformer: IURITransformer, depth: number): any { - - if (!obj || depth > 200) { - return null; - } - - if (typeof obj === 'object') { - - if ((obj).$mid === 1) { - return transformer.transformIncoming(obj); - } - - // walk object (or array) - for (let key in obj) { - if (Object.hasOwnProperty.call(obj, key)) { - const r = _transformIncomingURIs(obj[key], transformer, depth + 1); - if (r !== null) { - obj[key] = r; - } - } - } - } - - return null; -} - -function transformIncomingURIs(obj: T, transformer: IURITransformer): T { - const result = _transformIncomingURIs(obj, transformer, 0); - if (result === null) { - // no change - return obj; - } - return result; -} - export const enum RequestInitiator { LocalSide = 0, OtherSide = 1 -- GitLab