Post

Replies

Boosts

Views

Activity

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
1.9k
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 there a good way to translate timespec into NSDate
My new EndpointSecurity client code receives event messages of type esmessaget. These contain 3 time values. struct timespec time; uint64_t mach_time; uint64_t deadline; To interpret the deadline I refer to the mach_time. However, when I wish to log/formet/otherwise-consider the "wall time" where the event was created - I need to translate the timespec into NSDate (hmm... NSTimeInterval?) and I fail to find any documentation or hint about the right way to do so. What I tried so far looks like this: NSDate * timestamp = [NSDate dateWithTimeIntervalSince1970:(double)(message-&gt;time.tv_sec) + (double)(message-&gt;time.tv_sec) / 1E9 ]; which at least mathematically seems reasonable, but I'm not sure this is the right answer, and I don't know anything about the behaviour of timespec, its origin and accuracy, and whether or not it is consistent. Can anyone shed a little light on the relation between these two time formats? Thanks!
2
0
2.5k
Apr ’21
Can my User-Agent know (be notified) of Configuration profile changes?
My agent/service relies on Accessibility APIs. Being installed by IT on all corporate Macs, it receives its permission to use these APIs via a configuration profile installed on the Mac, and not via the System-Preferences Security &amp; Privacy panel (Privacy tab, Accessibility item). Problem is - if that profile is removed, or changed to remove this permission - The agent currently has no way to know it, and will hang on the next call to some AX API. our code calls  @result Returns TRUE if the current process is a trusted accessibility client, FALSE if it is not.  */ extern Boolean AXIsProcessTrustedWithOptions (CFDictionaryRef __nullable options) CF_AVAILABLE_MAC(10_9); before using other AX APIs, but sadly - the method returns true even when accessibility has been denied by removing the profile. By contrast - if If user manually un-checks the Accessibility for this agent in the System-Preferences panel - the function returns false immediately. If after removing the profile, I kill my agent (launchd then relaunches it) - then calling AXIsProcessTrustedWithOptions returns false as expected. This seems to be a bug of some kind or incomplete behaviour, but I need a workaround as soon as possible. My first "wish" would be to be able to register for and receive some system-wide NSNotification about "configuration profile changes", at which time, I could decide to exit my agent, and relaunch with accessibility permissions synchronised. Or is there any AX internal notification I could register for? haven't found any. Any clue would be greatly appreciated.
1
0
1.2k
Dec ’20