#include <napi.h>
// Apple APIs
#import <AVFoundation/AVFoundation.h>
#import <AppKit/AppKit.h>
#import <Contacts/Contacts.h>
#import <CoreBluetooth/CoreBluetooth.h>
#import <CoreLocation/CoreLocation.h>
#import <EventKit/EventKit.h>
#import <Foundation/Foundation.h>
#import <Photos/Photos.h>
#import <Speech/Speech.h>
#import <pwd.h>
/***** HELPER FUNCTIONS *****/
const std::string kAuthorized{"authorized"};
const std::string kDenied{"denied"};
const std::string kRestricted{"restricted"};
const std::string kNotDetermined{"not determined"};
NSURL *URLForDirectory(NSSearchPathDirectory directory) {
NSFileManager *fm = [NSFileManager defaultManager];
return [fm URLForDirectory:directory
inDomain:NSUserDomainMask
appropriateForURL:nil
create:false
error:nil];
}
// Dummy value to pass into function parameter for ThreadSafeFunction.
Napi::Value NoOp(const Napi::CallbackInfo &info) {
return info.Env().Undefined();
}
// Returns the user's home folder path.
NSString *GetUserHomeFolderPath() {
NSString *path;
BOOL isSandboxed =
(nil !=
NSProcessInfo.processInfo.environment[@"APP_SANDBOX_CONTAINER_ID"]);
if (isSandboxed) {
struct passwd *pw = getpwuid(getuid());
assert(pw);
path = [NSString stringWithUTF8String:pw->pw_dir];
} else {
path = NSHomeDirectory();
}
return path;
}
// This method determines whether or not a system preferences security
// authentication request is currently open on the user's screen and foregrounds
// it if found
bool HasOpenSystemPreferencesDialog() {
int MAX_NUM_LIKELY_OPEN_WINDOWS = 4;
bool isDialogOpen = false;
CFArrayRef windowList;
// loops for max 1 second, breaks if/when dialog is found
for (int index = 0; index <= MAX_NUM_LIKELY_OPEN_WINDOWS; index++) {
windowList = CGWindowListCopyWindowInfo(
kCGWindowListOptionOnScreenAboveWindow, kCGNullWindowID);
int numberOfWindows = CFArrayGetCount(windowList);
for (int windowIndex = 0; windowIndex < numberOfWindows; windowIndex++) {
NSDictionary *windowInfo =
(NSDictionary *)CFArrayGetValueAtIndex(windowList, windowIndex);
NSString *windowOwnerName = windowInfo[(id)kCGWindowOwnerName];
NSNumber *windowLayer = windowInfo[(id)kCGWindowLayer];
NSNumber *windowOwnerPID = windowInfo[(id)kCGWindowOwnerPID];
if ([windowLayer integerValue] == 0 &&
[windowOwnerName isEqual:@"universalAccessAuthWarn"]) {
// make sure the auth window is in the foreground
NSRunningApplication *authApplication = [NSRunningApplication
runningApplicationWithProcessIdentifier:[windowOwnerPID
integerValue]];
[NSRunningApplication.currentApplication
activateWithOptions:NSApplicationActivateAllWindows];
[authApplication activateWithOptions:NSApplicationActivateAllWindows];
isDialogOpen = true;
break;
}
}
CFRelease(windowList);
if (isDialogOpen) {
break;
}
usleep(250000);
}
return isDialogOpen;
}
// Returns a status indicating whether the user has authorized Contacts
// access.
std::string ContactAuthStatus() {
switch (
[CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts]) {
case CNAuthorizationStatusAuthorized:
return kAuthorized;
case CNAuthorizationStatusDenied:
return kDenied;
case CNAuthorizationStatusRestricted:
return kRestricted;
default:
return kNotDetermined;
}
}
// Returns a status indicating whether the user has authorized Bluetooth access.
std::string BluetoothAuthStatus() {
if (@available(macOS 10.15, *)) {
switch ([CBCentralManager authorization]) {
case CBManagerAuthorizationAllowedAlways:
return kAuthorized;
case CBManagerAuthorizationDenied:
return kDenied;
case CBManagerAuthorizationRestricted:
return kRestricted;
default:
return kNotDetermined;
}
}
return kAuthorized;
}
// Returns a status indicating whether the user has authorized
// Calendar/Reminders access.
std::string EventAuthStatus(const std::string &type) {
EKEntityType entity_type =
(type == "calendar") ? EKEntityTypeEvent : EKEntityTypeReminder;
switch ([EKEventStore authorizationStatusForEntityType:entity_type]) {
case EKAuthorizationStatusAuthorized:
return kAuthorized;
case EKAuthorizationStatusDenied:
return kDenied;
case EKAuthorizationStatusRestricted:
return kRestricted;
default:
return kNotDetermined;
}
}
// Returns a status indicating whether the user has Full Disk Access.
std::string FDAAuthStatus() {
std::string auth_status = kNotDetermined;
NSString *path;
NSString *home_folder = GetUserHomeFolderPath();
if (@available(macOS 10.15, *)) {
path = [home_folder
stringByAppendingPathComponent:@"Library/Safari/CloudTabs.db"];
} else {
path = [home_folder
stringByAppendingPathComponen
mac权限检测、申请
最新推荐文章于 2024-05-15 20:29:34 发布