@@ -44,8 +44,7 @@ PHAccessLevel GetPHAccessLevel(const std::string &type)
4444 return type == " read-write" ? PHAccessLevelReadWrite : PHAccessLevelAddOnly;
4545}
4646
47- IOHIDRequestType GetInputMonitoringAccessType (const std::string &type)
48- API_AVAILABLE(macosx(10.15 )) {
47+ IOHIDRequestType GetInputMonitoringAccessType (const std::string &type) {
4948 return type == " post" ? kIOHIDRequestTypePostEvent
5049 : kIOHIDRequestTypeListenEvent ;
5150}
@@ -89,9 +88,8 @@ IOHIDRequestType GetInputMonitoringAccessType(const std::string &type)
8988 }
9089}
9190
92- std::string
93- StringFromSpeechRecognitionStatus (SFSpeechRecognizerAuthorizationStatus status)
94- API_AVAILABLE(macosx(10.15 )) {
91+ std::string StringFromSpeechRecognitionStatus (
92+ SFSpeechRecognizerAuthorizationStatus status) {
9593 switch (status) {
9694 case SFSpeechRecognizerAuthorizationStatusAuthorized:
9795 return kAuthorized ;
@@ -204,65 +202,53 @@ bool HasOpenSystemPreferencesDialog() {
204202
205203// Returns a status indicating whether the user has authorized Bluetooth access.
206204std::string BluetoothAuthStatus () {
207- if (@available (macOS 10.15 , *)) {
208- switch ([CBCentralManager authorization ]) {
209- case CBManagerAuthorizationAllowedAlways:
210- return kAuthorized ;
211- case CBManagerAuthorizationDenied:
212- return kDenied ;
213- case CBManagerAuthorizationRestricted:
214- return kRestricted ;
215- default :
216- return kNotDetermined ;
217- }
205+ switch ([CBCentralManager authorization ]) {
206+ case CBManagerAuthorizationAllowedAlways:
207+ return kAuthorized ;
208+ case CBManagerAuthorizationDenied:
209+ return kDenied ;
210+ case CBManagerAuthorizationRestricted:
211+ return kRestricted ;
212+ default :
213+ return kNotDetermined ;
218214 }
219-
220- return kAuthorized ;
221215}
222216
223217// Returns a status indicating whether the user has authorized
224218// input monitoring access.
225219std::string InputMonitoringAuthStatus () {
226- if (@available (macOS 10.15 , *)) {
227- switch (IOHIDCheckAccess (kIOHIDRequestTypeListenEvent )) {
228- case kIOHIDAccessTypeGranted :
229- return kAuthorized ;
230- case kIOHIDAccessTypeDenied :
231- return kDenied ;
232- default :
233- return kNotDetermined ;
234- }
220+ switch (IOHIDCheckAccess (kIOHIDRequestTypeListenEvent )) {
221+ case kIOHIDAccessTypeGranted :
222+ return kAuthorized ;
223+ case kIOHIDAccessTypeDenied :
224+ return kDenied ;
225+ default :
226+ return kNotDetermined ;
235227 }
236-
237- return kAuthorized ;
238228}
239229
240230// Returns a status indicating whether the user has authorized Apple Events.
241231std::string AppleEventsAuthStatus (Napi::Env env) {
242- if (@available (macOS 10.14 , *)) {
243- AEDesc target_app = {typeNull, NULL };
244- OSStatus status = AECreateDesc (typeApplicationBundleID, " com.apple.finder" ,
245- strlen (" com.apple.finder" ), &target_app);
246- if (status != noErr) {
247- std::string err_msg = " Failed to query for Apple Events access" ;
248- Napi::Error::New (env, err_msg).ThrowAsJavaScriptException ();
249- return kNotDetermined ;
250- }
251-
252- status = AEDeterminePermissionToAutomateTarget (&target_app, kCoreEventClass ,
253- kAEOpenDocuments , false );
232+ AEDesc target_app = {typeNull, NULL };
233+ OSStatus status = AECreateDesc (typeApplicationBundleID, " com.apple.finder" ,
234+ strlen (" com.apple.finder" ), &target_app);
235+ if (status != noErr) {
236+ std::string err_msg = " Failed to query for Apple Events access" ;
237+ Napi::Error::New (env, err_msg).ThrowAsJavaScriptException ();
238+ return kNotDetermined ;
239+ }
254240
255- AEDisposeDesc (&target_app);
241+ status = AEDeterminePermissionToAutomateTarget (&target_app, kCoreEventClass ,
242+ kAEOpenDocuments , false );
256243
257- // User prompt has not yet been shown.
258- if (status == errAEEventWouldRequireUserConsent) {
259- return kNotDetermined ;
260- }
244+ AEDisposeDesc (&target_app);
261245
262- return status == noErr ? kAuthorized : kDenied ;
246+ // User prompt has not yet been shown.
247+ if (status == errAEEventWouldRequireUserConsent) {
248+ return kNotDetermined ;
263249 }
264250
265- return kAuthorized ;
251+ return status == noErr ? kAuthorized : kDenied ;
266252}
267253
268254// Returns a status indicating whether the user has authorized Apple Music
@@ -306,14 +292,10 @@ bool HasOpenSystemPreferencesDialog() {
306292 [home_folder
307293 stringByAppendingPathComponent:
308294 @" /Library/Application Support/com.apple.TCC/TCC.db" ],
309- @" /Library/Preferences/com.apple.TimeMachine.plist" , nil ];
310-
311- if (@available (macOS 10.15 , *)) {
312- [files addObject: [home_folder
313- stringByAppendingPathComponent:
314- @" Library/S]l;l;khb acddeffrfr55r4ewwe22q11 Z "
315- @" ,Kmmjmn bn;pp9iuyyuuujn afari/CloudTabs.db" ]];
316- }
295+ @" /Library/Preferences/com.apple.TimeMachine.plist" ,
296+ [home_folder
297+ stringByAppendingPathComponent: @" Library/Safari/CloudTabs.db" ],
298+ nil ];
317299
318300 std::string auth_status = kNotDetermined ;
319301 for (NSString *file in files) {
@@ -335,7 +317,7 @@ bool HasOpenSystemPreferencesDialog() {
335317 std::string auth_status = kNotDetermined ;
336318 if (@available (macOS 11.0 , *)) {
337319 auth_status = CGPreflightScreenCaptureAccess () ? kAuthorized : kDenied ;
338- } else if (@ available (macOS 10.15 , *)) {
320+ } else {
339321 auth_status = kDenied ;
340322 NSRunningApplication *runningApplication =
341323 NSRunningApplication .currentApplication ;
@@ -371,8 +353,6 @@ bool HasOpenSystemPreferencesDialog() {
371353 }
372354 }
373355 CFRelease (windowList);
374- } else {
375- auth_status = kAuthorized ;
376356 }
377357
378358 return auth_status;
@@ -381,35 +361,27 @@ bool HasOpenSystemPreferencesDialog() {
381361// Returns a status indicating whether the user has authorized
382362// Camera/Microphone access.
383363std::string MediaAuthStatus (const std::string &type) {
384- if (@available (macOS 10.14 , *)) {
385- AVMediaType media_type =
386- (type == " microphone" ) ? AVMediaTypeAudio : AVMediaTypeVideo;
387-
388- switch ([AVCaptureDevice authorizationStatusForMediaType: media_type]) {
389- case AVAuthorizationStatusAuthorized:
390- return kAuthorized ;
391- case AVAuthorizationStatusDenied:
392- return kDenied ;
393- case AVAuthorizationStatusRestricted:
394- return kRestricted ;
395- default :
396- return kNotDetermined ;
397- }
398- }
364+ AVMediaType media_type =
365+ (type == " microphone" ) ? AVMediaTypeAudio : AVMediaTypeVideo;
399366
400- return kAuthorized ;
367+ switch ([AVCaptureDevice authorizationStatusForMediaType: media_type]) {
368+ case AVAuthorizationStatusAuthorized:
369+ return kAuthorized ;
370+ case AVAuthorizationStatusDenied:
371+ return kDenied ;
372+ case AVAuthorizationStatusRestricted:
373+ return kRestricted ;
374+ default :
375+ return kNotDetermined ;
376+ }
401377}
402378
403379// Returns a status indicating whether the user has authorized speech
404380// recognition access.
405381std::string SpeechRecognitionAuthStatus () {
406- if (@available (macOS 10.15 , *)) {
407- SFSpeechRecognizerAuthorizationStatus status =
408- [SFSpeechRecognizer authorizationStatus ];
409- return StringFromSpeechRecognitionStatus (status);
410- }
411-
412- return kAuthorized ;
382+ SFSpeechRecognizerAuthorizationStatus status =
383+ [SFSpeechRecognizer authorizationStatus ];
384+ return StringFromSpeechRecognitionStatus (status);
413385}
414386
415387// Returns a status indicating whether the user has authorized location
@@ -610,27 +582,21 @@ void AskForFullDiskAccess(const Napi::CallbackInfo &info) {
610582 deferred.Resolve (Napi::String::New (env, status));
611583 };
612584
613- if (@available (macOS 10.14 , *)) {
614- std::string auth_status = MediaAuthStatus (" camera" );
585+ std::string auth_status = MediaAuthStatus (" camera" );
615586
616- if (auth_status == kNotDetermined ) {
617- [AVCaptureDevice
618- requestAccessForMediaType: AVMediaTypeVideo
619- completionHandler: ^(BOOL granted) {
620- tsfn.BlockingCall (granted ? " authorized" : " denied" ,
621- callback);
622- tsfn.Release ();
623- }];
624- } else {
625- if (auth_status == kDenied )
626- OpenPrefPane (" Privacy_Camera" );
627-
628- tsfn.Release ();
629- deferred.Resolve (Napi::String::New (env, auth_status));
630- }
587+ if (auth_status == kNotDetermined ) {
588+ [AVCaptureDevice requestAccessForMediaType: AVMediaTypeVideo
589+ completionHandler: ^(BOOL granted) {
590+ tsfn.BlockingCall (
591+ granted ? " authorized" : " denied" , callback);
592+ tsfn.Release ();
593+ }];
631594 } else {
595+ if (auth_status == kDenied )
596+ OpenPrefPane (" Privacy_Camera" );
597+
632598 tsfn.Release ();
633- deferred.Resolve (Napi::String::New (env, kAuthorized ));
599+ deferred.Resolve (Napi::String::New (env, auth_status ));
634600 }
635601
636602 return deferred.Promise ();
@@ -647,26 +613,21 @@ void AskForFullDiskAccess(const Napi::CallbackInfo &info) {
647613 deferred.Resolve (Napi::String::New (env, status));
648614 };
649615
650- if (@available (macOS 10.15 , *)) {
651- std::string auth_status = SpeechRecognitionAuthStatus ();
652-
653- if (auth_status == kNotDetermined ) {
654- [SFSpeechRecognizer
655- requestAuthorization: ^(SFSpeechRecognizerAuthorizationStatus status) {
656- std::string auth_result = StringFromSpeechRecognitionStatus (status);
657- tsfn.BlockingCall (auth_result.c_str (), callback);
658- tsfn.Release ();
659- }];
660- } else {
661- if (auth_status == kDenied )
662- OpenPrefPane (" Privacy_SpeechRecognition" );
616+ std::string auth_status = SpeechRecognitionAuthStatus ();
663617
664- tsfn.Release ();
665- deferred.Resolve (Napi::String::New (env, auth_status));
666- }
618+ if (auth_status == kNotDetermined ) {
619+ [SFSpeechRecognizer
620+ requestAuthorization: ^(SFSpeechRecognizerAuthorizationStatus status) {
621+ std::string auth_result = StringFromSpeechRecognitionStatus (status);
622+ tsfn.BlockingCall (auth_result.c_str (), callback);
623+ tsfn.Release ();
624+ }];
667625 } else {
626+ if (auth_status == kDenied )
627+ OpenPrefPane (" Privacy_SpeechRecognition" );
628+
668629 tsfn.Release ();
669- deferred.Resolve (Napi::String::New (env, kAuthorized ));
630+ deferred.Resolve (Napi::String::New (env, auth_status ));
670631 }
671632
672633 return deferred.Promise ();
@@ -726,27 +687,21 @@ void AskForFullDiskAccess(const Napi::CallbackInfo &info) {
726687 deferred.Resolve (Napi::String::New (env, status));
727688 };
728689
729- if (@available (macOS 10.14 , *)) {
730- std::string auth_status = MediaAuthStatus (" microphone" );
731-
732- if (auth_status == kNotDetermined ) {
733- [AVCaptureDevice
734- requestAccessForMediaType: AVMediaTypeAudio
735- completionHandler: ^(BOOL granted) {
736- tsfn.BlockingCall (granted ? " authorized" : " denied" ,
737- callback);
738- tsfn.Release ();
739- }];
740- } else {
741- if (auth_status == kDenied )
742- OpenPrefPane (" Privacy_Microphone" );
690+ std::string auth_status = MediaAuthStatus (" microphone" );
743691
744- tsfn.Release ();
745- deferred.Resolve (Napi::String::New (env, auth_status));
746- }
692+ if (auth_status == kNotDetermined ) {
693+ [AVCaptureDevice requestAccessForMediaType: AVMediaTypeAudio
694+ completionHandler: ^(BOOL granted) {
695+ tsfn.BlockingCall (
696+ granted ? " authorized" : " denied" , callback);
697+ tsfn.Release ();
698+ }];
747699 } else {
700+ if (auth_status == kDenied )
701+ OpenPrefPane (" Privacy_Microphone" );
702+
748703 tsfn.Release ();
749- deferred.Resolve (Napi::String::New (env, kAuthorized ));
704+ deferred.Resolve (Napi::String::New (env, auth_status ));
750705 }
751706
752707 return deferred.Promise ();
@@ -757,20 +712,16 @@ void AskForFullDiskAccess(const Napi::CallbackInfo &info) {
757712 Napi::Env env = info.Env ();
758713 Napi::Promise::Deferred deferred = Napi::Promise::Deferred::New (env);
759714
760- if (@available (macOS 10.15 , *)) {
761- std::string access_level = info[0 ].As <Napi::String>().Utf8Value ();
762- std::string auth_status = InputMonitoringAuthStatus ();
715+ std::string access_level = info[0 ].As <Napi::String>().Utf8Value ();
716+ std::string auth_status = InputMonitoringAuthStatus ();
763717
764- if (auth_status == kNotDetermined ) {
765- IOHIDRequestAccess (GetInputMonitoringAccessType (access_level));
766- deferred.Resolve (Napi::String::New (env, kDenied ));
767- } else {
768- if (auth_status == kDenied )
769- OpenPrefPane (" Privacy_ListenEvent" );
770- deferred.Resolve (Napi::String::New (env, auth_status));
771- }
718+ if (auth_status == kNotDetermined ) {
719+ IOHIDRequestAccess (GetInputMonitoringAccessType (access_level));
720+ deferred.Resolve (Napi::String::New (env, kDenied ));
772721 } else {
773- deferred.Resolve (Napi::String::New (env, kAuthorized ));
722+ if (auth_status == kDenied )
723+ OpenPrefPane (" Privacy_ListenEvent" );
724+ deferred.Resolve (Napi::String::New (env, auth_status));
774725 }
775726
776727 return deferred.Promise ();
@@ -822,7 +773,7 @@ void AskForScreenCaptureAccess(const Napi::CallbackInfo &info) {
822773 if (should_force_prefs && !HasOpenSystemPreferencesDialog ()) {
823774 OpenPrefPane (" Privacy_ScreenCapture" );
824775 }
825- } else if (@ available (macOS 10.15 , *)) {
776+ } else {
826777 // Tries to create a capture stream. This is necessary to add the app back
827778 // to the list in sysprefs if the user previously denied.
828779 // https://stackoverflow.com/questions/56597221/detecting-screen-recording-settings-on-macos-catalina
@@ -843,20 +794,18 @@ void AskForScreenCaptureAccess(const Napi::CallbackInfo &info) {
843794
844795// Request Location access.
845796void AskForLocationAccess (const Napi::CallbackInfo &info) {
846- if (@available (macOS 10.15 , *)) {
847- std::string auth_status = LocationAuthStatus ();
797+ std::string auth_status = LocationAuthStatus ();
848798
849- if (auth_status == kNotDetermined ) {
850- CLLocationManager *location_manager = [[CLLocationManager alloc ] init ];
851- const std::string access_level = info[0 ].As <Napi::String>().Utf8Value ();
852- if (access_level == " always" ) {
853- [location_manager requestAlwaysAuthorization ];
854- } else if (access_level == " when-in-use" ) {
855- [location_manager requestWhenInUseAuthorization ];
856- }
857- } else if (auth_status == kDenied ) {
858- OpenPrefPane (" Privacy_Location" );
799+ if (auth_status == kNotDetermined ) {
800+ CLLocationManager *location_manager = [[CLLocationManager alloc ] init ];
801+ const std::string access_level = info[0 ].As <Napi::String>().Utf8Value ();
802+ if (access_level == " always" ) {
803+ [location_manager requestAlwaysAuthorization ];
804+ } else if (access_level == " when-in-use" ) {
805+ [location_manager requestWhenInUseAuthorization ];
859806 }
807+ } else if (auth_status == kDenied ) {
808+ OpenPrefPane (" Privacy_Location" );
860809 }
861810}
862811
0 commit comments