Merge tag '2.23.1.2'

pull/1/head
Michael Kirk 7 years ago
commit 2d9eb2b619

@ -24,6 +24,7 @@ import LocalAuthentication
0 0
] ]
@objc public static let ScreenLockWasEnabled = Notification.Name("ScreenLockWasEnabled")
@objc public static let ScreenLockDidChange = Notification.Name("ScreenLockDidChange") @objc public static let ScreenLockDidChange = Notification.Name("ScreenLockDidChange")
let primaryStorage: OWSPrimaryStorage let primaryStorage: OWSPrimaryStorage
@ -86,8 +87,13 @@ import LocalAuthentication
AssertIsOnMainThread() AssertIsOnMainThread()
assert(OWSStorage.isStorageReady()) assert(OWSStorage.isStorageReady())
let isEnabling = value && !isScreenLockEnabled()
self.dbConnection.setBool(value, forKey: OWSScreenLock_Key_IsScreenLockEnabled, inCollection: OWSScreenLock_Collection) self.dbConnection.setBool(value, forKey: OWSScreenLock_Key_IsScreenLockEnabled, inCollection: OWSScreenLock_Collection)
if isEnabling {
NotificationCenter.default.postNotificationNameAsync(OWSScreenLock.ScreenLockWasEnabled, object: nil)
}
NotificationCenter.default.postNotificationNameAsync(OWSScreenLock.ScreenLockDidChange, object: nil) NotificationCenter.default.postNotificationNameAsync(OWSScreenLock.ScreenLockDidChange, object: nil)
} }

@ -31,12 +31,23 @@ NS_ASSUME_NONNULL_BEGIN
// UI is dismissing. // UI is dismissing.
@property (nonatomic) BOOL shouldClearAuthUIWhenActive; @property (nonatomic) BOOL shouldClearAuthUIWhenActive;
@property (nonatomic, nullable) NSDate *appEnteredBackgroundDate; // Indicates whether or not the user is currently locked out of
@property (nonatomic, nullable) NSDate *appEnteredForegroundDate; // the app. Only applies if OWSScreenLock.isScreenLockEnabled.
@property (nonatomic, nullable) NSDate *lastUnlockSuccessDate; //
// * The user is locked out out by default on app launch.
// * The user is also locked out if they spend more than
// "timeout" seconds outside the app. When the user leaves
// the app, a "countdown" begins.
@property (nonatomic) BOOL isScreenLockUnlocked;
@property (nonatomic, nullable) NSDate *screenLockCountdownDate;
// We normally start the "countdown" when the app enters the background,
// But we also want to start the "countdown" if the app is inactive for
// more than N seconds.
@property (nonatomic, nullable) NSTimer *inactiveTimer; @property (nonatomic, nullable) NSTimer *inactiveTimer;
@end @end
#pragma mark - #pragma mark -
@ -99,6 +110,10 @@ NS_ASSUME_NONNULL_BEGIN
selector:@selector(screenLockDidChange:) selector:@selector(screenLockDidChange:)
name:OWSScreenLock.ScreenLockDidChange name:OWSScreenLock.ScreenLockDidChange
object:nil]; object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(screenLockWasEnabled:)
name:OWSScreenLock.ScreenLockWasEnabled
object:nil];
} }
- (void)setupWithRootWindow:(UIWindow *)rootWindow - (void)setupWithRootWindow:(UIWindow *)rootWindow
@ -115,38 +130,57 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - Methods #pragma mark - Methods
- (void)setAppIsInactive:(BOOL)appIsInactive - (void)tryToActivateScreenLockUponBecomingActive
{ {
BOOL didChange = _appIsInactive != appIsInactive; OWSAssert(!self.appIsInactive);
if (!self.isScreenLockUnlocked) {
// Screen lock is already activated.
DDLogVerbose(@"%@ tryToActivateScreenLockUponBecomingActive NO 0", self.logTag);
return;
}
if (!self.screenLockCountdownDate) {
// We became inactive, but never started a countdown.
DDLogVerbose(@"%@ tryToActivateScreenLockUponBecomingActive NO 1", self.logTag);
return;
}
NSTimeInterval countdownInterval = fabs([self.screenLockCountdownDate timeIntervalSinceNow]);
OWSAssert(countdownInterval >= 0);
NSTimeInterval screenLockTimeout = OWSScreenLock.sharedManager.screenLockTimeout;
OWSAssert(screenLockTimeout >= 0);
if (countdownInterval >= screenLockTimeout) {
self.isScreenLockUnlocked = NO;
DDLogVerbose(@"%@ tryToActivateScreenLockUponBecomingActive YES 1 (%0.3f >= %0.3f)",
self.logTag,
countdownInterval,
screenLockTimeout);
} else {
DDLogVerbose(@"%@ tryToActivateScreenLockUponBecomingActive NO 2 (%0.3f < %0.3f)",
self.logTag,
countdownInterval,
screenLockTimeout);
}
}
- (void)setAppIsInactive:(BOOL)appIsInactive
{
_appIsInactive = appIsInactive; _appIsInactive = appIsInactive;
if (didChange) { if (!appIsInactive) {
// If app is inactive for more than N seconds, [self tryToActivateScreenLockUponBecomingActive];
// treat this as "entering the background" for the purposes
// of Screen Lock. self.screenLockCountdownDate = nil;
if (!appIsInactive) {
[self.inactiveTimer invalidate];
self.inactiveTimer = nil;
} else if (!self.isShowingScreenLockUI) {
[self.inactiveTimer invalidate];
self.inactiveTimer = [NSTimer weakScheduledTimerWithTimeInterval:45.f
target:self
selector:@selector(inactiveTimerDidFire)
userInfo:nil
repeats:NO];
}
} }
[self startInactiveTimerIfNecessary];
[self ensureScreenProtection]; [self ensureScreenProtection];
} }
- (void)setAppIsInBackground:(BOOL)appIsInBackground - (void)setAppIsInBackground:(BOOL)appIsInBackground
{ {
if (appIsInBackground) { if (appIsInBackground && !_appIsInBackground) {
if (!_appIsInBackground) { [self startScreenLockCountdownIfNecessary];
[self markAppAsInBackground];
}
} }
_appIsInBackground = appIsInBackground; _appIsInBackground = appIsInBackground;
@ -154,31 +188,16 @@ NS_ASSUME_NONNULL_BEGIN
[self ensureScreenProtection]; [self ensureScreenProtection];
} }
- (void)markAppAsInBackground - (void)startScreenLockCountdownIfNecessary
{ {
// Record the time when app entered background. if (!self.screenLockCountdownDate) {
BOOL shouldResetEnteredBackgroundDate = NO; DDLogVerbose(@"%@ startScreenLockCountdownIfNecessary.", self.logTag);
if (!self.appEnteredBackgroundDate) { self.screenLockCountdownDate = [NSDate new];
// If this is the first time we're entering the
// background, record the date.
shouldResetEnteredBackgroundDate = YES;
}
if (self.hasUnlockedScreenLock) {
// If we've unlocked the screen lock, record the date.
shouldResetEnteredBackgroundDate = YES;
} else {
// If we're returning to the background _without_
// having unlocked the screen lock, DO NOT update this
// value as that would reset the unlock timeout.
}
if (shouldResetEnteredBackgroundDate) {
self.appEnteredBackgroundDate = [NSDate new];
} }
self.didLastUnlockAttemptFail = NO; self.didLastUnlockAttemptFail = NO;
[self.inactiveTimer invalidate]; [self clearInactiveTimer];
self.inactiveTimer = nil;
} }
- (void)ensureScreenProtection - (void)ensureScreenProtection
@ -232,8 +251,11 @@ NS_ASSUME_NONNULL_BEGIN
[OWSScreenLock.sharedManager tryToUnlockScreenLockWithSuccess:^{ [OWSScreenLock.sharedManager tryToUnlockScreenLockWithSuccess:^{
DDLogInfo(@"%@ unlock screen lock succeeded.", self.logTag); DDLogInfo(@"%@ unlock screen lock succeeded.", self.logTag);
self.isShowingScreenLockUI = NO; self.isShowingScreenLockUI = NO;
self.lastUnlockSuccessDate = [NSDate new];
self.isScreenLockUnlocked = YES;
[self ensureScreenProtection]; [self ensureScreenProtection];
} }
failure:^(NSError *error) { failure:^(NSError *error) {
@ -284,17 +306,6 @@ NS_ASSUME_NONNULL_BEGIN
} }
} }
- (BOOL)hasUnlockedScreenLock
{
if (!self.lastUnlockSuccessDate) {
return NO;
} else if (!self.appEnteredBackgroundDate) {
return YES;
} else {
return [self.lastUnlockSuccessDate isAfterDate:self.appEnteredBackgroundDate];
}
}
- (BOOL)shouldHaveScreenLock - (BOOL)shouldHaveScreenLock
{ {
if (![TSAccountManager isRegistered]) { if (![TSAccountManager isRegistered]) {
@ -305,10 +316,6 @@ NS_ASSUME_NONNULL_BEGIN
// Don't show 'Screen Lock' if 'Screen Lock' isn't enabled. // Don't show 'Screen Lock' if 'Screen Lock' isn't enabled.
DDLogVerbose(@"%@ shouldHaveScreenLock NO 2.", self.logTag); DDLogVerbose(@"%@ shouldHaveScreenLock NO 2.", self.logTag);
return NO; return NO;
} else if (self.hasUnlockedScreenLock) {
// Don't show 'Screen Lock' if 'Screen Lock' has been unlocked.
DDLogVerbose(@"%@ shouldHaveScreenLock NO 3.", self.logTag);
return NO;
} else if (self.appIsInBackground) { } else if (self.appIsInBackground) {
// Don't show 'Screen Lock' if app is in background. // Don't show 'Screen Lock' if app is in background.
DDLogVerbose(@"%@ shouldHaveScreenLock NO 4.", self.logTag); DDLogVerbose(@"%@ shouldHaveScreenLock NO 4.", self.logTag);
@ -322,26 +329,10 @@ NS_ASSUME_NONNULL_BEGIN
// Don't show 'Screen Lock' if app is inactive. // Don't show 'Screen Lock' if app is inactive.
DDLogVerbose(@"%@ shouldHaveScreenLock NO 5.", self.logTag); DDLogVerbose(@"%@ shouldHaveScreenLock NO 5.", self.logTag);
return NO; return NO;
} else if (!self.appEnteredBackgroundDate) {
// Show 'Screen Lock' if app has just launched.
DDLogVerbose(@"%@ shouldHaveScreenLock YES 1.", self.logTag);
return YES;
} else { } else {
OWSAssert(self.appEnteredBackgroundDate); BOOL shouldHaveScreenLock = !self.isScreenLockUnlocked;
DDLogVerbose(@"%@ shouldHaveScreenLock ? %d.", self.logTag, shouldHaveScreenLock);
NSTimeInterval screenLockInterval = fabs([self.appEnteredBackgroundDate timeIntervalSinceNow]); return shouldHaveScreenLock;
NSTimeInterval screenLockTimeout = OWSScreenLock.sharedManager.screenLockTimeout;
OWSAssert(screenLockInterval >= 0);
OWSAssert(screenLockTimeout >= 0);
if (screenLockInterval < screenLockTimeout) {
// Don't show 'Screen Lock' if 'Screen Lock' timeout hasn't elapsed.
DDLogVerbose(@"%@ shouldHaveScreenLock NO 6.", self.logTag);
return NO;
} else {
// Otherwise, show 'Screen Lock'.
DDLogVerbose(@"%@ shouldHaveScreenLock YES 2.", self.logTag);
return YES;
}
} }
} }
@ -504,6 +495,16 @@ NS_ASSUME_NONNULL_BEGIN
[self ensureScreenProtection]; [self ensureScreenProtection];
} }
- (void)screenLockWasEnabled:(NSNotification *)notification
{
// When we enable screen lock, consider that an unlock.
self.isScreenLockUnlocked = YES;
DDLogVerbose(@"%@ screenLockWasEnabled", self.logTag);
[self ensureScreenProtection];
}
- (void)registrationStateDidChange - (void)registrationStateDidChange
{ {
OWSAssertIsOnMainThread(); OWSAssertIsOnMainThread();
@ -542,13 +543,7 @@ NS_ASSUME_NONNULL_BEGIN
- (void)applicationWillEnterForeground:(NSNotification *)notification - (void)applicationWillEnterForeground:(NSNotification *)notification
{ {
// Clear the "delay Screen Lock UI" state; we don't want any
// delays when presenting the "unlock screen lock UI" after
// returning from background.
self.lastUnlockSuccessDate = nil;
self.appIsInBackground = NO; self.appIsInBackground = NO;
self.appEnteredForegroundDate = [NSDate new];
} }
- (void)applicationDidEnterBackground:(NSNotification *)notification - (void)applicationDidEnterBackground:(NSNotification *)notification
@ -556,9 +551,29 @@ NS_ASSUME_NONNULL_BEGIN
self.appIsInBackground = YES; self.appIsInBackground = YES;
} }
#pragma mark - Inactive Timer
- (void)inactiveTimerDidFire - (void)inactiveTimerDidFire
{ {
[self markAppAsInBackground]; [self startScreenLockCountdownIfNecessary];
}
- (void)startInactiveTimerIfNecessary
{
if (self.appIsInactive && !self.isShowingScreenLockUI && !self.inactiveTimer) {
[self.inactiveTimer invalidate];
self.inactiveTimer = [NSTimer weakScheduledTimerWithTimeInterval:45.f
target:self
selector:@selector(inactiveTimerDidFire)
userInfo:nil
repeats:NO];
}
}
- (void)clearInactiveTimer
{
[self.inactiveTimer invalidate];
self.inactiveTimer = nil;
} }
@end @end

Loading…
Cancel
Save