Post

Replies

Boosts

Views

Created

Is it possible to run a Java .jar as a public XPC Service available to all Applications?
I apologize for attempting this monstrosity, but... It is forced on me. I have a .jar implementing logic that I receive prebuilt. This .jar exports some API you can use (... in Java...) to request information about file-system items you hand in as paths. This .jar is compatible with Java 11, and runs with the "Zulu" Java VM. I need to "wrap" it in some way that will behave like a global daemon, launched and managed by launchd, available to other components (apps, user-agents and global-daemons) in our product. Running it as a global daemon is a breeze - simply place a .plist in /Library/LaunchDaemons/myMonster.plist and have the java -jar <path to my .jar> arguments, throw in a 'keep alive' option, and it runs. Now... It makes sense for other components to pass it "queries" and receive "results" via XPC connection. First, because this way I could deny connection to unknown components, I could have a secure connection, and also integrate nicely from the other components ObjC code. However... XPC isn't something available in JDK, and the actual executable launched is the Zulu java command binary of course, that I can't modify. So... I tried to use JNA (Java Native Access) and (with much tears and sweat) get my java code to create an xpc connection (as client! not "service") to another XPC Service already running. Also, I was only able to do it via xpc.h (the old C API. not ObjC NSXPCConnection as of yet). The documentation on old C-style XPC Services is very thin, almost nothing... and the only thing about Creating an XPC Service of this style says: // If you are writing a low-level (C-based) XPC service, implement a minimal main function to register your event handler, as shown in the following code listing. Replace my_event_handler with the name of your event handler function. int main(int argc, const char *argv[]) { xpc_main(my_event_handler); // The xpc_main() function never returns. exit(EXIT_FAILURE); } Which of course, I can't do! I don't control the process 'main()' entry point (it's java...) and I can't block anything. So here's my question: Where in the lifecycle of a Java program can I call on my native code to set up The XPC Service? Is there a non-blocking alternative to xpc_main(my_event_handler) I can use to start my service? I know this calls for multi-disciplinary knowledge but any hint or idea will be greatly appreciated. Thanks!
4
0
2.0k
Dec ’21
UNUserNotificationCenter delegate does not receive UNNotificationDismissActionIdentifier when user dismisses whole thread pressing "Clear All" button
Hi. I'm implementing UNUserNotificationCenter delegate method: userNotificationCenter(_:didReceive:withCompletionHandler:) in MacOS Big-Sur and Catalina, in order to be notified when user dismisses local notifications of my App. (we also handle UNNotificationDefaultActionIdentifier to focus our UI on the item related to the clicked notification, and we also support 2 custom actionIDs. It all basically works, and even the UNNotificationDismissActionIdentifier arrives at the delegate when user dismisses a single notification. (presses the X shaped button on the top-left). However, when we have a thread of notifications (grouped by some unique threadID, and looks like a stack onscreen) and the user presses the X and then the "Clear all" button to dismiss the whole thread -- the delegate is only called once, for one arbitrary notification in the stack, and there is no way for me to know that a whole thread was dismissed. Am I doing something wrong? Is this a limitation of the delegate protocol? Is this a bug in UNUserNotificationCenter implementation? Is there a workaround, or some trick to know that a whole bunch of notifications were dismissed? Here's my delegate code (sans irrelevant code...) // Handle notification back-actions - (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(nonnull UNNotificationResponse *)response          withCompletionHandler:(nonnull void (^)(void))completionHandler API_AVAILABLE(macos(10.14)) {     NSString *actionId = response.actionIdentifier;     UNNotificationRequest *request = response.notification.request;     NSString *requestId = request.identifier;     NSString *userActionIdentifier = request.content.threadIdentifier;     NSDictionary * myInfo = request.content.userInfo;     if ([actionId isEqualToString:UNNotificationDefaultActionIdentifier]) { // user opened the application from the notification         if ([self.delegate respondsToSelector:@selector(displayThread:forInfo)]) {             dispatch_async(dispatch_get_main_queue(), ^{                 [self.delegate displayThread:userActionIdentifier forInfo: myInfo];             });         }         completionHandler();         return;     }         NSString *userReply = nil;     if ([actionId isEqualToString:UNNotificationDismissActionIdentifier]) { // user dismissed the notification         os_log_debug(myLog, "Notification: %{public}@ dismissed", requestId);     }     else { // custom action         NSString *categoryId = response.notification.request.content.categoryIdentifier;         if ([categoryId isEqualToString:OITNotification.copyAction]) {             os_log_debug(myLog, "Notification: %{public}@ dismissed with custom action:%{public}@", requestId, actionId);         }         if ([categoryId isEqualToString:OITPreventionNotification.copyActionWithReply]) {             if ([actionId isEqualToString:@"other"]) {                 userReply = [(UNTextInputNotificationResponse*)response userText];                 os_log_debug(myLog, "Notification: %{public}@ User custom reply: %{public}@", requestId, userReply);             }             else {                 userReply = actionId;                 os_log_debug(myLog, "Notification: %{public}@ User Action: %{public}@", requestId, actionId);             }         }     }     if ([self.delegate respondsToSelector:@selector(notification:dismissedWithReply:)]) {         [self.delegate notification:myInfo dismissedWithReply:userReply];     }     [self removeModelIdentifiers:@[response.notification.request.identifier]];     completionHandler();     return; } Please ignore the tedious handling of custom actions - my problem is only with "Clear All" thread dismissals. I bring the code just for completeness, in the hopes that someone sees a fault I can't see --- Thank you very much.
0
0
1.4k
Oct ’21
Is it possible to obtain the NSUserActivity related to EndpointSecurity message?
I believe this is a general problem when writing low-level security and monitoring tools. The EndpointSecurity framework provides lots of information for the events it allows to Monitor (and/or Authorize) but all these are "kernel level" details, that usually don't allow understanding (and aggregating) low-level events according to User Intent e.g. Saving all attachments of an e-mail message from Apple Mail program to a USB-disk, will create a long series of low-level file-system events, some preliminary (touching and verifying the destination can fit the attachments) some for moving/copying, some for rounding-up, some for indexing those files on the new volume, and so on. Is it possible to somehow obtain the NSUserActivity object/instance/Identifier related to such low-level event? Is the kernel itself aware of user activities? Any hint or suggestion or strategy will be greatly appreciated
0
0
1.1k
Jul ’21
Is it possible to use UNUserNotificationCenter from a LaunchAgent?
Hi, I have a LaunchAgent (whose .plist is in /Library/LaunchAgents/ as expected) It is build as a single un-bundled binary, and installed away from regular user access at /Library/MyCompany/executables/ When I try to init a reference to UNUserNotificationCenter: UNUserNotificationCenter *unc = [UNUserNotificationCenter currentNotificationCenter]; I immediately have an exception, like thus: 2021-05-02 19:57:39.297823+0300 agent[12504:225879] *** Assertion failure in +[UNUserNotificationCenter currentNotificationCenter], /AppleInternal/BuildRoot/Library/Caches/com.apple.xbs/Sources/UserNotifications/UserNotifications-281.6/UNUserNotificationCenter.m:44 2021-05-02 19:57:39.299464+0300 agent[12504:225879] [General] An uncaught exception was raised 2021-05-02 19:57:39.299518+0300 agent[12504:225879] [General] bundleProxyForCurrentProcess is nil: mainBundle.bundleURL file:///Users/mshneor/Library/Developer/Xcode/DerivedData/agent-dgvdlbtivmsjdgdkhhjwaxgrkyht/Build/Products/Debug/ Obviously the problem is bundleProxyForCurrentProcess is nil: mainBundle.bundleURL Now... I could try to bundle my agent somehow, but that's a bit awkward, and I don't know how - it's not an App, and It's not a part of any App, and I don't know about a special "Code Bundle" type (like plugins etc.) that fits a LaunchAgent. Moreover - it will never be "launched" by it's info.plist in the bundle - only via the .plist in /Library/LaunchAgents by launchd. So... is it possible to work around this? Could I somehow tell my Agent's process "Here is our main-bundle" at runtime, and provide a special bundle the agent is not embedded in? what does UNUserNotificationCenter need from main bundle? maybe I can supply this programmatically in advance? Any hint will be greatly appreciated.
4
0
2.5k
May ’21
How to publish an XPC Service in a global daemon that employs EndpointSecurity framework?
I have a global daemon managed by launchd, whose .plist is installed in /Library/LaunchDaemons). To be correctly entitled and code-signed so it can communicate with EndpointSecurity framework, its executable resides in a normal Mac App bundle (main() will run as minimal UI when launched from UI, and as a daemon when launched by launchd). This means that the ProgramArguments.0 in its .plist looks something like /Library/PrivilegedHelperTools/MyDaemonApp.app/Contents/MacOS/MyDaemonApp Now I need this daemon to publish an XPC Service (with few control commands) so that other components of our system (UI app, a user-context launchd-daemon and another launchd global-daemon) will be able to connect to The XPC Service and control it via the published protocol. I read some answers here, and also found a working order sample code that does just this here - https://github.com/jdspoone/SampleOSXLaunchDaemon But when I apply its content to my global daemon, word for word - it doesn't work - meaning, clients cannot create a connection to The XPC Service. The daemon is up and running, and functional. its .plist is quite simple and looks like this: <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Label</key> <string>com.mycompany.itm.service</string> <key>KeepAlive</key> <true/> <key>RunAtLoad</key> <true/> <key>MachServices</key> <dict> <key>com.mycompany.itm.service</key> <true/> </dict> <key>ProgramArguments</key> <array> <string>/Library/PrivilegedHelperTools/IMyDaemonApp.app/Contents/MacOS/MyDaemonApp</string> <string>-monitor</string> <string>-protectDeviceProtocol</string> <string>USB</string> </array> </dict> </plist> It creates and starts an XPC listener in MYXPCListener.h like thus: #import <Foundation/Foundation.h> #import "MYXPCProtocol.h" NS_ASSUME_NONNULL_BEGIN @interface OITPreventionXPCService : NSObject (instancetype) init; (void) start; /* Begin listening for incoming XPC connections */ (void) stop; /* Stop listening for incoming XPC connections */ @end NS_ASSUME_NONNULL_END and the implementation is: /* AppDelegate.m */ @interface MYXPCService () <NSXPCListenerDelegate, OITPreventionXPCProtocol> @property (nonatomic, strong, readwrite) NSXPCListener *listener; @property (nonatomic, readwrite) BOOL started; @end @implementation OITPreventionXPCService (instancetype) init {     if ((self = [super init]) != nil) {         _listener = [[NSXPCListener alloc] initWithMachServiceName:@"com.mycompany.itm.service"];         _listener.delegate = self;         if (_listener == nil) {             os_log_error(myLog, "XPCListener failed to initialize");         }         _started = NO;     }     return self; } (void) start {     assert(_started == NO);     [_listener resume];     os_log_info(myLog, "XPCListener resumed");     _started = YES; } (void) stop {     assert(_started == YES);     [_listener suspend];     os_log_info(myLog, "XPCListener suspended");     _started = NO; } /* NSXPCListenerDelegate implementation */ (BOOL) listener:(NSXPCListener *)listener shouldAcceptNewConnection:(NSXPCConnection *)newConnection {     os_log_info(myLog, "Prevention XPCListener is bequsted a new connection");     assert(listener == _listener);     assert(newConnection != nil);     newConnection.exportedInterface = [NSXPCInterface interfaceWithProtocol:@protocol(MYXPCProtocol)];     newConnection.exportedObject = self; &#9;&#9;[newConnection resume];     return YES; } /* Further down this implementation, I have implementations to all the methods in MYXPCProtocol. */ @end Now the client code (and I tried EVERY kind of client, signed unsigned, daemon, UI, root privileged, or user-scoped - whatever). For example, in the AppDelegate of a UI app: #import "AppDelegate.h" #import "MYXPCProtocol.h" @interface AppDelegate () @property (strong) IBOutlet NSWindow *window; @property (nonatomic, strong, readwrite) NSXPCConnection *connection; /* lazy initialized */ @end @implementation AppDelegate (NSXPCConnection *) connection {     if (_connection == nil) {         _connection = [[NSXPCConnection alloc] initWithMachServiceName:daemonLabel options:NSXPCConnectionPrivileged];         _connection.remoteObjectInterface = [NSXPCInterface interfaceWithProtocol:@protocol(MYXPCProtocol)];         _connection.invalidationHandler =  ^{             self->_connection = nil;             NSLog(@"connection has been invalidated");         };         [_connection resume];         /* New connections always start suspended */     }     return _connection; } (IBAction) getServiceStatus:(id)sender {     [self.connection.remoteObjectProxy getStatus:^(NSString * _Nonnull status) {         NSLog(@"MY XPC Service status is: %@", status);     }]; } @end but no matter what I do - I always get the "connection invalidated". The sample launchDaemon that works - is not code-signed at all!!! but mine, which is both signed and checking of which yields $ spctl --assess --verbose IMyDaemonApp.app IMyDaemonApp.app: accepted source=Notarized Developer ID   I'm at a loss - and would like to get any advice, or any helpful documentation (I've been reading TN2083, and man launchctl and man launchd.plist and many other pages - to no avail. There seems to be no real "programming guide" for XPC and no reasonable sample code on Apple developer site to fit my needs. Last - this is MacOS 10.15.7, and latest Xcode 12.3
7
0
2.9k
Jan ’21
Is it possible to run a Java .jar as a public XPC Service available to all Applications?
I apologize for attempting this monstrosity, but... It is forced on me. I have a .jar implementing logic that I receive prebuilt. This .jar exports some API you can use (... in Java...) to request information about file-system items you hand in as paths. This .jar is compatible with Java 11, and runs with the "Zulu" Java VM. I need to "wrap" it in some way that will behave like a global daemon, launched and managed by launchd, available to other components (apps, user-agents and global-daemons) in our product. Running it as a global daemon is a breeze - simply place a .plist in /Library/LaunchDaemons/myMonster.plist and have the java -jar <path to my .jar> arguments, throw in a 'keep alive' option, and it runs. Now... It makes sense for other components to pass it "queries" and receive "results" via XPC connection. First, because this way I could deny connection to unknown components, I could have a secure connection, and also integrate nicely from the other components ObjC code. However... XPC isn't something available in JDK, and the actual executable launched is the Zulu java command binary of course, that I can't modify. So... I tried to use JNA (Java Native Access) and (with much tears and sweat) get my java code to create an xpc connection (as client! not "service") to another XPC Service already running. Also, I was only able to do it via xpc.h (the old C API. not ObjC NSXPCConnection as of yet). The documentation on old C-style XPC Services is very thin, almost nothing... and the only thing about Creating an XPC Service of this style says: // If you are writing a low-level (C-based) XPC service, implement a minimal main function to register your event handler, as shown in the following code listing. Replace my_event_handler with the name of your event handler function. int main(int argc, const char *argv[]) { xpc_main(my_event_handler); // The xpc_main() function never returns. exit(EXIT_FAILURE); } Which of course, I can't do! I don't control the process 'main()' entry point (it's java...) and I can't block anything. So here's my question: Where in the lifecycle of a Java program can I call on my native code to set up The XPC Service? Is there a non-blocking alternative to xpc_main(my_event_handler) I can use to start my service? I know this calls for multi-disciplinary knowledge but any hint or idea will be greatly appreciated. Thanks!
Replies
4
Boosts
0
Views
2.0k
Activity
Dec ’21
UNUserNotificationCenter delegate does not receive UNNotificationDismissActionIdentifier when user dismisses whole thread pressing "Clear All" button
Hi. I'm implementing UNUserNotificationCenter delegate method: userNotificationCenter(_:didReceive:withCompletionHandler:) in MacOS Big-Sur and Catalina, in order to be notified when user dismisses local notifications of my App. (we also handle UNNotificationDefaultActionIdentifier to focus our UI on the item related to the clicked notification, and we also support 2 custom actionIDs. It all basically works, and even the UNNotificationDismissActionIdentifier arrives at the delegate when user dismisses a single notification. (presses the X shaped button on the top-left). However, when we have a thread of notifications (grouped by some unique threadID, and looks like a stack onscreen) and the user presses the X and then the "Clear all" button to dismiss the whole thread -- the delegate is only called once, for one arbitrary notification in the stack, and there is no way for me to know that a whole thread was dismissed. Am I doing something wrong? Is this a limitation of the delegate protocol? Is this a bug in UNUserNotificationCenter implementation? Is there a workaround, or some trick to know that a whole bunch of notifications were dismissed? Here's my delegate code (sans irrelevant code...) // Handle notification back-actions - (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(nonnull UNNotificationResponse *)response          withCompletionHandler:(nonnull void (^)(void))completionHandler API_AVAILABLE(macos(10.14)) {     NSString *actionId = response.actionIdentifier;     UNNotificationRequest *request = response.notification.request;     NSString *requestId = request.identifier;     NSString *userActionIdentifier = request.content.threadIdentifier;     NSDictionary * myInfo = request.content.userInfo;     if ([actionId isEqualToString:UNNotificationDefaultActionIdentifier]) { // user opened the application from the notification         if ([self.delegate respondsToSelector:@selector(displayThread:forInfo)]) {             dispatch_async(dispatch_get_main_queue(), ^{                 [self.delegate displayThread:userActionIdentifier forInfo: myInfo];             });         }         completionHandler();         return;     }         NSString *userReply = nil;     if ([actionId isEqualToString:UNNotificationDismissActionIdentifier]) { // user dismissed the notification         os_log_debug(myLog, "Notification: %{public}@ dismissed", requestId);     }     else { // custom action         NSString *categoryId = response.notification.request.content.categoryIdentifier;         if ([categoryId isEqualToString:OITNotification.copyAction]) {             os_log_debug(myLog, "Notification: %{public}@ dismissed with custom action:%{public}@", requestId, actionId);         }         if ([categoryId isEqualToString:OITPreventionNotification.copyActionWithReply]) {             if ([actionId isEqualToString:@"other"]) {                 userReply = [(UNTextInputNotificationResponse*)response userText];                 os_log_debug(myLog, "Notification: %{public}@ User custom reply: %{public}@", requestId, userReply);             }             else {                 userReply = actionId;                 os_log_debug(myLog, "Notification: %{public}@ User Action: %{public}@", requestId, actionId);             }         }     }     if ([self.delegate respondsToSelector:@selector(notification:dismissedWithReply:)]) {         [self.delegate notification:myInfo dismissedWithReply:userReply];     }     [self removeModelIdentifiers:@[response.notification.request.identifier]];     completionHandler();     return; } Please ignore the tedious handling of custom actions - my problem is only with "Clear All" thread dismissals. I bring the code just for completeness, in the hopes that someone sees a fault I can't see --- Thank you very much.
Replies
0
Boosts
0
Views
1.4k
Activity
Oct ’21
Is it possible to obtain the NSUserActivity related to EndpointSecurity message?
I believe this is a general problem when writing low-level security and monitoring tools. The EndpointSecurity framework provides lots of information for the events it allows to Monitor (and/or Authorize) but all these are "kernel level" details, that usually don't allow understanding (and aggregating) low-level events according to User Intent e.g. Saving all attachments of an e-mail message from Apple Mail program to a USB-disk, will create a long series of low-level file-system events, some preliminary (touching and verifying the destination can fit the attachments) some for moving/copying, some for rounding-up, some for indexing those files on the new volume, and so on. Is it possible to somehow obtain the NSUserActivity object/instance/Identifier related to such low-level event? Is the kernel itself aware of user activities? Any hint or suggestion or strategy will be greatly appreciated
Replies
0
Boosts
0
Views
1.1k
Activity
Jul ’21
Is it possible to use UNUserNotificationCenter from a LaunchAgent?
Hi, I have a LaunchAgent (whose .plist is in /Library/LaunchAgents/ as expected) It is build as a single un-bundled binary, and installed away from regular user access at /Library/MyCompany/executables/ When I try to init a reference to UNUserNotificationCenter: UNUserNotificationCenter *unc = [UNUserNotificationCenter currentNotificationCenter]; I immediately have an exception, like thus: 2021-05-02 19:57:39.297823+0300 agent[12504:225879] *** Assertion failure in +[UNUserNotificationCenter currentNotificationCenter], /AppleInternal/BuildRoot/Library/Caches/com.apple.xbs/Sources/UserNotifications/UserNotifications-281.6/UNUserNotificationCenter.m:44 2021-05-02 19:57:39.299464+0300 agent[12504:225879] [General] An uncaught exception was raised 2021-05-02 19:57:39.299518+0300 agent[12504:225879] [General] bundleProxyForCurrentProcess is nil: mainBundle.bundleURL file:///Users/mshneor/Library/Developer/Xcode/DerivedData/agent-dgvdlbtivmsjdgdkhhjwaxgrkyht/Build/Products/Debug/ Obviously the problem is bundleProxyForCurrentProcess is nil: mainBundle.bundleURL Now... I could try to bundle my agent somehow, but that's a bit awkward, and I don't know how - it's not an App, and It's not a part of any App, and I don't know about a special "Code Bundle" type (like plugins etc.) that fits a LaunchAgent. Moreover - it will never be "launched" by it's info.plist in the bundle - only via the .plist in /Library/LaunchAgents by launchd. So... is it possible to work around this? Could I somehow tell my Agent's process "Here is our main-bundle" at runtime, and provide a special bundle the agent is not embedded in? what does UNUserNotificationCenter need from main bundle? maybe I can supply this programmatically in advance? Any hint will be greatly appreciated.
Replies
4
Boosts
0
Views
2.5k
Activity
May ’21
How to publish an XPC Service in a global daemon that employs EndpointSecurity framework?
I have a global daemon managed by launchd, whose .plist is installed in /Library/LaunchDaemons). To be correctly entitled and code-signed so it can communicate with EndpointSecurity framework, its executable resides in a normal Mac App bundle (main() will run as minimal UI when launched from UI, and as a daemon when launched by launchd). This means that the ProgramArguments.0 in its .plist looks something like /Library/PrivilegedHelperTools/MyDaemonApp.app/Contents/MacOS/MyDaemonApp Now I need this daemon to publish an XPC Service (with few control commands) so that other components of our system (UI app, a user-context launchd-daemon and another launchd global-daemon) will be able to connect to The XPC Service and control it via the published protocol. I read some answers here, and also found a working order sample code that does just this here - https://github.com/jdspoone/SampleOSXLaunchDaemon But when I apply its content to my global daemon, word for word - it doesn't work - meaning, clients cannot create a connection to The XPC Service. The daemon is up and running, and functional. its .plist is quite simple and looks like this: <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Label</key> <string>com.mycompany.itm.service</string> <key>KeepAlive</key> <true/> <key>RunAtLoad</key> <true/> <key>MachServices</key> <dict> <key>com.mycompany.itm.service</key> <true/> </dict> <key>ProgramArguments</key> <array> <string>/Library/PrivilegedHelperTools/IMyDaemonApp.app/Contents/MacOS/MyDaemonApp</string> <string>-monitor</string> <string>-protectDeviceProtocol</string> <string>USB</string> </array> </dict> </plist> It creates and starts an XPC listener in MYXPCListener.h like thus: #import <Foundation/Foundation.h> #import "MYXPCProtocol.h" NS_ASSUME_NONNULL_BEGIN @interface OITPreventionXPCService : NSObject (instancetype) init; (void) start; /* Begin listening for incoming XPC connections */ (void) stop; /* Stop listening for incoming XPC connections */ @end NS_ASSUME_NONNULL_END and the implementation is: /* AppDelegate.m */ @interface MYXPCService () <NSXPCListenerDelegate, OITPreventionXPCProtocol> @property (nonatomic, strong, readwrite) NSXPCListener *listener; @property (nonatomic, readwrite) BOOL started; @end @implementation OITPreventionXPCService (instancetype) init {     if ((self = [super init]) != nil) {         _listener = [[NSXPCListener alloc] initWithMachServiceName:@"com.mycompany.itm.service"];         _listener.delegate = self;         if (_listener == nil) {             os_log_error(myLog, "XPCListener failed to initialize");         }         _started = NO;     }     return self; } (void) start {     assert(_started == NO);     [_listener resume];     os_log_info(myLog, "XPCListener resumed");     _started = YES; } (void) stop {     assert(_started == YES);     [_listener suspend];     os_log_info(myLog, "XPCListener suspended");     _started = NO; } /* NSXPCListenerDelegate implementation */ (BOOL) listener:(NSXPCListener *)listener shouldAcceptNewConnection:(NSXPCConnection *)newConnection {     os_log_info(myLog, "Prevention XPCListener is bequsted a new connection");     assert(listener == _listener);     assert(newConnection != nil);     newConnection.exportedInterface = [NSXPCInterface interfaceWithProtocol:@protocol(MYXPCProtocol)];     newConnection.exportedObject = self; &#9;&#9;[newConnection resume];     return YES; } /* Further down this implementation, I have implementations to all the methods in MYXPCProtocol. */ @end Now the client code (and I tried EVERY kind of client, signed unsigned, daemon, UI, root privileged, or user-scoped - whatever). For example, in the AppDelegate of a UI app: #import "AppDelegate.h" #import "MYXPCProtocol.h" @interface AppDelegate () @property (strong) IBOutlet NSWindow *window; @property (nonatomic, strong, readwrite) NSXPCConnection *connection; /* lazy initialized */ @end @implementation AppDelegate (NSXPCConnection *) connection {     if (_connection == nil) {         _connection = [[NSXPCConnection alloc] initWithMachServiceName:daemonLabel options:NSXPCConnectionPrivileged];         _connection.remoteObjectInterface = [NSXPCInterface interfaceWithProtocol:@protocol(MYXPCProtocol)];         _connection.invalidationHandler =  ^{             self->_connection = nil;             NSLog(@"connection has been invalidated");         };         [_connection resume];         /* New connections always start suspended */     }     return _connection; } (IBAction) getServiceStatus:(id)sender {     [self.connection.remoteObjectProxy getStatus:^(NSString * _Nonnull status) {         NSLog(@"MY XPC Service status is: %@", status);     }]; } @end but no matter what I do - I always get the "connection invalidated". The sample launchDaemon that works - is not code-signed at all!!! but mine, which is both signed and checking of which yields $ spctl --assess --verbose IMyDaemonApp.app IMyDaemonApp.app: accepted source=Notarized Developer ID   I'm at a loss - and would like to get any advice, or any helpful documentation (I've been reading TN2083, and man launchctl and man launchd.plist and many other pages - to no avail. There seems to be no real "programming guide" for XPC and no reasonable sample code on Apple developer site to fit my needs. Last - this is MacOS 10.15.7, and latest Xcode 12.3
Replies
7
Boosts
0
Views
2.9k
Activity
Jan ’21