Skip to content

Commit 2d1f6d4

Browse files
committed
Add localResourceRoots to webview options
Fixes microsoft#44039 Add a new option that lets extensions override which root folders a webview can load local resources from. Defaults to allowing any resource in the workspace
1 parent bcbd339 commit 2d1f6d4

8 files changed

Lines changed: 44 additions & 25 deletions

File tree

extensions/markdown/src/features/previewContentProvider.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,10 @@ export class MarkdownPreviewWebviewManager {
354354
const view = vscode.window.createWebview(
355355
localize('previewTitle', 'Preview {0}', path.basename(resource.fsPath)),
356356
viewColumn,
357-
{ enableScripts: true });
357+
{
358+
enableScripts: true,
359+
localResourceRoots: this.getLocalResourceRoots(resource)
360+
});
358361

359362
this.contentProvider.provideTextDocumentContent(resource, this.previewConfigurations).then(x => view.html = x);
360363

@@ -373,4 +376,19 @@ export class MarkdownPreviewWebviewManager {
373376
this.webviews.set(resource.fsPath, view);
374377
return view;
375378
}
379+
380+
private getLocalResourceRoots(
381+
resource: vscode.Uri
382+
): vscode.Uri[] {
383+
const folder = vscode.workspace.getWorkspaceFolder(resource);
384+
if (folder) {
385+
return [folder.uri];
386+
}
387+
388+
if (!resource.scheme || resource.scheme === 'file') {
389+
return [vscode.Uri.parse(path.dirname(resource.fsPath))];
390+
}
391+
392+
return [];
393+
}
376394
}

src/vs/vscode.proposed.d.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,7 @@ declare module 'vscode' {
396396
*/
397397
export interface WebviewOptions {
398398
/**
399-
* Should scripts be enabled in the webview contetn?
399+
* Should scripts be enabled in the webview content?
400400
*
401401
* Defaults to false (scripts-disabled).
402402
*/
@@ -423,6 +423,15 @@ declare module 'vscode' {
423423
* webview content cannot be quickly saved and restored.
424424
*/
425425
readonly keepAlive?: boolean;
426+
427+
/**
428+
* Root paths from which the webview can load local (filesystem) resources using the `vscode-workspace-resource:` scheme.
429+
*
430+
* Default to the root folders of the current workspace.
431+
*
432+
* Pass in an empty array to disallow access to any local resources.
433+
*/
434+
readonly localResourceRoots?: Uri[];
426435
}
427436

428437
/**

src/vs/workbench/api/electron-browser/mainThreadWebview.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,9 @@ class WebviewEditor extends BaseWebviewEditor {
201201

202202
this.webview.options = {
203203
allowScripts: input.options.enableScripts,
204-
enableWrappedPostMessage: true
204+
enableWrappedPostMessage: true,
205+
useSameOriginForRoot: false,
206+
localResourceRoots: (input && input.options.localResourceRoots) || this._contextService.getWorkspace().folders.map(x => x.uri)
205207
};
206208
this.webview.contents = input.html;
207209
}
@@ -215,7 +217,6 @@ class WebviewEditor extends BaseWebviewEditor {
215217
this._partService.getContainer(Parts.EDITOR_PART),
216218
this.themeService,
217219
this._environmentService,
218-
this._contextService,
219220
this._contextViewService,
220221
this.contextKey,
221222
this.findInputFocusContextKey,

src/vs/workbench/parts/extensions/browser/extensionEditor.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ import { Color } from 'vs/base/common/color';
5252
import { WorkbenchTree } from 'vs/platform/list/browser/listService';
5353
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
5454
import { assign } from 'vs/base/common/objects';
55-
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
5655
import { INotificationService } from 'vs/platform/notification/common/notification';
5756

5857
/** A context key that is set when an extension editor webview has focus. */
@@ -194,8 +193,7 @@ export class ExtensionEditor extends BaseEditor {
194193
@IContextViewService private readonly contextViewService: IContextViewService,
195194
@IContextKeyService private readonly contextKeyService: IContextKeyService,
196195
@IExtensionTipsService private readonly extensionTipsService: IExtensionTipsService,
197-
@IEnvironmentService private readonly environmentService: IEnvironmentService,
198-
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService
196+
@IEnvironmentService private readonly environmentService: IEnvironmentService
199197

200198
) {
201199
super(ExtensionEditor.ID, telemetryService, themeService);
@@ -421,7 +419,7 @@ export class ExtensionEditor extends BaseEditor {
421419
.then<void>(body => {
422420
const allowedBadgeProviders = this.extensionsWorkbenchService.allowedBadgeProviders;
423421
const webViewOptions = allowedBadgeProviders.length > 0 ? { allowScripts: false, allowSvgs: false, svgWhiteList: allowedBadgeProviders } : {};
424-
this.activeWebview = new Webview(this.content, this.partService.getContainer(Parts.EDITOR_PART), this.themeService, this.environmentService, this.contextService, this.contextViewService, this.contextKey, this.findInputFocusContextKey, webViewOptions);
422+
this.activeWebview = new Webview(this.content, this.partService.getContainer(Parts.EDITOR_PART), this.themeService, this.environmentService, this.contextViewService, this.contextKey, this.findInputFocusContextKey, webViewOptions);
425423
const removeLayoutParticipant = arrays.insert(this.layoutParticipants, this.activeWebview);
426424
this.contentDisposables.push(toDisposable(removeLayoutParticipant));
427425
this.activeWebview.contents = body;

src/vs/workbench/parts/html/browser/html.contribution.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ function getActivePreviewsForResource(accessor: ServicesAccessor, resource: URI
3030
}
3131

3232
// --- Register Editor
33+
3334
(<IEditorRegistry>Registry.as(EditorExtensions.Editors)).registerEditor(new EditorDescriptor(
3435
HtmlPreviewPart,
3536
HtmlPreviewPart.ID,

src/vs/workbench/parts/html/browser/htmlPreviewPart.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ import { Webview, WebviewOptions } from './webview';
2626
import { IStorageService } from 'vs/platform/storage/common/storage';
2727
import { WebviewEditor } from './webviewEditor';
2828
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
29-
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
3029

3130

3231
/**
@@ -55,8 +54,7 @@ export class HtmlPreviewPart extends WebviewEditor {
5554
@IOpenerService private readonly openerService: IOpenerService,
5655
@IPartService private readonly partService: IPartService,
5756
@IContextViewService private readonly _contextViewService: IContextViewService,
58-
@IEnvironmentService private readonly _environmentService: IEnvironmentService,
59-
@IWorkspaceContextService private readonly _contextService: IWorkspaceContextService
57+
@IEnvironmentService private readonly _environmentService: IEnvironmentService
6058
) {
6159
super(HtmlPreviewPart.ID, telemetryService, themeService, storageService, contextKeyService);
6260
}
@@ -93,7 +91,6 @@ export class HtmlPreviewPart extends WebviewEditor {
9391
this.partService.getContainer(Parts.EDITOR_PART),
9492
this.themeService,
9593
this._environmentService,
96-
this._contextService,
9794
this._contextViewService,
9895
this.contextKey,
9996
this.findInputFocusContextKey,

src/vs/workbench/parts/html/browser/webview.ts

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,14 @@ import { IContextKey } from 'vs/platform/contextkey/common/contextkey';
1717
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
1818
import { normalize, nativeSep } from 'vs/base/common/paths';
1919
import { startsWith } from 'vs/base/common/strings';
20-
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
2120

2221
export interface WebviewOptions {
2322
readonly allowScripts?: boolean;
2423
readonly allowSvgs?: boolean;
2524
readonly svgWhiteList?: string[];
2625
readonly enableWrappedPostMessage?: boolean;
2726
readonly useSameOriginForRoot?: boolean;
27+
readonly localResourceRoots?: URI[];
2828
}
2929

3030
export class Webview {
@@ -41,7 +41,6 @@ export class Webview {
4141
private readonly _styleElement: Element,
4242
private readonly _themeService: IThemeService,
4343
private readonly _environmentService: IEnvironmentService,
44-
private readonly _contextService: IWorkspaceContextService,
4544
private readonly _contextViewService: IContextViewService,
4645
private readonly _contextKey: IContextKey<boolean>,
4746
private readonly _findInputContextKey: IContextKey<boolean>,
@@ -321,16 +320,16 @@ export class Webview {
321320
return;
322321
}
323322

324-
registerFileProtocol(contents, 'vscode-core-resource', [
323+
registerFileProtocol(contents, 'vscode-core-resource', () => [
325324
this._environmentService.appRoot
326325
]);
327-
registerFileProtocol(contents, 'vscode-extension-resource', [
326+
registerFileProtocol(contents, 'vscode-extension-resource', () => [
328327
this._environmentService.extensionsPath,
329328
this._environmentService.appRoot,
330329
this._environmentService.extensionDevelopmentPath
331330
]);
332-
registerFileProtocol(contents, 'vscode-workspace-resource',
333-
this._contextService.getWorkspace().folders.map(folder => folder.uri.fsPath)
331+
registerFileProtocol(contents, 'vscode-workspace-resource', () =>
332+
this._options.localResourceRoots.map(uri => uri.fsPath)
334333
);
335334
}
336335

@@ -352,7 +351,6 @@ export class Webview {
352351

353352
this._findStarted = true;
354353
this._webview.findInPage(value, findOptions);
355-
return;
356354
}
357355

358356
/**
@@ -425,11 +423,11 @@ namespace ApiThemeClassName {
425423
function registerFileProtocol(
426424
contents: Electron.WebContents,
427425
protocol: string,
428-
roots: string[]
426+
getRoots: () => string[]
429427
) {
430428
contents.session.protocol.registerFileProtocol(protocol, (request, callback: any) => {
431429
const requestPath = URI.parse(request.url).fsPath;
432-
for (const root of roots) {
430+
for (const root of getRoots()) {
433431
const normalizedPath = normalize(requestPath, true);
434432
if (startsWith(normalizedPath, root + nativeSep)) {
435433
callback({ path: normalizedPath });

src/vs/workbench/parts/update/electron-browser/releaseNotesEditor.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ import { IEnvironmentService } from 'vs/platform/environment/common/environment'
2828
import { onUnexpectedError } from 'vs/base/common/errors';
2929
import { addGAParameters } from 'vs/platform/telemetry/node/telemetryNodeUtils';
3030
import { generateTokensCSSForColorMap } from 'vs/editor/common/modes/supports/tokenization';
31-
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
3231

3332
function renderBody(
3433
body: string,
@@ -64,8 +63,7 @@ export class ReleaseNotesEditor extends WebviewEditor {
6463
@IOpenerService private readonly openerService: IOpenerService,
6564
@IModeService private readonly modeService: IModeService,
6665
@IPartService private readonly partService: IPartService,
67-
@IContextViewService private readonly _contextViewService: IContextViewService,
68-
@IWorkspaceContextService private readonly _contextService: IWorkspaceContextService
66+
@IContextViewService private readonly _contextViewService: IContextViewService
6967
) {
7068
super(ReleaseNotesEditor.ID, telemetryService, themeService, storageService, contextKeyService);
7169
}
@@ -93,7 +91,6 @@ export class ReleaseNotesEditor extends WebviewEditor {
9391
this.partService.getContainer(Parts.EDITOR_PART),
9492
this.themeService,
9593
this.environmentService,
96-
this._contextService,
9794
this._contextViewService,
9895
this.contextKey,
9996
this.findInputFocusContextKey,

0 commit comments

Comments
 (0)