diff options
-rw-r--r-- | Firebase/Auth/Source/FIRAuth.m | 8 | ||||
-rw-r--r-- | Firebase/Auth/Source/FIRAuth_Internal.h | 16 | ||||
-rw-r--r-- | Firebase/Core/FIRApp.m | 8 | ||||
-rw-r--r-- | Firebase/Core/Private/FIRAppInternal.h | 23 | ||||
-rw-r--r-- | Firebase/Database/Api/FIRDatabase.m | 67 | ||||
-rw-r--r-- | Firebase/Database/Login/FAuthTokenProvider.h | 4 | ||||
-rw-r--r-- | Firebase/Database/Login/FAuthTokenProvider.m | 75 | ||||
-rw-r--r-- | Firebase/Database/Public/FIRDatabase.h | 2 |
8 files changed, 67 insertions, 136 deletions
diff --git a/Firebase/Auth/Source/FIRAuth.m b/Firebase/Auth/Source/FIRAuth.m index c0f6c1f..d5e6b0f 100644 --- a/Firebase/Auth/Source/FIRAuth.m +++ b/Firebase/Auth/Source/FIRAuth.m @@ -68,11 +68,6 @@ #pragma mark - Constants -NSString *const FIRAuthStateDidChangeInternalNotification = - @"FIRAuthStateDidChangeInternalNotification"; -NSString *const FIRAuthStateDidChangeInternalNotificationTokenKey = - @"FIRAuthStateDidChangeInternalNotificationTokenKey"; - #if defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0 const NSNotificationName FIRAuthStateDidChangeNotification = @"FIRAuthStateDidChangeNotification"; #else @@ -1054,6 +1049,9 @@ static NSMutableDictionary *gKeychainServiceNameForAppName; [self scheduleAutoTokenRefresh]; } NSMutableDictionary *internalNotificationParameters = [NSMutableDictionary dictionary]; + if (self.app) { + internalNotificationParameters[FIRAuthStateDidChangeInternalNotificationAppKey] = self.app; + } if (token.length) { internalNotificationParameters[FIRAuthStateDidChangeInternalNotificationTokenKey] = token; } diff --git a/Firebase/Auth/Source/FIRAuth_Internal.h b/Firebase/Auth/Source/FIRAuth_Internal.h index 245ce57..c9d210a 100644 --- a/Firebase/Auth/Source/FIRAuth_Internal.h +++ b/Firebase/Auth/Source/FIRAuth_Internal.h @@ -28,22 +28,6 @@ NS_ASSUME_NONNULL_BEGIN -/** @var FIRAuthStateDidChangeInternalNotification - @brief The name of the @c NSNotificationCenter notification which is posted when the auth state - changes (e.g. a new token has been produced, a user logs in or out). The object parameter of - the notification is a dictionary possibly containing the key: - @c FIRAuthStateDidChangeInternalNotificationTokenKey (the new access token.) If it does not - contain this key it indicates a sign-out event took place. - */ -extern NSString *const FIRAuthStateDidChangeInternalNotification; - -/** @var FIRAuthStateDidChangeInternalNotificationTokenKey - @brief A key present in the dictionary object parameter of the - @c FIRAuthStateDidChangeInternalNotification notification. The value associated with this - key will contain the new access token. - */ -extern NSString *const FIRAuthStateDidChangeInternalNotificationTokenKey; - @interface FIRAuth () /** @property requestConfiguration diff --git a/Firebase/Core/FIRApp.m b/Firebase/Core/FIRApp.m index 860bbd3..db2915d 100644 --- a/Firebase/Core/FIRApp.m +++ b/Firebase/Core/FIRApp.m @@ -51,6 +51,14 @@ NSString *const kFIRAppDiagnosticsFIRAppKey = @"FIRApp"; NSString *const kFIRAppDiagnosticsSDKNameKey = @"SDKName"; NSString *const kFIRAppDiagnosticsSDKVersionKey = @"SDKVersion"; +// Auth internal notification notification and key. +NSString *const FIRAuthStateDidChangeInternalNotification = + @"FIRAuthStateDidChangeInternalNotification"; +NSString *const FIRAuthStateDidChangeInternalNotificationAppKey = + @"FIRAuthStateDidChangeInternalNotificationAppKey"; +NSString *const FIRAuthStateDidChangeInternalNotificationTokenKey = + @"FIRAuthStateDidChangeInternalNotificationTokenKey"; + /** * The URL to download plist files. */ diff --git a/Firebase/Core/Private/FIRAppInternal.h b/Firebase/Core/Private/FIRAppInternal.h index 54098d1..aa73d8d 100644 --- a/Firebase/Core/Private/FIRAppInternal.h +++ b/Firebase/Core/Private/FIRAppInternal.h @@ -60,6 +60,29 @@ extern NSString *const kFIRAppIsDefaultAppKey; extern NSString *const kFIRAppNameKey; extern NSString *const kFIRGoogleAppIDKey; +/** @var FIRAuthStateDidChangeInternalNotification + @brief The name of the @c NSNotificationCenter notification which is posted when the auth state + changes (e.g. a new token has been produced, a user logs in or out). The object parameter of + the notification is a dictionary possibly containing the key: + @c FIRAuthStateDidChangeInternalNotificationTokenKey (the new access token.) If it does not + contain this key it indicates a sign-out event took place. + */ +extern NSString *const FIRAuthStateDidChangeInternalNotification; + +/** @var FIRAuthStateDidChangeInternalNotificationTokenKey + @brief A key present in the dictionary object parameter of the + @c FIRAuthStateDidChangeInternalNotification notification. The value associated with this + key will contain the new access token. + */ +extern NSString *const FIRAuthStateDidChangeInternalNotificationTokenKey; + +/** @var FIRAuthStateDidChangeInternalNotificationAppKey + @brief A key present in the dictionary object parameter of the + @c FIRAuthStateDidChangeInternalNotification notification. The value associated with this + key will contain the FIRApp associated with the auth instance. + */ +extern NSString *const FIRAuthStateDidChangeInternalNotificationAppKey; + /** @typedef FIRTokenCallback @brief The type of block which gets called when a token is ready. */ diff --git a/Firebase/Database/Api/FIRDatabase.m b/Firebase/Database/Api/FIRDatabase.m index 7466f4c..38ccd54 100644 --- a/Firebase/Database/Api/FIRDatabase.m +++ b/Firebase/Database/Api/FIRDatabase.m @@ -15,6 +15,7 @@ */ #import <Foundation/Foundation.h> +#import "FIRAppInternal.h" #import "FIRLogger.h" #import "FIRDatabase.h" #import "FIRDatabase_Private.h" @@ -25,25 +26,7 @@ #import "FRepoInfo.h" #import "FIRDatabaseConfig.h" #import "FIRDatabaseReference_Private.h" - -/** - * This is a hack that defines all the methods we need from FIRApp/Options. At runtime we use reflection to get the - * default FIRApp instance if we need it. Since protocols don't carry any runtime information and selectors - * are invoked by name we can write code against this protocol as long as the method signatures don't change. - * - * TODO: Consider weak-linking the actual Firebase/Core framework or something. - */ - -extern NSString *const kFIRDefaultAppName; - -@protocol FIROptionsLike <NSObject> -@property(nonatomic, readonly, copy) NSString *databaseURL; -@end - -@protocol FIRAppLike <NSObject> -@property(nonatomic, readonly) id<FIROptionsLike> options; -@property(nonatomic, copy, readonly) NSString *name; -@end +#import "FIROptions.h" @interface FIRDatabase () @property (nonatomic, strong) FRepoInfo *repoInfo; @@ -77,23 +60,25 @@ static const char *FIREBASE_SEMVER = (const char *)STR(FIRDatabase_VERSION); } + (FIRDatabase *)database { - id<FIRAppLike> app = [FIRDatabase getDefaultApp]; - if (app == nil) { - [NSException raise:@"FIRAppNotConfigured" format:@"Failed to get default FIRDatabase instance. Must call FIRApp.configure() before using FIRDatabase."]; + if (![FIRApp isDefaultAppConfigured]) { + [NSException raise:@"FIRAppNotConfigured" + format:@"Failed to get default Firebase Database instance. Must call `[FIRApp " + @"configure]` (`FirebaseApp.configure()` in Swift) before using " + @"Firebase Database."]; } - return [FIRDatabase databaseForApp:(FIRApp*)app]; + FIRApp *app = [FIRApp defaultApp]; + return [FIRDatabase databaseForApp:app]; } -+ (FIRDatabase *)databaseForApp:(id)app { ++ (FIRDatabase *)databaseForApp:(FIRApp *)app { if (app == nil) { [NSException raise:@"InvalidFIRApp" format:@"nil FIRApp instance passed to databaseForApp."]; } NSMutableDictionary *instances = [self instances]; @synchronized (instances) { - id<FIRAppLike> appLike = (id<FIRAppLike>)app; - FIRDatabase *database = instances[appLike.name]; + FIRDatabase *database = instances[app.name]; if (!database) { - NSString *databaseUrl = appLike.options.databaseURL; + NSString *databaseUrl = app.options.databaseURL; if (databaseUrl == nil) { [NSException raise:@"MissingDatabaseURL" format:@"Failed to get FIRDatabase instance: FIRApp object has no " "databaseURL in its FirebaseOptions object."]; @@ -106,20 +91,20 @@ static const char *FIREBASE_SEMVER = (const char *)STR(FIRDatabase_VERSION); databaseUrl, [parsedUrl.path toString]]; } - id<FAuthTokenProvider> authTokenProvider = [FAuthTokenProvider authTokenProviderForApp:appLike]; + id<FAuthTokenProvider> authTokenProvider = [FAuthTokenProvider authTokenProviderForApp:app]; // If this is the default app, don't set the session persistence key so that we use our // default ("default") instead of the FIRApp default ("[DEFAULT]") so that we // preserve the default location used by the legacy Firebase SDK. NSString *sessionIdentifier = @"default"; - if (![appLike.name isEqualToString:kFIRDefaultAppName]) { - sessionIdentifier = appLike.name; + if ([FIRApp isDefaultAppConfigured] && app == [FIRApp defaultApp]) { + sessionIdentifier = app.name; } FIRDatabaseConfig *config = [[FIRDatabaseConfig alloc] initWithSessionIdentifier:sessionIdentifier authTokenProvider:authTokenProvider]; - database = [[FIRDatabase alloc] initWithApp:appLike repoInfo:parsedUrl.repoInfo config:config]; - instances[appLike.name] = database; + database = [[FIRDatabase alloc] initWithApp:app repoInfo:parsedUrl.repoInfo config:config]; + instances[app.name] = database; } return database; @@ -148,12 +133,12 @@ static const char *FIREBASE_SEMVER = (const char *)STR(FIRDatabase_VERSION); } -- (id)initWithApp:(id <FIRAppLike>)appLike repoInfo:(FRepoInfo *)info config:(FIRDatabaseConfig *)config { +- (id)initWithApp:(FIRApp *)app repoInfo:(FRepoInfo *)info config:(FIRDatabaseConfig *)config { self = [super init]; if (self != nil) { self->_repoInfo = info; self->_config = config; - self->_app = (FIRApp*) appLike; + self->_app = app; } return self; } @@ -204,7 +189,6 @@ static const char *FIREBASE_SEMVER = (const char *)STR(FIRDatabase_VERSION); }); } - - (void)goOffline { [self ensureRepo]; @@ -213,19 +197,6 @@ static const char *FIREBASE_SEMVER = (const char *)STR(FIRDatabase_VERSION); }); } -+ (id<FIRAppLike>) getDefaultApp { - Class appClass = NSClassFromString(@"FIRApp"); - if (appClass == nil) { - [NSException raise:@"FailedToFindFIRApp" format:@"Failed to find FIRApp class."]; - return nil; - } else { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wundeclared-selector" - return [appClass performSelector:@selector(defaultApp)]; -#pragma clang diagnostic pop - } -} - - (void)setPersistenceEnabled:(BOOL)persistenceEnabled { [self assertUnfrozen:@"setPersistenceEnabled"]; self->_config.persistenceEnabled = persistenceEnabled; diff --git a/Firebase/Database/Login/FAuthTokenProvider.h b/Firebase/Database/Login/FAuthTokenProvider.h index dca0026..363b82f 100644 --- a/Firebase/Database/Login/FAuthTokenProvider.h +++ b/Firebase/Database/Login/FAuthTokenProvider.h @@ -19,6 +19,8 @@ #import "FTypedefs.h" #import "FTypedefs_Private.h" +@class FIRApp; + @protocol FAuthTokenProvider <NSObject> - (void) fetchTokenForcingRefresh:(BOOL)forceRefresh withCallback:(fbt_void_nsstring_nserror)callback; @@ -29,7 +31,7 @@ @interface FAuthTokenProvider : NSObject -+ (id<FAuthTokenProvider>) authTokenProviderForApp:(id)app; ++ (id<FAuthTokenProvider>) authTokenProviderForApp:(FIRApp *)app; - (instancetype)init NS_UNAVAILABLE; diff --git a/Firebase/Database/Login/FAuthTokenProvider.m b/Firebase/Database/Login/FAuthTokenProvider.m index f3c2a61..8d65609 100644 --- a/Firebase/Database/Login/FAuthTokenProvider.m +++ b/Firebase/Database/Login/FAuthTokenProvider.m @@ -16,65 +16,22 @@ #import "FAuthTokenProvider.h" #import "FUtilities.h" +#import "FIRAppInternal.h" #import "FIRLogger.h" #import "FIRDatabaseQuery_Private.h" #import "FIRNoopAuthTokenProvider.h" -static NSString *const FIRAuthStateDidChangeInternalNotification = @"FIRAuthStateDidChangeInternalNotification"; -static NSString *const FIRAuthStateDidChangeInternalNotificationTokenKey = @"FIRAuthStateDidChangeInternalNotificationTokenKey"; - - -/** - * This is a hack that defines all the methods we need from FIRFirebaseApp. At runtime we use reflection to get an - * actual instance of FIRFirebaseApp. Since protocols don't carry any runtime information and selectors are invoked - * by name we can write code against this protocol as long as the method signatures of FIRFirebaseApp don't change. - */ -@protocol FIRFirebaseAppLike <NSObject> - -- (void)getTokenForcingRefresh:(BOOL)forceRefresh withCallback:(void (^)(NSString *_Nullable token, NSError *_Nullable error))callback; - -@end - - -/** - * This is a hack that defines all the methods we need from FIRAuth. - */ -@protocol FIRFirebaseAuthLike <NSObject> - -- (id<FIRFirebaseAppLike>) app; - -@end - -/** - * This is a hack that copies the definitions of Firebase Auth error codes. If the error codes change in the original code, this - * will break at runtime due to undefined behavior! - */ -typedef NS_ENUM(NSUInteger, FIRErrorCode) { - /*! @var FIRErrorCodeNoAuth - @brief Represents the case where an auth-related message was sent to a @c FIRFirebaseApp - instance which has no associated @c FIRAuth instance. - */ - FIRErrorCodeNoAuth, - - /*! @var FIRErrorCodeNoSignedInUser - @brief Represents the case where an attempt was made to fetch a token when there is no signed - in user. - */ - FIRErrorCodeNoSignedInUser, -}; - - @interface FAuthStateListenerWrapper : NSObject @property (nonatomic, copy) fbt_void_nsstring listener; -@property (nonatomic, weak) id<FIRFirebaseAppLike> app; +@property (nonatomic, weak) FIRApp *app; @end @implementation FAuthStateListenerWrapper -- (instancetype) initWithListener:(fbt_void_nsstring)listener app:(id<FIRFirebaseAppLike>)app { +- (instancetype) initWithListener:(fbt_void_nsstring)listener app:(FIRApp *)app { self = [super init]; if (self != nil) { self->_listener = listener; @@ -88,9 +45,9 @@ typedef NS_ENUM(NSUInteger, FIRErrorCode) { } - (void) authStateDidChangeNotification:(NSNotification *)notification { - id<FIRFirebaseAuthLike> auth = notification.object; - if (auth.app == self->_app) { - NSDictionary *userInfo = notification.userInfo; + NSDictionary *userInfo = notification.userInfo; + FIRApp *authApp = userInfo[FIRAuthStateDidChangeInternalNotificationAppKey]; + if (authApp == self.app) { NSString *token = userInfo[FIRAuthStateDidChangeInternalNotificationTokenKey]; dispatch_async([FIRDatabaseQuery sharedQueue], ^{ self.listener(token); @@ -107,17 +64,17 @@ typedef NS_ENUM(NSUInteger, FIRErrorCode) { @interface FIRFirebaseAuthTokenProvider : NSObject <FAuthTokenProvider> -@property (nonatomic, strong) id<FIRFirebaseAppLike> app; +@property (nonatomic, strong) FIRApp *app; /** Strong references to the auth listeners as they are only weak in FIRFirebaseApp */ @property (nonatomic, strong) NSMutableArray *authListeners; -- (instancetype) initWithFirebaseApp:(id<FIRFirebaseAppLike>)app; +- (instancetype) initWithFirebaseApp:(FIRApp *)app; @end @implementation FIRFirebaseAuthTokenProvider -- (instancetype) initWithFirebaseApp:(id<FIRFirebaseAppLike>)app { +- (instancetype) initWithFirebaseApp:(FIRApp *)app { self = [super init]; if (self != nil) { self->_app = app; @@ -130,19 +87,7 @@ typedef NS_ENUM(NSUInteger, FIRErrorCode) { // TODO: Don't fetch token if there is no current user [self.app getTokenForcingRefresh:forceRefresh withCallback:^(NSString * _Nullable token, NSError * _Nullable error) { dispatch_async([FIRDatabaseQuery sharedQueue], ^{ - if (error != nil) { - if (error.code == FIRErrorCodeNoAuth) { - FFLog(@"I-RDB073001", @"Firebase Auth is not configured, not going to use authentication."); - callback(nil, nil); - } else if (error.code == FIRErrorCodeNoSignedInUser) { - // No signed in user is an expected case, callback as success with no token - callback(nil, nil); - } else { - callback(nil, error); - } - } else { - callback(token, nil); - } + callback(token, error); }); }]; } diff --git a/Firebase/Database/Public/FIRDatabase.h b/Firebase/Database/Public/FIRDatabase.h index fd4535f..a67f96d 100644 --- a/Firebase/Database/Public/FIRDatabase.h +++ b/Firebase/Database/Public/FIRDatabase.h @@ -51,7 +51,7 @@ FIR_SWIFT_NAME(Database) * @param app The FIRApp to get a FIRDatabase for. * @return A FIRDatabase instance. */ -+ (FIRDatabase *) databaseForApp:(FIRApp*)app FIR_SWIFT_NAME(database(app:)); ++ (FIRDatabase *) databaseForApp:(FIRApp *)app FIR_SWIFT_NAME(database(app:)); /** The FIRApp instance to which this FIRDatabase belongs. */ @property (weak, readonly, nonatomic) FIRApp *app; |