diff --git a/README.md b/README.md index c657d93..67cba2c 100644 --- a/README.md +++ b/README.md @@ -136,12 +136,13 @@ askForCalendarAccess().then(status => { ### `permissions.askForSpeechRecognitionAccess()` -Returns `Promise` - Whether or not the request succeeded or failed; can be `authorized` or `denied`. +Returns `Promise` - Whether or not the request succeeded or failed; can be `authorized`, `denied`, or `restricted`. Checks the authorization status for Speech Recognition access. If the status check returns: * `not determined` - The Speech Recognition access authorization will prompt the user to authorize or deny. The Promise is resolved after the user selection with either `authorized` or `denied`. * `denied` - The `Security & Privacy` System Preferences window is opened with the Speech Recognition privacy key highlighted. On open of the `Security & Privacy` window, the Promise is resolved as `denied`. +* `restricted` - The Promise is resolved as `restricted`. Your app must provide an explanation for its use of Speech Recognition using the `NSSpeechRecognitionUsageDescription` `Info.plist` key; @@ -303,7 +304,7 @@ askForMicrophoneAccess().then(status => { ### `permissions.askForMusicLibraryAccess()` -Returns `Promise` - Whether or not the request succeeded or failed; can be `authorized` or `denied`. +Returns `Promise` - Whether or not the request succeeded or failed; can be `authorized`, `denied`, or `restricted`. * `not determined` - The Music Library access authorization will prompt the user to authorize or deny. The Promise is resolved after the user selection with either `authorized` or `denied`. * `denied` - The `Security & Privacy` System Preferences window is opened with the Music Library privacy key highlighted. On open of the `Security & Privacy` window, the Promise is resolved as `denied`. diff --git a/permissions.mm b/permissions.mm index ac4b4b4..4796f61 100644 --- a/permissions.mm +++ b/permissions.mm @@ -31,6 +31,49 @@ error:nil]; } +std::string StringFromPhotosStatus(PHAuthorizationStatus status) { + switch (status) { + case PHAuthorizationStatusAuthorized: + return kAuthorized; + case PHAuthorizationStatusDenied: + return kDenied; + case PHAuthorizationStatusRestricted: + return kRestricted; + default: + return kNotDetermined; + } +} + +std::string +StringFromMusicLibraryStatus(SKCloudServiceAuthorizationStatus status) + API_AVAILABLE(macosx(11)) { + switch (status) { + case SKCloudServiceAuthorizationStatusAuthorized: + return kAuthorized; + case SKCloudServiceAuthorizationStatusDenied: + return kDenied; + case SKCloudServiceAuthorizationStatusRestricted: + return kRestricted; + default: + return kNotDetermined; + } +} + +std::string +StringFromSpeechRecognitionStatus(SFSpeechRecognizerAuthorizationStatus status) + API_AVAILABLE(macosx(10.15)) { + switch (status) { + case SFSpeechRecognizerAuthorizationStatusAuthorized: + return kAuthorized; + case SFSpeechRecognizerAuthorizationStatusDenied: + return kDenied; + case SFSpeechRecognizerAuthorizationStatusRestricted: + return kRestricted; + default: + return kNotDetermined; + } +} + // Open a specific pane in System Preferences Security and Privacy. void OpenPrefPane(const std::string &pane_string) { NSWorkspace *workspace = [[NSWorkspace alloc] init]; @@ -168,16 +211,9 @@ bool HasOpenSystemPreferencesDialog() { // Library access. std::string MusicLibraryAuthStatus() { if (@available(macOS 11, *)) { - switch ([SKCloudServiceController authorizationStatus]) { - case SKCloudServiceAuthorizationStatusAuthorized: - return kAuthorized; - case SKCloudServiceAuthorizationStatusDenied: - return kDenied; - case SKCloudServiceAuthorizationStatusRestricted: - return kRestricted; - default: - return kNotDetermined; - } + SKCloudServiceAuthorizationStatus status = + [SKCloudServiceController authorizationStatus]; + return StringFromMusicLibraryStatus(status); } return kAuthorized; @@ -306,16 +342,9 @@ bool HasOpenSystemPreferencesDialog() { // recognition access. std::string SpeechRecognitionAuthStatus() { if (@available(macOS 10.15, *)) { - switch ([SFSpeechRecognizer authorizationStatus]) { - case SFSpeechRecognizerAuthorizationStatusAuthorized: - return kAuthorized; - case SFSpeechRecognizerAuthorizationStatusDenied: - return kDenied; - case SFSpeechRecognizerAuthorizationStatusRestricted: - return kRestricted; - default: - return kNotDetermined; - } + SFSpeechRecognizerAuthorizationStatus status = + [SFSpeechRecognizer authorizationStatus]; + return StringFromSpeechRecognitionStatus(status); } return kAuthorized; @@ -339,16 +368,8 @@ bool HasOpenSystemPreferencesDialog() { // Returns a status indicating whether or not the user has authorized Photos // access. std::string PhotosAuthStatus() { - switch ([PHPhotoLibrary authorizationStatus]) { - case PHAuthorizationStatusAuthorized: - return kAuthorized; - case PHAuthorizationStatusDenied: - return kDenied; - case PHAuthorizationStatusRestricted: - return kRestricted; - default: - return kNotDetermined; - } + PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus]; + return StringFromPhotosStatus(status); } /***** EXPORTED FUNCTIONS *****/ @@ -554,11 +575,8 @@ void AskForFullDiskAccess(const Napi::CallbackInfo &info) { const char *granted) { deferred.Resolve(Napi::String::New(env, granted)); }; - tsfn.BlockingCall( - status == SFSpeechRecognizerAuthorizationStatusAuthorized - ? "authorized" - : "denied", - callback); + std::string auth_result = StringFromSpeechRecognitionStatus(status); + tsfn.BlockingCall(auth_result.c_str(), callback); tsfn.Release(); }]; } else if (auth_status == kDenied) { @@ -593,9 +611,8 @@ void AskForFullDiskAccess(const Napi::CallbackInfo &info) { const char *granted) { deferred.Resolve(Napi::String::New(env, granted)); }; - tsfn.BlockingCall(status == PHAuthorizationStatusAuthorized ? "authorized" - : "denied", - callback); + std::string auth_result = StringFromPhotosStatus(status); + tsfn.BlockingCall(auth_result.c_str(), callback); tsfn.Release(); }]; } else if (auth_status == kDenied) { @@ -695,10 +712,8 @@ void AskForFullDiskAccess(const Napi::CallbackInfo &info) { const char *granted) { deferred.Resolve(Napi::String::New(env, granted)); }; - - bool granted = - status == SKCloudServiceAuthorizationStatusAuthorized; - tsfn.BlockingCall(granted ? "authorized" : "denied", callback); + std::string auth_result = StringFromMusicLibraryStatus(status); + tsfn.BlockingCall(auth_result.c_str(), callback); tsfn.Release(); }]; } else if (auth_status == kDenied) {