Change:
*  Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ <del> import { $ } from 'vs/base/browser/dom'; </del> <ins> import { isWebKit } from 'vs/base/browser/browser'; import { $, addDisposableListener } from 'vs/base/browser/dom'; import { DeferredPromise } from 'vs/base/common/async'; import { Disposable } from 'vs/base/common/lifecycle'; </ins> import { URI } from 'vs/base/common/uri'; import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; <ins> import { ILayoutService } from 'vs/platform/layout/browser/layoutService'; import { ILogService } from 'vs/platform/log/common/log'; </ins> <del> export class BrowserClipboardService implements IClipboardService { </del> <ins> export class BrowserClipboardService extends Disposable implements IClipboardService { </ins> declare readonly _serviceBrand: undefined; private readonly mapTextToType = new Map<string, string>(); // unsupported in web (only in-memory) <ins> constructor( @ILayoutService private readonly layoutService: ILayoutService, @ILogService private readonly logService: ILogService) { super(); if (isWebKit) { this.installWebKitWriteTextWorkaround(); } } private webKitPendingClipboardWritePromise: DeferredPromise<string> | undefined; // In Safari, it has the following note: // // "The request to write to the clipboard must be triggered during a user gesture. // A call to clipboard.write or clipboard.writeText outside the scope of a user // gesture(such as "click" or "touch" event handlers) will result in the immediate // rejection of the promise returned by the API call." // From: https://webkit.org/blog/10855/async-clipboard-api/ // // Since extensions run in a web worker, and handle gestures in an asynchronous way, // they are not classified by Safari as "in response to a user gesture" and will reject. // // This function sets up some handlers to work around that behavior. private installWebKitWriteTextWorkaround(): void { const handler = () => { const currentWritePromise = new DeferredPromise<string>(); // Cancel the previous promise since we just created a new one in response to this new event if (this.webKitPendingClipboardWritePromise && !this.webKitPendingClipboardWritePromise.isSettled) { this.webKitPendingClipboardWritePromise.cancel(); } this.webKitPendingClipboardWritePromise = currentWritePromise; // The ctor of ClipboardItem allows you to pass in a promise that will resolve to a string. // This allows us to pass in a Promise that will either be cancelled by another event or // resolved with the contents of the first call to this.writeText. // see https://developer.mozilla.org/en-US/docs/Web/API/ClipboardItem/ClipboardItem#parameters navigator.clipboard.write([new ClipboardItem({ 'text/plain': currentWritePromise.p, })]).catch(async err => { if (!(err instanceof Error) || err.name !== 'NotAllowedError' || !currentWritePromise.isRejected) { this.logService.error(err); } }); }; this._register(addDisposableListener(this.layoutService.container, 'click', handler)); this._register(addDisposableListener(this.layoutService.container, 'keydown', handler)); } </ins> async writeText(text: string, type?: string): Promise<void> { // With type: only in-memory is supported

Discussion:
<!-- Do Not Delete This! bugreporttemplate --<!-- Please read our Rules of Conduct: --<!-- Please search existing issues to avoid creating duplicates. --<!-- Also please test using the latest insiders build to make sure your issue has not already been fixed: --<!-- Use Help Report Issue to prefill these. --- VSCode Version: Codespaces OS Version: MacOS Catalina and iPadOS 13 Steps to Reproduce: It seems the Clipboard API is not working, at least using Safari an extension using the which as documented, should be used on Remote Development: Codespaces and install the extension (My extension does exactly that) its command , which will select the word where the cursor is located and should copy the selected text to clipboard to other location command (or use shortcut) ’t work: instead of pasting the the newly selected/copied text, it pastes the previous clipboard content (not created using the extension) I tested on iPadOS 13 and MacOS Catalina and it fails. I tested on Edge (Chromium) and it works perfectly (I guess it should work on Chrome too) I didn’t test on Firefox (yet). BTW, I tried to debug my extension on Codespaces (on iPadOS), but it seems not possible/supported. I’m able to build the extension and hit the Debug button. The Debug toolbar appears but no window/tab appears. Is there a way to debug VSCode extensions right from Codespaces?. <!-- Launch with to check. --Does this issue occur when all extensions are disabled?: Yes
Updated the description and comments. Testing on Edge (Chromium) worked just fine.
Yes, it should open a new tab. Maybe it was blocked?
Hi , Sorry about not updating the description properly. I tested debugging again later (yesterday) and indeed it was blocked by Safari, but only on Desktop (macOS Catalina). On iPadOS, it doesn't display anything (neither a blocked windows warning/icon), so I couldn't debug, yet. I'll update the description. Thanks
I think the safari label should remain, because the issue is happening using Safari, both on MacOS and iPadOS.
It seems the Clipboard API is coming to Safari , we should reevaluate once it lands in Safari stable.
I tested the improvements of api in the latest Safari Technology Preview but it doesn't solve this particular problem.

The copy/paste request is coming from the extension host instead of user action, Safari will then block it.
Just hit this in
verification steps: Open on Safari (bonus points for it being on iPad but it doesn't matter) Install the GHPR extension Go to a random line in a file Run the command Your clipboard should contain the copied permalink now. Bonus points: make sure Edge or Chrome still also work.
Hi , I’m glad to report that it is also working on iPadOS 15.2 and MacOS Big Sur I just tested my Copy Word extension (the reason why I opened this issue) and it is working perfectly. Thank you!