123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117 |
- #import "RNPermissionHandlerFaceID.h"
-
- @import LocalAuthentication;
- @import UIKit;
-
- @interface RNPermissionHandlerFaceID()
-
- @property (nonatomic, strong) LAContext *laContext;
- @property (nonatomic, strong) void (^resolve)(RNPermissionStatus status);
- @property (nonatomic, strong) void (^reject)(NSError *error);
-
- @end
-
- @implementation RNPermissionHandlerFaceID
-
- + (NSArray<NSString *> * _Nonnull)usageDescriptionKeys {
- return @[@"NSFaceIDUsageDescription"];
- }
-
- + (NSString * _Nonnull)handlerUniqueId {
- return @"ios.permission.FACE_ID";
- }
-
- - (void)checkWithResolver:(void (^ _Nonnull)(RNPermissionStatus))resolve
- rejecter:(void (^ _Nonnull)(NSError * _Nonnull))reject {
- if (@available(iOS 11.0.1, *)) {
- LAContext *context = [LAContext new];
- NSError *error;
-
- [context canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error];
- bool hasFaceID = context.biometryType == LABiometryTypeFaceID;
-
- if (!hasFaceID) {
- return resolve(RNPermissionStatusNotAvailable);
- }
-
- if (error != nil) {
- if (error.code == LAErrorBiometryNotEnrolled)
- return resolve(RNPermissionStatusNotAvailable);
- if (error.code != LAErrorBiometryNotAvailable)
- return reject(error);
- if (hasFaceID)
- return resolve(RNPermissionStatusDenied);
-
- return resolve(RNPermissionStatusNotAvailable);
- }
-
- if (![RNPermissions isFlaggedAsRequested:[[self class] handlerUniqueId]]) {
- return resolve(RNPermissionStatusNotDetermined);
- }
-
- resolve(RNPermissionStatusAuthorized);
- } else {
- resolve(RNPermissionStatusNotAvailable);
- }
- }
-
- - (void)requestWithResolver:(void (^ _Nonnull)(RNPermissionStatus))resolve
- rejecter:(void (^ _Nonnull)(NSError * _Nonnull))reject {
- if (@available(iOS 11.0.1, *)) {
- LAContext *context = [LAContext new];
- NSError *error;
-
- [context canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error];
- bool hasFaceID = context.biometryType == LABiometryTypeFaceID;
-
- if (!hasFaceID) {
- return resolve(RNPermissionStatusNotAvailable);
- }
-
- if (error != nil) {
- if (error.code == LAErrorBiometryNotEnrolled)
- return resolve(RNPermissionStatusNotAvailable);
- if (error.code != LAErrorBiometryNotAvailable)
- return reject(error);
- if (hasFaceID)
- return resolve(RNPermissionStatusDenied);
-
- return resolve(RNPermissionStatusNotAvailable);
- }
-
- _resolve = resolve;
- _reject = reject;
- _laContext = context;
-
- [[NSNotificationCenter defaultCenter] addObserver:self
- selector:@selector(UIApplicationDidBecomeActiveNotification:)
- name:UIApplicationDidBecomeActiveNotification
- object:nil];
-
- [context evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics
- localizedReason:[[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSFaceIDUsageDescription"]
- reply:^(__unused BOOL success, __unused NSError * _Nullable error) {}];
-
- // Hack to invalidate FaceID verification immediately after being requested
- [self performSelector:@selector(invalidateContext) withObject:self afterDelay:0.05];
- } else {
- resolve(RNPermissionStatusNotAvailable);
- }
- }
-
- - (void)invalidateContext {
- [_laContext invalidate];
- _laContext = nil;
- }
-
- - (void)UIApplicationDidBecomeActiveNotification:(__unused NSNotification *)notification {
- [[NSNotificationCenter defaultCenter] removeObserver:self
- name:UIApplicationDidBecomeActiveNotification
- object:nil];
-
- [RNPermissions flagAsRequested:[[self class] handlerUniqueId]];
- [self checkWithResolver:_resolve rejecter:_reject];
- }
-
- @end
|