| Index: ios/chrome/browser/ui/settings/reauthentication_module.mm
|
| diff --git a/ios/chrome/browser/ui/settings/reauthentication_module.mm b/ios/chrome/browser/ui/settings/reauthentication_module.mm
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..8c5a0025fee2390313ad9c0ef929a1aa9bf7880d
|
| --- /dev/null
|
| +++ b/ios/chrome/browser/ui/settings/reauthentication_module.mm
|
| @@ -0,0 +1,87 @@
|
| +// Copyright 2015 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +#import "ios/chrome/browser/ui/settings/reauthentication_module.h"
|
| +
|
| +#import <LocalAuthentication/LocalAuthentication.h>
|
| +
|
| +#import "base/ios/weak_nsobject.h"
|
| +#include "base/mac/scoped_nsobject.h"
|
| +
|
| +@implementation ReauthenticationModule {
|
| + // Authentication context on which the authentication policy is evaluated.
|
| + base::scoped_nsobject<LAContext> _context;
|
| +
|
| + // Accessor allowing the module to request the update of the time when the
|
| + // successful re-authentication was performed and to get the time of the last
|
| + // successful re-authentication.
|
| + base::WeakNSProtocol<id<SuccessfulReauthTimeAccessor>>
|
| + _successfulReauthTimeAccessor;
|
| +}
|
| +
|
| +- (instancetype)initWithSuccessfulReauthTimeAccessor:
|
| + (id<SuccessfulReauthTimeAccessor>)successfulReauthTimeAccessor {
|
| + DCHECK(successfulReauthTimeAccessor);
|
| + self = [super init];
|
| + if (self) {
|
| + _context.reset([[LAContext alloc] init]);
|
| + _successfulReauthTimeAccessor.reset(successfulReauthTimeAccessor);
|
| + }
|
| + return self;
|
| +}
|
| +
|
| +- (BOOL)canAttemptReauth {
|
| + // The authentication method is Touch ID or passcode.
|
| + return
|
| + [_context canEvaluatePolicy:LAPolicyDeviceOwnerAuthentication error:nil];
|
| +}
|
| +
|
| +- (void)attemptReauthWithLocalizedReason:(NSString*)localizedReason
|
| + handler:(void (^)(BOOL success))handler {
|
| + if ([self isPreviousAuthValid]) {
|
| + handler(YES);
|
| + return;
|
| + }
|
| +
|
| + _context.reset([[LAContext alloc] init]);
|
| +
|
| + // No fallback option is provided.
|
| + _context.get().localizedFallbackTitle = @"";
|
| +
|
| + base::WeakNSObject<ReauthenticationModule> weakSelf(self);
|
| + void (^replyBlock)(BOOL, NSError*) = ^(BOOL success, NSError* error) {
|
| + dispatch_async(dispatch_get_main_queue(), ^{
|
| + base::scoped_nsobject<ReauthenticationModule> strongSelf(
|
| + [weakSelf retain]);
|
| + if (!strongSelf)
|
| + return;
|
| + if (success) {
|
| + [strongSelf.get()
|
| + ->_successfulReauthTimeAccessor updateSuccessfulReauthTime];
|
| + }
|
| + handler(success);
|
| + });
|
| + };
|
| +
|
| + [_context evaluatePolicy:LAPolicyDeviceOwnerAuthentication
|
| + localizedReason:localizedReason
|
| + reply:replyBlock];
|
| +}
|
| +
|
| +- (BOOL)isPreviousAuthValid {
|
| + BOOL previousAuthValid = NO;
|
| + const int kIntervalForValidAuthInSeconds = 60;
|
| + NSDate* lastSuccessfulReauthTime =
|
| + [_successfulReauthTimeAccessor lastSuccessfulReauthTime];
|
| + if (lastSuccessfulReauthTime) {
|
| + NSDate* currentTime = [NSDate date];
|
| + NSTimeInterval timeSincePreviousSuccessfulAuth =
|
| + [currentTime timeIntervalSinceDate:lastSuccessfulReauthTime];
|
| + if (timeSincePreviousSuccessfulAuth < kIntervalForValidAuthInSeconds) {
|
| + previousAuthValid = YES;
|
| + }
|
| + }
|
| + return previousAuthValid;
|
| +}
|
| +
|
| +@end
|
|
|