Skip to content

Commit 186591d

Browse files
authored
firebase-ios-sdk/1499: Restart streams on any token change. (#1692)
[Port of firebase/firebase-js-sdk#1120] Fixes #1499. This reworks our "user listener" into a "credential change listener" that fires on any token change, even if the User did not change. This allows us to restart our streams (but not switch mutation queues, etc.) on token changes.
1 parent f7b5869 commit 186591d

15 files changed

+73
-67
lines changed

Firestore/Example/Tests/SpecTests/FSTSyncEngineTestDriver.mm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ - (void)runTimer:(FSTTimerID)timerID {
250250
- (void)changeUser:(const User &)user {
251251
_currentUser = user;
252252
[self.dispatchQueue dispatchSync:^{
253-
[self.syncEngine userDidChange:user];
253+
[self.syncEngine credentialDidChangeWithUser:user];
254254
}];
255255
}
256256

Firestore/Source/Core/FSTFirestoreClient.mm

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -128,8 +128,8 @@ - (instancetype)initWithDatabaseInfo:(const DatabaseInfo &)databaseInfo
128128
auto userPromise = std::make_shared<std::promise<User>>();
129129

130130
__weak typeof(self) weakSelf = self;
131-
auto userChangeListener = [initialized = false, userPromise, weakSelf,
132-
workerDispatchQueue](User user) mutable {
131+
auto credentialChangeListener = [initialized = false, userPromise, weakSelf,
132+
workerDispatchQueue](User user) mutable {
133133
typeof(self) strongSelf = weakSelf;
134134
if (!strongSelf) return;
135135

@@ -138,14 +138,14 @@ - (instancetype)initWithDatabaseInfo:(const DatabaseInfo &)databaseInfo
138138
userPromise->set_value(user);
139139
} else {
140140
[workerDispatchQueue dispatchAsync:^{
141-
[strongSelf userDidChange:user];
141+
[strongSelf credentialDidChangeWithUser:user];
142142
}];
143143
}
144144
};
145145

146-
_credentialsProvider->SetUserChangeListener(userChangeListener);
146+
_credentialsProvider->SetCredentialChangeListener(credentialChangeListener);
147147

148-
// Defer initialization until we get the current user from the userChangeListener. This is
148+
// Defer initialization until we get the current user from the credentialChangeListener. This is
149149
// guaranteed to be synchronously dispatched onto our worker queue, so we will be initialized
150150
// before any subsequently queued work runs.
151151
[_workerDispatchQueue dispatchAsync:^{
@@ -159,6 +159,7 @@ - (instancetype)initWithDatabaseInfo:(const DatabaseInfo &)databaseInfo
159159
- (void)initializeWithUser:(const User &)user usePersistence:(BOOL)usePersistence {
160160
// Do all of our initialization on our own dispatch queue.
161161
[self.workerDispatchQueue verifyIsCurrentQueue];
162+
LOG_DEBUG("Initializing. Current user: %s", user.uid());
162163

163164
// Note: The initialization work must all be synchronous (we can't dispatch more work) since
164165
// external write/listen operations could get queued to run before that subsequent work
@@ -213,11 +214,11 @@ - (void)initializeWithUser:(const User &)user usePersistence:(BOOL)usePersistenc
213214
[_remoteStore start];
214215
}
215216

216-
- (void)userDidChange:(const User &)user {
217+
- (void)credentialDidChangeWithUser:(const User &)user {
217218
[self.workerDispatchQueue verifyIsCurrentQueue];
218219

219-
LOG_DEBUG("User Changed: %s", user.uid());
220-
[self.syncEngine userDidChange:user];
220+
LOG_DEBUG("Credential Changed. Current user: %s", user.uid());
221+
[self.syncEngine credentialDidChangeWithUser:user];
221222
}
222223

223224
- (void)applyChangedOnlineState:(FSTOnlineState)onlineState {
@@ -245,7 +246,7 @@ - (void)enableNetworkWithCompletion:(nullable FSTVoidErrorBlock)completion {
245246

246247
- (void)shutdownWithCompletion:(nullable FSTVoidErrorBlock)completion {
247248
[self.workerDispatchQueue dispatchAsync:^{
248-
self->_credentialsProvider->SetUserChangeListener(nullptr);
249+
self->_credentialsProvider->SetCredentialChangeListener(nullptr);
249250

250251
[self.remoteStore shutdown];
251252
[self.persistence shutdown];

Firestore/Source/Core/FSTSyncEngine.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ NS_ASSUME_NONNULL_BEGIN
100100
updateBlock:(FSTTransactionBlock)updateBlock
101101
completion:(FSTVoidIDErrorBlock)completion;
102102

103-
- (void)userDidChange:(const firebase::firestore::auth::User &)user;
103+
- (void)credentialDidChangeWithUser:(const firebase::firestore::auth::User &)user;
104104

105105
/** Applies an FSTOnlineState change to the sync engine and notifies any views of the change. */
106106
- (void)applyChangedOnlineState:(FSTOnlineState)onlineState;

Firestore/Source/Core/FSTSyncEngine.mm

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -560,15 +560,18 @@ - (void)removeLimboTargetForKey:(const DocumentKey &)key {
560560
return _limboTargetsByKey;
561561
}
562562

563-
- (void)userDidChange:(const User &)user {
563+
- (void)credentialDidChangeWithUser:(const firebase::firestore::auth::User &)user {
564+
BOOL userChanged = (_currentUser != user);
564565
_currentUser = user;
565566

566-
// Notify local store and emit any resulting events from swapping out the mutation queue.
567-
FSTMaybeDocumentDictionary *changes = [self.localStore userDidChange:user];
568-
[self emitNewSnapshotsWithChanges:changes remoteEvent:nil];
567+
if (userChanged) {
568+
// Notify local store and emit any resulting events from swapping out the mutation queue.
569+
FSTMaybeDocumentDictionary *changes = [self.localStore userDidChange:user];
570+
[self emitNewSnapshotsWithChanges:changes remoteEvent:nil];
571+
}
569572

570573
// Notify remote store so it can restart its streams.
571-
[self.remoteStore userDidChange:user];
574+
[self.remoteStore credentialDidChange];
572575
}
573576

574577
- (firebase::firestore::model::DocumentKeySet)remoteKeysForTarget:(FSTBoxedTargetID *)targetId {

Firestore/Source/Remote/FSTRemoteStore.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ NS_ASSUME_NONNULL_BEGIN
129129
* In response the remote store tears down streams and clears up any tracked operations that should
130130
* not persist across users. Restarts the streams if appropriate.
131131
*/
132-
- (void)userDidChange:(const firebase::firestore::auth::User &)user;
132+
- (void)credentialDidChange;
133133

134134
/** Listens to the target identified by the given FSTQueryData. */
135135
- (void)listenToTargetWithQueryData:(FSTQueryData *)queryData;

Firestore/Source/Remote/FSTRemoteStore.mm

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -209,12 +209,12 @@ - (void)shutdown {
209209
[self.onlineStateTracker updateState:FSTOnlineStateUnknown];
210210
}
211211

212-
- (void)userDidChange:(const User &)user {
213-
LOG_DEBUG("FSTRemoteStore %s changing users: %s", (__bridge void *)self, user.uid());
212+
- (void)credentialDidChange {
214213
if ([self isNetworkEnabled]) {
215214
// Tear down and re-create our network streams. This will ensure we get a fresh auth token
216215
// for the new user and re-fill the write pipeline with new mutations from the LocalStore
217216
// (since mutations are per-user).
217+
LOG_DEBUG("FSTRemoteStore %s restarting streams for new credential", (__bridge void *)self);
218218
[self disableNetworkInternal];
219219
[self.onlineStateTracker updateState:FSTOnlineStateUnknown];
220220
[self enableNetwork];

Firestore/core/src/firebase/firestore/auth/credentials_provider.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ namespace firebase {
2020
namespace firestore {
2121
namespace auth {
2222

23-
CredentialsProvider::CredentialsProvider() : user_change_listener_(nullptr) {
23+
CredentialsProvider::CredentialsProvider() : change_listener_(nullptr) {
2424
}
2525

2626
CredentialsProvider::~CredentialsProvider() {

Firestore/core/src/firebase/firestore/auth/credentials_provider.h

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ namespace auth {
3333
// `TokenErrorListener` is a listener that gets a token or an error.
3434
using TokenListener = std::function<void(util::StatusOr<Token>)>;
3535

36-
// Listener notified with a User change.
37-
using UserChangeListener = std::function<void(User user)>;
36+
// Listener notified with a credential change.
37+
using CredentialChangeListener = std::function<void(User user)>;
3838

3939
/**
4040
* Provides methods for getting the uid and token for the current user and
@@ -56,22 +56,24 @@ class CredentialsProvider {
5656
virtual void InvalidateToken() = 0;
5757

5858
/**
59-
* Sets the listener to be notified of user changes (sign-in / sign-out). It
60-
* is immediately called once with the initial user.
59+
* Sets the listener to be notified of credential changes (sign-in /
60+
* sign-out, token changes). It is immediately called once with the initial
61+
* user.
6162
*
6263
* Call with nullptr to remove previous listener.
6364
*/
64-
virtual void SetUserChangeListener(UserChangeListener listener) = 0;
65+
virtual void SetCredentialChangeListener(
66+
CredentialChangeListener changeListener) = 0;
6567

6668
protected:
6769
/**
68-
* A listener to be notified of user changes (sign-in / sign-out). It is
69-
* immediately called once with the initial user.
70+
* A listener to be notified of credential changes (sign-in / sign-out, token
71+
* changes). It is immediately called once with the initial user.
7072
*
7173
* Note that this block will be called back on an arbitrary thread that is not
7274
* the normal Firestore worker thread.
7375
*/
74-
UserChangeListener user_change_listener_;
76+
CredentialChangeListener change_listener_;
7577
};
7678

7779
} // namespace auth

Firestore/core/src/firebase/firestore/auth/empty_credentials_provider.cc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,10 @@ void EmptyCredentialsProvider::GetToken(TokenListener completion) {
2828
}
2929
}
3030

31-
void EmptyCredentialsProvider::SetUserChangeListener(
32-
UserChangeListener listener) {
33-
if (listener) {
34-
listener(User::Unauthenticated());
31+
void EmptyCredentialsProvider::SetCredentialChangeListener(
32+
CredentialChangeListener changeListener) {
33+
if (changeListener) {
34+
changeListener(User::Unauthenticated());
3535
}
3636
}
3737

Firestore/core/src/firebase/firestore/auth/empty_credentials_provider.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ class EmptyCredentialsProvider : public CredentialsProvider {
2828
public:
2929
void GetToken(TokenListener completion) override;
3030
void InvalidateToken() override;
31-
void SetUserChangeListener(UserChangeListener listener) override;
31+
void SetCredentialChangeListener(
32+
CredentialChangeListener changeListener) override;
3233
};
3334

3435
} // namespace auth

0 commit comments

Comments
 (0)