Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clipboard paste doesn't work in Google Chrome #319

Closed
gashtal opened this issue Aug 24, 2024 · 10 comments
Closed

Clipboard paste doesn't work in Google Chrome #319

gashtal opened this issue Aug 24, 2024 · 10 comments
Labels
bug Something isn't working clipboard

Comments

@gashtal
Copy link

gashtal commented Aug 24, 2024

Following up on this issue, currently I can copy/paste data in and out of applications through the HTML5 client using Firefox, with the exception of Google Chrome.

With Google Chrome, copy from server to client works, but not from client to server. If I copy something from client-side, I can paste it in other applications that are open in the same session, but not Google Chrome. If I first paste the clipboard content in another application that is open in the same session and copy again from that application, then I can paste the content in Google Chrome. This seems like it might be due to come security policy in Google Chrome that is preventing paste of data directly from the client-side. If I connect to the same open session using XPRA's OpenGL client instead, I can copy/paste data directly to the same Google Chrome instance without any issues.

Client OS: Windows 10 x64
Client browser: Firefox 129.0.2 x64
Server OS: Ubuntu 22.04
HTML5 Client: v15

@totaam
Copy link
Collaborator

totaam commented Aug 25, 2024

Are you saying that google-chrome is running in the server session and is being accessed using the xpra-html5 client running in Firefox? As a nested browser?

What is your full xpra server version?

@gashtal
Copy link
Author

gashtal commented Aug 25, 2024

@totaam Yes, that is correct. Basically, I am using Google Chrome to browse the internet on the server through XPRA. Server XPRA version is v6.1.1-r0.

@totaam
Copy link
Collaborator

totaam commented Aug 26, 2024

I see that #301 is also one of your tickets and is also clipboard related. Is that one fixed?

@gashtal
Copy link
Author

gashtal commented Aug 26, 2024

Yes, only thing that is still not working is pasting into Chrome from client-side, and I think this must have something to do with Chrome itself.

@totaam
Copy link
Collaborator

totaam commented Aug 27, 2024

Running my server in a Fedora 41 VM (as I don't want to interfere with my day to day browser session on my local desktop).
I see that chrome is requesting the clipboard's contents which I had set to sw.js.gz:

683 process clipboard token selection=CLIPBOARD, local clipboard name=CLIPBOARD, proxy=X11ClipboardProxy(CLIPBOARD)
686 _filter_targets(text/plain)=('text/plain',)
686 wire selection to raw, encoding=bytes, type=UTF8_STRING, format=8, len(data)=8
686 got token, selection=CLIPBOARD, targets=('text/plain',), target data={'UTF8_STRING': ('UTF8_STRING', 8, b'sw.js.gz')}, claim=True, can-receive=True
687 got_contents('TARGETS', 'ATOM', 32, b'\xa7\x01\x00\x00\x00\x00\x00\x00') pending=
687 got_contents('UTF8_STRING', 'UTF8_STRING', 8, b'sw.js.gz') pending=
688 claim() we already own the 'CLIPBOARD' selection
763 do_x11_selection_request(<X11:SelectionRequest {'serial': '0xe4f4', 'delivered_to': '0x20000d', 'window': '0x20000d', 'requestor': '10485760', 'selection': 'CLIPBOARD', 'target': 'TARGETS', 'property': 'CHROME_SELECTION', 'time': '0x0'}>)
764 do_selection_request_event(<X11:SelectionRequest {'serial': '0xe4f4', 'delivered_to': '0x20000d', 'window': '0x20000d', 'requestor': '10485760', 'selection': 'CLIPBOARD', 'target': 'TARGETS', 'property': 'CHROME_SELECTION', 'time': '0x0'}>)
764 clipboard request for CLIPBOARD from window ["'Chromium clipboard'", 'xid=a00000', 'pid=19989'], target=TARGETS, prop=CHROME_SELECTION
764 using existing TARGETS value as response: ('text/plain',)
764 set_selection_response(10485760, TARGETS, CHROME_SELECTION, ATOM, 32, b'\xa7\x01\x00\x00\x00\x00\x00\x00', 0)
766 do_x11_selection_request(<X11:SelectionRequest {'serial': '0xe501', 'delivered_to': '0x20000d', 'window': '0x20000d', 'requestor': '10485760', 'selection': 'CLIPBOARD', 'target': 'TARGETS', 'property': 'CHROME_SELECTION', 'time': '0x0'}>)
766 do_selection_request_event(<X11:SelectionRequest {'serial': '0xe501', 'delivered_to': '0x20000d', 'window': '0x20000d', 'requestor': '10485760', 'selection': 'CLIPBOARD', 'target': 'TARGETS', 'property': 'CHROME_SELECTION', 'time': '0x0'}>)
774 clipboard request for CLIPBOARD from window ["'Chromium clipboard'", 'xid=a00000', 'pid=19989'], target=TARGETS, prop=CHROME_SELECTION
774 using existing TARGETS value as response: ('text/plain',)
775 set_selection_response(10485760, TARGETS, CHROME_SELECTION, ATOM, 32, b'\xa7\x01\x00\x00\x00\x00\x00\x00', 0)
775 do_x11_selection_request(<X11:SelectionRequest {'serial': '0xe50c', 'delivered_to': '0x20000d', 'window': '0x20000d', 'requestor': '10485760', 'selection': 'CLIPBOARD', 'target': 'TARGETS', 'property': 'CHROME_SELECTION', 'time': '0x0'}>)
775 do_selection_request_event(<X11:SelectionRequest {'serial': '0xe50c', 'delivered_to': '0x20000d', 'window': '0x20000d', 'requestor': '10485760', 'selection': 'CLIPBOARD', 'target': 'TARGETS', 'property': 'CHROME_SELECTION', 'time': '0x0'}>)
775 clipboard request for CLIPBOARD from window ["'Chromium clipboard'", 'xid=a00000', 'pid=19989'], target=TARGETS, prop=CHROME_SELECTION
775 using existing TARGETS value as response: ('text/plain',)
776 set_selection_response(10485760, TARGETS, CHROME_SELECTION, ATOM, 32, b'\xa7\x01\x00\x00\x00\x00\x00\x00', 0)
776 do_x11_selection_request(<X11:SelectionRequest {'serial': '0xe517', 'delivered_to': '0x20000d', 'window': '0x20000d', 'requestor': '10485760', 'selection': 'CLIPBOARD', 'target': 'TARGETS', 'property': 'CHROME_SELECTION', 'time': '0x0'}>)
776 do_selection_request_event(<X11:SelectionRequest {'serial': '0xe517', 'delivered_to': '0x20000d', 'window': '0x20000d', 'requestor': '10485760', 'selection': 'CLIPBOARD', 'target': 'TARGETS', 'property': 'CHROME_SELECTION', 'time': '0x0'}>)
776 clipboard request for CLIPBOARD from window ["'Chromium clipboard'", 'xid=a00000', 'pid=19989'], target=TARGETS, prop=CHROME_SELECTION
776 using existing TARGETS value as response: ('text/plain',)
777 set_selection_response(10485760, TARGETS, CHROME_SELECTION, ATOM, 32, b'\xa7\x01\x00\x00\x00\x00\x00\x00', 0)
778 do_x11_selection_request(<X11:SelectionRequest {'serial': '0xe522', 'delivered_to': '0x20000d', 'window': '0x20000d', 'requestor': '10485760', 'selection': 'CLIPBOARD', 'target': 'text/plain', 'property': 'CHROME_SELECTION', 'time': '0x0'}>)
778 do_selection_request_event(<X11:SelectionRequest {'serial': '0xe522', 'delivered_to': '0x20000d', 'window': '0x20000d', 'requestor': '10485760', 'selection': 'CLIPBOARD', 'target': 'text/plain', 'property': 'CHROME_SELECTION', 'time': '0x0'}>)
778 clipboard request for CLIPBOARD from window ["'Chromium clipboard'", 'xid=a00000', 'pid=19989'], target=text/plain, prop=CHROME_SELECTION
778 send_clipboard_request_handler(X11ClipboardProxy(CLIPBOARD), 'CLIPBOARD', 'text/plain')
778 send_clipboard_request CLIPBOARD to CLIPBOARD, id=11
782 process clipboard contents, selection=CLIPBOARD, type=UTF8_STRING, format=8
782 wire selection to raw, encoding=bytes, type=UTF8_STRING, format=8, len(data)=8
782 clipboard wire -> raw: ('UTF8_STRING', 8, 'bytes', sw.js.gz) -> sw.js.gz
783 clipboard got contents(11, 'UTF8_STRING', 8, sw.js.gz): proxy=X11ClipboardProxy(CLIPBOARD) for selection=CLIPBOARD
783 got_contents('text/plain', 'UTF8_STRING', 8, sw.js.gz) pending=(10485760, 'text/plain', 'CHROME_SELECTION', 0)
783 setting response <class 'str'>: sw.js.gz as 'text/plain' on property 'CHROME_SELECTION' of window ["'Chromium clipboard'", 'xid=a00000', 'pid=19989'] as UTF8_STRING
783 set_selection_response(10485760, text/plain, CHROME_SELECTION, UTF8_STRING, 8, sw.js.gz, 0)
783 do_x11_selection_request(<X11:SelectionRequest {'serial': '0xe530', 'delivered_to': '0x20000d', 'window': '0x20000d', 'requestor': '10485760', 'selection': 'CLIPBOARD', 'target': 'TARGETS', 'property': 'CHROME_SELECTION', 'time': '0x0'}>)
783 do_selection_request_event(<X11:SelectionRequest {'serial': '0xe530', 'delivered_to': '0x20000d', 'window': '0x20000d', 'requestor': '10485760', 'selection': 'CLIPBOARD', 'target': 'TARGETS', 'property': 'CHROME_SELECTION', 'time': '0x0'}>)
784 clipboard request for CLIPBOARD from window ["'Chromium clipboard'", 'xid=a00000', 'pid=19989'], target=TARGETS, prop=CHROME_SELECTION
784 using existing TARGETS value as response: ('text/plain',)
784 set_selection_response(10485760, TARGETS, CHROME_SELECTION, ATOM, 32, b'\xa7\x01\x00\x00\x00\x00\x00\x00', 0)
785 do_x11_selection_request(<X11:SelectionRequest {'serial': '0xe53b', 'delivered_to': '0x20000d', 'window': '0x20000d', 'requestor': '10485760', 'selection': 'CLIPBOARD', 'target': 'TARGETS', 'property': 'CHROME_SELECTION', 'time': '0x0'}>)
785 do_selection_request_event(<X11:SelectionRequest {'serial': '0xe53b', 'delivered_to': '0x20000d', 'window': '0x20000d', 'requestor': '10485760', 'selection': 'CLIPBOARD', 'target': 'TARGETS', 'property': 'CHROME_SELECTION', 'time': '0x0'}>)
785 clipboard request for CLIPBOARD from window ["'Chromium clipboard'", 'xid=a00000', 'pid=19989'], target=TARGETS, prop=CHROME_SELECTION
785 using existing TARGETS value as response: ('text/plain',)
786 set_selection_response(10485760, TARGETS, CHROME_SELECTION, ATOM, 32, b'\xa7\x01\x00\x00\x00\x00\x00\x00', 0)
786 do_x11_selection_request(<X11:SelectionRequest {'serial': '0xe546', 'delivered_to': '0x20000d', 'window': '0x20000d', 'requestor': '10485760', 'selection': 'CLIPBOARD', 'target': 'TARGETS', 'property': 'CHROME_SELECTION', 'time': '0x0'}>)
786 do_selection_request_event(<X11:SelectionRequest {'serial': '0xe546', 'delivered_to': '0x20000d', 'window': '0x20000d', 'requestor': '10485760', 'selection': 'CLIPBOARD', 'target': 'TARGETS', 'property': 'CHROME_SELECTION', 'time': '0x0'}>)
811 clipboard request for CLIPBOARD from window ["'Chromium clipboard'", 'xid=a00000', 'pid=19989'], target=TARGETS, prop=CHROME_SELECTION
812 using existing TARGETS value as response: ('text/plain',)
812 set_selection_response(10485760, TARGETS, CHROME_SELECTION, ATOM, 32, b'\xa7\x01\x00\x00\x00\x00\x00\x00', 0)
813 do_x11_selection_request(<X11:SelectionRequest {'serial': '0xe551', 'delivered_to': '0x20000d', 'window': '0x20000d', 'requestor': '10485760', 'selection': 'CLIPBOARD', 'target': 'TARGETS', 'property': 'CHROME_SELECTION', 'time': '0x0'}>)
813 do_selection_request_event(<X11:SelectionRequest {'serial': '0xe551', 'delivered_to': '0x20000d', 'window': '0x20000d', 'requestor': '10485760', 'selection': 'CLIPBOARD', 'target': 'TARGETS', 'property': 'CHROME_SELECTION', 'time': '0x0'}>)
813 clipboard request for CLIPBOARD from window ["'Chromium clipboard'", 'xid=a00000', 'pid=19989'], target=TARGETS, prop=CHROME_SELECTION
814 using existing TARGETS value as response: ('text/plain',)
814 set_selection_response(10485760, TARGETS, CHROME_SELECTION, ATOM, 32, b'\xa7\x01\x00\x00\x00\x00\x00\x00', 0)
814 do_x11_selection_request(<X11:SelectionRequest {'serial': '0xe55c', 'delivered_to': '0x20000d', 'window': '0x20000d', 'requestor': '10485760', 'selection': 'CLIPBOARD', 'target': 'TARGETS', 'property': 'CHROME_SELECTION', 'time': '0x0'}>)
814 do_selection_request_event(<X11:SelectionRequest {'serial': '0xe55c', 'delivered_to': '0x20000d', 'window': '0x20000d', 'requestor': '10485760', 'selection': 'CLIPBOARD', 'target': 'TARGETS', 'property': 'CHROME_SELECTION', 'time': '0x0'}>)
814 clipboard request for CLIPBOARD from window ["'Chromium clipboard'", 'xid=a00000', 'pid=19989'], target=TARGETS, prop=CHROME_SELECTION
814 using existing TARGETS value as response: ('text/plain',)
815 set_selection_response(10485760, TARGETS, CHROME_SELECTION, ATOM, 32, b'\xa7\x01\x00\x00\x00\x00\x00\x00', 0)
815 do_x11_selection_request(<X11:SelectionRequest {'serial': '0xe567', 'delivered_to': '0x20000d', 'window': '0x20000d', 'requestor': '10485760', 'selection': 'CLIPBOARD', 'target': 'text/plain', 'property': 'CHROME_SELECTION', 'time': '0x0'}>)
815 do_selection_request_event(<X11:SelectionRequest {'serial': '0xe567', 'delivered_to': '0x20000d', 'window': '0x20000d', 'requestor': '10485760', 'selection': 'CLIPBOARD', 'target': 'text/plain', 'property': 'CHROME_SELECTION', 'time': '0x0'}>)
821 clipboard request for CLIPBOARD from window ["'Chromium clipboard'", 'xid=a00000', 'pid=19989'], target=text/plain, prop=CHROME_SELECTION
821 send_clipboard_request_handler(X11ClipboardProxy(CLIPBOARD), 'CLIPBOARD', 'text/plain')
821 send_clipboard_request CLIPBOARD to CLIPBOARD, id=12
822 process clipboard contents, selection=CLIPBOARD, type=UTF8_STRING, format=8
822 wire selection to raw, encoding=bytes, type=UTF8_STRING, format=8, len(data)=8
823 clipboard wire -> raw: ('UTF8_STRING', 8, 'bytes', sw.js.gz) -> sw.js.gz
823 clipboard got contents(12, 'UTF8_STRING', 8, sw.js.gz): proxy=X11ClipboardProxy(CLIPBOARD) for selection=CLIPBOARD
823 got_contents('text/plain', 'UTF8_STRING', 8, sw.js.gz) pending=(10485760, 'text/plain', 'CHROME_SELECTION', 0)
823 setting response <class 'str'>: sw.js.gz as 'text/plain' on property 'CHROME_SELECTION' of window ["'Chromium clipboard'", 'xid=a00000', 'pid=19989'] as UTF8_STRING
823 set_selection_response(10485760, text/plain, CHROME_SELECTION, UTF8_STRING, 8, sw.js.gz, 0)
823 do_x11_selection_request(<X11:SelectionRequest {'serial': '0xe575', 'delivered_to': '0x20000d', 'window': '0x20000d', 'requestor': '10485760', 'selection': 'CLIPBOARD', 'target': 'TARGETS', 'property': 'CHROME_SELECTION', 'time': '0x0'}>)
824 do_selection_request_event(<X11:SelectionRequest {'serial': '0xe575', 'delivered_to': '0x20000d', 'window': '0x20000d', 'requestor': '10485760', 'selection': 'CLIPBOARD', 'target': 'TARGETS', 'property': 'CHROME_SELECTION', 'time': '0x0'}>)
824 clipboard request for CLIPBOARD from window ["'Chromium clipboard'", 'xid=a00000', 'pid=19989'], target=TARGETS, prop=CHROME_SELECTION
824 using existing TARGETS value as response: ('text/plain',)
824 set_selection_response(10485760, TARGETS, CHROME_SELECTION, ATOM, 32, b'\xa7\x01\x00\x00\x00\x00\x00\x00', 0)

TILs:

  • we receive the clipboard data from Firefox:
got token, selection=CLIPBOARD, targets=('text/plain',), target data={'UTF8_STRING': ('UTF8_STRING', 8, b'sw.js.gz')}, claim=True, can-receive=True
got_contents('TARGETS', 'ATOM', 32, b'\xa7\x01\x00\x00\x00\x00\x00\x00') pending=
got_contents('UTF8_STRING', 'UTF8_STRING', 8, b'sw.js.gz') pending=
claim() we already own the 'CLIPBOARD' selection
  • Chromium requests the TARGETS and we respond with text/plain - chrome does this 4 times in a row!?:
clipboard request for CLIPBOARD from window ["'Chromium clipboard'", 'xid=a00000', 'pid=19989'], target=TARGETS, prop=CHROME_SELECTION
using existing TARGETS value as response: ('text/plain',)
(..)
  • Chromium requests the text/plain target we exposed:
clipboard request for CLIPBOARD from window ["'Chromium clipboard'", 'xid=a00000', 'pid=19989'], target=text/plain, prop=CHROME_SELECTION
send_clipboard_request_handler(X11ClipboardProxy(CLIPBOARD), 'CLIPBOARD', 'text/plain')
send_clipboard_request CLIPBOARD to CLIPBOARD, id=11
setting response <class 'str'>: sw.js.gz as 'text/plain' on property 'CHROME_SELECTION' of window ["'Chromium clipboard'", 'xid=a00000', 'pid=19989'] as UTF8_STRING
783 set_selection_response(10485760, text/plain, CHROME_SELECTION, UTF8_STRING, 8, sw.js.gz, 0)

What's wrong with text/plain?
Surely we don't have to send UTF8_STRING?

@totaam totaam added bug Something isn't working clipboard labels Aug 27, 2024
@totaam
Copy link
Collaborator

totaam commented Aug 27, 2024

I can also reproduce this bug using google-chrome --user-data-dir=~/Downloads in parallel to my usual session.
Comparing this with the native client copying foobar:

  • on right click, the browser requests the TARGETS:
clipboard request for CLIPBOARD from window ["'Chromium clipboard'", 'xid=c00000', 'pid=565521'], target=TARGETS, prop=CHROME_SELECTION
  • the client queries the Terminal app that I used for copying:
requesting local XConvertSelection from ["'Terminal'", 'xid=2a00002', 'pid=516806'] as 'TARGETS' into 'CLIPBOARD-TARGETS'
  • and the server responds to the browser with the value returned by the client:
using existing TARGETS value as response: ('TIMESTAMP', 'TARGETS', 'MULTIPLE', 'SAVE_TARGETS', 'UTF8_STRING', 'COMPOUND_TEXT', 'TEXT', 'STRING', 'text/plain;charset=utf-8', 'text/plain')
  • again, chrome asks for the TARGETS multiple times...
  • eventually, it requests UTF8_STRING:
clipboard request for CLIPBOARD from window ["'Chromium clipboard'", 'xid=c00000', 'pid=565521'], target=UTF8_STRING, prop=CHROME_SELECTION
  • we forward the request to the client and once we get the response, tell the browser:
setting response <class 'bytes'>: b'foobar' as 'UTF8_STRING' on property 'CHROME_SELECTION' of window ["'Chromium clipboard'", 'xid=c00000', 'pid=565521'] as UTF8_STRING
  • on clicking the paste menu entry, google-chrome repeats all these steps again...
    (why bother getting the value if it isn't going to be used?)

At first glance, the only noticeable difference that I can see is text/plain vs UTF8_STRING.

totaam added a commit that referenced this issue Aug 27, 2024
@totaam
Copy link
Collaborator

totaam commented Aug 27, 2024

This xpra server commit fixes things: Xpra-org/xpra@8f446c4

You should have been able to also workaround this issue by selecting UTF8 as the preferred clipboard format from the connect dialog - unfortunately, the html5 client did not honour this setting until c90e479.

Either fix works-for-me(tm).
Both are worth having.

Let me know if you are still having issues.

@totaam totaam closed this as completed Aug 27, 2024
@gashtal
Copy link
Author

gashtal commented Aug 28, 2024

@totaam Thank you for looking into this. I updated to the latest master of the HTML5 client and tried setting the preferred clipboard format to UTF8. At this point, copy from client to server side completely stopped working in every application. Going back to the default text/plain, restores the original behavior where copy from client to server works everywhere except in Google Chrome. My understanding is that this should work without updating XPRA server, correct? I am pulling XPRA from the xpra.org main repository and it will probably take some time until your fix in XPRA server makes it to the repository.

@totaam
Copy link
Collaborator

totaam commented Aug 28, 2024

@gashtal you can easily apply Xpra-org/xpra@8f446c4 to your existing installation.
Using UTF8 worked for me 🤷

@gashtal
Copy link
Author

gashtal commented Aug 28, 2024

@totaam Great suggestion. I modified the file manually and clipboard copy now works in both direction in every application. Copy/pasting clipboard content even seems to be faster than before. 😄
I can finally stop using the OpenGL client. Thank you for your continued support. 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working clipboard
Projects
None yet
Development

No branches or pull requests

2 participants