Skip to content

Commit d7f08bf

Browse files
chkuang-ga-maurice
authored andcommitted
Trigger listener events in Auth right after it is registered.
Also make sure it only triggers immediate if the persistent cache is loaded. PiperOrigin-RevId: 246345230
1 parent b2d69f4 commit d7f08bf

File tree

3 files changed

+47
-10
lines changed

3 files changed

+47
-10
lines changed

auth/src/auth.cc

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -192,8 +192,9 @@ static bool PushBackIfMissing(const T& entry, std::vector<T>* v) {
192192
// Store a unique listener of type T in a listener_vector and unique auth
193193
// object in auth_vector. Both vectors must be in sync, i.e addition must
194194
// either succeed or fail otherwise this method asserts.
195+
// Return whether the listener is added.
195196
template <typename T>
196-
static void AddListener(T listener, std::vector<T>* listener_vector, Auth* auth,
197+
static bool AddListener(T listener, std::vector<T>* listener_vector, Auth* auth,
197198
std::vector<Auth*>* auth_vector, Mutex* mutex) {
198199
MutexLock lock(*mutex);
199200
// Add to array of listeners if not already there.
@@ -203,26 +204,38 @@ static void AddListener(T listener, std::vector<T>* listener_vector, Auth* auth,
203204

204205
// The listener and Auth should either point at each other or not point
205206
// at each other.
206-
FIREBASE_ASSERT_RETURN_VOID(listener_added == auth_added);
207+
FIREBASE_ASSERT_RETURN(false, listener_added == auth_added);
207208
(void)auth_added;
208-
(void)listener_added;
209+
210+
return listener_added;
209211
}
210212

211213
void Auth::AddAuthStateListener(AuthStateListener* listener) {
212214
if (!auth_data_) return;
213-
AddListener(listener, &auth_data_->listeners, this, &listener->auths_,
214-
&auth_data_->listeners_mutex);
215+
bool added = AddListener(listener, &auth_data_->listeners, this,
216+
&listener->auths_, &auth_data_->listeners_mutex);
217+
// If the listener is registered successfully and persistent cache has been
218+
// loaded, trigger OnAuthStateChanged() immediately. Otherwise, wait until
219+
// the cache is loaded, through AuthStateListener event
220+
if (added && auth_data_->persistent_cache_loaded) {
221+
listener->OnAuthStateChanged(this);
222+
}
215223
}
216224

217225
void Auth::AddIdTokenListener(IdTokenListener* listener) {
218226
if (!auth_data_) return;
219-
int listener_count = auth_data_->id_token_listeners.size();
220-
AddListener(listener, &auth_data_->id_token_listeners, this,
221-
&listener->auths_, &auth_data_->listeners_mutex);
227+
bool added = AddListener(listener, &auth_data_->id_token_listeners, this,
228+
&listener->auths_, &auth_data_->listeners_mutex);
222229
// AddListener is valid even if the listener is already registered.
223230
// This makes sure that we only increase the reference count if a listener
224231
// was actually added.
225-
if (auth_data_->id_token_listeners.size() > listener_count) {
232+
if (added) {
233+
// If the listener is registered successfully and persistent cache has been
234+
// loaded, trigger OnAuthStateChanged() immediately. Otherwise, wait until
235+
// the cache is loaded, through AuthStateListener event
236+
if (auth_data_->persistent_cache_loaded) {
237+
listener->OnIdTokenChanged(this);
238+
}
226239
EnableTokenAutoRefresh(auth_data_);
227240
}
228241
}
@@ -321,10 +334,15 @@ static inline bool VectorContains(const T& entry, const std::vector<T>& v) {
321334
/* Notify the listener. */ \
322335
listener->notification_method(auth_data->auth); \
323336
} \
337+
\
338+
/* Auth should have loaded persistent cache if exists when the listener */ \
339+
/* event is triggered for the first time. */ \
340+
auth_data->persistent_cache_loaded = true; \
324341
}
325342

326343
AUTH_NOTIFY_LISTENERS(NotifyAuthStateListeners, "Auth state", listeners,
327344
OnAuthStateChanged);
345+
328346
AUTH_NOTIFY_LISTENERS(NotifyIdTokenListeners, "ID token", id_token_listeners,
329347
OnIdTokenChanged);
330348

auth/src/data.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,8 @@ struct AuthData {
7878
user_impl(nullptr),
7979
listener_impl(nullptr),
8080
id_token_listener_impl(nullptr),
81-
expect_id_token_listener_callback(false) {}
81+
expect_id_token_listener_callback(false),
82+
persistent_cache_loaded(false) {}
8283

8384
~AuthData() {
8485
ClearUserInfos(this);
@@ -155,6 +156,9 @@ struct AuthData {
155156
// Tracks if the Id Token listener is expecting a callback to occur.
156157
bool expect_id_token_listener_callback;
157158

159+
// Tracks if the persistent cache has been loaded.
160+
bool persistent_cache_loaded;
161+
158162
// Mutex protecting `expect_id_token_listener_callback`
159163
Mutex expect_id_token_mutex;
160164

auth/src/include/firebase/auth.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,10 +137,17 @@ class Auth {
137137
~Auth();
138138

139139
/// Synchronously gets the cached current user, or nullptr if there is none.
140+
/// Current user might not be available immediately after Auth is created, if
141+
/// a user has signed in before. It is recommended to use AuthStateListener as
142+
/// the source of truth whether a user has logged in or not.
140143
/// <SWIG>
141144
/// @xmlonly
142145
/// <csproperty name="CurrentUser">
143146
/// Synchronously gets the cached current user, or null if there is none.
147+
/// CurrentUser might not be available immediately after FirebaseAuth is
148+
/// created, if a user has signed in before. It is recommended to use
149+
/// StateChanged delegate as the source of truth whether a user has logged in
150+
/// or not.
144151
/// </csproperty>
145152
/// @endxmlonly
146153
/// </SWIG>
@@ -399,6 +406,7 @@ class Auth {
399406
/// The listeners are called asynchronously, possibly on a different thread.
400407
///
401408
/// Authentication state changes are:
409+
/// - Right after the listener has been registered
402410
/// - When a user signs in
403411
/// - When the current user signs out
404412
/// - When the current user changes
@@ -430,6 +438,7 @@ class Auth {
430438
/// The listeners are called asynchronously, possibly on a different thread.
431439
///
432440
/// Authentication state changes are:
441+
/// - Right after the listener has been registered
433442
/// - When a user signs in
434443
/// - When the current user signs out
435444
/// - When the current user changes
@@ -526,6 +535,7 @@ class AuthStateListener {
526535
virtual ~AuthStateListener();
527536

528537
/// Called when the authentication state of `auth` changes.
538+
/// - Right after the listener has been registered
529539
/// - When a user is signed in
530540
/// - When the current user is signed out
531541
/// - When the current user changes
@@ -558,6 +568,11 @@ class IdTokenListener {
558568
virtual ~IdTokenListener();
559569

560570
/// Called when there is a change in the current user's token.
571+
/// - Right after the listener has been registered
572+
/// - When a user signs in
573+
/// - When the current user signs out
574+
/// - When the current user changes
575+
/// - When there is a change in the current user's token
561576
///
562577
/// @param[in] auth Disambiguates which @ref Auth instance the event
563578
/// corresponds to, in the case where you are using more than one at the same

0 commit comments

Comments
 (0)