From 5bc089837bf9162ea576f8f9dd1017ce27313e93 Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Thu, 22 Mar 2018 16:10:38 -0400 Subject: [PATCH] Respond to CR. --- Signal/src/util/OWSScreenLock.swift | 113 ++++++------------ Signal/src/util/OWSScreenLockUI.m | 5 +- .../translations/en.lproj/Localizable.strings | 61 ++++------ 3 files changed, 59 insertions(+), 120 deletions(-) diff --git a/Signal/src/util/OWSScreenLock.swift b/Signal/src/util/OWSScreenLock.swift index a32ac537e..a2317a696 100644 --- a/Signal/src/util/OWSScreenLock.swift +++ b/Signal/src/util/OWSScreenLock.swift @@ -7,8 +7,6 @@ import LocalAuthentication @objc public class OWSScreenLock: NSObject { - let TAG = "[OWSScreenLock]" - public enum OWSScreenLockOutcome { case success case cancel @@ -56,7 +54,7 @@ import LocalAuthentication AssertIsOnMainThread() if !OWSStorage.isStorageReady() { - owsFail("\(TAG) accessed screen lock state before storage is ready.") + owsFail("\(logTag) accessed screen lock state before storage is ready.") return false } @@ -76,7 +74,7 @@ import LocalAuthentication AssertIsOnMainThread() if !OWSStorage.isStorageReady() { - owsFail("\(TAG) accessed screen lock state before storage is ready.") + owsFail("\(logTag) accessed screen lock state before storage is ready.") return 0 } @@ -100,13 +98,8 @@ import LocalAuthentication // Success and cancel can be differentiated by consulting // isScreenLockEnabled. @objc public func tryToEnableScreenLock(completion: @escaping ((Error?) -> Void)) { - tryToVerifyLocalAuthentication(defaultReason: NSLocalizedString("SCREEN_LOCK_REASON_ENABLE_SCREEN_LOCK", - comment: "Description of how and why Signal iOS uses Touch ID/Face ID to enable 'screen lock'."), - touchIdReason: NSLocalizedString("SCREEN_LOCK_REASON_ENABLE_SCREEN_LOCK_TOUCH_ID", - comment: "Description of how and why Signal iOS uses Touch ID to enable 'screen lock'."), - faceIdReason: NSLocalizedString("SCREEN_LOCK_REASON_ENABLE_SCREEN_LOCK_FACE_ID", - comment: "Description of how and why Signal iOS uses Face ID to enable 'screen lock'."), - + tryToVerifyLocalAuthentication(localizedReason: NSLocalizedString("SCREEN_LOCK_REASON_ENABLE_SCREEN_LOCK", + comment: "Description of how and why Signal iOS uses Touch ID/Face ID/Phone Passcode to enable 'screen lock'."), completion: { (outcome: OWSScreenLockOutcome) in AssertIsOnMainThread() @@ -127,13 +120,8 @@ import LocalAuthentication // Success and cancel can be differentiated by consulting // isScreenLockEnabled. @objc public func tryToDisableScreenLock(completion: @escaping ((Error?) -> Void)) { - tryToVerifyLocalAuthentication(defaultReason: NSLocalizedString("SCREEN_LOCK_REASON_DISABLE_SCREEN_LOCK", - comment: "Description of how and why Signal iOS uses Touch ID/Face ID to disable 'screen lock'."), - touchIdReason: NSLocalizedString("SCREEN_LOCK_REASON_DISABLE_SCREEN_LOCK_TOUCH_ID", - comment: "Description of how and why Signal iOS uses Touch ID to disable 'screen lock'."), - faceIdReason: NSLocalizedString("SCREEN_LOCK_REASON_DISABLE_SCREEN_LOCK_FACE_ID", - comment: "Description of how and why Signal iOS uses Face ID to disable 'screen lock'."), - + tryToVerifyLocalAuthentication(localizedReason: NSLocalizedString("SCREEN_LOCK_REASON_DISABLE_SCREEN_LOCK", + comment: "Description of how and why Signal iOS uses Touch ID/Face ID/Phone Passcode to disable 'screen lock'."), completion: { (outcome: OWSScreenLockOutcome) in AssertIsOnMainThread() @@ -152,13 +140,8 @@ import LocalAuthentication @objc public func tryToUnlockScreenLock(success: @escaping (() -> Void), failure: @escaping ((Error) -> Void), cancel: @escaping (() -> Void)) { - tryToVerifyLocalAuthentication(defaultReason: NSLocalizedString("SCREEN_LOCK_REASON_UNLOCK_SCREEN_LOCK", - comment: "Description of how and why Signal iOS uses Touch ID/Face ID to unlock 'screen lock'."), - touchIdReason: NSLocalizedString("SCREEN_LOCK_REASON_UNLOCK_SCREEN_LOCK_TOUCH_ID", - comment: "Description of how and why Signal iOS uses Touch ID to unlock 'screen lock'."), - faceIdReason: NSLocalizedString("SCREEN_LOCK_REASON_UNLOCK_SCREEN_LOCK_FACE_ID", - comment: "Description of how and why Signal iOS uses Face ID to unlock 'screen lock'."), - + tryToVerifyLocalAuthentication(localizedReason: NSLocalizedString("SCREEN_LOCK_REASON_UNLOCK_SCREEN_LOCK", + comment: "Description of how and why Signal iOS uses Touch ID/Face ID/Phone Passcode to unlock 'screen lock'."), completion: { (outcome: OWSScreenLockOutcome) in AssertIsOnMainThread() @@ -177,16 +160,14 @@ import LocalAuthentication // On success or cancel, completion is called with nil argument. // Success and cancel can be differentiated by consulting // isScreenLockEnabled. - private func tryToVerifyLocalAuthentication(defaultReason: String, - touchIdReason: String, - faceIdReason: String, + private func tryToVerifyLocalAuthentication(localizedReason: String, completion completionParam: @escaping ((OWSScreenLockOutcome) -> Void)) { // Ensure completion is always called on the main thread. let completion = { (outcome: OWSScreenLockOutcome) in switch outcome { case .failure(let error): - Logger.error("\(self.TAG) local authentication failed with error: \(error)") + Logger.error("\(self.logTag) local authentication failed with error: \(error)") default: break } @@ -197,18 +178,18 @@ import LocalAuthentication let context = screenLockContext() let defaultErrorDescription = NSLocalizedString("SCREEN_LOCK_ENABLE_UNKNOWN_ERROR", - comment: "Indicates that an unknown error occurred while using Touch ID or Face ID.") + comment: "Indicates that an unknown error occurred while using Touch ID/Face ID/Phone Passcode.") var authError: NSError? - let canEvaluatePolicy = context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &authError) + let canEvaluatePolicy = context.canEvaluatePolicy(.deviceOwnerAuthentication, error: &authError) if !canEvaluatePolicy || authError != nil { - Logger.error("\(TAG) could not determine if local authentication is supported: \(String(describing: authError))") + Logger.error("\(logTag) could not determine if local authentication is supported: \(String(describing: authError))") let outcome = self.outcomeForLAError(errorParam: authError, defaultErrorDescription: defaultErrorDescription) switch outcome { case .success: - owsFail("\(self.TAG) local authentication unexpected success") + owsFail("\(self.logTag) local authentication unexpected success") completion(.failure(error:defaultErrorDescription)) case .cancel, .failure: completion(outcome) @@ -216,25 +197,16 @@ import LocalAuthentication return } - var localizedReason = defaultReason - if #available(iOS 11.0, *) { - if context.biometryType == .touchID { - localizedReason = touchIdReason - } else if context.biometryType == .faceID { - localizedReason = faceIdReason - } - } - - context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: localizedReason) { success, evaluateError in + context.evaluatePolicy(.deviceOwnerAuthentication, localizedReason: localizedReason) { success, evaluateError in if success { - Logger.info("\(self.TAG) local authentication succeeded.") + Logger.info("\(self.logTag) local authentication succeeded.") completion(.success) } else { let outcome = self.outcomeForLAError(errorParam: evaluateError, defaultErrorDescription: defaultErrorDescription) switch outcome { case .success: - owsFail("\(self.TAG) local authentication unexpected success") + owsFail("\(self.logTag) local authentication unexpected success") completion(.failure(error:defaultErrorDescription)) case .cancel, .failure: completion(outcome) @@ -254,17 +226,17 @@ import LocalAuthentication if #available(iOS 11.0, *) { switch laError.code { case .biometryNotAvailable: - Logger.error("\(self.TAG) local authentication error: biometryNotAvailable.") + Logger.error("\(self.logTag) local authentication error: biometryNotAvailable.") return .failure(error: NSLocalizedString("SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_AVAILABLE", - comment: "Indicates that Touch ID/Face ID are not available on this device.")) + comment: "Indicates that Touch ID/Face ID/Phone Passcode are not available on this device.")) case .biometryNotEnrolled: - Logger.error("\(self.TAG) local authentication error: biometryNotEnrolled.") + Logger.error("\(self.logTag) local authentication error: biometryNotEnrolled.") return .failure(error: NSLocalizedString("SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_ENROLLED", - comment: "Indicates that Touch ID/Face ID is not configured on this device.")) + comment: "Indicates that Touch ID/Face ID/Phone Passcode is not configured on this device.")) case .biometryLockout: - Logger.error("\(self.TAG) local authentication error: biometryLockout.") + Logger.error("\(self.logTag) local authentication error: biometryLockout.") return .failure(error: NSLocalizedString("SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_LOCKOUT", - comment: "Indicates that Touch ID/Face ID is 'locked out' on this device due to authentication failures.")) + comment: "Indicates that Touch ID/Face ID/Phone Passcode is 'locked out' on this device due to authentication failures.")) default: // Fall through to second switch break @@ -273,33 +245,33 @@ import LocalAuthentication switch laError.code { case .authenticationFailed: - Logger.error("\(self.TAG) local authentication error: authenticationFailed.") + Logger.error("\(self.logTag) local authentication error: authenticationFailed.") return .failure(error: NSLocalizedString("SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_FAILED", - comment: "Indicates that Touch ID/Face ID authentication failed.")) + comment: "Indicates that Touch ID/Face ID/Phone Passcode authentication failed.")) case .userCancel, .userFallback, .systemCancel, .appCancel: - Logger.info("\(self.TAG) local authentication cancelled.") + Logger.info("\(self.logTag) local authentication cancelled.") return .cancel case .passcodeNotSet: - Logger.error("\(self.TAG) local authentication error: passcodeNotSet.") + Logger.error("\(self.logTag) local authentication error: passcodeNotSet.") return .failure(error: NSLocalizedString("SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_PASSCODE_NOT_SET", - comment: "Indicates that Touch ID/Face ID passcode is not set.")) + comment: "Indicates that Touch ID/Face ID/Phone Passcode passcode is not set.")) case .touchIDNotAvailable: - Logger.error("\(self.TAG) local authentication error: touchIDNotAvailable.") + Logger.error("\(self.logTag) local authentication error: touchIDNotAvailable.") return .failure(error: NSLocalizedString("SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_AVAILABLE", - comment: "Indicates that Touch ID/Face ID are not available on this device.")) + comment: "Indicates that Touch ID/Face ID/Phone Passcode are not available on this device.")) case .touchIDNotEnrolled: - Logger.error("\(self.TAG) local authentication error: touchIDNotEnrolled.") + Logger.error("\(self.logTag) local authentication error: touchIDNotEnrolled.") return .failure(error: NSLocalizedString("SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_ENROLLED", - comment: "Indicates that Touch ID/Face ID is not configured on this device.")) + comment: "Indicates that Touch ID/Face ID/Phone Passcode is not configured on this device.")) case .touchIDLockout: - Logger.error("\(self.TAG) local authentication error: touchIDLockout.") + Logger.error("\(self.logTag) local authentication error: touchIDLockout.") return .failure(error: NSLocalizedString("SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_LOCKOUT", - comment: "Indicates that Touch ID/Face ID is 'locked out' on this device due to authentication failures.")) + comment: "Indicates that Touch ID/Face ID/Phone Passcode is 'locked out' on this device due to authentication failures.")) case .invalidContext: - owsFail("\(self.TAG) context not valid.") + owsFail("\(self.logTag) context not valid.") break case .notInteractive: - owsFail("\(self.TAG) context not interactive.") + owsFail("\(self.logTag) context not interactive.") break } } @@ -316,18 +288,7 @@ import LocalAuthentication private func screenLockContext() -> LAContext { let context = LAContext() - // if #available(iOS 11, *) { - // context.biometryType = [.touchId,.faceId] - // } - - // Time interval for accepting a successful Touch ID or Face ID device unlock (on the lock screen) from the past. - // - // TODO: Review. - context.touchIDAuthenticationAllowableReuseDuration = TimeInterval(5.0) - - // Don't set context.maxBiometryFailures. - // - // TODO: Review. + context.touchIDAuthenticationAllowableReuseDuration = TimeInterval(screenLockTimeout()) return context } diff --git a/Signal/src/util/OWSScreenLockUI.m b/Signal/src/util/OWSScreenLockUI.m index 0d0e6ec99..85049f93b 100644 --- a/Signal/src/util/OWSScreenLockUI.m +++ b/Signal/src/util/OWSScreenLockUI.m @@ -179,9 +179,8 @@ NS_ASSUME_NONNULL_BEGIN DDLogInfo(@"%@ unlock screen lock cancelled.", self.logTag); self.isShowingScreenLockUI = NO; - [self showScreenLockFailureAlertWithMessage: - NSLocalizedString(@"SCREEN_LOCK_UNLOCK_CANCELLED", - @"Message for alert indicating that screen lock unlock was cancelled.")]; + // Re-show the unlock UI. + [self ensureScreenProtection]; }]; } } diff --git a/Signal/translations/en.lproj/Localizable.strings b/Signal/translations/en.lproj/Localizable.strings index fb0b73646..72d3657cf 100644 --- a/Signal/translations/en.lproj/Localizable.strings +++ b/Signal/translations/en.lproj/Localizable.strings @@ -1546,56 +1546,35 @@ /* Title for alert indicating that screen lock could not be enabled. */ "SCREEN_LOCK_ENABLE_FAILED" = "Screen Lock Could Not Be Enabled"; -/* Indicates that an unknown error occurred while using Touch ID or Face ID. */ -"SCREEN_LOCK_ENABLE_UNKNOWN_ERROR" = "Touch ID and Face ID could not be accessed."; +/* Indicates that an unknown error occurred while using Touch ID/Face ID/Phone Passcode. */ +"SCREEN_LOCK_ENABLE_UNKNOWN_ERROR" = "Authentication could not be accessed."; -/* Indicates that Touch ID/Face ID authentication failed. */ -"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_FAILED" = "Authentication with Touch ID or Face ID failed."; +/* Indicates that Touch ID/Face ID/Phone Passcode authentication failed. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_FAILED" = "Authentication failed."; -/* Indicates that Touch ID/Face ID is 'locked out' on this device due to authentication failures. */ -"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_LOCKOUT" = "Touch ID or Face ID is locked out; too many failures."; +/* Indicates that Touch ID/Face ID/Phone Passcode is 'locked out' on this device due to authentication failures. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_LOCKOUT" = "Too many failures. Please try again later."; -/* Indicates that Touch ID/Face ID are not available on this device. */ -"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_AVAILABLE" = "Touch ID or Face ID is not available on this device."; +/* Indicates that Touch ID/Face ID/Phone Passcode are not available on this device. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_AVAILABLE" = "You must configure a passcode on your phone to use Screen Lock."; -/* Indicates that Touch ID/Face ID is not configured on this device. */ -"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_ENROLLED" = "Touch ID or Face ID is not configured."; +/* Indicates that Touch ID/Face ID/Phone Passcode is not configured on this device. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_ENROLLED" = "You must configure a passcode on your phone to use Screen Lock."; -/* Indicates that Touch ID/Face ID passcode is not set. */ -"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_PASSCODE_NOT_SET" = "Touch ID or Face ID is not available; no passcode has been set."; +/* Indicates that Touch ID/Face ID/Phone Passcode passcode is not set. */ +"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_PASSCODE_NOT_SET" = "You must configure a passcode on your phone to use Screen Lock."; -/* Description of how and why Signal iOS uses Touch ID/Face ID to disable 'screen lock'. */ -"SCREEN_LOCK_REASON_DISABLE_SCREEN_LOCK" = "Use Touch ID or Face ID to disable Screen Lock."; +/* Description of how and why Signal iOS uses Touch ID/Face ID/Phone Passcode to disable 'screen lock'. */ +"SCREEN_LOCK_REASON_DISABLE_SCREEN_LOCK" = "Authenticate to disable Screen Lock."; -/* Description of how and why Signal iOS uses Face ID to disable 'screen lock'. */ -"SCREEN_LOCK_REASON_DISABLE_SCREEN_LOCK_FACE_ID" = "Use Face ID to disable Screen Lock."; +/* Description of how and why Signal iOS uses Touch ID/Face ID/Phone Passcode to enable 'screen lock'. */ +"SCREEN_LOCK_REASON_ENABLE_SCREEN_LOCK" = "Authenticate to lock access to Signal."; -/* Description of how and why Signal iOS uses Touch ID to disable 'screen lock'. */ -"SCREEN_LOCK_REASON_DISABLE_SCREEN_LOCK_TOUCH_ID" = "Use Touch ID to disable Screen Lock."; - -/* Description of how and why Signal iOS uses Touch ID/Face ID to enable 'screen lock'. */ -"SCREEN_LOCK_REASON_ENABLE_SCREEN_LOCK" = "Use Touch ID or Face ID to lock access to Signal."; - -/* Description of how and why Signal iOS uses Face ID to enable 'screen lock'. */ -"SCREEN_LOCK_REASON_ENABLE_SCREEN_LOCK_FACE_ID" = "Use Face ID to lock access to Signal."; - -/* Description of how and why Signal iOS uses Touch ID to enable 'screen lock'. */ -"SCREEN_LOCK_REASON_ENABLE_SCREEN_LOCK_TOUCH_ID" = "Use Touch ID to lock access to Signal."; - -/* Description of how and why Signal iOS uses Touch ID/Face ID to unlock 'screen lock'. */ -"SCREEN_LOCK_REASON_UNLOCK_SCREEN_LOCK" = "Use Touch ID or Face ID to unlock Screen Lock."; - -/* Description of how and why Signal iOS uses Face ID to unlock 'screen lock'. */ -"SCREEN_LOCK_REASON_UNLOCK_SCREEN_LOCK_FACE_ID" = "Use Face ID to unlock Screen Lock."; - -/* Description of how and why Signal iOS uses Touch ID to unlock 'screen lock'. */ -"SCREEN_LOCK_REASON_UNLOCK_SCREEN_LOCK_TOUCH_ID" = "Use Touch ID to unlock Screen Lock."; - -/* Message for alert indicating that screen lock unlock was cancelled. */ -"SCREEN_LOCK_UNLOCK_CANCELLED" = "Unlock of Screen Lock was cancelled."; +/* Description of how and why Signal iOS uses Touch ID/Face ID/Phone Passcode to unlock 'screen lock'. */ +"SCREEN_LOCK_REASON_UNLOCK_SCREEN_LOCK" = "Authenticate to access Signal."; /* Title for alert indicating that screen lock could not be unlocked. */ -"SCREEN_LOCK_UNLOCK_FAILED" = "Unlock of Screen Lock failed."; +"SCREEN_LOCK_UNLOCK_FAILED" = "Authentication Failed"; /* No comment provided by engineer. */ "SEARCH_BYNAMEORNUMBER_PLACEHOLDER_TEXT" = "Search by name or number"; @@ -1811,7 +1790,7 @@ "SETTINGS_SCREEN_LOCK_ACTIVITY_TIMEOUT" = "Screen Lock Timeout"; /* Footer for the 'screen lock' section of the privacy settings. */ -"SETTINGS_SCREEN_LOCK_SECTION_FOOTER" = "Lock Signal access with iOS Touch ID or Face ID."; +"SETTINGS_SCREEN_LOCK_SECTION_FOOTER" = "Lock Signal when it hasn't been used recently. Unlock it with Touch ID, Face ID or your passcode."; /* Title for the 'screen lock' section of the privacy settings. */ "SETTINGS_SCREEN_LOCK_SECTION_TITLE" = "Screen Lock";