From 6e6ea206066ff8b506d95c1da28a4edb2346c64c Mon Sep 17 00:00:00 2001 From: Simon Graband Date: Mon, 12 Dec 2022 11:17:25 +0100 Subject: [PATCH] [vscode] Add `WebviewOptions.enableForms` Added the optional `enableForms` field to `WebviewOptions`. This allows the `allow-forms` sandbox attribute to be set. Contributed on behalf of STMicroelectronics --- CHANGELOG.md | 1 + .../main/browser/custom-editors/custom-editors-main.ts | 3 ++- packages/plugin-ext/src/main/browser/webview/pre/main.js | 9 ++++++++- packages/plugin-ext/src/main/browser/webview/webview.ts | 1 + packages/plugin-ext/src/main/browser/webviews-main.ts | 9 ++++++--- packages/plugin/src/theia.d.ts | 8 ++++++++ 6 files changed, 26 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fa4febd586bd6..89c8de7ec92d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ ## v1.33.0 - unreleased - [scripts] integrated start-up performance scripts into nightly master build [#10463](https://github.com/eclipse-theia/theia/pull/10463) - Contributed on behalf of STMicroelectronics +- [plugin] added `enableForms` field to `WebviewOptions` [#11983](https://github.com/eclipse-theia/theia/pull/11983) - Contributed on behalf of STMicroelectronics [Breaking Changes:](#breaking_changes_1.33.0) diff --git a/packages/plugin-ext/src/main/browser/custom-editors/custom-editors-main.ts b/packages/plugin-ext/src/main/browser/custom-editors/custom-editors-main.ts index 73511bf102426..6886ab2faab1e 100644 --- a/packages/plugin-ext/src/main/browser/custom-editors/custom-editors-main.ts +++ b/packages/plugin-ext/src/main/browser/custom-editors/custom-editors-main.ts @@ -223,11 +223,12 @@ export class CustomEditorsMainImpl implements CustomEditorsMain, Disposable { const view = await this.widgetManager.getOrCreateWidget(CustomEditorWidget.FACTORY_ID, { id: panelId }); this.webviewsMain.hookWebview(view); view.title.label = title; - const { enableFindWidget, retainContextWhenHidden, enableScripts, localResourceRoots, ...contentOptions } = options; + const { enableFindWidget, retainContextWhenHidden, enableScripts, enableForms, localResourceRoots, ...contentOptions } = options; view.viewColumn = ViewColumn.One; // behaviour might be overridden later using widgetOpenerOptions (if available) view.options = { enableFindWidget, retainContextWhenHidden }; view.setContentOptions({ allowScripts: enableScripts, + allowForms: enableForms, localResourceRoots: localResourceRoots && localResourceRoots.map(root => root.toString()), ...contentOptions, ...view.contentOptions diff --git a/packages/plugin-ext/src/main/browser/webview/pre/main.js b/packages/plugin-ext/src/main/browser/webview/pre/main.js index b7b1e2eef71e4..ec05c6a3663d0 100644 --- a/packages/plugin-ext/src/main/browser/webview/pre/main.js +++ b/packages/plugin-ext/src/main/browser/webview/pre/main.js @@ -479,7 +479,14 @@ const newFrame = document.createElement('iframe'); newFrame.setAttribute('id', 'pending-frame'); newFrame.setAttribute('frameborder', '0'); - newFrame.setAttribute('sandbox', options.allowScripts ? 'allow-scripts allow-forms allow-same-origin allow-downloads' : 'allow-same-origin'); + const sandboxOptions = ['allow-same-origin']; + if (options.allowScripts) { + sandboxOptions.push('allow-scripts', 'allow-downloads'); + } + if (options.allowForms || (options.allowScripts && options.allowForms === undefined)) { + sandboxOptions.push('allow-forms'); + } + newFrame.setAttribute('sandbox', sandboxOptions.join(' ')); if (host.fakeLoad) { // We should just be able to use srcdoc, but I wasn't // seeing the service worker applying properly. diff --git a/packages/plugin-ext/src/main/browser/webview/webview.ts b/packages/plugin-ext/src/main/browser/webview/webview.ts index 1461e2ebfcb43..b40dde18dc422 100644 --- a/packages/plugin-ext/src/main/browser/webview/webview.ts +++ b/packages/plugin-ext/src/main/browser/webview/webview.ts @@ -73,6 +73,7 @@ export const enum WebviewMessageChannels { export interface WebviewContentOptions { readonly allowScripts?: boolean; + readonly allowForms?: boolean; readonly localResourceRoots?: ReadonlyArray; readonly portMapping?: ReadonlyArray; readonly enableCommandUris?: boolean; diff --git a/packages/plugin-ext/src/main/browser/webviews-main.ts b/packages/plugin-ext/src/main/browser/webviews-main.ts index 12d80739d7715..904d5efc4fcf7 100644 --- a/packages/plugin-ext/src/main/browser/webviews-main.ts +++ b/packages/plugin-ext/src/main/browser/webviews-main.ts @@ -67,10 +67,11 @@ export class WebviewsMainImpl implements WebviewsMain, Disposable { this.hookWebview(view); view.viewType = viewType; view.title.label = title; - const { enableFindWidget, retainContextWhenHidden, enableScripts, localResourceRoots, ...contentOptions } = options; + const { enableFindWidget, retainContextWhenHidden, enableScripts, enableForms, localResourceRoots, ...contentOptions } = options; view.options = { enableFindWidget, retainContextWhenHidden }; view.setContentOptions({ allowScripts: enableScripts, + allowForms: enableForms, localResourceRoots: localResourceRoots && localResourceRoots.map(root => root.toString()), ...contentOptions }); @@ -171,9 +172,10 @@ export class WebviewsMainImpl implements WebviewsMain, Disposable { async $setOptions(handle: string, options: WebviewOptions): Promise { const webview = await this.getWebview(handle); - const { enableScripts, localResourceRoots, ...contentOptions } = options; + const { enableScripts, enableForms, localResourceRoots, ...contentOptions } = options; webview.setContentOptions({ allowScripts: enableScripts, + allowForms: enableForms, localResourceRoots: localResourceRoots && localResourceRoots.map(root => root.toString()), ...contentOptions }); @@ -210,10 +212,11 @@ export class WebviewsMainImpl implements WebviewsMain, Disposable { } const options = widget.options; - const { allowScripts, localResourceRoots, ...contentOptions } = widget.contentOptions; + const { allowScripts, allowForms, localResourceRoots, ...contentOptions } = widget.contentOptions; this.updateViewState(widget); await this.proxy.$deserializeWebviewPanel(handle, widget.viewType, title, state, widget.viewState, { enableScripts: allowScripts, + enableForms: allowForms, localResourceRoots: localResourceRoots && localResourceRoots.map(root => URI.parse(root)), ...contentOptions, ...options diff --git a/packages/plugin/src/theia.d.ts b/packages/plugin/src/theia.d.ts index 0422b0d005d7f..788364a80ca39 100644 --- a/packages/plugin/src/theia.d.ts +++ b/packages/plugin/src/theia.d.ts @@ -3768,6 +3768,14 @@ export module '@theia/plugin' { */ readonly enableScripts?: boolean; + /** + * Controls whether forms are enabled in the webview content or not. + * + * Defaults to true if {@link WebviewOptions.enableScripts scripts are enabled}. Otherwise defaults to false. + * Explicitly setting this property to either true or false overrides the default. + */ + readonly enableForms?: boolean; + /** * Controls whether command uris are enabled in webview content or not. *