Closed Bug 1619947 Opened 4 years ago Closed 3 years ago

Implement ClipboardItem

Categories

(Core :: DOM: Events, enhancement)

enhancement
Not set
normal

Tracking

()

RESOLVED FIXED
87 Branch
Tracking Status
firefox87 --- fixed

People

(Reporter: tt, Assigned: evilpie)

References

(Blocks 1 open bug, )

Details

(Keywords: dev-doc-complete, parity-chrome)

Attachments

(4 files, 2 obsolete files)

We should implement ClipboardItem for Clipboard API.

Spec: https://w3c.github.io/clipboard-apis/

What we have at this moment: https://searchfox.org/mozilla-central/rev/d5b34cc8872177d3ee071e06f787c2a14268595b/dom/webidl/Clipboard.webidl

Wpt expected results at this moment: https://searchfox.org/mozilla-central/rev/d5b34cc8872177d3ee071e06f787c2a14268595b/testing/web-platform/meta/clipboard-apis/async-interfaces.https.html.ini

(I found bug 1619723 while I was trying to find if we have had a bug for this. I'm not sure if it's the same bug. Please feel free to mark this as a dup if someone thinks so)

Yeah. This is basically a dupe of bug 1619723, but this also has a bit more info.

Blocks: 1619251

I started trying to implement this and I think Chrome doesn't actually implement what the spec says?
The ClipboardItem constructor is defined as

constructor(record<DOMString, ClipboardItemData> items, optional ClipboardItemOptions options = {});

and ClipboardItemData is defined as

typedef Promise<ClipboardItemDataType> ClipboardItemData;

So a valid constructor call would look something like

new ClipboardItem({"text/plain": Promise.resolve(new Blob(["hey"]))});

However Chrome seems to expect

new ClipboardItem({"text/plain": new Blob(["hey"])});

This is also what is documented on MDN: https://developer.mozilla.org/en-US/docs/Web/API/ClipboardItem

Anne do you know what is going?

Flags: needinfo?(annevk)

Passing a normal Blob must be fine, as the IDL layer should call Promise.resolve for them. See also: https://heycam.github.io/webidl/#es-promise

Okay, but passing a Promise wrapping a Blob doesn't work in Chrome. And looking at Chrome's IDL they don't use a Promise in IDL either.

  [RaisesException] constructor(record<DOMString, Blob> items,
              optional ClipboardItemOptions options = {});

Additionally Chrome's implementation also doesn't support presentationStyle, lastModified, delayed or createDelayed. On the other hand they have something called raw, which seems to be disabled by default.

Honestly their interface definition would probably be a lot easier to implement, but it seems quite unfortunate that the specification is completely ignored.

So, I finished an implemented of clipboard.write that can handle Blob promises. I also re0implemented clipboard.writeText in terms of write using a sequence of ClipboardItems.

Something I noticed however is that ClipboardItemDataType is (DOMString or Blob), but ClipboardItem.getType returns Promise<Blob> not sure how that is supposed to work. Are we supposed to implicitly convert the promises? I can't actually find any specification of how ClipboardItem is supposed to work in that regard.

So finally probably the biggest issue I've run into: nsIClipboard doesn't actually seems able to handle multiple transferables. That means only a single type will ever end up on the clipboard. That seems like a very serious limitation and makes all of this work of handling multiple items of multiple types sort of pointless. Am I missing something?
We write all data to index 0 so this actually probably works.

Oh and the current implementation doesn't actually work for images and probably non-text. Not sure how possible it will be to solve that.

Assignee: nobody → evilpies

Depends on D97860

It seems like Kagami cleared my needinfo, thanks! I think we should aim for Safari-parity in terms of functionality (see also comments in bugs about read() and execCommand("paste") elsewhere) and file issues against the specification whenever it doesn't allow for Safari-parity or is nonsensical.

(It would also be ideal to make progress on bug 1676643 to ensure browsers stay consistent, but asking that from volunteers seems too much. Hopefully we can work on that next year.)

Flags: needinfo?(annevk)
See Also: 1619723
Attachment #9189426 - Attachment is obsolete: true

Nika already pointed out that holding the MozPromise in ItemEntry could leak

Attachment #9189383 - Attachment description: Bug 1619947 - [WIP] Implement ClipboardItem skeleton code → Bug 1619947 - Implement ClipboardItem skeleton code
Attachment #9189423 - Attachment description: Bug 1619947 - [WIP] Reimplement navigator.clipboard.write to use ClipboardItem → Bug 1619947 - Reimplement navigator.clipboard.write to use ClipboardItem
Attachment #9190028 - Attachment description: Bug 1619947 - [WIP] Update tests → Bug 1619947 - Update tests
Attachment #9192225 - Attachment is obsolete: true
Blocks: 1688279

Depends on D97854

Attachment #9190028 - Attachment description: Bug 1619947 - Update tests → Bug 1619947 - Update tests for ClipboardItem

For documentation purposes:

  • Firefox now supports ClipboardItem behind the pref dom.events.asyncClipboard.clipboardItem, which is disabled even on Nightly.
  • navigator.clipboard.write now uses a sequence/list of ClipboardItems instead of DataTransfer. The pref changed from dom.events.asyncClipboard.dataTransfer to dom.events.asyncClipboard.clipboardItem. Also disabled by default.
Pushed by evilpies@gmail.com:
https://hg.mozilla.org/integration/autoland/rev/ecc8d26d5e8a
Implement ClipboardItem skeleton code r=nika
https://hg.mozilla.org/integration/autoland/rev/2c1a7aba4f05
Make MozPromise::All work correctly with const r=bwc
https://hg.mozilla.org/integration/autoland/rev/6a5dba78faa3
Reimplement navigator.clipboard.write to use ClipboardItem r=nika
https://hg.mozilla.org/integration/autoland/rev/5029740559a7
Update tests for ClipboardItem r=nika
Created web-platform-tests PR https://github.com/web-platform-tests/wpt/pull/27311 for changes under testing/web-platform/tests
Upstream PR merged by moz-wptsync-bot

Rumyra documented all this stuff really nicely in https://github.com/mdn/content/issues/2514.

:evilpie: seeing the tests modified in https://bugzilla.mozilla.org/attachment.cgi?id=9190028, is ClipboardItem's constructor already supposed to work with Promises? Please see https://jsfiddle.net/j76wfzt3/ for an example and some more links to Safari/Chromium issues.

Currently, it doesn't work, also with dom.events.asyncClipboard.clipboardItem set to true.
After clicking the "copy" button, the clipboard contains

"[object Promise]"

instead of

"<rect width="300" height="100"
style="fill:rgb(0,0,255);stroke-width:3;stroke:rgb(0,0,0)"></rect>
Sorry, your browser does not support inline SVG."

Question came up because of https://groups.google.com/forum/?utm_medium=email&utm_source=footer#!msg/compat2021/9yrdEPyBygQ/B685_XSwFAAJ.

Flags: needinfo?(evilpies)

No we don't support Promises in the ClipboardItem constructor.

Flags: needinfo?(evilpies)

(In reply to Tom Schuster [:evilpie] from comment #26)

No we don't support Promises in the ClipboardItem constructor.

Thanks. Presumably, it would make sense to throw an error?

Then, the jsfiddle mentioned in #c25 would run into the catch case, which works. See https://jsfiddle.net/80hq96ym/ for an adaptation of the above jsfiddle.

That is, the example of https://groups.google.com/forum/?utm_medium=email&utm_source=footer#!msg/compat2021/9yrdEPyBygQ/B685_XSwFAAJ would write the correct content to the clipboard instead of "[object Promise]".

(In reply to Mirko Brodesser (:mbrodesser) from comment #27)

(In reply to Tom Schuster [:evilpie] from comment #26)

No we don't support Promises in the ClipboardItem constructor.

Thanks. Presumably, it would make sense to throw an error?

No. This is just how WebIDL behave. Chrome throws when passing a Promise, because they only support Blob and not DOMString. We support DOMString so we implicitly coerce to strings.

Then, the jsfiddle mentioned in #c25 would run into the catch case, which works. See https://jsfiddle.net/80hq96ym/ for an adaptation of the above jsfiddle.

That is, the example of https://groups.google.com/forum/?utm_medium=email&utm_source=footer#!msg/compat2021/9yrdEPyBygQ/B685_XSwFAAJ would write the correct content to the clipboard instead of "[object Promise]".

I am going to open a new bug for adding Promise support. I think Safari should in theory support passing a normal Blob instead of Promise.resolve(blob), because the former should really automatically convert to the later.

Anyway the right solution here is for Chrome to implement the API properly or for Safari and the spec the change. We will presumably not ship this API before those questions are resolved.

Blocks: 1712122
Blocks: 1778971

(In reply to Tom Schuster [:evilpie] from comment #19)

For documentation purposes:

  • Firefox now supports ClipboardItem behind the pref dom.events.asyncClipboard.clipboardItem, which is disabled even on Nightly.
  • navigator.clipboard.write now uses a sequence/list of ClipboardItems instead of DataTransfer. The pref changed from dom.events.asyncClipboard.dataTransfer to dom.events.asyncClipboard.clipboardItem. Also disabled by default.

What are the current obstacles to dom.events.asyncClipboard.clipboardItem being enabled by default?

It'd be nice if dom.events.asyncClipboard.clipboardItem would be enabled by default. ClipboardItem is required to copy images to clipboard, and I have been using it with the pref enabled for a while now without any issues.

Is there an bug to track this enablement or should we re-open this one until it is?

You need to log in before you can comment on or make changes to this bug.