From 13f2dad45a75d341327f5e324a0ec1fba5b290f3 Mon Sep 17 00:00:00 2001 From: Pine Wu Date: Thu, 3 Nov 2016 16:12:02 -0700 Subject: [PATCH] Validate user provided viewletId --- .../treeExplorerViewlet.contribution.ts | 68 +++++++++++++------ .../parts/explorers/common/treeExplorer.ts | 5 ++ 2 files changed, 51 insertions(+), 22 deletions(-) diff --git a/src/vs/workbench/parts/explorers/browser/treeExplorerViewlet.contribution.ts b/src/vs/workbench/parts/explorers/browser/treeExplorerViewlet.contribution.ts index db2744281aa..7ac981d3419 100644 --- a/src/vs/workbench/parts/explorers/browser/treeExplorerViewlet.contribution.ts +++ b/src/vs/workbench/parts/explorers/browser/treeExplorerViewlet.contribution.ts @@ -16,11 +16,14 @@ import { ITreeExplorerViewletService, TreeExplorerViewletService } from 'vs/work import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { ViewletRegistry, Extensions as ViewletExtensions, ViewletDescriptor } from 'vs/workbench/browser/viewlet'; import { ITreeExplorer } from 'vs/platform/extensionManagement/common/extensionManagement'; -import { toCustomViewletId, toCustomViewletCSSClass } from 'vs/workbench/parts/explorers/common/treeExplorer'; +import { toCustomViewletId, toCustomViewletCSSClass, isValidViewletId } from 'vs/workbench/parts/explorers/common/treeExplorer'; +import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; +import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions'; +import { IMessageService, Severity } from 'vs/platform/message/common/message'; registerSingleton(ITreeExplorerViewletService, TreeExplorerViewletService); -const explorerContribtion: IJSONSchema = { +const explorerSchema: IJSONSchema = { description: localize('vscode.extension.contributes.explorer', "Contributes custom tree explorer viewlet to the sidebar"), type: 'object', properties: { @@ -29,7 +32,7 @@ const explorerContribtion: IJSONSchema = { type: 'string' }, treeLabel: { - description: localize('vscode.extension.contributes.explorer.treeLabel', 'Human readable string used to render the custom tree viewlet'), + description: localize('vscode.extension.contributes.explorer.treeLabel', 'Human readable string used to render the custom tree explorer'), type: 'string' }, icon: { @@ -39,25 +42,46 @@ const explorerContribtion: IJSONSchema = { } }; -ExtensionsRegistry.registerExtensionPoint('explorer', [], explorerContribtion).setHandler(extensions => { - for (let extension of extensions) { - const { treeExplorerNodeProviderId, treeLabel, icon } = extension.value; +export class ExplorerContribtion implements IWorkbenchContribution { - const getIconRule = (iconPath) => { return `background-image: url('${iconPath}')`; }; - if (icon) { - const iconClass = `.monaco-workbench > .activitybar .monaco-action-bar .action-label.${toCustomViewletCSSClass(treeExplorerNodeProviderId)}`; - const iconPath = join(extension.description.extensionFolderPath, icon); - createCSSRule(iconClass, getIconRule(iconPath)); - } + constructor( + @IMessageService private messageService: IMessageService + ) { + this.init(); + } + + public getId(): string { + return 'vs.explorer'; + } - Registry.as(ViewletExtensions.Viewlets).registerViewlet(new ViewletDescriptor( - 'vs/workbench/parts/explorers/browser/treeExplorerViewlet', - 'TreeExplorerViewlet', - toCustomViewletId(treeExplorerNodeProviderId), - treeLabel, - toCustomViewletCSSClass(treeExplorerNodeProviderId), - -1, // Extension viewlets are ordered by enabling sequence, so order here doesn't matter. - true - )); + private init() { + ExtensionsRegistry.registerExtensionPoint('explorer', [], explorerSchema).setHandler(extensions => { + for (let extension of extensions) { + const { treeExplorerNodeProviderId, treeLabel, icon } = extension.value; + + if (!isValidViewletId(treeExplorerNodeProviderId)) { + return this.messageService.show(Severity.Error, localize('customExplorer.invalidId', 'Tree Explorer extension {0} has invalid id and failed to activate.', treeLabel)); + } + + const getIconRule = (iconPath) => { return `background-image: url('${iconPath}')`; }; + if (icon) { + const iconClass = `.monaco-workbench > .activitybar .monaco-action-bar .action-label.${toCustomViewletCSSClass(treeExplorerNodeProviderId)}`; + const iconPath = join(extension.description.extensionFolderPath, icon); + createCSSRule(iconClass, getIconRule(iconPath)); + } + + Registry.as(ViewletExtensions.Viewlets).registerViewlet(new ViewletDescriptor( + 'vs/workbench/parts/explorers/browser/treeExplorerViewlet', + 'TreeExplorerViewlet', + toCustomViewletId(treeExplorerNodeProviderId), + treeLabel, + toCustomViewletCSSClass(treeExplorerNodeProviderId), + -1, // Extension viewlets are ordered by enabling sequence, so order here doesn't matter. + true + )); + } + }); } -}); \ No newline at end of file +} + +(Registry.as(WorkbenchExtensions.Workbench)).registerWorkbenchContribution(ExplorerContribtion); \ No newline at end of file diff --git a/src/vs/workbench/parts/explorers/common/treeExplorer.ts b/src/vs/workbench/parts/explorers/common/treeExplorer.ts index fc7f6c327cd..ea5e59c9e24 100644 --- a/src/vs/workbench/parts/explorers/common/treeExplorer.ts +++ b/src/vs/workbench/parts/explorers/common/treeExplorer.ts @@ -14,4 +14,9 @@ export function toCustomViewletActionId(viewletId: string): string { export function toCustomViewletCSSClass(viewletId: string): string { return 'customExplorer-' + viewletId; +} + +export function isValidViewletId(viewletId: string): boolean { + // Only allow alphanumeric letters, `_` and `-`. + return /^[a-z0-9_-]+$/i.test(viewletId); } \ No newline at end of file -- GitLab