NSXPCConnection between app and FinderSync extension

Hello,
I'm trying to get my app to communicate with a FinderSync extension using XPC.
In my app, I run the listener:
_xpcListener = [[NSXPCListener alloc] initWithMachServiceName:_serviceName];
_xpcListener.delegate = self;
[_xpcListener resume];
Where _serviceName="a.b.c.d.e.f"

In Info.plist of the app bundle, I have:
<key>MachServices</key>
<dict>
<key>a.b.c.d.e.f</key>
<true/>
</dict>

In the FinderSync ext, I try to connect to the XPC service:
_xpcConnection = [[NSXPCConnection alloc] initWithMachServiceName:_serviceName options:0];
...
[_xpcConnection resume];

It works in debug, but not when the app is installed.
In this case, _xpcConnection.invalidationHandler is called.

The FinderSync ext belongs to the app bundle.
The .entitlements of the App:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "...">
<plist version="1.0">
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>a.b.c.d.e</string>
</array>
</dict>
</plist>

The .entitlements of the FinderSync:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "...">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.application-groups</key>
<array>
<string>a.b.c.d.e</string>
</array>
</dict>
</plist>

The app is notorized:
% spctl --assess -vvvv /Applications/myApp.app                
/Applications/myApp.app: accepted
source=Notarized Developer ID
origin=Developer ID Application: ...

In the Console, just after the start of the listener, there is this error (3 times) for myApp process:
Trust evaluate failure: [leaf TemporalValidity]

So I checked its certificates, but they are valid:
% codesign -dvvvv --extract-certificates /Applications/myApp.app
% openssl x509 -inform DER -in codesign0 -text
...
Validity
      Not Before: Jun 22 11:59:25 2020 GMT
      Not After : Jun 23 11:59:25 2025 GMT
..
% openssl x509 -inform DER -in codesign1 -text
...
Validity
      Not Before: Feb 1 22:12:15 2012 GMT
      Not After : Feb 1 22:12:15 2027 GMT
...
% openssl x509 -inform DER -in codesign2 -text
...
Validity
      Not Before: Apr 25 21:40:36 2006 GMT
      Not After : Feb 9 21:40:36 2035 GMT
...

The computer date is Ok:
% date
Thu Apr 8 09:20:44 CEST 2021

In the console, there is also this error for tccd process:
Prompting policy for hardened runtime; service: kTCCServiceAppleEvents requires entitlement com.apple.security.automation.apple-events but it is missing for accessing={identifier=a.b.c.d.e, pid=12245, auid=501, euid=501, binary_path=/Applications/myApp.app/Contents/PlugIns/Extension.appex/Contents/MacOS/Extension}, requesting={identifier=com.apple.appleeventsd, pid=328, auid=55, euid=55, binary_path=/System/Library/CoreServices/appleeventsd},

I tried to add this com.apple.security.automation.apple-events entitlement to App and ext, but it didn't fix the problem.

How can I debug this issue?
Thank you.

Accepted Reply

I finally managed to make it working.
The thing is initWithMachServiceName must be called with:
  • from the app: the full path of the login item bundle, i.e. /Applications/myApp.app/Contents/Library/LoginItems/a.b.c.d.e.LoginItemAgent.app

  • from the FinderSync ext: the bundle id of the login item, i.e. a.b.c.d.e.LoginItemAgent

Replies

I have also tried without success to set com.apple.security.temporary-exception.mach-register.global-name/com.apple.security.temporary-exception.mach-lookup.global-name entitlements.

In myApp.entitlements:
...
<key>com.apple.security.temporary-exception.mach-register.global-name</key>
<array>
<string>a.b.c.d.e.f</string>
</array>

And in Extension.entitlements:
...
<key>com.apple.security.temporary-exception.mach-lookup.global-name</key>
<array>
<string>a.b.c.d.e.f</string>
</array>


Should I use an XPC login item app between the app and the extension?
myApp <=> XPC login item app <=> FinderSync ext

By dint of searching, I came across the AppLoginItemXPCDemo example, but it dates from 2012 ... No better solution has been proposed by Apple since? It seems like it's a common problem to get an application to communicate with a FinderSync extension ...



Should I use an XPC login item app between the app and the extension?

Yes. The problem here is that XPC does not let you register arbitrary services; rather, the XPC service must somehow be managed by launchd. This means that you can’t register a service in your app so that your appex can connect to it, or vice versa. The best way around this conundrum is to register the XPC service in a Service Management login item, which both your app and your appex can ‘see’.

Note that this does not require the login item to relay each message. You can have the local peer (the app or the appex) create an anonymous listener and send its endpoint to the remote peer via an initial XPC message relayed by the login item. Once you do that, however, the remote peer can then connect to the local peer directly via that endpoint.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
  • | "[the] way around this conundrum is to register the XPC service in a Service Management login item"

    And how does one "register the XPC service" - the docs make no mention of having to do any registration.

Add a Comment
Ok, thank you.
So I'm trying to make working the AppLoginItemXPCDemo example.

In the readme, I found that "The bundle identifier of a login item must start with your Team ID", but my Team ID starts with a figure and this is not accepted by XCode.
Is there a solution?
So, I've been able to set my bundle id starting with a figure from the Build Settings tab...

Now my app can communicate with the login item agent, but the FinderSync, still not...
I found this error in the Console:
Sandbox: Extension(7145) deny(1) file-read-data .....myApp.app/Contents/Library/LoginItems/a.b.c.d.e.LoginItemAgent.app

The app, FinderSync ext and login item agent are all in the same App Group, sandboxed and signed with "Apple Development" (debuging in XCode).
Any idea?

I finally managed to make it working.
The thing is initWithMachServiceName must be called with:
  • from the app: the full path of the login item bundle, i.e. /Applications/myApp.app/Contents/Library/LoginItems/a.b.c.d.e.LoginItemAgent.app

  • from the FinderSync ext: the bundle id of the login item, i.e. a.b.c.d.e.LoginItemAgent

And how does one "register the XPC service"

XPC service is an overloaded term, which makes the text you quoted ambiguous. Sorry about that.

An XPC service is a bundled program embedded within an app, framework, and so on. When launchd discovers an XPC service, it registers a named XPC endpoint using the XPC service’s bundle ID. A client in the right context [1] can connect to that endpoint using -initWithServiceName:.

There are a number of other ways to publish a named XPC endpoint. For example, if you have a launchd daemon or agent then the names you list in your MachServices property are registered by launchd. In this specific case, if you create a Service Management login item [2], launchd will register its bundle ID has a named XPC endpoint. Your app and Finder Sync extension can open a connection to its listener by passing that name to -initWithMachServiceName:options.

For more general background on this stuff, see the docs and DevForums posts linked to by XPC Resources.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] The phrase “right context” is carrying a lot of weight here (-:

[2] As illustrated by the AppSandboxLoginItemXPCDemo sample code.