flutter / devtools

Performance tools for Flutter
https://flutter.dev/docs/development/tools/devtools/
BSD 3-Clause "New" or "Revised" License
1.57k stars 324 forks source link

copy is not successful NotAllowedError: The Clipboard API has been blocked #5775

Closed CoderDake closed 11 months ago

CoderDake commented 1 year ago

While testing log copying behaviour in VSCode, I noticed that the copy button is no longer working, when using it in the context of VSCode.

Alternatively, I have run Dart Devtools from the command line using flutter run -d chrome. When running devtools like this, the copy functionality seems to work just fine.

The following is the log message that is output in the vscode developer console when the copy fails.

copy is not successful NotAllowedError: The Clipboard API has been blocked because of a permissions policy applied to the current document. See https://goo.gl/EuHzyv for more details.
main.dart.js:44705 [zoneGuarded]: PlatformException(copy_fail, Clipboard.setData failed, null, null)
cg3 @ main.dart.js:44705
$1 @ main.dart.js:87529
bwd @ main.dart.js:4702
(anonymous) @ main.dart.js:156473
qh @ main.dart.js:55529
qi @ main.dart.js:55506
pp @ main.dart.js:55235
k0 @ main.dart.js:55211
pp @ main.dart.js:54607
I @ main.dart.js:54551
aaH @ main.dart.js:148455
c2 @ main.dart.js:148450
bQC @ main.dart.js:8253
$2 @ main.dart.js:62342
Ax @ main.dart.js:55635
$5 @ main.dart.js:55664
ut @ main.dart.js:55489
ks @ main.dart.js:55523
Lm @ main.dart.js:4548
fZ @ main.dart.js:54840
iY @ main.dart.js:54418
k @ main.dart.js:4402
(anonymous) @ main.dart.js:20137
(anonymous) @ main.dart.js:4411
$2 @ main.dart.js:54430
$2 @ main.dart.js:54427
bwc @ main.dart.js:4705
(anonymous) @ main.dart.js:156474
Ax @ main.dart.js:55531
YT @ main.dart.js:54770
$0 @ main.dart.js:54927
Lm @ main.dart.js:4570
fZ @ main.dart.js:54840
iY @ main.dart.js:54418
k @ main.dart.js:4402
(anonymous) @ main.dart.js:33074
(anonymous) @ main.dart.js:4411
$2 @ main.dart.js:54430
$2 @ main.dart.js:54427
bwc @ main.dart.js:4705
(anonymous) @ main.dart.js:156474
Ax @ main.dart.js:55531
YT @ main.dart.js:54770
$0 @ main.dart.js:54927
Lm @ main.dart.js:4570
fZ @ main.dart.js:54840
iY @ main.dart.js:54418
k @ main.dart.js:4402
(anonymous) @ main.dart.js:124353
(anonymous) @ main.dart.js:4411
$2 @ main.dart.js:54430
$1 @ main.dart.js:54424
bwd @ main.dart.js:4699
(anonymous) @ main.dart.js:156473
qh @ main.dart.js:55529
$0 @ main.dart.js:54917
Lm @ main.dart.js:4570
qO @ main.dart.js:54837
$0 @ main.dart.js:54884
bwb @ main.dart.js:4696
(anonymous) @ main.dart.js:156472
tl @ main.dart.js:55527
tm @ main.dart.js:55502
$0 @ main.dart.js:55579
cc3 @ main.dart.js:4602
ccw @ main.dart.js:4604
$1 @ main.dart.js:54369
cft @ main.dart.js:3130
(anonymous) @ main.dart.js:3138
childList (async)
$1 @ main.dart.js:54376
bQR @ main.dart.js:4609
bwe @ main.dart.js:4717
qv @ main.dart.js:55545
u6 @ main.dart.js:54850
fZ @ main.dart.js:54759
iY @ main.dart.js:54749
js @ main.dart.js:54750
$1 @ main.dart.js:60099
cft @ main.dart.js:3130
(anonymous) @ main.dart.js:3138
Promise.then (async)
kp @ main.dart.js:7285
(anonymous) @ main.dart.js:48660
(anonymous) @ main.dart.js:4411
$2 @ main.dart.js:54430
m @ main.dart.js:4397
aoX @ main.dart.js:48681
mx @ main.dart.js:48652
aoY @ main.dart.js:48619
aSR @ main.dart.js:49422
QX @ main.dart.js:123874
(anonymous) @ main.dart.js:124358
(anonymous) @ main.dart.js:4411
$2 @ main.dart.js:54430
m @ main.dart.js:4397
aKN @ main.dart.js:124366
mJ @ main.dart.js:124351
(anonymous) @ main.dart.js:124427
(anonymous) @ main.dart.js:4411
$2 @ main.dart.js:54430
m @ main.dart.js:4397
b3m @ main.dart.js:124431
ex @ main.dart.js:124423
(anonymous) @ main.dart.js:33076
(anonymous) @ main.dart.js:4411
$2 @ main.dart.js:54430
m @ main.dart.js:4397
zF @ main.dart.js:33078
(anonymous) @ main.dart.js:20139
(anonymous) @ main.dart.js:4411
$2 @ main.dart.js:54430
m @ main.dart.js:4397
yY @ main.dart.js:20142
$0 @ main.dart.js:90228
NC @ main.dart.js:102862
(anonymous) @ main.dart.js:3170
aiP @ main.dart.js:98745
f1 @ main.dart.js:98749
ai5 @ main.dart.js:98909
a51 @ main.dart.js:98882
ai2 @ main.dart.js:98845
jA @ main.dart.js:98807
(anonymous) @ main.dart.js:3171
aCI @ main.dart.js:98703
$2 @ main.dart.js:98715
a0 @ main.dart.js:53850
a6e @ main.dart.js:98710
alu @ main.dart.js:98708
na @ main.dart.js:97808
XW @ main.dart.js:97802
XW @ main.dart.js:126879
a7V @ main.dart.js:97796
YZ @ main.dart.js:97785
TP @ main.dart.js:97783
aIk @ main.dart.js:97776
(anonymous) @ main.dart.js:3171
bwd @ main.dart.js:4702
(anonymous) @ main.dart.js:156473
qh @ main.dart.js:55529
qi @ main.dart.js:55506
azQ @ main.dart.js:879
aNZ @ main.dart.js:49677
(anonymous) @ main.dart.js:3171
$1 @ main.dart.js:49947
$1 @ main.dart.js:49901
$1 @ main.dart.js:49692
$1 @ main.dart.js:49682
c4W @ main.dart.js:3009
caJ @ main.dart.js:7265
(anonymous) @ main.dart.js:7261
main.dart.js:3049 Uncaught PlatformException(copy_fail, Clipboard.setData failed, null, null)
    at Object.i (http://127.0.0.1:9100/main.dart.js:3049:3)
    at aTi.ago (http://127.0.0.1:9100/main.dart.js:124076:9)
    at http://127.0.0.1:9100/main.dart.js:124362:98
    at bwA.a (http://127.0.0.1:9100/main.dart.js:4411:62)
    at bwA.$2 (http://127.0.0.1:9100/main.dart.js:54430:14)
    at bub.$1 (http://127.0.0.1:9100/main.dart.js:54424:21)
    at Object.bwd (http://127.0.0.1:9100/main.dart.js:4699:19)
    at ahq.<anonymous> (http://127.0.0.1:9100/main.dart.js:156473:68)
    at Y8.qh (http://127.0.0.1:9100/main.dart.js:55529:12)
    at bhi.$0 (http://127.0.0.1:9100/main.dart.js:54917:11)

DevTools version: 2.23.1 Connected Device: CPU / OS: x64 (64 bit) macos Dart Version: 3.1.0-63.1.beta Flutter Version: 3.11.0-1.0.pre.1 / beta Framework / Engine: 74e4b092e5 / 992cdb6cd4 Connected app type: Flutter native (debug build)

CoderDake commented 1 year ago

Looking into the source for vscode it looks like the iframe allows clipboard read and write, so I wonder if this has something to do with the gesture not being connected directly to the action Screenshot 2023-05-11 at 3 13 35 PM

With some research it looks like browsers have security features that protect against clipboard access that isn't associated with user actions

kenzieschmoll commented 1 year ago

@DanTup

DanTup commented 1 year ago

We're an iframe inside an iframe here. VS Code iframes the Dart-Code extensions webview, and the webview then has to iframe DevTools (we can't set a raw URL for the first iframe, we can only set its html contents). I suspect we just need to put the same allow attribute onto Dart-Code iframe.

I've opened https://github.com/Dart-Code/Dart-Code/issues/4540 about this.

DanTup commented 1 year ago

I've been digging into this, but been unable to fix. I added some notes about this to https://github.com/Dart-Code/Dart-Code/issues/4540. It seems like passing clipboard access cross-origin in iframes isn't working (this might be the cause of our other issue - https://github.com/microsoft/vscode/issues/129178).

Some people are falling back to older clipboard APIs that don'thave the same permissions requirements, but since this is handled by Flutter I don't know if that's a simple option.

One possibility could be to pass the text up to the parent iframe via postMessage where we can write to the clipboard, but it feels a bit weird to be doing that in DevTools. Thoughts?

DanTup commented 1 year ago

Since this same setup seems to work outside of VS Code (nested iframes crossing origins with allow=clipboard-wite) I've opened https://github.com/microsoft/vscode/issues/182642 about this to see if the VS Code devs might consider this a VS Code bug.