mirror of
https://github.com/microsoft/vscode.git
synced 2026-07-08 15:55:15 +01:00
Merge pull request #319813 from microsoft/dev/mjbvz/zestful-rat
Block programmatic webview click and keypress re-dispatch events in some cases
This commit is contained in:
@@ -152,6 +152,7 @@ export function reviveWebviewContentOptions(webviewOptions: extHostProtocol.IWeb
|
||||
return {
|
||||
allowScripts: webviewOptions.enableScripts,
|
||||
allowForms: webviewOptions.enableForms,
|
||||
forwardUntrustedKeypressEvents: true, // This is always enabled for extensions
|
||||
enableCommandUris: webviewOptions.enableCommandUris,
|
||||
localResourceRoots: Array.isArray(webviewOptions.localResourceRoots) ? webviewOptions.localResourceRoots.map(r => URI.revive(r)) : undefined,
|
||||
portMapping: webviewOptions.portMapping,
|
||||
|
||||
@@ -1205,6 +1205,7 @@ export class BackLayerWebView<T extends ICommonCellInfo> extends Themable {
|
||||
contentOptions: {
|
||||
allowMultipleAPIAcquire: true,
|
||||
allowScripts: true,
|
||||
forwardUntrustedKeypressEvents: false,
|
||||
localResourceRoots: this.localResourceRootsCache,
|
||||
},
|
||||
extension: undefined,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<meta charset="UTF-8">
|
||||
|
||||
<meta http-equiv="Content-Security-Policy"
|
||||
content="default-src 'none'; script-src 'sha256-q+WTr+fBXpLLE3++yWNaxT6BTWQtsKscoeIlynBRk4E=' 'self'; frame-src 'self'; style-src 'unsafe-inline';">
|
||||
content="default-src 'none'; script-src 'sha256-nXjtuhBilO++r8hfxl5VjEScSmdm07wDAk6jw228DgM=' 'self'; frame-src 'self'; style-src 'unsafe-inline';">
|
||||
|
||||
<!-- Disable pinch zooming -->
|
||||
<meta name="viewport"
|
||||
@@ -533,7 +533,7 @@
|
||||
* @param {MouseEvent} event
|
||||
*/
|
||||
const handleInnerClick = (event) => {
|
||||
if (!event?.view?.document) {
|
||||
if (!event.isTrusted || !event?.view?.document) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -606,7 +606,8 @@
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
hostMessaging.postMessage('did-keydown', {
|
||||
/** @type {import('../webviewMessages').FromWebviewMessage['did-keydown']} */
|
||||
const data = {
|
||||
key: e.key,
|
||||
keyCode: e.keyCode,
|
||||
code: e.code,
|
||||
@@ -614,14 +615,17 @@
|
||||
altKey: e.altKey,
|
||||
ctrlKey: e.ctrlKey,
|
||||
metaKey: e.metaKey,
|
||||
repeat: e.repeat
|
||||
});
|
||||
repeat: e.repeat,
|
||||
isTrusted: e.isTrusted
|
||||
};
|
||||
hostMessaging.postMessage('did-keydown', data);
|
||||
};
|
||||
/**
|
||||
* @param {KeyboardEvent} e
|
||||
*/
|
||||
const handleInnerKeyup = (e) => {
|
||||
hostMessaging.postMessage('did-keyup', {
|
||||
/** @type {import('../webviewMessages').FromWebviewMessage['did-keyup']} */
|
||||
const data = {
|
||||
key: e.key,
|
||||
keyCode: e.keyCode,
|
||||
code: e.code,
|
||||
@@ -629,8 +633,10 @@
|
||||
altKey: e.altKey,
|
||||
ctrlKey: e.ctrlKey,
|
||||
metaKey: e.metaKey,
|
||||
repeat: e.repeat
|
||||
});
|
||||
repeat: e.repeat,
|
||||
isTrusted: e.isTrusted
|
||||
};
|
||||
hostMessaging.postMessage('did-keyup', data);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -123,6 +123,18 @@ export interface WebviewContentOptions {
|
||||
*/
|
||||
readonly allowForms?: boolean;
|
||||
|
||||
/**
|
||||
* Should untrusted key events from the webview be forwarded to the workbench? Defaults to false.
|
||||
*
|
||||
* This blocks keypress events that are triggered by scripts. Webviews should not allow untrusted scripts
|
||||
* to be run, so this is more of a defense-in-depth measure.
|
||||
*
|
||||
* There are valid reasons to enable this, such as when a webview embeds an iframe. In those cases, keyboard events can
|
||||
* be eaten by the iframe, so the inner iframe needs to forward keyboard events to the parent webview,
|
||||
* which then needs to forward them to the workbench.
|
||||
*/
|
||||
readonly forwardUntrustedKeypressEvents?: boolean;
|
||||
|
||||
/**
|
||||
* Set of root paths from which the webview can load local resources.
|
||||
*/
|
||||
@@ -149,6 +161,7 @@ export function areWebviewContentOptionsEqual(a: WebviewContentOptions, b: Webvi
|
||||
a.allowMultipleAPIAcquire === b.allowMultipleAPIAcquire
|
||||
&& a.allowScripts === b.allowScripts
|
||||
&& a.allowForms === b.allowForms
|
||||
&& a.forwardUntrustedKeypressEvents === b.forwardUntrustedKeypressEvents
|
||||
&& equals(a.localResourceRoots, b.localResourceRoots, isEqual)
|
||||
&& equals(a.portMapping, b.portMapping, (a, b) => a.extensionHostPort === b.extensionHostPort && a.webviewPort === b.webviewPort)
|
||||
&& areEnableCommandUrisEqual(a, b)
|
||||
|
||||
@@ -247,9 +247,6 @@ export class WebviewElement extends Disposable implements IWebviewElement, Webvi
|
||||
}));
|
||||
|
||||
this._register(this.on('did-keydown', (data) => {
|
||||
// Electron: workaround for https://github.com/electron/electron/issues/14258
|
||||
// We have to detect keyboard events in the <webview> and dispatch them to our
|
||||
// keybinding service because these events do not bubble to the parent window anymore.
|
||||
this.handleKeyEvent('keydown', data);
|
||||
}));
|
||||
|
||||
@@ -713,7 +710,18 @@ export class WebviewElement extends Disposable implements IWebviewElement, Webvi
|
||||
}
|
||||
}
|
||||
|
||||
private shouldForwardKeyEvent(event: KeyEvent): boolean {
|
||||
return event.isTrusted || !!this._content.options.forwardUntrustedKeypressEvents;
|
||||
}
|
||||
|
||||
private handleKeyEvent(type: 'keydown' | 'keyup', event: KeyEvent) {
|
||||
if (!this.shouldForwardKeyEvent(event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Electron: workaround for https://github.com/electron/electron/issues/14258
|
||||
// We have to detect keyboard events in the <webview> and dispatch them to our
|
||||
// keybinding service because these events do not bubble to the parent window anymore.
|
||||
// Create a fake KeyboardEvent from the data provided
|
||||
const emulatedKeyboardEvent = new KeyboardEvent(type, event);
|
||||
// Force override the target
|
||||
|
||||
@@ -7,18 +7,19 @@ import type { IMouseWheelEvent } from '../../../../base/browser/mouseEvent.js';
|
||||
import type { WebviewStyles } from './webview.js';
|
||||
|
||||
type KeyEvent = {
|
||||
key: string;
|
||||
keyCode: number;
|
||||
code: string;
|
||||
shiftKey: boolean;
|
||||
altKey: boolean;
|
||||
ctrlKey: boolean;
|
||||
metaKey: boolean;
|
||||
repeat: boolean;
|
||||
readonly key: string;
|
||||
readonly keyCode: number;
|
||||
readonly code: string;
|
||||
readonly shiftKey: boolean;
|
||||
readonly altKey: boolean;
|
||||
readonly ctrlKey: boolean;
|
||||
readonly metaKey: boolean;
|
||||
readonly repeat: boolean;
|
||||
readonly isTrusted: boolean;
|
||||
}
|
||||
|
||||
type WebViewDragEvent = {
|
||||
shiftKey: boolean;
|
||||
readonly shiftKey: boolean;
|
||||
}
|
||||
|
||||
export type FromWebviewMessage = {
|
||||
|
||||
@@ -184,6 +184,7 @@ export function restoreWebviewOptions(options: SerializedWebviewOptions): Webvie
|
||||
export function restoreWebviewContentOptions(options: SerializedWebviewOptions): WebviewContentOptions {
|
||||
return {
|
||||
...options,
|
||||
forwardUntrustedKeypressEvents: options.forwardUntrustedKeypressEvents ?? true, // default to true for backwards compatibility
|
||||
localResourceRoots: options.localResourceRoots?.map(uri => reviveUri(uri)),
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user