Open Bug 1420244 Opened 7 years ago Updated 2 years ago

execCommand('copy') model broken due to clipboardWrite requirement for > 1MB data

Categories

(Core :: DOM: Core & HTML, defect, P2)

57 Branch
defect

Tracking

()

UNCONFIRMED

People

(Reporter: alec, Unassigned, NeedInfo)

Details

User Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:57.0) Gecko/20100101 Firefox/57.0
Build ID: 20171112125346

Steps to reproduce:

A catch-22 situation with how Firefox implements execCommand support.

We have a menu command to put SVG and other data onto the clipboard from our design tool.  This data can be several MB in size.   This stalls the browser for over a minute for 6.2MB.  On investigating, it wasn't the SVG generation.  It was textArea formatting to transfer the text to the clipboard, followed by a failed document.execCommand('copy') calls.

There is a failure case when a user action exceeds some undocumented amount of time, where execCommand fails.  I moved the execCommand to a setTimeout callback and that fixed Chrome/Safari.  The textArea is set in the user action, and the timeout calls execCommand.  That doesn't fix Firefox due to the clipboardWrite permissions requirement that fail the call from setTimeout.

Clipboard handling is already broken enough in the browser, but the textArea formatting time and secretly failed execCommand call are problematic for all web applications.  There is far too much nuance to getting data to the clipboard in all browsers.



Actual results:

You should be able to get large amounts of content to the clipboard quickly.  These are the current timings taken from Chrome, but the timings are similar in Firefox.  

1. +0.0029s generating 6.2MB of SVG 
2. +32s       formatting that text in a textArea takes 32s (no spell check, kerning ascii 7-bit chars)
3. +32s       failing the execCommand and displaying the textArea in a popup for user to cmd+c copy
   this additional popup should never be present to the user.




Expected results:

1. The formatting of ascii text should have a fast/instant path, or there should be a fast path to copy it to clipboard via execCommand (via execCommand arguments).  In this case, SVG is already base64 encoded and a single image can lead to multiple MB of image data.

2. execCommand should be able to be run from setTimeout after the textArea finishes formatting.
Component: Event Handling → Editor
This issue is CopySupport, widget, or IPC.  Editor uses nsITransferable object that is in widget.
Component: Editor → DOM
I think Nika knows what's going on here.
Flags: needinfo?(nika)
Priority: -- → P2
The problem which you're running into here is multiple-fold, so I'll approach it:

1. A click callback taking too long can cause the user-initiated-event flag to be unset, which causes document.execCommand('copy') to fail.

This was bug 1360441 - It should be fixed as of Firefox 55. We no longer time out the user-initiated event for some actions, including copying text to the clipboard. If this is still happening on 55+, I'd love a reproduction test case.

2. execCommand can't be called from within a setTimeout call.

This is a consequence of the way that user initiated input event information is recorded in Firefox. We record this information based on the direct JS call stack for the running code, which means that we don't consider the setTimeout callback to be user initiated.

There is some talk of getting a better cross-browser specification of what user initiated means, but we don't have one yet.

3. Copying a large amount of text to the clipboard is really slow, because we have to put it into a text area.

You don't actually need to put the text into a text area in order to copy it to the clipboard. It's possible to register a `"copy"` event handler and use that to directly insert the text data onto the clipboard. I wrote an example library which tries to do this reliably across different browsers (which is unfortunately complicated): https://github.com/mystor/raw_copy

With this sort of approach you can copy 8MB of text to the clipboard in ~200ms instead of ~5s. If all browsers were spec compliant you'd be able to do it even faster.
Flags: needinfo?(nika) → needinfo?(alec)
Component: DOM → DOM: Core & HTML
Severity: normal → S3
You need to log in before you can comment on or make changes to this bug.