Re: [w3c/clipboard-apis] Add clipboard IDL description. (#158)

@mbrodesser requested changes on this pull request.

Thanks for continuing working on this. It's going in the right direction.

>  
-    Promise<Blob> getType(DOMString type);
-  };
+   dictionary ClipboardItemOptions {
+   PresentationStyle presentationStyle = "unspecified";
+   };
+  </pre>
+  <p><dfn export for=ClipboardItem id=concept-clipboard-item>ClipboardItem</dfn></p>
+  The [=ClipboardItem=] object has MIME types that are in the {{ClipboardItem/types}} list, and [=Blob=]s corresponding to the {{ClipboardItem/types}}.

It could be clearer to phrase this along the lines: A `ClipboardItem` contains multiple representations. Each representation consists of a MIME type and a corresponding `DOMString` or Blob.

>  
-    Promise&lt;Blob> getType(DOMString type);
-  };
+   dictionary ClipboardItemOptions {
+   PresentationStyle presentationStyle = "unspecified";
+   };
+  </pre>
+  <p><dfn export for=ClipboardItem id=concept-clipboard-item>ClipboardItem</dfn></p>
+  The [=ClipboardItem=] object has MIME types that are in the {{ClipboardItem/types}} list, and [=Blob=]s corresponding to the {{ClipboardItem/types}}.
+  It has a mapping of the MIME types in {{DOMString}} format and a [=Blob=] corresponding to the MIME types that contains the actual payload.
+  There can be multiple [=ClipboardItem=]s as each [=ClipboardItem=] represents contents of a clipboard, and there can be multiple clipboards supported on a platform such as iOS/iPadOS.

Since this is about multiple `ClipboardItem`s, that information seems to belong to the "Clipboard Interface" section (7.3, currently).

Moreover, the wording is not entirely accurate. On iOS, "multiple clipboards" (it seems "multiple clipboard items" is more accurate) seem to mean something different than multiple clipboards on Linux.
On the former, multiple clipboard items may belong to the same group of user-selected items, see https://github.com/w3c/clipboard-apis/issues/93#issuecomment-853727779.
On the latter, the multiple clipboards don't necessarily correspond to the same user selection. E.g., when pressing Ctrl+c, one clipboard is filled, and when selecting text with the mouse, another clipboard [readable by clicking the middle mouse button] is filled.
The intention of multiple clipboard items is to cover the iOS case, but exclude the Linux case.

> +  A web author needs to create a |data| which is a [=ClipboardItems=] object in order to write content to multiple clipboards using the {{Clipboard/write(data)}} method. {{Clipboard/read()}} returns a [=Promise=] to [=ClipboardItems=] object
+  that represents contents of multiple clipboards. A [=ClipboardItem=] can be read from [=ClipboardItems=], which then can be used to read a specific |type| using {{ClipboardItem/getType(type)}}.

This seems to belong to the "Clipboard Interface" section (currently 7.3).

> +  <dl class=note>
+   <dt><code><var>clipboardItem</var> = new ClipboardItem([<var>items</var>, <var>options</var>])</code>
+   <dd>
+   Creates a new [=ClipboardItem=] object. <var>items</var> are used to fill its MIME types and [=Promise=]s to [=Blob=]s corresponding to the MIME types, <var>options</var> can be used to fill its {{ClipboardItemOptions}},
+   as per the example below.
+
+   <pre class="example javascript">
+   const format1 = 'text/plain';
+   const promise_text_blob = Promise.resolve(new Blob(['hello'], {type: format1}));
+   const clipboardItemInput = new ClipboardItem(
+    {[format1]: promise_text_blob},
+    {options: "unspecified"});
+   </pre>
+
+   <dt><code><var>clipboardItem</var>.getType(<var>type</var>)</code>
+   <dd><p>Returns a  [=Promise=] to the [=Blob=] corresponding to the <var>type</var>.</p>

"corresponding to `type`"

> +  Issue: Add definition to clarify what {{ClipboardItem/createDelayed()}} method does. From the discussions it looks like a Windows/Mac only feature where the
+  platform supports writing of the data to the system clipboard in a delayed fashion so the system clipboard can request data on-demand.
+  See https://docs.microsoft.com/en-us/windows/win32/dataxchg/clipboard-operations#delayed-rendering
+
+  <h4 attribute for=ClipboardItem lt=presentationStyle>presentationStyle</h4>
+  <p>It is an <a href=https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#enumerated-attribute>enumerated attribute</a> whose keywords are the <code>string</code>, <code>unspecified</code>, <code>inline</code> and <code>attachment</code>.
+  
+  Note: {{ClipboardItem/presentationStyle}} helps distinguish between "inline" data(e.g. selecting text on a web page and copying), vs. file-like data (e.g. copying a plain text file).
+      This difference is used to provide a hint when writing to the system pasteboard on iOS/iPadOS. This allows apps like Notes to insert a file attachment when copying a plain text file from the Files app, but insert text inline when
+      copying a selected piece of plain text from another app. In both cases, the MIME type in the pasteboard would be text/plain. This is used for both reading and writing.
+  </p>
+
+  <p>{{ClipboardItem/presentationStyle}} getter steps are to return [=this=]'s {{ClipboardItem/presentationStyle}}</p>
+
+  Issue: Currently {{ClipboardItem/lastModified}} is not supported in Chromium and Safari, Should we remove it?
+

These are not issues of `presentationStyle`, but from `ClipboardItem`, please move them.

> +  platform supports writing of the data to the system clipboard in a delayed fashion so the system clipboard can request data on-demand.
+  See https://docs.microsoft.com/en-us/windows/win32/dataxchg/clipboard-operations#delayed-rendering
+
+  <h4 attribute for=ClipboardItem lt=presentationStyle>presentationStyle</h4>
+  <p>It is an <a href=https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#enumerated-attribute>enumerated attribute</a> whose keywords are the <code>string</code>, <code>unspecified</code>, <code>inline</code> and <code>attachment</code>.
+  
+  Note: {{ClipboardItem/presentationStyle}} helps distinguish between "inline" data(e.g. selecting text on a web page and copying), vs. file-like data (e.g. copying a plain text file).
+      This difference is used to provide a hint when writing to the system pasteboard on iOS/iPadOS. This allows apps like Notes to insert a file attachment when copying a plain text file from the Files app, but insert text inline when
+      copying a selected piece of plain text from another app. In both cases, the MIME type in the pasteboard would be text/plain. This is used for both reading and writing.
+  </p>
+
+  <p>{{ClipboardItem/presentationStyle}} getter steps are to return [=this=]'s {{ClipboardItem/presentationStyle}}</p>
+
+  Issue: Currently {{ClipboardItem/lastModified}} is not supported in Chromium and Safari, Should we remove it?
+
+  Issue: Delay rendering support has not been added to Chromium and Safari so {{ClipboardItem/delayed}} is unused.

It's the first time mentioned in the spec that `delayed` is about delayed rendering. I wonder if, like `lastModified`, it should be considered for removal, too.

>  
-    Promise&lt;Blob> getType(DOMString type);
-  };
+   dictionary ClipboardItemOptions {
+   PresentationStyle presentationStyle = "unspecified";
+   };
+  </pre>
+  <p><dfn export for=ClipboardItem id=concept-clipboard-item>ClipboardItem</dfn></p>
+  The [=ClipboardItem=] object has MIME types that are in the {{ClipboardItem/types}} list, and [=Blob=]s corresponding to the {{ClipboardItem/types}}.
+  It has a mapping of the MIME types in {{DOMString}} format and a [=Blob=] corresponding to the MIME types that contains the actual payload.
+  There can be multiple [=ClipboardItem=]s as each [=ClipboardItem=] represents contents of a clipboard, and there can be multiple clipboards supported on a platform such as iOS/iPadOS.
+  A web author needs to create a |data| which is a [=ClipboardItems=] object in order to write content to multiple clipboards using the {{Clipboard/write(data)}} method. {{Clipboard/read()}} returns a [=Promise=] to [=ClipboardItems=] object
+  that represents contents of multiple clipboards. A [=ClipboardItem=] can be read from [=ClipboardItems=], which then can be used to read a specific |type| using {{ClipboardItem/getType(type)}}.
+  <dl class=note>

I'm not sure whether that information belongs in a note. @annevk: do you know?

>  
-  dictionary ClipboardItemOptions {
-    PresentationStyle presentationStyle = "unspecified";
+   1. Let |p| be a new [=Promise=].
+
+   1. If |type| is not listed in the [=mandatory data types=] list, then reject |p| with a "The type was not found" DOMException.
+
+   1. Let |data| be the result of reading the |type| from the [=system clipboard=].

What if a `ClipboardItem` already contains a resolved promise, as in the example above? I'm confused, when data is read from the system clipboard and when not.

> +
+   1. If |type| is not listed in the [=mandatory data types=] list, then reject |p| with a "The type was not found" DOMException.
+
+   1. Let |data| be the result of reading the |type| from the [=system clipboard=].
+
+   1. Let |blobData| be the |data| represented as a [=Blob=].
+
+   1. Resolve |p| with |blobData|.
+
+  <h4 typedef>ClipboardItemDataType</h4>
+  <p>
+    It is a {{DOMString}} or [=Blob=] type. This contains the payload corresponding to the MIME type while creating a [=ClipboardItem=] object.
+  </p>
+  <h4 typedef>ClipboardItemData</h4>
+  <p>
+   It is a [=Promise=] to the {{ClipboardItemDataType}}.

Simpler: A `Promise` to a `ClipboardItemDataType`. Also consider "a" vs "the".

> +
+  <h4 typedef>ClipboardItemDataType</h4>
+  <p>
+    It is a {{DOMString}} or [=Blob=] type. This contains the payload corresponding to the MIME type while creating a [=ClipboardItem=] object.
+  </p>
+  <h4 typedef>ClipboardItemData</h4>
+  <p>
+   It is a [=Promise=] to the {{ClipboardItemDataType}}.
+  </p>
+
+ <h3 id="clipboard-interface">Clipboard Interface</h3>
+
+  <pre class="idl" data-highlight="webidl">
+  typedef sequence&lt;ClipboardItem> ClipboardItems;
+
+  [SecureContext, Exposed=Window] interface Clipboard : EventTarget {

For the record: I'm unfamiliar with `SecureContext, Expose`, so not sure whether those make sense. CC @annevk 

> +  <h4 typedef>ClipboardItemDataType</h4>
+  <p>
+    It is a {{DOMString}} or [=Blob=] type. This contains the payload corresponding to the MIME type while creating a [=ClipboardItem=] object.
+  </p>
+  <h4 typedef>ClipboardItemData</h4>
+  <p>
+   It is a [=Promise=] to the {{ClipboardItemDataType}}.
+  </p>
+
+ <h3 id="clipboard-interface">Clipboard Interface</h3>
+
+  <pre class="idl" data-highlight="webidl">
+  typedef sequence&lt;ClipboardItem> ClipboardItems;
+
+  [SecureContext, Exposed=Window] interface Clipboard : EventTarget {
+    Promise&lt;ClipboardItems> read();

Nit-picking: not sure whether `&gt;` should be used instead of ">".

> @@ -632,11 +711,15 @@ urlPrefix: https://w3c.github.io/FileAPI/#dfn-; type: dfn;
    1. Run the following steps [=in parallel=]:
 
     1. Let |r| be the result of running [=check clipboard read permission=] [=in parallel=]
+     Note: Clipboard permission is not supported on Safari. However, the read() method must be called inside

This is not rendered as a note, the below notes are. Don't know why.

> @@ -632,11 +711,15 @@ urlPrefix: https://w3c.github.io/FileAPI/#dfn-; type: dfn;
    1. Run the following steps [=in parallel=]:
 
     1. Let |r| be the result of running [=check clipboard read permission=] [=in parallel=]
+     Note: Clipboard permission is not supported on Safari. However, the read() method must be called inside
+     a user gesture event and the user must select the paste option from the native context menu that pops up
+     when read() is called from JS, otherwise, the promise will be rejected.
 
     1. If |r| is not "granted", then reject |p| with a "NotAllowedError" DOMException

Not sure if "NotAllowedError" etc. could be referenced.

>  
     1. If |r| is not "granted", then reject |p| with a "NotAllowedError" DOMException
 
-    1. Let |data| be a copy of the [=system clipboard data=] represented as
-     a sequence of {{ClipboardItem}}s.
+    1. Let |data| be a copy of the [=system clipboard data=] represented as [=ClipboardItems=]. For the MIME types defined in the [=mandatory data types=] list, |data| contains the sanitized copy of text/html format, but image/png format has unsanitized payload to preserve meta data.
+
+     Note: Currently in Chromium, only one [=ClipboardItem=] object is supported for reading and writing via [=clipboard=] object.

Nit-picking: "via the". There is only one clipboard object.

> @@ -701,17 +784,28 @@ urlPrefix: https://w3c.github.io/FileAPI/#dfn-; type: dfn;
 
     1. If |r| is not "granted", then reject |p| with a "NotAllowedError" DOMException
 

What about clipboard write permissions on macOS? CC @rniwa 

> @@ -701,17 +784,28 @@ urlPrefix: https://w3c.github.io/FileAPI/#dfn-; type: dfn;
 
     1. If |r| is not "granted", then reject |p| with a "NotAllowedError" DOMException
 
-    1. Let |cleanItemList| be an empty sequence&lt;{{Blob}}>.
+    1. Let |itemList| and |cleanItemList| be an empty sequence&lt;{{Blob}}>.
+
+    1. For each |itemData| in |data|:

It seems renaming `itemData` to `clipboardItem` would be clearer.

> @@ -701,17 +784,28 @@ urlPrefix: https://w3c.github.io/FileAPI/#dfn-; type: dfn;
 
     1. If |r| is not "granted", then reject |p| with a "NotAllowedError" DOMException
 
-    1. Let |cleanItemList| be an empty sequence&lt;{{Blob}}>.
+    1. Let |itemList| and |cleanItemList| be an empty sequence&lt;{{Blob}}>.
+
+    1. For each |itemData| in |data|:
+
+     1. For each |item| in |itemData|:
+      1. If [=Promise=] to {{Blob}} in |item| is rejected, then throw "Promises to Blobs were rejected." DOMException.

What if `item` contained a `DOMString`? Somewhere a conversion to a `Blob` would have to happen.

> @@ -701,17 +784,28 @@ urlPrefix: https://w3c.github.io/FileAPI/#dfn-; type: dfn;
 
     1. If |r| is not "granted", then reject |p| with a "NotAllowedError" DOMException
 
-    1. Let |cleanItemList| be an empty sequence&lt;{{Blob}}>.
+    1. Let |itemList| and |cleanItemList| be an empty sequence&lt;{{Blob}}>.
+
+    1. For each |itemData| in |data|:
+
+     1. For each |item| in |itemData|:
+      1. If [=Promise=] to {{Blob}} in |item| is rejected, then throw "Promises to Blobs were rejected." DOMException.
+
+      1. Add the {{Blob}} in |item| to |itemList| after the promise has been resolved.

Perhaps the Promise to the blob should be bound to a variable, which would be reused here. CC @annevk 

> @@ -701,17 +784,28 @@ urlPrefix: https://w3c.github.io/FileAPI/#dfn-; type: dfn;
 
     1. If |r| is not "granted", then reject |p| with a "NotAllowedError" DOMException
 
-    1. Let |cleanItemList| be an empty sequence&lt;{{Blob}}>.
+    1. Let |itemList| and |cleanItemList| be an empty sequence&lt;{{Blob}}>.
+
+    1. For each |itemData| in |data|:
+
+     1. For each |item| in |itemData|:
+      1. If [=Promise=] to {{Blob}} in |item| is rejected, then throw "Promises to Blobs were rejected." DOMException.
+
+      1. Add the {{Blob}} in |item| to |itemList| after the promise has been resolved.
+
+     1. For each {{Blob}} |itemBlob| in |itemList|:

Perhaps `blob` instead of `itemBlob` would be clearer.

> @@ -701,17 +784,28 @@ urlPrefix: https://w3c.github.io/FileAPI/#dfn-; type: dfn;
 
     1. If |r| is not "granted", then reject |p| with a "NotAllowedError" DOMException
 
-    1. Let |cleanItemList| be an empty sequence&lt;{{Blob}}>.
+    1. Let |itemList| and |cleanItemList| be an empty sequence&lt;{{Blob}}>.
+
+    1. For each |itemData| in |data|:
+
+     1. For each |item| in |itemData|:
+      1. If [=Promise=] to {{Blob}} in |item| is rejected, then throw "Promises to Blobs were rejected." DOMException.
+
+      1. Add the {{Blob}} in |item| to |itemList| after the promise has been resolved.
+
+     1. For each {{Blob}} |itemBlob| in |itemList|:
+
+      1. If {{Blob/type}} is not in the [=mandatory data types=] list, then reject |p| with a "Type {{Blob/type}} not supported on write." DOMException.

`type` needs to be defined from somewhere. I guess it would have to be stored corresponding to the blobs in `itemList`.

>  
-    1. Replace the [=system clipboard data=] with |cleanItemList|.
+     1. Replace the [=system clipboard data=] with |cleanItemList|.

Something is wrong here. All cleaned items corresponding to exactly one `ClipboardItem` need to grouped together. And all groups together will replace the system clipboard data. With a note that currently only Apple-OSs support multiple clipboard items.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/w3c/clipboard-apis/pull/158#pullrequestreview-779457726

Received on Thursday, 14 October 2021 10:25:06 UTC