Conversation
95d425a to
e0d96a5
Compare
There was a problem hiding this comment.
Pull request overview
This pull request replaces UNIX socket-based IPC with XPC (Apple's Inter-Process Communication) for communication between the Nextcloud desktop client and its macOS FinderSync extension. This modernizes the macOS integration to use Apple's recommended XPC framework instead of file-based sockets.
Changes:
- Introduced XPC-based communication infrastructure (
FinderSyncXPC,FinderSyncService,FinderSyncXPCManager) to replace socket-based communication - Removed legacy socket server components (
FileProviderSocketServer,FileProviderSocketController,FinderSyncSocketLineProcessor) - Added XPC protocol definitions (
FinderSyncProtocol,FinderSyncAppProtocol) for bidirectional communication - Updated FinderSync extension to use XPC client instead of socket client
- Maintained SocketApi as the core business logic layer (reused for XPC transport)
Reviewed changes
Copilot reviewed 34 out of 35 changed files in this pull request and generated 17 comments.
Show a summary per file
| File | Description |
|---|---|
| src/gui/macOS/findersyncxpc_mac.mm | New XPC listener implementation for accepting FinderSync connections |
| src/gui/macOS/findersyncxpc.h | XPC manager interface for broadcasting status updates to extensions |
| src/gui/macOS/findersyncservice.mm | XPC service delegate implementing FinderSyncAppProtocol for extension requests |
| src/gui/macOS/findersyncservice.h | Service interface wrapping SocketApi for XPC transport |
| src/gui/socketapi/socketapi.cpp | Added XPC broadcast support alongside socket broadcasts |
| src/gui/socketapi/socketapi.h | Added friend declaration for FinderSyncService to access FileData |
| src/gui/application.cpp | Initialize XPC infrastructure on macOS |
| shell_integration/.../FinderSyncXPCManager.m | XPC client for FinderSync extension to connect to main app |
| shell_integration/.../FinderSync.m | Migrated from socket client to XPC manager |
| src/gui/macOS/fileprovidersocketserver*.* | Removed legacy socket server (File Provider uses XPC now) |
| src/gui/CMakeLists.txt | Updated build to include new XPC files and remove socket files |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
shell_integration/MacOSX/NextcloudIntegration/FinderSyncExt/FinderSyncXPCManager.m
Outdated
Show resolved
Hide resolved
...acOSX/NextcloudFileProviderKit/Sources/NextcloudFileProviderKit/Enumeration/Enumerator.swift
Outdated
Show resolved
Hide resolved
shell_integration/MacOSX/NextcloudIntegration/FinderSyncExt/FinderSyncXPCManager.m
Outdated
Show resolved
Hide resolved
e0d96a5 to
d9f2bba
Compare
d9f2bba to
f521a65
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 33 out of 33 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| for try await result in group { | ||
| for try await _ in group { | ||
| progress.completedUnitCount = 1 |
There was a problem hiding this comment.
Bug: progress.completedUnitCount is being set to 1 instead of incremented. This should be progress.completedUnitCount += 1 or progress.completedUnitCount++ to properly track progress. Currently, it will always show as 1 out of N items completed, never reaching 100%.
| progress.completedUnitCount = 1 | |
| progress.completedUnitCount += 1 |
| const auto parts = msg.mid(7).split(':', Qt::SkipEmptyParts); // Skip "STRING:" | ||
| if (parts.size() >= 2) { | ||
| const QString key = parts[0]; | ||
| const QString value = parts.mid(1).join(':'); // Rejoin in case value contains ':' | ||
| result[key] = value; | ||
| } |
There was a problem hiding this comment.
Potential parsing issue: The split operation uses Qt::SkipEmptyParts which will skip empty values in the split result. If a localized string key or value is intentionally empty, it will be lost. Consider using Qt::KeepEmptyParts and checking parts.size() == 2 exactly, rather than >= 2, to handle this edge case correctly.
nilsding
left a comment
There was a problem hiding this comment.
Some comments for now -- couldn't manage to get the FinderSync XPC connection working in a local dev setup due to sandboxing issues :(
| * This class replaces the LocalSocketClient for FinderSync, providing XPC-based | ||
| * communication instead of UNIX sockets. It establishes a connection to the main app's | ||
| * XPC service and handles method calls in both directions. |
There was a problem hiding this comment.
Speaking of LocalSocketClient, is the shell_integration/MacOSX/NextcloudIntegration/NCDesktopClientSocketKit still required?
There was a problem hiding this comment.
is this duplicate of FinderSyncExt/Services/FinderSyncAppProtocol.h on purpose? if yes: could a symlink to it work here as well?
| // Store socketApi pointer after null check to prevent TOCTOU race | ||
| auto *socketApi = _service ? _service->socketApi() : nullptr; | ||
| if (!socketApi) { | ||
| NSError *error = [NSError errorWithDomain:@"com.nextcloud.desktopclient.FinderSyncService" |
There was a problem hiding this comment.
Does this domain identifier need to be changed if the bundle ID is different as well?
src/gui/macOS/findersyncxpc_mac.mm
Outdated
| // Use __weak to safely capture the connection - it will be zeroed if connection is deallocated | ||
| __weak NSXPCConnection *weakConnection = newConnection; |
There was a problem hiding this comment.
This fails to compile: error: cannot create __weak reference in file using manual reference counting
src/gui/macOS/findersyncservice.mm
Outdated
| { | ||
| } | ||
|
|
||
| void sendMessage(const QString &message, bool = false) const override |
There was a problem hiding this comment.
in order to allow this method to be overridden, the method in the parent class needs to be virtual
|
|
||
| void sendMessage(const QString &message, bool = false) const override | ||
| { | ||
| // Cast away const to store messages (this is a mock for testing) |
There was a problem hiding this comment.
Would say this is a part of the socketless implementation, and not for testing
| // Note: SocketApi is NOT socket-specific - it's the core business logic class that handles | ||
| // file status queries, menu commands, and sync operations across ALL platforms. | ||
| // We reuse SocketApi here as a transport adapter to avoid duplicating business logic. |
There was a problem hiding this comment.
SocketApi still starts up a local socket for listeners to connect though -- if the goal is to remove this for macOS entirely, that class would need to be split into the listener handler + the actual actions to be performed (i.e. API).
Signed-off-by: Iva Horn <iva.horn@nextcloud.com>
f521a65 to
e630785
Compare
|
Artifact containing the AppImage: nextcloud-appimage-pr-9463.zip Digest: To test this change/fix you can download the above artifact file, unzip it, and run it. Please make sure to quit your existing Nextcloud app and backup your data. |
|




The extensions shipped with our app should use XPC exclusively for interprocess communication and drop UNIX file sockets.