Re: [w3c/editing] Should we modify the clipboard API spec to match Safari's behavior for HTML-referenced media? (#285)

Here are additional thoughts on how authors can opt into Safari-compatible behavior to produce blob URLs for HTML while avoiding leaks for existing clipboard code.

## Goals
* Do not leak blobs for existing clipboard code on the web
* Work for the HTML format provided by the [async](https://www.w3.org/TR/clipboard-apis/#async-clipboard-api) and [event-based (sync)](https://www.w3.org/TR/clipboard-apis/#clipboard-event-api) clipboard APIs
* Be compatible with Safari's current implementation

## Amendments to the Original Proposal
For the async clipboard API, extend [`ClipboardItem`](https://www.w3.org/TR/clipboard-apis/#clipboarditem)'s [`getType`](https://www.w3.org/TR/clipboard-apis/#dom-clipboarditem-gettype) method to accept a dictionary of options, one of which will be `boolean includeFiles`.  When true, in the context of the `"text/html"` type, the user agent will replace file URLs with blob URLs referring to the file's contents and the author will be responsible for revoking those blob URLs at an appropriate time.

For the event-based clipboard API, extend [`DataTransfer`](https://html.spec.whatwg.org/multipage/dnd.html#datatransfer)'s [`getData`](https://html.spec.whatwg.org/multipage/dnd.html#dom-datatransfer-getdata) method to accept the same dictionary of options which triggers the same behaviors.

The async clipboard read would look like this (note the `{ includeFiles:true }`):

```javascript
navigator.clipboard.read()
    .then(items => {
        for(const item of items) {
            for (const type of item.types) {
                if (type == "text/html") {
                    // return the first HTML we find
                    return item.getType("text/html", { includeFiles:true })
                }
            }
        }
    })
    .then(html => {
        // parse the HTML
        const clipboardDocument = document.implementation.createHTMLDocument()
        clipboardDocument.write(html)

        // find all elements having a blob URL to process them
        const elements = clipboardDocument.querySelectorAll("[src^='blob:']")
        for (const element of elements) {
            // fetch the bits for each blob
            fetch(element.getAttribute("src"))
                .then(r => r.blob())
                .then(b => {
                    // Process the blob in some site-specific way
                }
            )
        }
    })
```

## Compatibility with Safari
Safari currently returns blobs for the HTML format whether the author asks for them or not. This will likely to result in leaks as mentioned in [earlier comments](https://github.com/w3c/editing/issues/285#issuecomment-794599214).  With the proposed approach, authors can supply the option to `includeFiles` to get Safari-compatible behavior in any compliant browser and Safari. At a time of their choosing (or never if there is a compatibility concern), the Safari implementors can update the behavior of `getType` and `getData` to stop returning blobs unless the author explicitly requests them for the sake of interop and to eliminate their current leaks.

## Alternatives Considered
**Providing options to `navigator.clipboard.read()`:** this felt ambiguous since the option applies to one particular sanitized format.  Additionally, supplying the option to `getType` seems to have nice symmetry with extending `getData` for the event-based API.

**Always including blobs for HTML, but revoking them at the end of the paste event:** this didn't solve the problem for the async clipboard API since it can be used to read HTML outside of the paste event.

**Auto-revoking generated blob URLs after they have been fetched once:** this would have solved Safari's leak problems, but if the author wanted the bits of the blobs and fetched the blob URLs found in the markup, the author would have also had to replace the blob URLs in the markup being pasted to avoid a race between the author fetching the bits explicitly and the new pasted elements in the DOM trying to loading the blob.


-- 
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/editing/issues/285#issuecomment-805516320

Received on Wednesday, 24 March 2021 05:41:43 UTC