feat: add GET_PRIVATE_LINK socket command for Wayland clipboard support#12535
feat: add GET_PRIVATE_LINK socket command for Wayland clipboard support#12535DeepDiver1975 wants to merge 5 commits into
Conversation
|
Thanks for opening this pull request! The maintainers of this repository would appreciate it if you would create a changelog item based on your changes. |
Sends PRIVATE_LINK:<url> back over the socket so that file manager extensions running inside processes with a valid Wayland surface can write to the clipboard themselves, working around the compositor serial requirement that prevents the background daemon from doing so. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Thomas Müller <1005065+DeepDiver1975@users.noreply.github.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Thomas Müller <1005065+DeepDiver1975@users.noreply.github.com>
cff9221 to
413bd02
Compare
The test duplicated the Unix socket path logic, which broke on macOS where socketApiSocketPath() returns an XPC-style name instead of a filesystem path. Use the canonical helper so the test connects to the same socket the server listens on across all platforms. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Thomas Müller <1005065+DeepDiver1975@users.noreply.github.com>
Without OWNCLOUDGUI_EXPORT the symbol had hidden visibility and was not exported, causing an undefined symbol linker error when SocketApiTest tried to call it on macOS. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Thomas Müller <1005065+DeepDiver1975@users.noreply.github.com>
The previous test used QLocalSocket to connect to the SocketApi server, which doesn't work on macOS where the server uses an XPC-based transport instead of a local socket file. Replace with direct invocation of command_GET_PRIVATE_LINK via QMetaObject::invokeMethod, capturing output in a QBuffer backed SocketListener. This is a pure unit test of the command handler with no dependency on the platform-specific socket transport. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Thomas Müller <1005065+DeepDiver1975@users.noreply.github.com>
dj4oC
left a comment
There was a problem hiding this comment.
Adds a new GET_PRIVATE_LINK socket-API command so shell-integration extensions can retrieve a private-link URL directly (for platforms where clipboard write is unreliable, e.g. Wayland), plus a new unit test.
Findings
Security: Clean — reuses the existing fetchPrivateLinkUrlHelper already used by COPY_PRIVATE_LINK/EMAIL_PRIVATE_LINK; any peer already authorized to reach the socket can already obtain this URL via those commands, so this adds a delivery mechanism rather than new attack surface. The socket's peer-auth model (0700 runtime-dir socket / per-user named pipe) is untouched. The new OWNCLOUDGUI_EXPORT on socketApiSocketPath() is a visibility annotation for the test binary, not a new external interface.
Stability: Block — command_GET_PRIVATE_LINK captures a raw SocketListener *listener pointer in a lambda passed to the asynchronous fetchPrivateLinkUrlHelper (a PROPFIND round-trip). Every existing V1 handler only touches listener synchronously; if the socket disconnects before the async reply arrives, _listeners.remove(socket) drops the last QSharedPointer<SocketListener> and frees the object, and the pending lambda's listener->sendMessage(...) becomes a use-after-free. Recommend retaining a QSharedPointer<SocketListener> by value in the capture (as SocketApiJobV2 already does for exactly this problem) instead of a raw pointer, or implementing this as a V2 command.
Performance: Clean — same async, non-blocking pattern as sibling commands; no new UI-thread blocking or polling.
Coverage: Gap — the two added tests cover the happy path and "file not synced," but not: capability disabled (privateLinkPropertyAvailable() == false, which silently no-ops), PROPFIND failure/timeout, or an empty privatelink property — all of which currently collapse to the same silent "no message sent" as the tested negative case. Since this directly backs Wayland clipboard UX, at least a disabled-capability and a PROPFIND-error test should be added.
Cross-platform check
Clean — additive Q_INVOKABLE command, no wire-format change to existing commands; old clients unaffected.
Verdict
Changes requested
🤖 Automated review by Claude Code (security · stability · performance · coverage)
Generated by Claude Code
Problem
On native Wayland sessions the ownCloud daemon has no compositor surface.
QApplication::clipboard()->setText()requires a valid Waylandwl_data_deviceserialfrom a recent input event, but a tray-only app (system tray via
StatusNotifierItem)never receives seat events and so never has one. The compositor silently drops the
clipboard write. Copy private link to clipboard is broken for all users on Wayland.
Qt 6.9+ added
zwlr-data-controlsupport as a partial fix (QT_WAYLAND_USE_DATA_CONTROL=1),but it requires an environment variable and only works on KDE/wlroots compositors — not on
GNOME/Mutter, which is the primary affected environment.
Solution
Add
GET_PRIVATE_LINK:<file>→PRIVATE_LINK:<url>to the socket protocol. File managerextensions that run inside processes with a real Wayland surface (Nautilus, Dolphin) can
request the URL and write to the clipboard themselves.
The command reuses
fetchPrivateLinkUrlHelper()— ~7 lines of new production code.COPY_PRIVATE_LINKis unchanged for X11 and for extensions that do not yet use the newcommand.
Related
Backward compatibility
GET_PRIVATE_LINKtimes out (3 s), falls through toCOPY_PRIVATE_LINKCOPY_PRIVATE_LINK)