From fd9fd271d0dba3935a6f5611a1554f2c59b696af Mon Sep 17 00:00:00 2001 From: zxu Date: Thu, 15 Feb 2018 17:23:08 -0500 Subject: replacing Auth/FSTUser by C++ auth implementation (#804) * replacing Auth/FSTUser by C++ auth implementation * address changes --- .../Tests/Local/FSTLevelDBLocalStoreTests.mm | 1 - .../Tests/Local/FSTLevelDBMutationQueueTests.mm | 5 +- .../Example/Tests/Local/FSTLocalStoreTests.mm | 9 ++- .../Tests/Local/FSTMemoryMutationQueueTests.mm | 8 ++- .../Example/Tests/Local/FSTMutationQueueTests.mm | 8 ++- Firestore/Example/Tests/SpecTests/FSTSpecTests.mm | 21 +++++-- .../Tests/SpecTests/FSTSyncEngineTestDriver.h | 20 ++++--- .../Tests/SpecTests/FSTSyncEngineTestDriver.mm | 50 +++++++++------- Firestore/Source/API/FIRFirestore.mm | 2 +- Firestore/Source/Auth/FSTCredentialsProvider.h | 13 +++-- Firestore/Source/Auth/FSTCredentialsProvider.mm | 43 +++++++++----- .../Source/Auth/FSTEmptyCredentialsProvider.mm | 7 ++- Firestore/Source/Auth/FSTUser.h | 43 -------------- Firestore/Source/Auth/FSTUser.mm | 68 ---------------------- Firestore/Source/Core/FSTFirestoreClient.mm | 16 +++-- Firestore/Source/Core/FSTSyncEngine.h | 8 ++- Firestore/Source/Core/FSTSyncEngine.mm | 32 +++++----- Firestore/Source/Local/FSTLevelDB.mm | 4 +- Firestore/Source/Local/FSTLevelDBMutationQueue.h | 5 +- Firestore/Source/Local/FSTLevelDBMutationQueue.mm | 9 +-- Firestore/Source/Local/FSTLocalStore.h | 8 ++- Firestore/Source/Local/FSTLocalStore.mm | 7 ++- Firestore/Source/Local/FSTMemoryPersistence.mm | 19 +++--- Firestore/Source/Local/FSTPersistence.h | 5 +- Firestore/Source/Remote/FSTRemoteStore.h | 5 +- Firestore/Source/Remote/FSTRemoteStore.mm | 11 +++- Firestore/core/src/firebase/firestore/auth/user.h | 19 ++++++ .../core/test/firebase/firestore/auth/user_test.cc | 5 ++ 28 files changed, 221 insertions(+), 230 deletions(-) delete mode 100644 Firestore/Source/Auth/FSTUser.h delete mode 100644 Firestore/Source/Auth/FSTUser.mm diff --git a/Firestore/Example/Tests/Local/FSTLevelDBLocalStoreTests.mm b/Firestore/Example/Tests/Local/FSTLevelDBLocalStoreTests.mm index f71f5c9..97e3c5b 100644 --- a/Firestore/Example/Tests/Local/FSTLevelDBLocalStoreTests.mm +++ b/Firestore/Example/Tests/Local/FSTLevelDBLocalStoreTests.mm @@ -18,7 +18,6 @@ #import -#import "Firestore/Source/Auth/FSTUser.h" #import "Firestore/Source/Local/FSTLevelDB.h" #import "Firestore/Example/Tests/Local/FSTLocalStoreTests.h" diff --git a/Firestore/Example/Tests/Local/FSTLevelDBMutationQueueTests.mm b/Firestore/Example/Tests/Local/FSTLevelDBMutationQueueTests.mm index fe79598..2e24055 100644 --- a/Firestore/Example/Tests/Local/FSTLevelDBMutationQueueTests.mm +++ b/Firestore/Example/Tests/Local/FSTLevelDBMutationQueueTests.mm @@ -20,7 +20,6 @@ #include #import "Firestore/Protos/objc/firestore/local/Mutation.pbobjc.h" -#import "Firestore/Source/Auth/FSTUser.h" #import "Firestore/Source/Local/FSTLevelDB.h" #import "Firestore/Source/Local/FSTLevelDBKey.h" #import "Firestore/Source/Local/FSTWriteGroup.h" @@ -28,6 +27,7 @@ #import "Firestore/Example/Tests/Local/FSTMutationQueueTests.h" #import "Firestore/Example/Tests/Local/FSTPersistenceTestHelpers.h" +#include "Firestore/core/src/firebase/firestore/auth/user.h" #include "Firestore/core/src/firebase/firestore/util/ordered_code.h" NS_ASSUME_NONNULL_BEGIN @@ -37,6 +37,7 @@ using leveldb::Slice; using leveldb::Status; using leveldb::WriteOptions; using Firestore::StringView; +using firebase::firestore::auth::User; using firebase::firestore::util::OrderedCode; // A dummy mutation value, useful for testing code that's known to examine only mutation keys. @@ -69,7 +70,7 @@ std::string MutationLikeKey(StringView table, StringView userID, FSTBatchID batc - (void)setUp { [super setUp]; _db = [FSTPersistenceTestHelpers levelDBPersistence]; - self.mutationQueue = [_db mutationQueueForUser:[[FSTUser alloc] initWithUID:@"user"]]; + self.mutationQueue = [_db mutationQueueForUser:User("user")]; self.persistence = _db; FSTWriteGroup *group = [self.persistence startGroupWithAction:@"Start MutationQueue"]; diff --git a/Firestore/Example/Tests/Local/FSTLocalStoreTests.mm b/Firestore/Example/Tests/Local/FSTLocalStoreTests.mm index 45d1815..f3493ce 100644 --- a/Firestore/Example/Tests/Local/FSTLocalStoreTests.mm +++ b/Firestore/Example/Tests/Local/FSTLocalStoreTests.mm @@ -18,7 +18,6 @@ #import -#import "Firestore/Source/Auth/FSTUser.h" #import "Firestore/Source/Core/FSTQuery.h" #import "Firestore/Source/Core/FSTTimestamp.h" #import "Firestore/Source/Local/FSTEagerGarbageCollector.h" @@ -42,6 +41,10 @@ #import "Firestore/third_party/Immutable/Tests/FSTImmutableSortedDictionary+Testing.h" #import "Firestore/third_party/Immutable/Tests/FSTImmutableSortedSet+Testing.h" +#include "Firestore/core/src/firebase/firestore/auth/user.h" + +using firebase::firestore::auth::User; + NS_ASSUME_NONNULL_BEGIN /** Creates a document version dictionary mapping the document in @a mutation to @a version. */ @@ -77,7 +80,7 @@ FSTDocumentVersionDictionary *FSTVersionDictionary(FSTMutation *mutation, id garbageCollector = [[FSTEagerGarbageCollector alloc] init]; self.localStore = [[FSTLocalStore alloc] initWithPersistence:persistence garbageCollector:garbageCollector - initialUser:[FSTUser unauthenticatedUser]]; + initialUser:User::Unauthenticated()]; [self.localStore start]; _batches = [NSMutableArray array]; @@ -112,7 +115,7 @@ FSTDocumentVersionDictionary *FSTVersionDictionary(FSTMutation *mutation, id garbageCollector = [[FSTNoOpGarbageCollector alloc] init]; self.localStore = [[FSTLocalStore alloc] initWithPersistence:self.localStorePersistence garbageCollector:garbageCollector - initialUser:[FSTUser unauthenticatedUser]]; + initialUser:User::Unauthenticated()]; [self.localStore start]; } diff --git a/Firestore/Example/Tests/Local/FSTMemoryMutationQueueTests.mm b/Firestore/Example/Tests/Local/FSTMemoryMutationQueueTests.mm index ab7afee..5567078 100644 --- a/Firestore/Example/Tests/Local/FSTMemoryMutationQueueTests.mm +++ b/Firestore/Example/Tests/Local/FSTMemoryMutationQueueTests.mm @@ -16,12 +16,15 @@ #import "Firestore/Source/Local/FSTMemoryMutationQueue.h" -#import "Firestore/Source/Auth/FSTUser.h" #import "Firestore/Source/Local/FSTMemoryPersistence.h" #import "Firestore/Example/Tests/Local/FSTMutationQueueTests.h" #import "Firestore/Example/Tests/Local/FSTPersistenceTestHelpers.h" +#include "Firestore/core/src/firebase/firestore/auth/user.h" + +using firebase::firestore::auth::User; + @interface FSTMemoryMutationQueueTests : FSTMutationQueueTests @end @@ -35,8 +38,7 @@ [super setUp]; self.persistence = [FSTPersistenceTestHelpers memoryPersistence]; - self.mutationQueue = - [self.persistence mutationQueueForUser:[[FSTUser alloc] initWithUID:@"user"]]; + self.mutationQueue = [self.persistence mutationQueueForUser:User("user")]; } @end diff --git a/Firestore/Example/Tests/Local/FSTMutationQueueTests.mm b/Firestore/Example/Tests/Local/FSTMutationQueueTests.mm index 020a0a7..62d30fb 100644 --- a/Firestore/Example/Tests/Local/FSTMutationQueueTests.mm +++ b/Firestore/Example/Tests/Local/FSTMutationQueueTests.mm @@ -16,7 +16,6 @@ #import "Firestore/Example/Tests/Local/FSTMutationQueueTests.h" -#import "Firestore/Source/Auth/FSTUser.h" #import "Firestore/Source/Core/FSTQuery.h" #import "Firestore/Source/Core/FSTTimestamp.h" #import "Firestore/Source/Local/FSTEagerGarbageCollector.h" @@ -28,6 +27,10 @@ #import "Firestore/Example/Tests/Util/FSTHelpers.h" +#include "Firestore/core/src/firebase/firestore/auth/user.h" + +using firebase::firestore::auth::User; + NS_ASSUME_NONNULL_BEGIN @implementation FSTMutationQueueTests @@ -127,8 +130,7 @@ NS_ASSUME_NONNULL_BEGIN // Restart the queue so that nextBatchID will be reset. [self.mutationQueue shutdown]; - self.mutationQueue = - [self.persistence mutationQueueForUser:[[FSTUser alloc] initWithUID:@"user"]]; + self.mutationQueue = [self.persistence mutationQueueForUser:User("user")]; FSTWriteGroup *group = [self.persistence startGroupWithAction:@"Start MutationQueue"]; [self.mutationQueue startWithGroup:group]; diff --git a/Firestore/Example/Tests/SpecTests/FSTSpecTests.mm b/Firestore/Example/Tests/SpecTests/FSTSpecTests.mm index 3335990..87e3213 100644 --- a/Firestore/Example/Tests/SpecTests/FSTSpecTests.mm +++ b/Firestore/Example/Tests/SpecTests/FSTSpecTests.mm @@ -19,7 +19,6 @@ #import #import -#import "Firestore/Source/Auth/FSTUser.h" #import "Firestore/Source/Core/FSTEventManager.h" #import "Firestore/Source/Core/FSTQuery.h" #import "Firestore/Source/Core/FSTSnapshotVersion.h" @@ -43,6 +42,12 @@ #import "Firestore/Example/Tests/SpecTests/FSTSyncEngineTestDriver.h" #import "Firestore/Example/Tests/Util/FSTHelpers.h" +#include "Firestore/core/src/firebase/firestore/auth/user.h" +#include "Firestore/core/src/firebase/firestore/util/string_apple.h" + +namespace util = firebase::firestore::util; +using firebase::firestore::auth::User; + NS_ASSUME_NONNULL_BEGIN // Disables all other tests; useful for debugging. Multiple tests can have this tag and they'll all @@ -327,15 +332,19 @@ static NSString *const kNoIOSTag = @"no-ios"; } - (void)doChangeUser:(id)UID { - FSTUser *user = [UID isEqual:[NSNull null]] ? [FSTUser unauthenticatedUser] - : [[FSTUser alloc] initWithUID:UID]; - [self.driver changeUser:user]; + if (UID == nil || [UID isEqual:[NSNull null]]) { + [self.driver changeUser:User::Unauthenticated()]; + } else { + XCTAssert([UID isKindOfClass:[NSString class]]); + [self.driver changeUser:User(UID)]; + } } - (void)doRestart { // Any outstanding user writes should be automatically re-sent, so we want to preserve them // when re-creating the driver. - FSTOutstandingWriteQueues *outstandingWrites = self.driver.outstandingWrites; + FSTOutstandingWriteQueues outstandingWrites = self.driver.outstandingWrites; + User currentUser = self.driver.currentUser; [self.driver shutdown]; @@ -347,7 +356,7 @@ static NSString *const kNoIOSTag = @"no-ios"; self.driver = [[FSTSyncEngineTestDriver alloc] initWithPersistence:self.driverPersistence garbageCollector:self.garbageCollector - initialUser:self.driver.currentUser + initialUser:currentUser outstandingWrites:outstandingWrites]; [self.driver start]; } diff --git a/Firestore/Example/Tests/SpecTests/FSTSyncEngineTestDriver.h b/Firestore/Example/Tests/SpecTests/FSTSyncEngineTestDriver.h index 46601d7..466a347 100644 --- a/Firestore/Example/Tests/SpecTests/FSTSyncEngineTestDriver.h +++ b/Firestore/Example/Tests/SpecTests/FSTSyncEngineTestDriver.h @@ -16,16 +16,19 @@ #import +#include + #import "Firestore/Source/Core/FSTTypes.h" #import "Firestore/Source/Remote/FSTRemoteStore.h" +#include "Firestore/core/src/firebase/firestore/auth/user.h" + @class FSTDocumentKey; @class FSTMutation; @class FSTMutationResult; @class FSTQuery; @class FSTQueryData; @class FSTSnapshotVersion; -@class FSTUser; @class FSTViewSnapshot; @class FSTWatchChange; @protocol FSTGarbageCollector; @@ -54,7 +57,10 @@ NS_ASSUME_NONNULL_BEGIN @end /** Mapping of user => array of FSTMutations for that user. */ -typedef NSDictionary *> FSTOutstandingWriteQueues; +typedef std::unordered_map *, + firebase::firestore::auth::HashUser> + FSTOutstandingWriteQueues; /** * A test driver for FSTSyncEngine that allows simulated event delivery and capture. As much as @@ -93,8 +99,8 @@ typedef NSDictionary *> FSTOutstanding */ - (instancetype)initWithPersistence:(id)persistence garbageCollector:(id)garbageCollector - initialUser:(FSTUser *)initialUser - outstandingWrites:(FSTOutstandingWriteQueues *)outstandingWrites + initialUser:(const firebase::firestore::auth::User &)initialUser + outstandingWrites:(const FSTOutstandingWriteQueues &)outstandingWrites NS_DESIGNATED_INITIALIZER; - (instancetype)init NS_UNAVAILABLE; @@ -222,7 +228,7 @@ typedef NSDictionary *> FSTOutstanding * each user, so future receiveWriteAck/Error operations will validate the write sent to the mock * datastore matches the next outstanding write for that user. */ -- (void)changeUser:(FSTUser *)user; +- (void)changeUser:(const firebase::firestore::auth::User &)user; /** * Returns all query events generated by the FSTSyncEngine in response to the event injection @@ -246,10 +252,10 @@ typedef NSDictionary *> FSTOutstanding * sentWritesCount, but not necessarily, since the FSTRemoteStore limits the number of * outstanding writes to the backend at a given time. */ -@property(nonatomic, strong, readonly) FSTOutstandingWriteQueues *outstandingWrites; +@property(nonatomic, assign, readonly) const FSTOutstandingWriteQueues &outstandingWrites; /** The current user for the FSTSyncEngine; determines which mutation queue is active. */ -@property(nonatomic, strong, readonly) FSTUser *currentUser; +@property(nonatomic, assign, readonly) const firebase::firestore::auth::User ¤tUser; /** The current set of documents in limbo. */ @property(nonatomic, strong, readonly) diff --git a/Firestore/Example/Tests/SpecTests/FSTSyncEngineTestDriver.mm b/Firestore/Example/Tests/SpecTests/FSTSyncEngineTestDriver.mm index a4de615..1c7eadf 100644 --- a/Firestore/Example/Tests/SpecTests/FSTSyncEngineTestDriver.mm +++ b/Firestore/Example/Tests/SpecTests/FSTSyncEngineTestDriver.mm @@ -16,10 +16,11 @@ #import "Firestore/Example/Tests/SpecTests/FSTSyncEngineTestDriver.h" +#include + #import #import -#import "Firestore/Source/Auth/FSTUser.h" #import "Firestore/Source/Core/FSTEventManager.h" #import "Firestore/Source/Core/FSTQuery.h" #import "Firestore/Source/Core/FSTSnapshotVersion.h" @@ -36,6 +37,11 @@ #import "Firestore/Example/Tests/Core/FSTSyncEngine+Testing.h" #import "Firestore/Example/Tests/SpecTests/FSTMockDatastore.h" +#include "Firestore/core/src/firebase/firestore/auth/user.h" + +using firebase::firestore::auth::HashUser; +using firebase::firestore::auth::User; + NS_ASSUME_NONNULL_BEGIN @implementation FSTQueryEvent @@ -71,35 +77,32 @@ NS_ASSUME_NONNULL_BEGIN @property(nonatomic, strong, readonly) NSMutableDictionary *queryListeners; -#pragma mark - Other data structures. -@property(nonatomic, strong, readwrite) FSTUser *currentUser; - @end @implementation FSTSyncEngineTestDriver { // ivar is declared as mutable. - NSMutableDictionary *> *_outstandingWrites; + std::unordered_map *, HashUser> _outstandingWrites; + + User _currentUser; } - (instancetype)initWithPersistence:(id)persistence garbageCollector:(id)garbageCollector { return [self initWithPersistence:persistence garbageCollector:garbageCollector - initialUser:[FSTUser unauthenticatedUser] - outstandingWrites:@{}]; + initialUser:User::Unauthenticated() + outstandingWrites:{}]; } - (instancetype)initWithPersistence:(id)persistence garbageCollector:(id)garbageCollector - initialUser:(FSTUser *)initialUser - outstandingWrites:(FSTOutstandingWriteQueues *)outstandingWrites { + initialUser:(const User &)initialUser + outstandingWrites:(const FSTOutstandingWriteQueues &)outstandingWrites { if (self = [super init]) { - // Create mutable copy of outstandingWrites. - _outstandingWrites = [NSMutableDictionary dictionary]; - [outstandingWrites enumerateKeysAndObjectsUsingBlock:^( - FSTUser *user, NSArray *writes, BOOL *stop) { - _outstandingWrites[user] = [writes mutableCopy]; - }]; + // Do a deep copy. + for (const auto &pair : outstandingWrites) { + _outstandingWrites[pair.first] = [pair.second mutableCopy]; + } _events = [NSMutableArray array]; @@ -139,9 +142,12 @@ NS_ASSUME_NONNULL_BEGIN return self; } -- (NSDictionary *> *)outstandingWrites { - return static_cast *> *>( - _outstandingWrites); +- (const FSTOutstandingWriteQueues &)outstandingWrites { + return _outstandingWrites; +} + +- (const User &)currentUser { + return _currentUser; } - (void)applyChangedOnlineState:(FSTOnlineState)onlineState { @@ -200,8 +206,8 @@ NS_ASSUME_NONNULL_BEGIN [self.remoteStore enableNetwork]; } -- (void)changeUser:(FSTUser *)user { - self.currentUser = user; +- (void)changeUser:(const User &)user { + _currentUser = user; [self.syncEngine userDidChange:user]; } @@ -309,10 +315,10 @@ NS_ASSUME_NONNULL_BEGIN #pragma mark - Helper Methods - (NSMutableArray *)currentOutstandingWrites { - NSMutableArray *writes = _outstandingWrites[self.currentUser]; + NSMutableArray *writes = _outstandingWrites[_currentUser]; if (!writes) { writes = [NSMutableArray array]; - _outstandingWrites[self.currentUser] = writes; + _outstandingWrites[_currentUser] = writes; } return writes; } diff --git a/Firestore/Source/API/FIRFirestore.mm b/Firestore/Source/API/FIRFirestore.mm index 5e978cc..6d2d27b 100644 --- a/Firestore/Source/API/FIRFirestore.mm +++ b/Firestore/Source/API/FIRFirestore.mm @@ -51,7 +51,7 @@ extern "C" NSString *const FIRFirestoreErrorDomain = @"FIRFirestoreErrorDomain"; @interface FIRFirestore () { /** The actual owned DatabaseId instance is allocated in FIRFirestore. */ - firebase::firestore::model::DatabaseId _databaseID; + DatabaseId _databaseID; } @property(nonatomic, strong) NSString *persistenceKey; diff --git a/Firestore/Source/Auth/FSTCredentialsProvider.h b/Firestore/Source/Auth/FSTCredentialsProvider.h index 92d5fdc..230a22d 100644 --- a/Firestore/Source/Auth/FSTCredentialsProvider.h +++ b/Firestore/Source/Auth/FSTCredentialsProvider.h @@ -16,16 +16,17 @@ #import +#include "Firestore/core/src/firebase/firestore/auth/user.h" + NS_ASSUME_NONNULL_BEGIN @class FIRApp; @class FSTDispatchQueue; -@class FSTUser; #pragma mark - FSTGetTokenResult /** - * The current FSTUser and the authentication token provided by the underlying authentication + * The current User and the authentication token provided by the underlying authentication * mechanism. This is the result of calling -[FSTCredentialsProvider getTokenForcingRefresh]. * * ## Portability notes: no TokenType on iOS @@ -38,11 +39,11 @@ NS_ASSUME_NONNULL_BEGIN @interface FSTGetTokenResult : NSObject - (instancetype)init NS_UNAVAILABLE; -- (instancetype)initWithUser:(FSTUser *)user +- (instancetype)initWithUser:(const firebase::firestore::auth::User &)user token:(NSString *_Nullable)token NS_DESIGNATED_INITIALIZER; /** The user with which the token is associated (used for persisting user state on disk, etc.). */ -@property(nonatomic, nonnull, readonly) FSTUser *user; +@property(nonatomic, assign, readonly) const firebase::firestore::auth::User &user; /** The actual raw token. */ @property(nonatomic, copy, nullable, readonly) NSString *token; @@ -60,8 +61,8 @@ NS_ASSUME_NONNULL_BEGIN typedef void (^FSTVoidGetTokenResultBlock)(FSTGetTokenResult *_Nullable token, NSError *_Nullable error); -/** Listener block notified with an FSTUser. */ -typedef void (^FSTVoidUserBlock)(FSTUser *user); +/** Listener block notified with a User. */ +typedef void (^FSTVoidUserBlock)(const firebase::firestore::auth::User &user); #pragma mark - FSTCredentialsProvider diff --git a/Firestore/Source/Auth/FSTCredentialsProvider.mm b/Firestore/Source/Auth/FSTCredentialsProvider.mm index 653d7ff..cf045e3 100644 --- a/Firestore/Source/Auth/FSTCredentialsProvider.mm +++ b/Firestore/Source/Auth/FSTCredentialsProvider.mm @@ -21,36 +21,53 @@ #import #import "FIRFirestoreErrors.h" -#import "Firestore/Source/Auth/FSTUser.h" #import "Firestore/Source/Util/FSTAssert.h" #import "Firestore/Source/Util/FSTClasses.h" #import "Firestore/Source/Util/FSTDispatchQueue.h" +#include "Firestore/core/src/firebase/firestore/auth/user.h" +#include "Firestore/core/src/firebase/firestore/util/string_apple.h" + +namespace util = firebase::firestore::util; +using firebase::firestore::auth::User; + NS_ASSUME_NONNULL_BEGIN #pragma mark - FSTGetTokenResult +@interface FSTGetTokenResult () { + User _user; +} + +@end + @implementation FSTGetTokenResult -- (instancetype)initWithUser:(FSTUser *)user token:(NSString *_Nullable)token { + +- (instancetype)initWithUser:(const User &)user token:(NSString *_Nullable)token { if (self = [super init]) { _user = user; _token = token; } return self; } + +- (const User &)user { + return _user; +} + @end #pragma mark - FSTFirebaseCredentialsProvider -@interface FSTFirebaseCredentialsProvider () +@interface FSTFirebaseCredentialsProvider () { + /** The current user as reported to us via our AuthStateDidChangeListener. */ + User _currentUser; +} @property(nonatomic, strong, readonly) FIRApp *app; /** Handle used to stop receiving auth changes once userChangeListener is removed. */ @property(nonatomic, strong, nullable, readwrite) id authListenerHandle; -/** The current user as reported to us via our AuthStateDidChangeListener. */ -@property(nonatomic, strong, nonnull, readwrite) FSTUser *currentUser; - /** * Counter used to detect if the user changed while a -getTokenForcingRefresh: request was * outstanding. @@ -67,7 +84,7 @@ NS_ASSUME_NONNULL_BEGIN self = [super init]; if (self) { _app = app; - _currentUser = [[FSTUser alloc] initWithUID:[self.app getUID]]; + _currentUser = User([self.app getUID]); _userCounter = 0; // Register for user changes so that we can internally track the current user. @@ -90,13 +107,13 @@ NS_ASSUME_NONNULL_BEGIN } NSString *userID = userInfo[FIRAuthStateDidChangeInternalNotificationUIDKey]; - FSTUser *newUser = [[FSTUser alloc] initWithUID:userID]; - if (![newUser isEqual:self.currentUser]) { - self.currentUser = newUser; + User newUser = User(userID); + if (newUser != _currentUser) { + _currentUser = newUser; self.userCounter++; FSTVoidUserBlock listenerBlock = self.userChangeListener; if (listenerBlock) { - listenerBlock(self.currentUser); + listenerBlock(_currentUser); } } } @@ -127,7 +144,7 @@ NS_ASSUME_NONNULL_BEGIN completion(nil, cancelError); } else { FSTGetTokenResult *result = - [[FSTGetTokenResult alloc] initWithUser:self.currentUser token:token]; + [[FSTGetTokenResult alloc] initWithUser:_currentUser token:token]; completion(result, error); } }; @@ -142,7 +159,7 @@ NS_ASSUME_NONNULL_BEGIN FSTAssert(!_userChangeListener, @"UserChangeListener set twice!"); // Fire initial event. - block(self.currentUser); + block(_currentUser); } else { FSTAssert(self.authListenerHandle, @"UserChangeListener removed twice!"); FSTAssert(_userChangeListener, @"UserChangeListener removed without being set!"); diff --git a/Firestore/Source/Auth/FSTEmptyCredentialsProvider.mm b/Firestore/Source/Auth/FSTEmptyCredentialsProvider.mm index e78452a..8139d79 100644 --- a/Firestore/Source/Auth/FSTEmptyCredentialsProvider.mm +++ b/Firestore/Source/Auth/FSTEmptyCredentialsProvider.mm @@ -16,10 +16,13 @@ #import "Firestore/Source/Auth/FSTEmptyCredentialsProvider.h" -#import "Firestore/Source/Auth/FSTUser.h" #import "Firestore/Source/Util/FSTAssert.h" #import "Firestore/Source/Util/FSTDispatchQueue.h" +#include "Firestore/core/src/firebase/firestore/auth/user.h" + +using firebase::firestore::auth::User; + NS_ASSUME_NONNULL_BEGIN @implementation FSTEmptyCredentialsProvider @@ -33,7 +36,7 @@ NS_ASSUME_NONNULL_BEGIN // Since the user never changes, we just need to fire the initial event and don't need to hang // onto the block. if (block) { - block([FSTUser unauthenticatedUser]); + block(User::Unauthenticated()); } } diff --git a/Firestore/Source/Auth/FSTUser.h b/Firestore/Source/Auth/FSTUser.h deleted file mode 100644 index 68ecc4c..0000000 --- a/Firestore/Source/Auth/FSTUser.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2017 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import - -NS_ASSUME_NONNULL_BEGIN - -/** - * Simple wrapper around a nullable UID. Mostly exists to make code more readable and for use as - * a key in dictionaries (since keys cannot be nil). - */ -@interface FSTUser : NSObject - -/** Returns an FSTUser with a nil UID. */ -+ (instancetype)unauthenticatedUser; - -// Porting note: no GOOGLE_CREDENTIALS or FIRST_PARTY equivalent on iOS, see FSTGetTokenResult for -// more details. - -/** Initializes an FSTUser with the given UID. */ -- (instancetype)initWithUID:(NSString *_Nullable)UID NS_DESIGNATED_INITIALIZER; -- (instancetype)init NS_UNAVAILABLE; - -@property(nonatomic, copy, nullable, readonly) NSString *UID; - -@property(nonatomic, assign, readonly, getter=isUnauthenticated) BOOL unauthenticated; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Firestore/Source/Auth/FSTUser.mm b/Firestore/Source/Auth/FSTUser.mm deleted file mode 100644 index 605b4e6..0000000 --- a/Firestore/Source/Auth/FSTUser.mm +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2017 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import "Firestore/Source/Auth/FSTUser.h" - -NS_ASSUME_NONNULL_BEGIN - -#pragma mark - FSTUser - -@implementation FSTUser - -@dynamic unauthenticated; - -+ (instancetype)unauthenticatedUser { - return [[FSTUser alloc] initWithUID:nil]; -} - -- (instancetype)initWithUID:(NSString *_Nullable)UID { - if (self = [super init]) { - _UID = UID; - } - return self; -} - -- (BOOL)isEqual:(id)object { - if (self == object) { - return YES; - } else if (![object isKindOfClass:[FSTUser class]]) { - return NO; - } else { - FSTUser *other = object; - return (self.isUnauthenticated && other.isUnauthenticated) || - [self.UID isEqualToString:other.UID]; - } -} - -- (NSUInteger)hash { - return [self.UID hash]; -} - -- (id)copyWithZone:(nullable NSZone *)zone { - return self; // since FSTUser objects are immutable -} - -- (NSString *)description { - return [NSString stringWithFormat:@"", self.UID]; -} - -- (BOOL)isUnauthenticated { - return self.UID == nil; -} - -@end - -NS_ASSUME_NONNULL_END diff --git a/Firestore/Source/Core/FSTFirestoreClient.mm b/Firestore/Source/Core/FSTFirestoreClient.mm index 1961460..823f488 100644 --- a/Firestore/Source/Core/FSTFirestoreClient.mm +++ b/Firestore/Source/Core/FSTFirestoreClient.mm @@ -38,6 +38,8 @@ #include "Firestore/core/src/firebase/firestore/model/database_id.h" #include "Firestore/core/src/firebase/firestore/util/string_apple.h" +namespace util = firebase::firestore::util; +using firebase::firestore::auth::User; using firebase::firestore::core::DatabaseInfo; using firebase::firestore::model::DatabaseId; @@ -98,13 +100,15 @@ NS_ASSUME_NONNULL_BEGIN _workerDispatchQueue = workerDispatchQueue; dispatch_semaphore_t initialUserAvailable = dispatch_semaphore_create(0); - __block FSTUser *initialUser; + __block bool initialized = false; + __block User initialUser; FSTWeakify(self); - _credentialsProvider.userChangeListener = ^(FSTUser *user) { + _credentialsProvider.userChangeListener = ^(const User &user) { FSTStrongify(self); if (self) { - if (!initialUser) { + if (!initialized) { initialUser = user; + initialized = true; dispatch_semaphore_signal(initialUserAvailable); } else { [workerDispatchQueue dispatchAsync:^{ @@ -126,7 +130,7 @@ NS_ASSUME_NONNULL_BEGIN return self; } -- (void)initializeWithUser:(FSTUser *)user usePersistence:(BOOL)usePersistence { +- (void)initializeWithUser:(const User &)user usePersistence:(BOOL)usePersistence { // Do all of our initialization on our own dispatch queue. [self.workerDispatchQueue verifyIsCurrentQueue]; @@ -189,10 +193,10 @@ NS_ASSUME_NONNULL_BEGIN [_remoteStore start]; } -- (void)userDidChange:(FSTUser *)user { +- (void)userDidChange:(const User &)user { [self.workerDispatchQueue verifyIsCurrentQueue]; - FSTLog(@"User Changed: %@", user); + FSTLog(@"User Changed: %@", util::WrapNSStringNoCopy(user.uid())); [self.syncEngine userDidChange:user]; } diff --git a/Firestore/Source/Core/FSTSyncEngine.h b/Firestore/Source/Core/FSTSyncEngine.h index 7060155..3b28e36 100644 --- a/Firestore/Source/Core/FSTSyncEngine.h +++ b/Firestore/Source/Core/FSTSyncEngine.h @@ -19,13 +19,14 @@ #import "Firestore/Source/Core/FSTTypes.h" #import "Firestore/Source/Remote/FSTRemoteStore.h" +#include "Firestore/core/src/firebase/firestore/auth/user.h" + @class FSTDispatchQueue; @class FSTLocalStore; @class FSTMutation; @class FSTQuery; @class FSTRemoteEvent; @class FSTRemoteStore; -@class FSTUser; @class FSTViewSnapshot; NS_ASSUME_NONNULL_BEGIN @@ -57,7 +58,8 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)init NS_UNAVAILABLE; - (instancetype)initWithLocalStore:(FSTLocalStore *)localStore remoteStore:(FSTRemoteStore *)remoteStore - initialUser:(FSTUser *)user NS_DESIGNATED_INITIALIZER; + initialUser:(const firebase::firestore::auth::User &)user + NS_DESIGNATED_INITIALIZER; /** * A delegate to be notified when queries being listened to produce new view snapshots or @@ -98,7 +100,7 @@ NS_ASSUME_NONNULL_BEGIN updateBlock:(FSTTransactionBlock)updateBlock completion:(FSTVoidIDErrorBlock)completion; -- (void)userDidChange:(FSTUser *)user; +- (void)userDidChange:(const firebase::firestore::auth::User &)user; /** Applies an FSTOnlineState change to the sync engine and notifies any views of the change. */ - (void)applyChangedOnlineState:(FSTOnlineState)onlineState; diff --git a/Firestore/Source/Core/FSTSyncEngine.mm b/Firestore/Source/Core/FSTSyncEngine.mm index d6ee956..61fac7d 100644 --- a/Firestore/Source/Core/FSTSyncEngine.mm +++ b/Firestore/Source/Core/FSTSyncEngine.mm @@ -16,10 +16,11 @@ #import "Firestore/Source/Core/FSTSyncEngine.h" +#include + #import #import "FIRFirestoreErrors.h" -#import "Firestore/Source/Auth/FSTUser.h" #import "Firestore/Source/Core/FSTQuery.h" #import "Firestore/Source/Core/FSTSnapshotVersion.h" #import "Firestore/Source/Core/FSTTransaction.h" @@ -40,8 +41,11 @@ #import "Firestore/Source/Util/FSTDispatchQueue.h" #import "Firestore/Source/Util/FSTLogger.h" +#include "Firestore/core/src/firebase/firestore/auth/user.h" #include "Firestore/core/src/firebase/firestore/core/target_id_generator.h" +using firebase::firestore::auth::HashUser; +using firebase::firestore::auth::User; using firebase::firestore::core::TargetIdGenerator; NS_ASSUME_NONNULL_BEGIN @@ -139,23 +143,22 @@ static const FSTListenSequenceNumber kIrrelevantSequenceNumber = -1; /** The garbage collector used to collect documents that are no longer in limbo. */ @property(nonatomic, strong, readonly) FSTEagerGarbageCollector *limboCollector; -/** Stores user completion blocks, indexed by user and FSTBatchID. */ -@property(nonatomic, strong) - NSMutableDictionary *> - *mutationCompletionBlocks; - -@property(nonatomic, strong) FSTUser *currentUser; - @end @implementation FSTSyncEngine { /** Used for creating the FSTTargetIDs for the listens used to resolve limbo documents. */ TargetIdGenerator _targetIdGenerator; + + /** Stores user completion blocks, indexed by user and FSTBatchID. */ + std::unordered_map *, HashUser> + _mutationCompletionBlocks; + + User _currentUser; } - (instancetype)initWithLocalStore:(FSTLocalStore *)localStore remoteStore:(FSTRemoteStore *)remoteStore - initialUser:(FSTUser *)initialUser { + initialUser:(const User &)initialUser { if (self = [super init]) { _localStore = localStore; _remoteStore = remoteStore; @@ -169,7 +172,6 @@ static const FSTListenSequenceNumber kIrrelevantSequenceNumber = -1; _limboDocumentRefs = [[FSTReferenceSet alloc] init]; [_limboCollector addGarbageSource:_limboDocumentRefs]; - _mutationCompletionBlocks = [NSMutableDictionary dictionary]; _targetIdGenerator = TargetIdGenerator::SyncEngineTargetIdGenerator(0); _currentUser = initialUser; } @@ -227,10 +229,10 @@ static const FSTListenSequenceNumber kIrrelevantSequenceNumber = -1; - (void)addMutationCompletionBlock:(FSTVoidErrorBlock)completion batchID:(FSTBatchID)batchID { NSMutableDictionary *completionBlocks = - self.mutationCompletionBlocks[self.currentUser]; + _mutationCompletionBlocks[_currentUser]; if (!completionBlocks) { completionBlocks = [NSMutableDictionary dictionary]; - self.mutationCompletionBlocks[self.currentUser] = completionBlocks; + _mutationCompletionBlocks[_currentUser] = completionBlocks; } [completionBlocks setObject:completion forKey:@(batchID)]; } @@ -400,7 +402,7 @@ static const FSTListenSequenceNumber kIrrelevantSequenceNumber = -1; - (void)processUserCallbacksForBatchID:(FSTBatchID)batchID error:(NSError *_Nullable)error { NSMutableDictionary *completionBlocks = - self.mutationCompletionBlocks[self.currentUser]; + _mutationCompletionBlocks[_currentUser]; // NOTE: Mutations restored from persistence won't have completion blocks, so it's okay for // this (or the completion below) to be nil. @@ -527,8 +529,8 @@ static const FSTListenSequenceNumber kIrrelevantSequenceNumber = -1; return [self.limboTargetsByKey copy]; } -- (void)userDidChange:(FSTUser *)user { - self.currentUser = user; +- (void)userDidChange:(const User &)user { + _currentUser = user; // Notify local store and emit any resulting events from swapping out the mutation queue. FSTMaybeDocumentDictionary *changes = [self.localStore userDidChange:user]; diff --git a/Firestore/Source/Local/FSTLevelDB.mm b/Firestore/Source/Local/FSTLevelDB.mm index 7fb3a66..9d3c35e 100644 --- a/Firestore/Source/Local/FSTLevelDB.mm +++ b/Firestore/Source/Local/FSTLevelDB.mm @@ -29,11 +29,13 @@ #import "Firestore/Source/Util/FSTAssert.h" #import "Firestore/Source/Util/FSTLogger.h" +#include "Firestore/core/src/firebase/firestore/auth/user.h" #include "Firestore/core/src/firebase/firestore/core/database_info.h" #include "Firestore/core/src/firebase/firestore/model/database_id.h" #include "Firestore/core/src/firebase/firestore/util/string_apple.h" namespace util = firebase::firestore::util; +using firebase::firestore::auth::User; using firebase::firestore::core::DatabaseInfo; using firebase::firestore::model::DatabaseId; @@ -198,7 +200,7 @@ using leveldb::WriteOptions; #pragma mark - Persistence Factory methods -- (id)mutationQueueForUser:(FSTUser *)user { +- (id)mutationQueueForUser:(const User &)user { return [FSTLevelDBMutationQueue mutationQueueWithUser:user db:_ptr serializer:self.serializer]; } diff --git a/Firestore/Source/Local/FSTLevelDBMutationQueue.h b/Firestore/Source/Local/FSTLevelDBMutationQueue.h index cc05db7..3f1bd51 100644 --- a/Firestore/Source/Local/FSTLevelDBMutationQueue.h +++ b/Firestore/Source/Local/FSTLevelDBMutationQueue.h @@ -19,11 +19,12 @@ #include #import "Firestore/Source/Local/FSTMutationQueue.h" + +#include "Firestore/core/src/firebase/firestore/auth/user.h" #include "leveldb/db.h" @class FSTLevelDB; @class FSTLocalSerializer; -@class FSTUser; @protocol FSTGarbageCollector; NS_ASSUME_NONNULL_BEGIN @@ -42,7 +43,7 @@ NS_ASSUME_NONNULL_BEGIN * @param user The user for which to create a mutation queue. * @param db The LevelDB in which to create the queue. */ -+ (instancetype)mutationQueueWithUser:(FSTUser *)user ++ (instancetype)mutationQueueWithUser:(const firebase::firestore::auth::User &)user db:(std::shared_ptr)db serializer:(FSTLocalSerializer *)serializer; diff --git a/Firestore/Source/Local/FSTLevelDBMutationQueue.mm b/Firestore/Source/Local/FSTLevelDBMutationQueue.mm index 85f163d..982e09c 100644 --- a/Firestore/Source/Local/FSTLevelDBMutationQueue.mm +++ b/Firestore/Source/Local/FSTLevelDBMutationQueue.mm @@ -22,7 +22,6 @@ #include #import "Firestore/Protos/objc/firestore/local/Mutation.pbobjc.h" -#import "Firestore/Source/Auth/FSTUser.h" #import "Firestore/Source/Core/FSTQuery.h" #import "Firestore/Source/Local/FSTLevelDB.h" #import "Firestore/Source/Local/FSTLevelDBKey.h" @@ -34,12 +33,15 @@ #import "Firestore/Source/Model/FSTPath.h" #import "Firestore/Source/Util/FSTAssert.h" +#include "Firestore/core/src/firebase/firestore/auth/user.h" +#include "Firestore/core/src/firebase/firestore/util/string_apple.h" #include "Firestore/core/src/firebase/firestore/util/string_util.h" NS_ASSUME_NONNULL_BEGIN namespace util = firebase::firestore::util; using Firestore::StringView; +using firebase::firestore::auth::User; using leveldb::DB; using leveldb::Iterator; using leveldb::ReadOptions; @@ -89,11 +91,10 @@ static ReadOptions StandardReadOptions() { std::shared_ptr _db; } -+ (instancetype)mutationQueueWithUser:(FSTUser *)user ++ (instancetype)mutationQueueWithUser:(const User &)user db:(std::shared_ptr)db serializer:(FSTLocalSerializer *)serializer { - FSTAssert(![user.UID isEqual:@""], @"UserID must not be an empty string."); - NSString *userID = user.isUnauthenticated ? @"" : user.UID; + NSString *userID = user.is_authenticated() ? util::WrapNSStringNoCopy(user.uid()) : @""; return [[FSTLevelDBMutationQueue alloc] initWithUserID:userID db:db serializer:serializer]; } diff --git a/Firestore/Source/Local/FSTLocalStore.h b/Firestore/Source/Local/FSTLocalStore.h index 19803ac..4ec23fd 100644 --- a/Firestore/Source/Local/FSTLocalStore.h +++ b/Firestore/Source/Local/FSTLocalStore.h @@ -21,6 +21,8 @@ #import "Firestore/Source/Model/FSTDocumentKeySet.h" #import "Firestore/Source/Model/FSTDocumentVersionDictionary.h" +#include "Firestore/core/src/firebase/firestore/auth/user.h" + @class FSTLocalViewChanges; @class FSTLocalWriteResult; @class FSTMutation; @@ -29,7 +31,6 @@ @class FSTQuery; @class FSTQueryData; @class FSTRemoteEvent; -@class FSTUser; @protocol FSTPersistence; @protocol FSTGarbageCollector; @@ -80,7 +81,8 @@ NS_ASSUME_NONNULL_BEGIN /** Creates a new instance of the FSTLocalStore with its required dependencies as parameters. */ - (instancetype)initWithPersistence:(id)persistence garbageCollector:(id)garbageCollector - initialUser:(FSTUser *)initialUser NS_DESIGNATED_INITIALIZER; + initialUser:(const firebase::firestore::auth::User &)initialUser + NS_DESIGNATED_INITIALIZER; - (instancetype)init NS_UNAVAILABLE; @@ -96,7 +98,7 @@ NS_ASSUME_NONNULL_BEGIN * In response the local store switches the mutation queue to the new user and returns any * resulting document changes. */ -- (FSTMaybeDocumentDictionary *)userDidChange:(FSTUser *)user; +- (FSTMaybeDocumentDictionary *)userDidChange:(const firebase::firestore::auth::User &)user; /** Accepts locally generated Mutations and commits them to storage. */ - (FSTLocalWriteResult *)locallyWriteMutations:(NSArray *)mutations; diff --git a/Firestore/Source/Local/FSTLocalStore.mm b/Firestore/Source/Local/FSTLocalStore.mm index 8a383e5..d12a45b 100644 --- a/Firestore/Source/Local/FSTLocalStore.mm +++ b/Firestore/Source/Local/FSTLocalStore.mm @@ -16,7 +16,6 @@ #import "Firestore/Source/Local/FSTLocalStore.h" -#import "Firestore/Source/Auth/FSTUser.h" #import "Firestore/Source/Core/FSTListenSequence.h" #import "Firestore/Source/Core/FSTQuery.h" #import "Firestore/Source/Core/FSTSnapshotVersion.h" @@ -41,8 +40,10 @@ #import "Firestore/Source/Util/FSTAssert.h" #import "Firestore/Source/Util/FSTLogger.h" +#include "Firestore/core/src/firebase/firestore/auth/user.h" #include "Firestore/core/src/firebase/firestore/core/target_id_generator.h" +using firebase::firestore::auth::User; using firebase::firestore::core::TargetIdGenerator; NS_ASSUME_NONNULL_BEGIN @@ -99,7 +100,7 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)initWithPersistence:(id)persistence garbageCollector:(id)garbageCollector - initialUser:(FSTUser *)initialUser { + initialUser:(const User &)initialUser { if (self = [super init]) { _persistence = persistence; _mutationQueue = [persistence mutationQueueForUser:initialUser]; @@ -166,7 +167,7 @@ NS_ASSUME_NONNULL_BEGIN [self.queryCache shutdown]; } -- (FSTMaybeDocumentDictionary *)userDidChange:(FSTUser *)user { +- (FSTMaybeDocumentDictionary *)userDidChange:(const User &)user { // Swap out the mutation queue, grabbing the pending mutation batches before and after. NSArray *oldBatches = [self.mutationQueue allMutationBatches]; diff --git a/Firestore/Source/Local/FSTMemoryPersistence.mm b/Firestore/Source/Local/FSTMemoryPersistence.mm index e301820..ba71f9c 100644 --- a/Firestore/Source/Local/FSTMemoryPersistence.mm +++ b/Firestore/Source/Local/FSTMemoryPersistence.mm @@ -16,7 +16,8 @@ #import "Firestore/Source/Local/FSTMemoryPersistence.h" -#import "Firestore/Source/Auth/FSTUser.h" +#include + #import "Firestore/Source/Local/FSTMemoryMutationQueue.h" #import "Firestore/Source/Local/FSTMemoryQueryCache.h" #import "Firestore/Source/Local/FSTMemoryRemoteDocumentCache.h" @@ -24,12 +25,15 @@ #import "Firestore/Source/Local/FSTWriteGroupTracker.h" #import "Firestore/Source/Util/FSTAssert.h" +#include "Firestore/core/src/firebase/firestore/auth/user.h" + +using firebase::firestore::auth::HashUser; +using firebase::firestore::auth::User; + NS_ASSUME_NONNULL_BEGIN @interface FSTMemoryPersistence () @property(nonatomic, strong, nonnull) FSTWriteGroupTracker *writeGroupTracker; -@property(nonatomic, strong, nonnull) - NSMutableDictionary> *mutationQueues; @property(nonatomic, assign, getter=isStarted) BOOL started; @end @@ -46,6 +50,8 @@ NS_ASSUME_NONNULL_BEGIN /** The FSTRemoteDocumentCache representing the persisted cache of remote documents. */ FSTMemoryRemoteDocumentCache *_remoteDocumentCache; + + std::unordered_map, HashUser> _mutationQueues; } + (instancetype)persistence { @@ -57,7 +63,6 @@ NS_ASSUME_NONNULL_BEGIN _writeGroupTracker = [FSTWriteGroupTracker tracker]; _queryCache = [[FSTMemoryQueryCache alloc] init]; _remoteDocumentCache = [[FSTMemoryRemoteDocumentCache alloc] init]; - _mutationQueues = [NSMutableDictionary dictionary]; } return self; } @@ -75,11 +80,11 @@ NS_ASSUME_NONNULL_BEGIN self.started = NO; } -- (id)mutationQueueForUser:(FSTUser *)user { - id queue = self.mutationQueues[user]; +- (id)mutationQueueForUser:(const User &)user { + id queue = _mutationQueues[user]; if (!queue) { queue = [FSTMemoryMutationQueue mutationQueue]; - self.mutationQueues[user] = queue; + _mutationQueues[user] = queue; } return queue; } diff --git a/Firestore/Source/Local/FSTPersistence.h b/Firestore/Source/Local/FSTPersistence.h index cf07a9e..30eb211 100644 --- a/Firestore/Source/Local/FSTPersistence.h +++ b/Firestore/Source/Local/FSTPersistence.h @@ -16,7 +16,8 @@ #import -@class FSTUser; +#include "Firestore/core/src/firebase/firestore/auth/user.h" + @class FSTWriteGroup; @protocol FSTMutationQueue; @protocol FSTQueryCache; @@ -75,7 +76,7 @@ NS_ASSUME_NONNULL_BEGIN * implementation to the extent possible (e.g. in the case of uid switching from * sally=>jack=>sally, sally's mutation queue will be preserved). */ -- (id)mutationQueueForUser:(FSTUser *)user; +- (id)mutationQueueForUser:(const firebase::firestore::auth::User &)user; /** Creates an FSTQueryCache representing the persisted cache of queries. */ - (id)queryCache; diff --git a/Firestore/Source/Remote/FSTRemoteStore.h b/Firestore/Source/Remote/FSTRemoteStore.h index b5dd204..4ea9379 100644 --- a/Firestore/Source/Remote/FSTRemoteStore.h +++ b/Firestore/Source/Remote/FSTRemoteStore.h @@ -19,6 +19,8 @@ #import "Firestore/Source/Core/FSTTypes.h" #import "Firestore/Source/Model/FSTDocumentVersionDictionary.h" +#include "Firestore/core/src/firebase/firestore/auth/user.h" + @class FSTDatastore; @class FSTDocumentKey; @class FSTLocalStore; @@ -28,7 +30,6 @@ @class FSTQueryData; @class FSTRemoteEvent; @class FSTTransaction; -@class FSTUser; NS_ASSUME_NONNULL_BEGIN @@ -121,7 +122,7 @@ NS_ASSUME_NONNULL_BEGIN * In response the remote store tears down streams and clears up any tracked operations that should * not persist across users. Restarts the streams if appropriate. */ -- (void)userDidChange:(FSTUser *)user; +- (void)userDidChange:(const firebase::firestore::auth::User &)user; /** Listens to the target identified by the given FSTQueryData. */ - (void)listenToTargetWithQueryData:(FSTQueryData *)queryData; diff --git a/Firestore/Source/Remote/FSTRemoteStore.mm b/Firestore/Source/Remote/FSTRemoteStore.mm index 123df49..c6668bf 100644 --- a/Firestore/Source/Remote/FSTRemoteStore.mm +++ b/Firestore/Source/Remote/FSTRemoteStore.mm @@ -35,6 +35,12 @@ #import "Firestore/Source/Util/FSTAssert.h" #import "Firestore/Source/Util/FSTLogger.h" +#include "Firestore/core/src/firebase/firestore/auth/user.h" +#include "Firestore/core/src/firebase/firestore/util/string_apple.h" + +namespace util = firebase::firestore::util; +using firebase::firestore::auth::User; + NS_ASSUME_NONNULL_BEGIN /** @@ -268,8 +274,9 @@ static const int kOnlineAttemptsBeforeFailure = 2; [self updateOnlineState:FSTOnlineStateUnknown]; } -- (void)userDidChange:(FSTUser *)user { - FSTLog(@"FSTRemoteStore %p changing users: %@", (__bridge void *)self, user); +- (void)userDidChange:(const User &)user { + FSTLog(@"FSTRemoteStore %p changing users: %@", (__bridge void *)self, + util::WrapNSStringNoCopy(user.uid())); if ([self isNetworkEnabled]) { // Tear down and re-create our network streams. This will ensure we get a fresh auth token // for the new user and re-fill the write pipeline with new mutations from the LocalStore diff --git a/Firestore/core/src/firebase/firestore/auth/user.h b/Firestore/core/src/firebase/firestore/auth/user.h index 58b8b55..cc7b66d 100644 --- a/Firestore/core/src/firebase/firestore/auth/user.h +++ b/Firestore/core/src/firebase/firestore/auth/user.h @@ -17,6 +17,11 @@ #ifndef FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_AUTH_USER_H_ #define FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_AUTH_USER_H_ +#if defined(__OBJC__) +#import +#include "Firestore/core/src/firebase/firestore/util/string_apple.h" +#endif // defined(__OBJC__) + #include #include "absl/strings/string_view.h" @@ -38,6 +43,12 @@ class User { /** Construct an authenticated user with the given UID. */ explicit User(const absl::string_view uid); +#if defined(__OBJC__) + explicit User(NSString* uid) + : User(firebase::firestore::util::MakeStringView(uid)) { + } +#endif // defined(__OBJC__) + const std::string& uid() const { return uid_; } @@ -69,6 +80,14 @@ inline bool operator!=(const User& lhs, const User& rhs) { return !(lhs == rhs); } +// Specializations of std::hash is prohibited. We define a hash function to be +// passed through manually. +struct HashUser { + inline int64_t operator()(const User& user) const { + return std::hash{}(user.uid()); + } +}; + } // namespace auth } // namespace firestore } // namespace firebase diff --git a/Firestore/core/test/firebase/firestore/auth/user_test.cc b/Firestore/core/test/firebase/firestore/auth/user_test.cc index a9f764d..7277283 100644 --- a/Firestore/core/test/firebase/firestore/auth/user_test.cc +++ b/Firestore/core/test/firebase/firestore/auth/user_test.cc @@ -49,6 +49,11 @@ TEST(User, Comparison) { EXPECT_NE(User("abc"), User("xyz")); } +TEST(User, Hash) { + const HashUser hash; + EXPECT_EQ(hash(User("abc")), hash(User("abc"))); +} + } // namespace auth } // namespace firestore } // namespace firebase -- cgit v1.2.3