diff --git a/Classes/BITAuthenticator.h b/Classes/BITAuthenticator.h index 280b15480c..1fc16bef68 100644 --- a/Classes/BITAuthenticator.h +++ b/Classes/BITAuthenticator.h @@ -89,6 +89,17 @@ typedef void(^tValidationCompletion)(BOOL validated, NSError *error); */ @property (nonatomic, readonly) NSString *installationIdentification; +/** + * Specifies if the installationIdentification has been validated + * + * Depending on authenticationType and validationType this flag switches between + * YES/NO during application runtime. If it's YES, the installationIdentification has been + * validated (either against the backend on app launch / initial run of this version) or validation + * is not required. The flag is first updated (and stays NO) until the manager has been started. + * KVO'able + */ +@property (nonatomic, readonly) BOOL installationIdentificationValidated; + #pragma mark - UDID auth /** diff --git a/Classes/BITAuthenticator.m b/Classes/BITAuthenticator.m index df1c8cf7f0..d1d559c58c 100644 --- a/Classes/BITAuthenticator.m +++ b/Classes/BITAuthenticator.m @@ -21,7 +21,7 @@ static NSString* const kBITAuthenticatorDidSkipOptionalLogin = @"BITAuthenticato @implementation BITAuthenticator { id _appDidBecomeActiveObserver; - + id _appWillResignActiveObserver; UIViewController *_authenticationController; } @@ -241,6 +241,7 @@ static NSString* const kBITAuthenticatorDidSkipOptionalLogin = @"BITAuthenticato [_authenticationController dismissModalViewControllerAnimated:YES]; _authenticationController = nil; self.authenticationToken = token; + self.installationIdentificationValidated = YES; self.lastAuthenticatedVersion = [self executableUUID]; if(self.authenticationCompletionBlock) { self.authenticationCompletionBlock(self.authenticationToken, nil); @@ -451,6 +452,7 @@ static NSString* const kBITAuthenticatorDidSkipOptionalLogin = @"BITAuthenticato } - (void)validationSucceededWithCompletion:(tValidationCompletion) completion { + self.installationIdentificationValidated = YES; if(completion) { completion(YES, nil); } @@ -469,8 +471,8 @@ static NSString* const kBITAuthenticatorDidSkipOptionalLogin = @"BITAuthenticato } - (void) registerObservers { + __weak typeof(self) weakSelf = self; if(nil == _appDidBecomeActiveObserver) { - __weak typeof(self) weakSelf = self; _appDidBecomeActiveObserver = [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidBecomeActiveNotification object:nil queue:NSOperationQueue.mainQueue @@ -479,6 +481,15 @@ static NSString* const kBITAuthenticatorDidSkipOptionalLogin = @"BITAuthenticato [strongSelf applicationDidBecomeActive:note]; }]; } + if(nil == _appWillResignActiveObserver) { + _appWillResignActiveObserver = [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationWillResignActiveNotification + object:nil + queue:NSOperationQueue.mainQueue + usingBlock:^(NSNotification *note) { + typeof(self) strongSelf = weakSelf; + [strongSelf applicationWillResignActive:note]; + }]; + } } - (void) unregisterObservers { @@ -486,6 +497,10 @@ static NSString* const kBITAuthenticatorDidSkipOptionalLogin = @"BITAuthenticato [[NSNotificationCenter defaultCenter] removeObserver:_appDidBecomeActiveObserver]; _appDidBecomeActiveObserver = nil; } + if(_appWillResignActiveObserver) { + [[NSNotificationCenter defaultCenter] removeObserver:_appWillResignActiveObserver]; + _appWillResignActiveObserver = nil; + } } #pragma mark - Property overrides @@ -569,5 +584,10 @@ static NSString* const kBITAuthenticatorDidSkipOptionalLogin = @"BITAuthenticato } }; }; +- (void)applicationWillResignActive:(NSNotification *)note { + if(BITAuthenticatorValidationTypeOnAppActive == self.validationType) { + self.installationIdentificationValidated = NO; + } +} @end diff --git a/Classes/BITAuthenticator_Private.h b/Classes/BITAuthenticator_Private.h index d0907d6033..8c53f1df27 100644 --- a/Classes/BITAuthenticator_Private.h +++ b/Classes/BITAuthenticator_Private.h @@ -41,6 +41,12 @@ */ - (void) cleanupInternalStorage; +@property (nonatomic, readwrite) BOOL installationIdentificationValidated; + +/** + * method registered as observer for applicationWillBecomeInactive events + */ +- (void) applicationWillResignActive:(NSNotification*) note; /** * method registered as observer for applicationsDidBecomeActive events diff --git a/Support/HockeySDKTests/BITAuthenticatorTests.m b/Support/HockeySDKTests/BITAuthenticatorTests.m index 06bc54f449..47d252e20e 100644 --- a/Support/HockeySDKTests/BITAuthenticatorTests.m +++ b/Support/HockeySDKTests/BITAuthenticatorTests.m @@ -363,4 +363,39 @@ static void *kInstallationIdentification = &kInstallationIdentification; ident = [_sut installationIdentification]; assertThat(ident, isNot(equalTo(@"SuperToken"))); } + +#pragma mark - Test installationIdentificationValidated Flag +- (void) testThatFlagIsResetOnFailedValidation { + _sut.validationType = BITAuthenticatorValidationTypeOnFirstLaunch; + assertThatBool(_sut.installationIdentificationValidated, equalToBool(NO)); +} + +- (void) testThatFlagIsSetOnFailedValidation { + _sut.validationType = BITAuthenticatorValidationTypeOnFirstLaunch; + [_sut validationSucceededWithCompletion:nil]; + assertThatBool(_sut.installationIdentificationValidated, equalToBool(YES)); +} + +- (void) testThatApplicationBackgroundingResetsValidatedFlagInValidationTypeOnAppActive { + _sut.validationType = BITAuthenticatorValidationTypeOnAppActive; + //trigger flag set to YES + [_sut validationSucceededWithCompletion:nil]; + [_sut applicationWillResignActive:nil]; + assertThatBool(_sut.installationIdentificationValidated, equalToBool(NO)); +} + +- (void) testThatApplicationBackgroundingKeepValidatedFlag { + _sut.validationType = BITAuthenticatorValidationTypeOnFirstLaunch; + //trigger flag set to YES + [_sut validationSucceededWithCompletion:nil]; + [_sut applicationWillResignActive:nil]; + assertThatBool(_sut.installationIdentificationValidated, equalToBool(YES)); +} + +- (void) testThatInitialAuthSetsValidatedFlag { + _sut.validationType = BITAuthenticatorValidationTypeOnFirstLaunch; + [_sut didAuthenticateWithToken:@"MyToken"]; + assertThatBool(_sut.installationIdentificationValidated, equalToBool(YES)); +} + @end