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

@domenic commented on this pull request.



>  
-    Promise<Blob> getType(DOMString type);
-  };
+   <dt><code><var>clipboardItem</var>.<var>types</var></code>
+   <dd><p>Returns the list of <var>types</var> contained in the <var>clipboardItem</var> object.
+
+  </dl>
+
+  <h4 id="clipboard-item">Clipboard Item</h4>
+
+  A [=clipboard item=] is conceptually data that the user has expressed a desire to make shareable by invoking a "cut" or "copy" command.

This should be a definition, i.e. `A <dfn>clipboard item</dfn> is...`. You can either formally make it a `[=struct=]` with `[=struct/items=]`, as @mbrodesser suggests, or just say what it's associated values are (i.e. its list of representations and presentation style) like you do now.

> +   <dt><code><var>clipboardItem</var>.<var>types</var></code>
+   <dd><p>Returns the list of <var>types</var> contained in the <var>clipboardItem</var> object.
+
+  </dl>
+
+  <h4 id="clipboard-item">Clipboard Item</h4>
+
+  A [=clipboard item=] is conceptually data that the user has expressed a desire to make shareable by invoking a "cut" or "copy" command.
+
+  <p class=note>
+   For example, if a user copies a range of cells from a spreadsheet of a native application, it will result in one [=clipboard item=]. If a user copies a set of files from their desktop, that list of files will be represented by multiple [=clipboard item=]s.
+  </p>
+
+  Some platforms may support having more than one [=clipboard item=] at a time on the [=Clipboard=], while other platforms replace the previous [=clipboard item=] with the new one. 
+
+  A [=clipboard item=] has a <dfn>list of representations</dfn>, each <dfn>representation</dfn> with an associated [=mime type=] and <dfn>data</dfn>.

```suggestion
  A [=clipboard item=] has a <dfn>list of representations</dfn>, each <dfn>representation</dfn> with an associated <dfn for="representation">mime type</dfn> (a [=MIME type=]) and <dfn for="representation">data</dfn> (a {{ClipboardItemData}}).
```

> +  <p class=note>
+   Making the range of cells available as an image will allow the user to paste the cells into a photo editing app, while the text/plain format can be used by text editor apps.
+  </p>
+
+  A [=clipboard item=] can also optionally have a <dfn>presentation style</dfn> that helps distinguish whether apps "pasting" a [=clipboard item=] should insert the contents of an appropriate [=representation=] inline at the point of paste or if it should be treated as an attachment.
+
+  Apps that support pasting only a single [=clipboard item=] should use the first [=clipboard item=].
+  Apps that support pasting more than one [=clipboard item=] could, for example, provide a user interface that previews the contents of each [=clipboard item=] and allow the user to choose which one to paste.
+  Further, apps are expected to enumerate the [=mime type=]s of the [=clipboard item=] they are pasting and select the one best-suited for the app according to some app-specific algorithm.
+  Alternatively, an app can present the user with options on how to paste a [=clipboard item=], e.g. "paste as image" or "paste formatted text", etc.
+
+  A {{ClipboardItem}} object has an associated <dfn for="ClipboardItem">clipboard item</dfn>, which is a [=clipboard item=].
+
+  A {{ClipboardItem}} object has an associated <dfn for="ClipboardItem">types array</dfn>, which is a {{FrozenArray}}.
+
+  To <dfn>create a {{ClipboardItem}} object</dfn>, given a [=clipboard item=] |clipboardItem|'s [=relevant realm=] |realm|, run these steps:

```suggestion
  To <dfn>create a {{ClipboardItem}} object</dfn>, given a [=clipboard item=] |clipboardItem| and a [=Realm=] |realm|:
```

> +
+  Apps that support pasting only a single [=clipboard item=] should use the first [=clipboard item=].
+  Apps that support pasting more than one [=clipboard item=] could, for example, provide a user interface that previews the contents of each [=clipboard item=] and allow the user to choose which one to paste.
+  Further, apps are expected to enumerate the [=mime type=]s of the [=clipboard item=] they are pasting and select the one best-suited for the app according to some app-specific algorithm.
+  Alternatively, an app can present the user with options on how to paste a [=clipboard item=], e.g. "paste as image" or "paste formatted text", etc.
+
+  A {{ClipboardItem}} object has an associated <dfn for="ClipboardItem">clipboard item</dfn>, which is a [=clipboard item=].
+
+  A {{ClipboardItem}} object has an associated <dfn for="ClipboardItem">types array</dfn>, which is a {{FrozenArray}}.
+
+  To <dfn>create a {{ClipboardItem}} object</dfn>, given a [=clipboard item=] |clipboardItem|'s [=relevant realm=] |realm|, run these steps:
+   1. Let |clipboardItemObject| be a [=new=] {{ClipboardItem}} with |realm|.
+
+   1. Set |clipboardItemObject|'s [=clipboard item=] to |clipboardItem|.
+
+  The <a constructor lt="ClipboardItem()">constructor</a> steps for <code>new ClipboardItem(<var>items</var>, <var>options</var>)</code> are:

```suggestion
  The <dfn constructor for="ClipboardItem" lt="ClipboardItem(items, options)"><code>new ClipboardItem(<var>items</var>, <var>options</var>)</code></dfn> constructor steps are:
```

> +  The <a constructor lt="ClipboardItem()">constructor</a> steps for <code>new ClipboardItem(<var>items</var>, <var>options</var>)</code> are:
+   1. Set [=this=]'s [=ClipboardItem/clipboard item=] to a new [=clipboard item=].
+
+   1. Set [=this=]'s [=ClipboardItem/clipboard item=]'s [=presentation style=] to |options|["{{ClipboardItemOptions/presentationStyle}}"].
+
+   1. Let |types| be a list of {{DOMString}}.
+
+   1. For each (|key|, |value|) in |items|:
+
+    1. Let |mimeType| be the result of [=parse a mime type=] given |key|.
+
+    1. If |mimeType| is failure, then throw a {{TypeError}}.
+
+    1. Let |representation| be a new [=representation=].
+
+    1. Set |representation|'s [=mime type=] to |key|.

```suggestion
    1. Set |representation|'s [=representation/MIME type=] to |key|.
```

> +
+   1. Set [=this=]'s [=ClipboardItem/clipboard item=]'s [=presentation style=] to |options|["{{ClipboardItemOptions/presentationStyle}}"].
+
+   1. Let |types| be a list of {{DOMString}}.
+
+   1. For each (|key|, |value|) in |items|:
+
+    1. Let |mimeType| be the result of [=parse a mime type=] given |key|.
+
+    1. If |mimeType| is failure, then throw a {{TypeError}}.
+
+    1. Let |representation| be a new [=representation=].
+
+    1. Set |representation|'s [=mime type=] to |key|.
+
+    1. Set |representation|'s [=data=] to |value|.

```suggestion
    1. Set |representation|'s [=representation/data=] to |value|.
```

> +
+   1. For each (|key|, |value|) in |items|:
+
+    1. Let |mimeType| be the result of [=parse a mime type=] given |key|.
+
+    1. If |mimeType| is failure, then throw a {{TypeError}}.
+
+    1. Let |representation| be a new [=representation=].
+
+    1. Set |representation|'s [=mime type=] to |key|.
+
+    1. Set |representation|'s [=data=] to |value|.
+
+    1. Append |representation| to [=this=]'s [=ClipboardItem/clipboard item=]'s [=list of representations=].
+
+    1. Let |mimeTypeString| be the result of [=serialize a mime type=] with |mimeType|.

```suggestion
    1. Let |mimeTypeString| be the result of [=serializing a MIME type=] with |mimeType|.
```

> +
+  To <dfn>create a {{ClipboardItem}} object</dfn>, given a [=clipboard item=] |clipboardItem|'s [=relevant realm=] |realm|, run these steps:
+   1. Let |clipboardItemObject| be a [=new=] {{ClipboardItem}} with |realm|.
+
+   1. Set |clipboardItemObject|'s [=clipboard item=] to |clipboardItem|.
+
+  The <a constructor lt="ClipboardItem()">constructor</a> steps for <code>new ClipboardItem(<var>items</var>, <var>options</var>)</code> are:
+   1. Set [=this=]'s [=ClipboardItem/clipboard item=] to a new [=clipboard item=].
+
+   1. Set [=this=]'s [=ClipboardItem/clipboard item=]'s [=presentation style=] to |options|["{{ClipboardItemOptions/presentationStyle}}"].
+
+   1. Let |types| be a list of {{DOMString}}.
+
+   1. For each (|key|, |value|) in |items|:
+
+    1. Let |mimeType| be the result of [=parse a mime type=] given |key|.

```suggestion
    1. Let |mimeType| be the result of [=parsing a MIME type=] given |key|.
```

> +    1. Append |representation| to [=this=]'s [=ClipboardItem/clipboard item=]'s [=list of representations=].
+
+    1. Let |mimeTypeString| be the result of [=serialize a mime type=] with |mimeType|.
+    
+    1. Add |mimeTypeString| to |types|.
+
+   1. Set [=this=]'s [=ClipboardItem/types array=] to the result of running [=create a frozen array=] from |types|.
+
+  <h4 attribute for=ClipboardItem lt=presentationStyle>presentationStyle</h4>
+  <p>
+   The {{ClipboardItem/presentationStyle}} getter steps are to return [=this=]'s [=ClipboardItem/clipboard item=]'s [=presentation style=].
+  </p>
+
+  <h4 attribute for=ClipboardItem lt=types>types</h4>
+  <p>
+   {{ClipboardItem/types}} getter steps are to return [=this=]'s [=ClipboardItem/types array=].

```suggestion
   The {{ClipboardItem/types}} getter steps are to return [=this=]'s [=ClipboardItem/types array=].
```

> +
+  <h4 attribute for=ClipboardItem lt=presentationStyle>presentationStyle</h4>
+  <p>
+   The {{ClipboardItem/presentationStyle}} getter steps are to return [=this=]'s [=ClipboardItem/clipboard item=]'s [=presentation style=].
+  </p>
+
+  <h4 attribute for=ClipboardItem lt=types>types</h4>
+  <p>
+   {{ClipboardItem/types}} getter steps are to return [=this=]'s [=ClipboardItem/types array=].
+  </p>
+
+  <h4 method for=ClipboardItem lt=getType(type)>getType(type)</a> must run the below steps:</h4>
+
+   1. Let |realm| be [=this=]'s [=relevant realm=].
+
+   1. Let |mimeType| be the result of [=parse a mime type=] given |type|.

```suggestion
   1. Let |mimeType| be the result of [=parsing a MIME type=] given |type|.
```

> +
+  <h4 method for=ClipboardItem lt=getType(type)>getType(type)</a> must run the below steps:</h4>
+
+   1. Let |realm| be [=this=]'s [=relevant realm=].
+
+   1. Let |mimeType| be the result of [=parse a mime type=] given |type|.
+
+   1. If |mimeType| is failure, then throw a {{TypeError}}.
+
+   1. Let |itemTypeList| be [=this=]'s [=ClipboardItem/clipboard item=]'s [=list of representations=].
+
+   1. For each |representation| in |itemTypeList|:
+
+    1. If |representation|'s [=mime type=] is |mimeType|, then:
+
+     1. Let |blobData| be a [=Blob=] created using |representation|'s [=data=] and with its {{Blob/type}} set to |mimeType|, [=serialize a MIME type|serialized=].

representation's data is a `ClipboardItemData`, i.e. a `Promise<(DOMString or Blob)>`. You cannot create a blob from a promise.

I think you need to use https://webidl.spec.whatwg.org/#dfn-perform-steps-once-promise-is-settled .

- In your fulfillment steps, you will get either a `DOMString` or a `Blob`.
  - If it is a `DOMString`, probably you want to [encode](https://encoding.spec.whatwg.org/#utf-8-encode) the result into bytes, and then create a `Blob` from that.
  - If it is a `Blob`... do you want to create a new `Blob`? Or do you want to return the existing one? This is an observable choice.
- In your rejection steps, you want to reject |p|. (Where |p| is a promise you create before the for each loop.)

>  
    1. Run the following steps [=in parallel=]:
 
-    1. Let |r| be the result of running [=check clipboard read permission=] [=in parallel=]
+    1. Let |r| be the result of running [=check clipboard read permission=].
+
+     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 [=Queue a global task=] on the [=permission task source=], given |realm|'s [=Realm/global object=], to perform the below step:

"check clipboard read permission" returns true or false, not "granted".

>  
-    1. If |r| is not "granted", then reject |p| with a "NotAllowedError" DOMException
+     1. Abort all steps.

This is confusing, since you can't queue a task to abort steps happening in parallel.

I think the phrasing you want is something like:

> 1. If r is not granted, then:
>    1. Queue a global task ... to reject p with ...
>    1. Abort these steps. 

>  
-    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 [=clipboard items=]. 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 [=clipboard item=] object is supported for reading and writing via the [=clipboard=] object.

I don't really understand this note. However, notes on what specific implementations do don't have a place in the standard, so this is best deleted.

>       
      Note: As further described in [[#image-transcode]] this explicitly does not transcode images.
      Rather the original unmodified image data should be exposed to the website.
 
-    1. Resolve |p| with |data|.
+    1. [=Queue a global task=] on the [=clipboard task source=], given |realm|'s [=Realm/global object=], to perform the below steps:
+
+     1. Let |items| be a [=sequence=]&lt;{{ClipboardItem}}&gt;.
+
+     1. For each [=clipboard item=] |underlyingItem| of |data|:
+
+      1. Let |item| be the result of running the steps of [=create a ClipboardItem object=] given |underlyingItem|.
+
+      1. Append |item| to |items|.
+
+      1. Resolve |p| with |items|.

I don't think you want to resolve this each time you loop. It should probably be dedented.

>    <pre class="idl" data-highlight="webidl">
-  typedef sequence&lt;ClipboardItem> ClipboardItems;
+   typedef (DOMString or Blob) ClipboardItemDataType;

Since this typedef is only used once, I think it is best not to have a typedef at all, and just inline it into the next line.

-- 
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-830520504

Received on Monday, 13 December 2021 17:23:14 UTC