Re: [w3c/clipboard-apis] Add comprehensive clipboardchange event specification with ClipboardChangeEventInit dictionary (PR #239)

@zgroza commented on this pull request.



> @@ -224,12 +224,166 @@ url: https://w3c.github.io/permissions/#permissions-task-source; type: dfn;
    * Scripts that use the [[#async-clipboard-api]] to write to the clipboard
    * Actions that update the clipboard outside the user agent
 
-   If the clipboard contents are changed outside the user agent, then the
-   {{GlobalEventHandlers/clipboardchange}} event MUST fire when the user agent regains focus.
+   <div class="algorithm" data-algorithm="fire-clipboardchange-event">
+   <h5 id="h-fire-clipboardchange-event">To fire a clipboardchange event</h5>
+
+   To <dfn export>fire a clipboardchange event</dfn> given a {{Document}} <var>document</var>:
+
+   1. If <var>document</var> does not have [=sticky activation=], then return.
+
+   2. Let <var>global</var> be <var>document</var>'s [=relevant global object=].
+
+   3. If <var>document</var> has <a>focus</a>:

Can maybe [system focus](https://html.spec.whatwg.org/multipage/interaction.html#system-focus) be used here and in other places? The current specification mentions only [has focus](https://html.spec.whatwg.org/multipage/interaction.html#has-focus-steps) in the [Privacy and the Asychronous Clipboard API](https://w3c.github.io/clipboard-apis/#privacy-async) section, which directly references this term.
```suggestion
   3. If <var>document</var> has [=system focus=]:
```

Alternatively, just like the spec currently does,
```suggestion
   3. If <var>document</var> [=has focus steps|has focus=]:
```

> @@ -224,12 +224,166 @@ url: https://w3c.github.io/permissions/#permissions-task-source; type: dfn;
    * Scripts that use the [[#async-clipboard-api]] to write to the clipboard
    * Actions that update the clipboard outside the user agent
 
-   If the clipboard contents are changed outside the user agent, then the
-   {{GlobalEventHandlers/clipboardchange}} event MUST fire when the user agent regains focus.
+   <div class="algorithm" data-algorithm="fire-clipboardchange-event">
+   <h5 id="h-fire-clipboardchange-event">To fire a clipboardchange event</h5>
+
+   To <dfn export>fire a clipboardchange event</dfn> given a {{Document}} <var>document</var>:
+
+   1. If <var>document</var> does not have [=sticky activation=], then return.
+
+   2. Let <var>global</var> be <var>document</var>'s [=relevant global object=].
+
+   3. If <var>document</var> has <a>focus</a>:
+    1. Let <var>types</var> be a [=list=] of [=mandatory data types=] available on the [=system clipboard=].
+    2. Let <var>changeId</var> be a unique identifier for this clipboard change, generated by applying an origin-specific transformation to a system-level clipboard change identifier, ensuring that different origins receive different identifiers for the same clipboard change while maintaining consistency within the same origin.

Maybe let's use partitions here? [Specification](https://w3ctag.github.io/privacy-principles/#user-agent-recognition) says that
> [User agents](https://infra.spec.whatwg.org/#user-agent) should prevent people from being [recognized](https://w3ctag.github.io/privacy-principles/#dfn-recognize) across [partitions](https://w3ctag.github.io/privacy-principles/#dfn-partition) unless they intend to be recognized.

```suggestion
    2. Let <var>changeId</var> be a unique identifier for this clipboard change, generated by applying an origin-specific transformation to a system-level clipboard change identifier, ensuring that different [=dfn-partition|partitions=] receive different identifiers for the same clipboard change while maintaining consistency within the same [=dfn-partition|partition=].
```

> +   is not triggered by a user action but rather by changes to the [=system clipboard=] state.
+
+   <div id="clipboardchangeeventinit-idl">
+
+   <pre class="idl" data-highlight="webidl">
+   dictionary ClipboardChangeEventInit : EventInit {
+    sequence&lt;DOMString&gt; types = [];
+    DOMString changeId = "";
+   };
+   </pre>
+
+   : <dfn for="ClipboardChangeEventInit" data-export>types</dfn>
+   :: A sequence of {{DOMString}} representing the [=mandatory data types=] available on the [=system clipboard=].
+
+   : <dfn for="ClipboardChangeEventInit" data-export>changeId</dfn>
+   :: A {{DOMString}} representing a unique identifier for this clipboard change operation.

I wonder a bit whether a random `BigInt` wouldn't be more straightforward here. Having a UUID in the form of a `DOMString` here forces:
* user agent to convert to/from the standard UUID text serialization (and worry about adhering to particular format)—which requires either some library dependency or a custom implementation
* web applications to compare strings (or convert them), which might be *a bit* less straightforward than just comparing integers

Those are arguably very small overheads, so it's not really a very strong preference—it might however improve sheer simplicity.

> @@ -224,12 +224,166 @@ url: https://w3c.github.io/permissions/#permissions-task-source; type: dfn;
    * Scripts that use the [[#async-clipboard-api]] to write to the clipboard
    * Actions that update the clipboard outside the user agent
 
-   If the clipboard contents are changed outside the user agent, then the
-   {{GlobalEventHandlers/clipboardchange}} event MUST fire when the user agent regains focus.
+   <div class="algorithm" data-algorithm="fire-clipboardchange-event">
+   <h5 id="h-fire-clipboardchange-event">To fire a clipboardchange event</h5>
+
+   To <dfn export>fire a clipboardchange event</dfn> given a {{Document}} <var>document</var>:
+
+   1. If <var>document</var> does not have [=sticky activation=], then return.

This troubles me a bit, as it doesn't work well with the current spec and use cases. In case of the persistent clipboard permissions, site could theoretically read from clipboard on focus—but before gaining sticky activation—and then not be notified when the read data is already stale.
Maybe it would be better to either:
* Move this like focus to the current step `3.`—and set the pending flag also if the sticky activation is not yet there?
* Add sticky activation requirement to the [Privacy and the Asychronous Clipboard API](https://w3c.github.io/clipboard-apis/#privacy-async) of the entire API overall? This could potentially break current websites—on the other hand, would align with the current Firefox and Safari implementation, which requires transient user activation (which is impossible to get without sticky activation) anyway.
* Add a provision that if the persistent clipboard permission is granted (provided that the user agent supports it), sticky activation check is skipped? It doesn't make much sense then anyway, as the application can just read the clipboard—which provides much more sensitive data than just a change notification.

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

Message ID: <w3c/clipboard-apis/pull/239/review/3136276750@github.com>

Received on Wednesday, 20 August 2025 12:49:31 UTC