15
15
*/
16
16
17
17
import { User } from '../auth/user' ;
18
- import { assert , fail } from '../util/assert' ;
18
+ import { assert } from '../util/assert' ;
19
19
import { Code , FirestoreError } from '../util/error' ;
20
20
import { FirebaseApp } from '@firebase/app-types' ;
21
21
import { _FirebaseApp } from '@firebase/app-types/private' ;
@@ -63,9 +63,11 @@ export class OAuthToken implements Token {
63
63
}
64
64
65
65
/**
66
- * A Listener for user change events.
66
+ * A Listener for credential change events. The listener should fetch a new
67
+ * token and may need to invalidate other state if the current user has also
68
+ * changed.
67
69
*/
68
- export type UserListener = ( user : User ) => void ;
70
+ export type CredentialChangeListener = ( user : User ) => void ;
69
71
70
72
/**
71
73
* Provides methods for getting the uid and token for the current user and
@@ -82,23 +84,24 @@ export interface CredentialsProvider {
82
84
invalidateToken ( ) : void ;
83
85
84
86
/**
85
- * Specifies a listener to be notified of user changes (sign-in / sign-out).
86
- * It immediately called once with the initial user.
87
+ * Specifies a listener to be notified of credential changes
88
+ * (sign-in / sign-out, token changes). It is immediately called once with the
89
+ * initial user.
87
90
*/
88
- setUserChangeListener ( listener : UserListener ) : void ;
91
+ setChangeListener ( changeListener : CredentialChangeListener ) : void ;
89
92
90
- /** Removes the previously-set user change listener. */
91
- removeUserChangeListener ( ) : void ;
93
+ /** Removes the previously-set change listener. */
94
+ removeChangeListener ( ) : void ;
92
95
}
93
96
94
97
/** A CredentialsProvider that always yields an empty token. */
95
98
export class EmptyCredentialsProvider implements CredentialsProvider {
96
99
/**
97
- * Stores the User listener registered with setUserChangeListener ()
100
+ * Stores the listener registered with setChangeListener ()
98
101
* This isn't actually necessary since the UID never changes, but we use this
99
102
* to verify the listen contract is adhered to in tests.
100
103
*/
101
- private userListener : UserListener | null = null ;
104
+ private changeListener : CredentialChangeListener | null = null ;
102
105
103
106
constructor ( ) { }
104
107
@@ -108,19 +111,19 @@ export class EmptyCredentialsProvider implements CredentialsProvider {
108
111
109
112
invalidateToken ( ) : void { }
110
113
111
- setUserChangeListener ( listener : UserListener ) : void {
112
- assert ( ! this . userListener , 'Can only call setUserChangeListener () once.' ) ;
113
- this . userListener = listener ;
114
+ setChangeListener ( changeListener : CredentialChangeListener ) : void {
115
+ assert ( ! this . changeListener , 'Can only call setChangeListener () once.' ) ;
116
+ this . changeListener = changeListener ;
114
117
// Fire with initial user.
115
- listener ( User . UNAUTHENTICATED ) ;
118
+ changeListener ( User . UNAUTHENTICATED ) ;
116
119
}
117
120
118
- removeUserChangeListener ( ) : void {
121
+ removeChangeListener ( ) : void {
119
122
assert (
120
- this . userListener !== null ,
121
- 'removeUserChangeListener () when no listener registered'
123
+ this . changeListener !== null ,
124
+ 'removeChangeListener () when no listener registered'
122
125
) ;
123
- this . userListener = null ;
126
+ this . changeListener = null ;
124
127
}
125
128
}
126
129
@@ -135,31 +138,26 @@ export class FirebaseCredentialsProvider implements CredentialsProvider {
135
138
private currentUser : User ;
136
139
137
140
/**
138
- * Counter used to detect if the user changed while a getToken request was
141
+ * Counter used to detect if the token changed while a getToken request was
139
142
* outstanding.
140
143
*/
141
- private userCounter = 0 ;
144
+ private tokenCounter = 0 ;
142
145
143
- /** The User listener registered with setUserChangeListener (). */
144
- private userListener : UserListener | null = null ;
146
+ /** The listener registered with setChangeListener (). */
147
+ private changeListener : CredentialChangeListener | null = null ;
145
148
146
149
private forceRefresh = false ;
147
150
148
151
constructor ( private readonly app : FirebaseApp ) {
149
- // We listen for token changes but all we really care about is knowing when
150
- // the uid may have changed.
151
152
this . tokenListener = ( ) => {
152
- const newUser = this . getUser ( ) ;
153
- if ( ! this . currentUser || ! newUser . isEqual ( this . currentUser ) ) {
154
- this . currentUser = newUser ;
155
- this . userCounter ++ ;
156
- if ( this . userListener ) {
157
- this . userListener ( this . currentUser ) ;
158
- }
153
+ this . tokenCounter ++ ;
154
+ this . currentUser = this . getUser ( ) ;
155
+ if ( this . changeListener ) {
156
+ this . changeListener ( this . currentUser ) ;
159
157
}
160
158
} ;
161
159
162
- this . userCounter = 0 ;
160
+ this . tokenCounter = 0 ;
163
161
164
162
// Will fire at least once where we set this.currentUser
165
163
( this . app as _FirebaseApp ) . INTERNAL . addAuthTokenListener (
@@ -173,21 +171,21 @@ export class FirebaseCredentialsProvider implements CredentialsProvider {
173
171
'getToken cannot be called after listener removed.'
174
172
) ;
175
173
176
- // Take note of the current value of the userCounter so that this method can
177
- // fail (with an ABORTED error) if there is a user change while the request
178
- // is outstanding.
179
- const initialUserCounter = this . userCounter ;
174
+ // Take note of the current value of the tokenCounter so that this method
175
+ // can fail (with an ABORTED error) if there is a token change while the
176
+ // request is outstanding.
177
+ const initialTokenCounter = this . tokenCounter ;
180
178
const forceRefresh = this . forceRefresh ;
181
179
this . forceRefresh = false ;
182
180
return ( this . app as _FirebaseApp ) . INTERNAL . getToken ( forceRefresh ) . then (
183
181
tokenData => {
184
- // Cancel the request since the user changed while the request was
185
- // outstanding so the response is likely for a previous user (which
182
+ // Cancel the request since the token changed while the request was
183
+ // outstanding so the response is potentially for a previous user (which
186
184
// user, we can't be sure).
187
- if ( this . userCounter !== initialUserCounter ) {
185
+ if ( this . tokenCounter !== initialTokenCounter ) {
188
186
throw new FirestoreError (
189
187
Code . ABORTED ,
190
- 'getToken aborted due to uid change.'
188
+ 'getToken aborted due to token change.'
191
189
) ;
192
190
} else {
193
191
if ( tokenData ) {
@@ -208,40 +206,30 @@ export class FirebaseCredentialsProvider implements CredentialsProvider {
208
206
this . forceRefresh = true ;
209
207
}
210
208
211
- setUserChangeListener ( listener : UserListener ) : void {
212
- assert ( ! this . userListener , 'Can only call setUserChangeListener () once.' ) ;
213
- this . userListener = listener ;
209
+ setChangeListener ( changeListener : CredentialChangeListener ) : void {
210
+ assert ( ! this . changeListener , 'Can only call setChangeListener () once.' ) ;
211
+ this . changeListener = changeListener ;
214
212
215
213
// Fire the initial event, but only if we received the initial user
216
214
if ( this . currentUser ) {
217
- listener ( this . currentUser ) ;
215
+ changeListener ( this . currentUser ) ;
218
216
}
219
217
}
220
218
221
- removeUserChangeListener ( ) : void {
222
- assert (
223
- this . tokenListener != null ,
224
- 'removeUserChangeListener() called twice'
225
- ) ;
219
+ removeChangeListener ( ) : void {
220
+ assert ( this . tokenListener != null , 'removeChangeListener() called twice' ) ;
226
221
assert (
227
- this . userListener !== null ,
228
- 'removeUserChangeListener () called when no listener registered'
222
+ this . changeListener !== null ,
223
+ 'removeChangeListener () called when no listener registered'
229
224
) ;
230
225
( this . app as _FirebaseApp ) . INTERNAL . removeAuthTokenListener (
231
226
this . tokenListener !
232
227
) ;
233
228
this . tokenListener = null ;
234
- this . userListener = null ;
229
+ this . changeListener = null ;
235
230
}
236
231
237
232
private getUser ( ) : User {
238
- // TODO(mikelehen): Remove this check once we're shipping with firebase.js.
239
- if ( typeof ( this . app as _FirebaseApp ) . INTERNAL . getUid !== 'function' ) {
240
- fail (
241
- 'This version of the Firestore SDK requires at least version' +
242
- ' 3.7.0 of firebase.js.'
243
- ) ;
244
- }
245
233
const currentUid = ( this . app as _FirebaseApp ) . INTERNAL . getUid ( ) ;
246
234
assert (
247
235
currentUid === null || typeof currentUid === 'string' ,
@@ -304,12 +292,12 @@ export class FirstPartyCredentialsProvider implements CredentialsProvider {
304
292
305
293
// TODO(33108925): can someone switch users w/o a page refresh?
306
294
// TODO(33110621): need to understand token/session lifecycle
307
- setUserChangeListener ( listener : UserListener ) : void {
295
+ setChangeListener ( changeListener : CredentialChangeListener ) : void {
308
296
// Fire with initial uid.
309
- listener ( User . FIRST_PARTY ) ;
297
+ changeListener ( User . FIRST_PARTY ) ;
310
298
}
311
299
312
- removeUserChangeListener ( ) : void { }
300
+ removeChangeListener ( ) : void { }
313
301
314
302
invalidateToken ( ) : void { }
315
303
}
0 commit comments