Skip to content

Fix copying webview image via context menu (#292567)#320234

Open
Parasaran-Python wants to merge 1 commit into
microsoft:mainfrom
Parasaran-Python:fix/292567-webview-copy-image
Open

Fix copying webview image via context menu (#292567)#320234
Parasaran-Python wants to merge 1 commit into
microsoft:mainfrom
Parasaran-Python:fix/292567-webview-copy-image

Conversation

@Parasaran-Python
Copy link
Copy Markdown
Contributor

Fixes #292567

Problem

Right-clicking an image in a webview and choosing Copy from the context menu copied nothing to the clipboard. The only workaround was to manually select the image first and then copy.

The webview context-menu Copy action runs document.execCommand('copy'), which only copies the current selection. A right-clicked image creates no selection, so execCommand('copy') succeeds but copies empty content — the image never reaches the clipboard.

Fix

In the webview preload (src/vs/workbench/contrib/webview/browser/pre/index.html):

  • Remember the image element the context menu was opened on.
  • When Copy is invoked on it, write the image bitmap to the clipboard directly instead of relying on execCommand('copy').

The copy runs inside the content frame's window, where the clipboard-write permission and the frame's origin apply. It draws the image to a canvas and uses navigator.clipboard.write([new ClipboardItem(...)]), with fallbacks:

  1. Canvas → image/png (primary).
  2. Re-fetch the image bytes and write the resulting blob (handles cross-origin/tainted-canvas images).
  3. writeText(src) as a last resort.

A short focus-retry loop handles the clipboard API's requirement that the document be focused (the copy can fire while focus is still returning to the webview). This mirrors the existing, proven image-copy implementation in the Markdown preview, generalized so every webview benefits with no extension changes.

The inline-script CSP hash in the preload is updated to match the new script content.

Testing

Verified with the reporter's reproduction extension (vscode-image-copy-to-clipboard-webview): right-click image → Copy → paste now yields the image bitmap, without the select-first workaround. Also confirmed copying selected text and non-image right-clicks behave as before, and the webview loads with no CSP violations.

Copilot AI review requested due to automatic review settings June 6, 2026 14:36
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds support for copying images from the webview context menu by writing the image bitmap to the clipboard (with fallbacks), and updates the CSP to match the changed inline script.

Changes:

  • Updated CSP script-src hash for the modified inline script
  • Tracked the image element under the last context-menu invocation
  • Implemented image-to-clipboard copy flow (canvas → refetch blob → copy URL)

Comment thread src/vs/workbench/contrib/webview/browser/pre/index.html
Comment thread src/vs/workbench/contrib/webview/browser/pre/index.html
Comment thread src/vs/workbench/contrib/webview/browser/pre/index.html
Comment thread src/vs/workbench/contrib/webview/browser/pre/index.html
@Parasaran-Python Parasaran-Python force-pushed the fix/292567-webview-copy-image branch from e719746 to bdfadde Compare June 6, 2026 14:42
Right-clicking an image in a webview and choosing "Copy" copied nothing. The
webview context menu "Copy" action runs `document.execCommand('copy')`, which
only copies the current selection; a right-clicked image has no selection, so
nothing was placed on the clipboard.

Remember the image the context menu was opened on, and when "Copy" is invoked
on it, write the image bitmap to the clipboard directly. The copy runs inside
the content frame's window (where the `clipboard-write` permission and origin
apply): it draws the image to a canvas and uses
`navigator.clipboard.write([new ClipboardItem(...)])`, falling back to
re-fetching the image bytes (for cross-origin/tainted images) and finally to
copying the image url as text. A short focus-retry loop handles the clipboard
API's requirement that the document be focused.

Also updates the inline-script CSP hash to match the new preload script.
@Parasaran-Python Parasaran-Python force-pushed the fix/292567-webview-copy-image branch from bdfadde to ed907af Compare June 6, 2026 15:19
@Parasaran-Python Parasaran-Python requested a review from Copilot June 6, 2026 15:51
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 4 comments.

Comment on lines +111 to +118
const clipboard = frameWindow.navigator.clipboard;
if (!clipboard || typeof ClipboardItem === 'undefined') {
return;
}

try {
await clipboard.write([new ClipboardItem({
'image/png': new Promise((resolve, reject) => {
Comment on lines +1264 to +1268
// Remember if the context menu was opened on an image so that the "Copy" action
// can copy the image even when there is no active selection.
const targetElement = /** @type {HTMLElement | null} */ (e.target);
lastContextMenuImageTarget = /** @type {HTMLImageElement | undefined} */ (targetElement?.closest?.('img') ?? undefined);

Comment on lines +1356 to +1364
if (data === 'copy' && contentWindow && lastContextMenuImageTarget && lastContextMenuImageTarget.ownerDocument === contentDocument) {
const image = lastContextMenuImageTarget;
lastContextMenuImageTarget = undefined;
const selection = contentDocument.getSelection();
if (!selection || selection.isCollapsed) {
copyImageToClipboard(contentWindow, image);
return;
}
}
Comment on lines +119 to +122
const canvas = frameDocument.createElement('canvas');
canvas.width = image.naturalWidth;
canvas.height = image.naturalHeight;
const context = canvas.getContext('2d');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Can't copy webview image to clipboard

2 participants