diff options
-rw-r--r-- | AuthSamples/Sample/MainViewController.m | 80 | ||||
-rw-r--r-- | AuthSamples/Sample/StaticContentTableViewManager.h | 2 | ||||
-rw-r--r-- | AuthSamples/Sample/UIViewController+Alerts.h | 2 | ||||
-rw-r--r-- | AuthSamples/Samples.xcodeproj/project.pbxproj | 4 | ||||
-rw-r--r-- | Firebase/Auth/Source/FIRAuth.m | 88 | ||||
-rw-r--r-- | Firebase/Auth/Source/FIRAuth_Internal.h | 6 | ||||
-rw-r--r-- | Firebase/Auth/Source/FIRUser.m | 2 |
7 files changed, 144 insertions, 40 deletions
diff --git a/AuthSamples/Sample/MainViewController.m b/AuthSamples/Sample/MainViewController.m index 20f76fe..9876195 100644 --- a/AuthSamples/Sample/MainViewController.m +++ b/AuthSamples/Sample/MainViewController.m @@ -20,6 +20,7 @@ #import "FIRAdditionalUserInfo.h" #import "FIRApp.h" +#import "FIRAppAssociationRegistration.h" #import "FIROAuthProvider.h" #import "FIRPhoneAuthCredential.h" #import "FIRPhoneAuthProvider.h" @@ -362,6 +363,11 @@ static NSString *const kCreateUserTitle = @"Create User"; */ static NSString *const kDeleteAppTitle = @"Delete App"; +/** @var kTimeAuthInitTitle + @brief The text of the "Time Auth Initialization" button. + */ +static NSString *const kTimeAuthInitTitle = @"Time Auth Initialization"; + /** @var kSectionTitleManualTests @brief The section title for automated manual tests. */ @@ -493,6 +499,30 @@ typedef void (^FIRTokenCallback)(NSString *_Nullable token, NSError *_Nullable e - (void)getTokenForcingRefresh:(BOOL)forceRefresh withCallback:(nonnull FIRTokenCallback)callback; @end +/** @category FIRAppAssociationRegistration(Deregistration) + @brief The category for the deregistration method. + */ +@interface FIRAppAssociationRegistration (Deregistration) +/** @fn deregisteredObjectWithHost:key: + @brief Removes the object that was registered with a particular host and key, if one exists. + @param host The host object. + @param key The key to specify the registered object on the host. + */ ++ (void)deregisterObjectWithHost:(id)host key:(NSString *)key; +@end + +@implementation FIRAppAssociationRegistration (Deregistration) + ++ (void)deregisterObjectWithHost:(id)host key:(NSString *)key { + @synchronized(self) { + SEL dictKey = @selector(registeredObjectWithHost:key:creationBlock:); + NSMutableDictionary<NSString *, id> *objectsByKey = objc_getAssociatedObject(host, dictKey); + [objectsByKey removeObjectForKey:key]; + } +} + +@end + @implementation MainViewController { NSMutableString *_consoleString; @@ -681,7 +711,9 @@ typedef void (^FIRTokenCallback)(NSString *_Nullable token, NSError *_Nullable e [StaticContentTableViewCell cellWithTitle:kTokenGetButtonText action:^{ [weakSelf getAppTokenWithForce:NO]; }], [StaticContentTableViewCell cellWithTitle:kTokenRefreshButtonText - action:^{ [weakSelf getAppTokenWithForce:YES]; }] + action:^{ [weakSelf getAppTokenWithForce:YES]; }], + [StaticContentTableViewCell cellWithTitle:kTimeAuthInitTitle + action:^{ [weakSelf timeAuthInitialization]; }] ]], [StaticContentTableViewSection sectionWithTitle:kSectionTitleListeners cells:@[ [StaticContentTableViewCell cellWithTitle:kAddAuthStateListenerTitle @@ -730,8 +762,8 @@ typedef void (^FIRTokenCallback)(NSString *_Nullable token, NSError *_Nullable e /** @fn signInWithProvider:provider: @brief Perform sign in with credential operataion, for given auth provider. - @provider The auth provider. - @callback The callback to continue the flow which executed this sign-in. + @param provider The auth provider. + @param callback The callback to continue the flow which executed this sign-in. */ - (void)signInWithProvider:(nonnull id<AuthProvider>)provider callback:(void(^)(void))callback { if (!provider) { @@ -2382,6 +2414,48 @@ typedef void (^FIRTokenCallback)(NSString *_Nullable token, NSError *_Nullable e }]; } +/** @fn timeAuthInitialization + @brief Times FIRAuth instance initialization time. + */ +- (void)timeAuthInitialization { + // Temporarily disable auth state listener to avoid interfering with the result. + [[NSNotificationCenter defaultCenter] removeObserver:self + name:FIRAuthStateDidChangeNotification + object:nil]; + [self showSpinner:^() { + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^() { + const int numberOfRuns = 4096; + FIRApp *app = [FIRApp defaultApp]; + NSString *key = NSStringFromClass([FIRAuth class]); + NSDate *startTime = [NSDate date]; + for (int i = 0; i < numberOfRuns; i++) { + @autoreleasepool { + [FIRAppAssociationRegistration deregisterObjectWithHost:app key:key]; + [FIRAuth auth]; + } + } + NSDate *endTime = [NSDate date]; + dispatch_async(dispatch_get_main_queue(), ^() { + // Re-enable auth state listener. + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(authStateChangedForAuth:) + name:FIRAuthStateDidChangeNotification + object:nil]; + [self hideSpinner:^() { + NSTimeInterval averageTime = [endTime timeIntervalSinceDate:startTime] / numberOfRuns; + NSString *message = [NSString stringWithFormat: + @"Each [FIRAuth auth] takes average of %.3f ms for %d runs", + averageTime * 1000, numberOfRuns]; + [self showMessagePromptWithTitle:@"Timing Result" + message:message + showCancelButton:NO + completion:nil]; + }]; + }); + }); + }]; +} + #pragma mark - Helpers /** @fn user diff --git a/AuthSamples/Sample/StaticContentTableViewManager.h b/AuthSamples/Sample/StaticContentTableViewManager.h index cb56391..5a7c123 100644 --- a/AuthSamples/Sample/StaticContentTableViewManager.h +++ b/AuthSamples/Sample/StaticContentTableViewManager.h @@ -242,8 +242,6 @@ typedef void(^StaticContentTableViewCellAction)(void); @param customCell The custom @c UITableViewCell to use for this cell. @param title If no custom cell is being used, this is the text of the @c titleLabel of the @c UITableViewCell. - @param title If no custom cell is being used, this is the text of the @c detailTextLabel of the - @c UITableViewCell. @param action A block which is executed when the cell is selected. @param accessibilityID The accessibility ID to add to the cell. */ diff --git a/AuthSamples/Sample/UIViewController+Alerts.h b/AuthSamples/Sample/UIViewController+Alerts.h index 375a0ed..88686c1 100644 --- a/AuthSamples/Sample/UIViewController+Alerts.h +++ b/AuthSamples/Sample/UIViewController+Alerts.h @@ -23,7 +23,7 @@ NS_ASSUME_NONNULL_BEGIN */ typedef void (^AlertPromptCompletionBlock)(BOOL userPressedOK, NSString *_Nullable userInput); -/*! @class Alerts +/*! @category UIViewController(Alerts) @brief Wrapper for @c UIAlertController and @c UIAlertView for backwards compatability with iOS 6+. */ diff --git a/AuthSamples/Samples.xcodeproj/project.pbxproj b/AuthSamples/Samples.xcodeproj/project.pbxproj index dfe1e17..89d78c3 100644 --- a/AuthSamples/Samples.xcodeproj/project.pbxproj +++ b/AuthSamples/Samples.xcodeproj/project.pbxproj @@ -1399,7 +1399,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.3; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -1442,7 +1442,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.3; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; diff --git a/Firebase/Auth/Source/FIRAuth.m b/Firebase/Auth/Source/FIRAuth.m index 9363069..7a25919 100644 --- a/Firebase/Auth/Source/FIRAuth.m +++ b/Firebase/Auth/Source/FIRAuth.m @@ -199,6 +199,11 @@ static NSMutableDictionary *gKeychainServiceNameForAppName; @end @implementation FIRAuth { + /** @var _currentUser + @brief The current user. + */ + FIRUser *_currentUser; + /** @var _firebaseAppName @brief The Firebase app name. */ @@ -315,6 +320,7 @@ static NSMutableDictionary *gKeychainServiceNameForAppName; app.getTokenImplementation = ^(BOOL forceRefresh, FIRTokenCallback callback) { dispatch_async(FIRAuthGlobalWorkQueue(), ^{ FIRAuth *strongSelf = weakSelf; + // Enable token auto-refresh if not aleady enabled. if (strongSelf && !strongSelf->_autoRefreshTokens) { FIRLogInfo(kFIRLoggerAuth, @"I-AUT000002", @"Token auto-refresh enabled."); strongSelf->_autoRefreshTokens = YES; @@ -346,15 +352,17 @@ static NSMutableDictionary *gKeychainServiceNameForAppName; }]; #endif } - if (!strongSelf.currentUser) { + // Call back with 'nil' if there is no current user. + if (!strongSelf || !strongSelf->_currentUser) { dispatch_async(dispatch_get_main_queue(), ^{ callback(nil, nil); }); return; } - [strongSelf.currentUser internalGetTokenForcingRefresh:forceRefresh - callback:^(NSString *_Nullable token, - NSError *_Nullable error) { + // Call back with current user token. + [strongSelf->_currentUser internalGetTokenForcingRefresh:forceRefresh + callback:^(NSString *_Nullable token, + NSError *_Nullable error) { dispatch_async(dispatch_get_main_queue(), ^{ callback(token, error); }); @@ -378,33 +386,47 @@ static NSMutableDictionary *gKeychainServiceNameForAppName; _listenerHandles = [NSMutableArray array]; _APIKey = [APIKey copy]; _firebaseAppName = [appName copy]; - NSString *keychainServiceName = [FIRAuth keychainServiceNameForAppName:appName]; - if (keychainServiceName) { - _keychain = [[FIRAuthKeychain alloc] initWithService:keychainServiceName]; - } - // Load current user from keychain. - FIRUser *user; - NSError *error; - if ([self getUser:&user error:&error]) { - [self updateCurrentUser:user byForce:NO savingToDisk:NO error:&error]; - } else { - FIRLogError(kFIRLoggerAuth, @"I-AUT000001", - @"Error loading saved user when starting up: %@", error); - } - #if TARGET_OS_IOS - // Initialize for phone number auth. - _tokenManager = - [[FIRAuthAPNSTokenManager alloc] initWithApplication:[UIApplication sharedApplication]]; + UIApplication *application = [UIApplication sharedApplication]; + #endif + + // Continue with the rest of initialization in the work thread. + __weak FIRAuth *weakSelf = self; + dispatch_async(FIRAuthGlobalWorkQueue(), ^{ + // Load current user from Keychain. + FIRAuth *strongSelf = weakSelf; + if (!strongSelf) { + return; + } + NSString *keychainServiceName = + [FIRAuth keychainServiceNameForAppName:strongSelf->_firebaseAppName]; + if (keychainServiceName) { + strongSelf->_keychain = [[FIRAuthKeychain alloc] initWithService:keychainServiceName]; + } + FIRUser *user; + NSError *error; + if ([strongSelf getUser:&user error:&error]) { + [strongSelf updateCurrentUser:user byForce:NO savingToDisk:NO error:&error]; + } else { + FIRLogError(kFIRLoggerAuth, @"I-AUT000001", + @"Error loading saved user when starting up: %@", error); + } - _appCredentialManager = [[FIRAuthAppCredentialManager alloc] initWithKeychain:_keychain]; + #if TARGET_OS_IOS + // Initialize for phone number auth. + strongSelf->_tokenManager = + [[FIRAuthAPNSTokenManager alloc] initWithApplication:application]; - _notificationManager = - [[FIRAuthNotificationManager alloc] initWithApplication:[UIApplication sharedApplication] - appCredentialManager:_appCredentialManager]; + strongSelf->_appCredentialManager = + [[FIRAuthAppCredentialManager alloc] initWithKeychain:strongSelf->_keychain]; - [[FIRAuthAppDelegateProxy sharedInstance] addHandler:self]; - #endif + strongSelf->_notificationManager = [[FIRAuthNotificationManager alloc] + initWithApplication:application + appCredentialManager:strongSelf->_appCredentialManager]; + + [[FIRAuthAppDelegateProxy sharedInstance] addHandler:strongSelf]; + #endif + }); } return self; } @@ -431,6 +453,14 @@ static NSMutableDictionary *gKeychainServiceNameForAppName; #pragma mark - Public API +- (FIRUser *)currentUser { + __block FIRUser *result; + dispatch_sync(FIRAuthGlobalWorkQueue(), ^{ + result = _currentUser; + }); + return result; +} + - (void)fetchProvidersForEmail:(NSString *)email completion:(FIRProviderQueryCallback)completion { dispatch_async(FIRAuthGlobalWorkQueue(), ^{ @@ -1275,10 +1305,6 @@ static NSMutableDictionary *gKeychainServiceNameForAppName; return YES; } -/** @fn getUID - @brief Gets the identifier of the current user, if any. - @return The identifier of the current user, or nil if there is no current user. - */ - (nullable NSString *)getUID { return _currentUser.uid; } diff --git a/Firebase/Auth/Source/FIRAuth_Internal.h b/Firebase/Auth/Source/FIRAuth_Internal.h index 94363a1..5d1d13f 100644 --- a/Firebase/Auth/Source/FIRAuth_Internal.h +++ b/Firebase/Auth/Source/FIRAuth_Internal.h @@ -75,6 +75,12 @@ extern NSString *const FIRAuthStateDidChangeInternalNotificationTokenKey; - (nullable instancetype)initWithAPIKey:(NSString *)APIKey appName:(NSString *)appName NS_DESIGNATED_INITIALIZER; +/** @fn getUID + @brief Gets the identifier of the current user, if any. + @return The identifier of the current user, or nil if there is no current user. + */ +- (nullable NSString *)getUID; + /** @fn notifyListenersOfAuthStateChange @brief Posts the @c FIRAuthStateDidChangeNotification notification. @remarks Called by @c FIRUser when token changes occur. diff --git a/Firebase/Auth/Source/FIRUser.m b/Firebase/Auth/Source/FIRUser.m index 112b870..cd168cf 100644 --- a/Firebase/Auth/Source/FIRUser.m +++ b/Firebase/Auth/Source/FIRUser.m @@ -734,7 +734,7 @@ static void callInMainThreadWithAuthDataResultAndError( callInMainThreadWithAuthDataResultAndError(completion, authResult, error); return; } - if (![authResult.user.uid isEqual:_auth.currentUser.uid]) { + if (![authResult.user.uid isEqual:[_auth getUID]]) { callInMainThreadWithAuthDataResultAndError(completion, authResult, [FIRAuthErrorUtils userMismatchError]); return; |