Skip to content

Replace UNIX sockets with XPC on macOS#9463

Merged
i2h3 merged 6 commits intomasterfrom
i2h3/feature/9430-all-xpc
Mar 25, 2026
Merged

Replace UNIX sockets with XPC on macOS#9463
i2h3 merged 6 commits intomasterfrom
i2h3/feature/9430-all-xpc

Conversation

@i2h3
Copy link
Copy Markdown
Collaborator

@i2h3 i2h3 commented Feb 17, 2026

Summary

Replaces UNIX socket-based inter-process communication between the Nextcloud desktop client and the macOS Finder Sync extension with Apple's native XPC (cross-process communication) mechanism.

Closes #9430

Motivation

The previous architecture used UNIX domain sockets with a custom line-based text protocol to communicate between the main app and the Finder Sync extension. This approach had several drawbacks:

  • No built-in security: Any process with access to the socket path could connect and send commands
  • Manual protocol parsing: All messages were newline-delimited strings that required hand-written parsing on both ends
  • Fragile connection lifecycle: Socket disconnections, partial reads, and reconnection logic had to be managed manually
  • Platform mismatch: UNIX sockets are a generic POSIX mechanism, not designed for the macOS app extension sandbox model

XPC is Apple's recommended IPC mechanism for app extensions. It provides type-safe method dispatch, automatic connection lifecycle management, and code-signing validation out of the box.

Architecture

Old Architecture (Removed)

Finder Sync Extension
    → LocalSocketClient (UNIX socket connection)
    → FinderSyncSocketLineProcessor (text protocol parser)
    → NCDesktopClientSocketKit (shared socket framework)
                    ↕ UNIX Socket
Main App
    → FileProviderSocketServer (QLocalServer listener)
    → FileProviderSocketController (per-connection handler, text protocol)

New Architecture

Finder Sync Extension
    → FinderSyncXPCManager (XPC client, implements FinderSyncProtocol)
                    ↕ XPC (Mach services)
Main App
    → FinderSyncXPC (XPC listener, broadcasts to connected extensions)
    → FinderSyncService (implements FinderSyncAppProtocol, adapts to SocketApi)

Communication is bidirectional via two complementary protocols:

  • FinderSyncAppProtocol (extension → app): File/folder status queries, context menu requests, command execution
  • FinderSyncProtocol (app → extension): Path registration, status badge pushes, localized string delivery, menu item streaming

Key Design Decisions

  1. SocketApi reuse: Rather than reimplementing business logic, FinderSyncService adapts XPC calls to the existing cross-platform SocketApi class via a ResponseCapturingListener that intercepts command output in-memory instead of writing to a socket. SocketApi is declared as a friend class to allow direct access to FileData.

  2. Thread marshaling: The XPC listener runs on a system-provided thread, but SocketApi must be accessed on Qt's main thread. All calls cross this boundary via QMetaObject::invokeMethod with Qt::BlockingQueuedConnection.

  3. Command whitelisting: The app-side FinderSyncService only allows a predefined set of commands (SHARE, LOCK_FILE, ACTIVITY, etc.) to be executed via XPC, preventing arbitrary command injection from a compromised extension.

  4. Reconnection with exponential backoff: The extension-side FinderSyncXPCManager reconnects automatically on connection interruption (1s → 2s → 4s → 8s max).

  5. Lazy bootstrap: When an extension connects, the app emits extensionConnected() and pushes all currently registered sync folder paths. The extension has no persistent state about folders.

  6. Synchronous menu contract: Finder's menuForMenuKind: API is synchronous, but XPC is async. The extension bridges this with an NSCondition that blocks until the app delivers all menu items and signals completion.

Files Changed

Removed (socket infrastructure)

  • NCDesktopClientSocketKit/ — Entire shared socket framework (LocalSocketClient, LineProcessor)
  • FinderSyncSocketLineProcessor — Extension-side socket protocol parser
  • FileProviderSocketLineProcessor — File provider extension socket parser
  • FileProviderSocketServer / FileProviderSocketController — App-side socket server and per-connection handler

Added (XPC infrastructure)

  • Extension side:
    • FinderSyncXPCManager.h/.m — XPC client with reconnection, status caching, and delegate callbacks
    • Services/FinderSyncAppProtocol.h — Protocol for extension → app calls
    • Services/FinderSyncProtocol.h — Protocol for app → extension calls
  • App side:
    • findersyncxpc.h/.mm — XPC listener, connection management, broadcast to extensions
    • findersyncservice.h/.mm — Implements FinderSyncAppProtocol, adapts XPC to SocketApi
    • FinderSyncProtocol.h / FinderSyncAppProtocol.h — Symlinked protocol headers

Modified

  • FinderSync.h/.m — Rewired from socket line processor to FinderSyncXPCManager
  • FileProviderExtension.swift — Removed socket-related code
  • application.cpp/.h — Instantiates FinderSyncXPC and FinderSyncService, connects extensionConnected signal
  • socketapi.cpp/.h — Added friend declaration for FinderSyncService, minor refactoring
  • CMakeLists.txt — Replaced socket source files with XPC source files
  • macosx.entitlements.cmake — Added mach-register.global-name for XPC service
  • FinderSyncExt.entitlements.cmake — Added mach-lookup.global-name and application groups
  • Signer.swift — Added entitlements for Finder Sync extension during code signing
  • project.pbxproj — Removed socket kit targets and references, added XPC files

Copilot AI review requested due to automatic review settings February 17, 2026 10:54
@i2h3 i2h3 self-assigned this Feb 17, 2026
@i2h3 i2h3 added os: 🍎 macOS Apple macOS, formerly also known as OS X feature: 🐚 shell integration 3. to review feature: 📁 file provider macOS File Provider Extension, more general also known as virtual file system. labels Feb 17, 2026
@github-project-automation github-project-automation Bot moved this to 🧭 Planning evaluation (don't pick) in 💻 Desktop Clients team Feb 17, 2026
@i2h3 i2h3 moved this from 🧭 Planning evaluation (don't pick) to 🏗️ In progress in 💻 Desktop Clients team Feb 17, 2026
@i2h3 i2h3 force-pushed the i2h3/feature/9430-all-xpc branch from 95d425a to e0d96a5 Compare February 17, 2026 10:55
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread src/gui/macOS/findersyncservice.mm Outdated
Comment thread src/gui/macOS/findersyncxpc_mac.mm Outdated
Comment thread src/gui/macOS/findersyncservice.mm Outdated
Comment thread src/gui/macOS/findersyncservice.mm
Comment thread src/gui/macOS/findersyncxpc_mac.mm
Comment thread src/gui/macOS/findersyncservice.mm Outdated
Comment thread src/gui/macOS/findersyncxpc_mac.mm Outdated
@i2h3 i2h3 force-pushed the i2h3/feature/9430-all-xpc branch from e0d96a5 to d9f2bba Compare February 17, 2026 12:17
@i2h3 i2h3 added this to the 33.0.0 milestone Feb 17, 2026
@i2h3 i2h3 force-pushed the i2h3/feature/9430-all-xpc branch from d9f2bba to f521a65 Compare February 17, 2026 13:44
@i2h3 i2h3 requested a review from Copilot February 17, 2026 13:44
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread src/gui/macOS/findersyncservice.mm Outdated
Copy link
Copy Markdown
Member

@nilsding nilsding left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some comments for now -- couldn't manage to get the FinderSync XPC connection working in a local dev setup due to sandboxing issues :(

Comment thread shell_integration/MacOSX/NextcloudIntegration/FinderSyncAppProtocol.h Outdated
Comment thread src/gui/macOS/findersyncservice.mm
Comment thread src/gui/macOS/findersyncxpc_mac.mm Outdated
Comment thread src/gui/macOS/findersyncservice.mm
Comment thread src/gui/macOS/findersyncservice.mm Outdated
Comment thread src/gui/macOS/findersyncservice.mm
@i2h3 i2h3 force-pushed the i2h3/feature/9430-all-xpc branch from f521a65 to e630785 Compare February 18, 2026 07:43
@i2h3 i2h3 removed this from the 33.0.0 milestone Feb 18, 2026
@i2h3 i2h3 marked this pull request as draft February 18, 2026 08:41
@i2h3 i2h3 modified the milestone: 33.0.0 Feb 18, 2026
@i2h3 i2h3 modified the milestones: 33.1.0, 33.0.1, 34.0.0 Feb 26, 2026
@i2h3 i2h3 force-pushed the i2h3/feature/9430-all-xpc branch from e630785 to 0a25197 Compare March 17, 2026 14:00
@i2h3 i2h3 changed the title feat(macOS): Replace UNIX sockets with XPC Replace UNIX sockets with XPC on macOS Mar 18, 2026
@i2h3 i2h3 force-pushed the i2h3/feature/9430-all-xpc branch 3 times, most recently from a821dcd to eab690c Compare March 24, 2026 14:41
@i2h3 i2h3 marked this pull request as ready for review March 24, 2026 16:07
@i2h3
Copy link
Copy Markdown
Collaborator Author

i2h3 commented Mar 24, 2026

The failing tests are not related to this pull request, as it appears.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 41 out of 41 changed files in this pull request and generated 15 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/gui/macOS/findersyncservice.mm Outdated
Comment thread src/gui/macOS/findersyncxpc_mac.mm
Comment thread shell_integration/MacOSX/NextcloudIntegration/FinderSyncExt/FinderSync.m Outdated
Comment thread src/gui/macOS/findersyncservice.mm
Comment thread src/gui/macOS/findersyncservice.mm
Comment thread src/gui/macOS/findersyncservice.mm
Comment thread src/gui/macOS/findersyncxpc_mac.mm
Comment thread src/gui/macOS/findersyncxpc_mac.mm Outdated
Comment thread src/gui/application.cpp
Comment thread src/gui/socketapi/socketapi.cpp Outdated
@i2h3 i2h3 force-pushed the i2h3/feature/9430-all-xpc branch from eab690c to d3a3678 Compare March 25, 2026 09:24
Replace the UNIX domain socket IPC between the desktop client and the
macOS Finder Sync extension with Apple's native XPC mechanism.

Motivation:

The socket-based approach used a custom line-based text protocol over
UNIX domain sockets, requiring manual parsing, hand-managed connection
lifecycles, and offering no built-in security validation. XPC is Apple's
recommended IPC for app extensions, providing type-safe method dispatch,
automatic lifecycle management, and code-signing verification.

Architecture:

Two Objective-C protocols define a bidirectional XPC contract:

- FinderSyncAppProtocol (extension -> app): file/folder status queries,
  context menu requests, and command execution.
- FinderSyncProtocol (app -> extension): path registration, status badge
  pushes, localized string delivery, and menu item streaming.

On the app side, FinderSyncXPC manages the XPC listener and broadcasts
to all connected extensions. FinderSyncService implements the app
protocol by adapting calls to the existing cross-platform SocketApi
business logic via a ResponseCapturingListener, avoiding any
reimplementation of sync status or menu command handling. Thread safety
across XPC and Qt threads is ensured via QMetaObject::invokeMethod with
blocking queued connections.

On the extension side, FinderSyncXPCManager handles connection setup,
reconnection with exponential backoff, and status caching. FinderSync
(the FIFinderSync subclass) delegates all communication to the XPC
manager and bridges Finder's synchronous menuForMenuKind: API to XPC's
async model using NSCondition.

Security is enforced through macOS entitlements (mach-register and
mach-lookup for the FinderSyncService name) and a server-side command
whitelist that restricts executable commands to a predefined set.

Removed:

- NCDesktopClientSocketKit framework (LocalSocketClient, LineProcessor)
- FinderSyncSocketLineProcessor and FileProviderSocketLineProcessor
- FileProviderSocketServer and FileProviderSocketController

Resolves #9430

Signed-off-by: Iva Horn <iva.horn@nextcloud.com>
@i2h3 i2h3 force-pushed the i2h3/feature/9430-all-xpc branch from d3a3678 to c447fdb Compare March 25, 2026 12:31
i2h3 and others added 5 commits March 25, 2026 14:38
qobject_cast<Application*> requires the complete type definition, not
just the forward declaration from folderman.h. This fixes the macOS
classic client build (without BUILD_FILE_PROVIDER_MODULE).

Signed-off-by: Iva Horn <iva.horn@nextcloud.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
clang-tidy-diff defaults to processing .m and .mm files, but the CI
runs on ubuntu-latest where macOS framework headers (Foundation, etc.)
are unavailable. Add -regex flag to restrict analysis to C/C++ files.

Signed-off-by: Iva Horn <iva.horn@nextcloud.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
QPointer<QIODevice> requires QIODevice to be a complete type so the
compiler can verify it inherits from QObject. Without the include,
clang-tidy on Linux (where QIODevice is not transitively included)
fails with an incomplete-type error.

Signed-off-by: Iva Horn <iva.horn@nextcloud.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
application.h only forward-declares Mac::FinderSyncXPC. The call to
finderSyncXPC->setStatusResult() requires the full definition, so
include findersyncxpc.h directly (guarded by Q_OS_MACOS).

Signed-off-by: Iva Horn <iva.horn@nextcloud.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The previous regex excluded .m/.mm files but Objective-C headers (.h)
under macOS/ and MacOSX/ directories still import Foundation and Cocoa
frameworks unavailable on Linux. Use negative lookahead to skip files
in these directories entirely.

Signed-off-by: Iva Horn <iva.horn@nextcloud.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

Artifact containing the AppImage: nextcloud-appimage-pr-9463.zip

Digest: sha256:039fce4d53c52d6eadc12cc810286e9fb7df6b5791d0098862be9d8b1e91438d

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.

@sonarqubecloud
Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
50.0% Coverage on New Code (required ≥ 80%)
B Maintainability Rating on New Code (required ≥ A)
D Security Rating on New Code (required ≥ A)
52 New Code Smells (required ≤ 0)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

@i2h3 i2h3 merged commit 802ebf9 into master Mar 25, 2026
22 of 23 checks passed
@i2h3 i2h3 deleted the i2h3/feature/9430-all-xpc branch March 25, 2026 15:36
@github-project-automation github-project-automation Bot moved this from 🏗️ In progress to ☑️ Done in 💻 Desktop Clients team Mar 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

3. to review feature: 📁 file provider macOS File Provider Extension, more general also known as virtual file system. feature: 🐚 shell integration os: 🍎 macOS Apple macOS, formerly also known as OS X

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Replace UNIX Sockets with XPC

4 participants