16
16
*/
17
17
18
18
import * as externs from '@firebase/auth-types-exp' ;
19
- import { FirebaseError } from '@firebase/util' ;
20
19
21
20
import { Auth } from '../../model/auth' ;
22
- import {
23
- AuthEvent ,
24
- AuthEventConsumer ,
25
- AuthEventType ,
26
- EventManager ,
27
- PopupRedirectResolver
28
- } from '../../model/popup_redirect' ;
21
+ import { AuthEventType , PopupRedirectResolver } from '../../model/popup_redirect' ;
29
22
import { User , UserCredential } from '../../model/user' ;
30
23
import { AUTH_ERROR_FACTORY , AuthErrorCode } from '../errors' ;
31
24
import { Delay } from '../util/delay' ;
32
25
import { _generateEventId } from '../util/event_id' ;
26
+ import { _getInstance } from '../util/instantiator' ;
33
27
import { AuthPopup } from '../util/popup' ;
34
- import { _link , _reauth , _signIn , IdpTask , IdpTaskParams } from './idp ' ;
28
+ import { AbstractPopupRedirectAction } from './abstract_popup_redirect_action ' ;
35
29
36
30
// The event timeout is the same on mobile and desktop, no need for Delay.
37
31
export const _AUTH_EVENT_TIMEOUT = 2020 ;
38
32
export const _POLL_WINDOW_CLOSE_TIMEOUT = new Delay ( 2000 , 10000 ) ;
39
33
40
- interface PendingPromise {
41
- resolve : ( cred : UserCredential ) => void ;
42
- reject : ( error : Error ) => void ;
43
- }
44
-
45
34
export async function signInWithPopup (
46
35
authExtern : externs . Auth ,
47
36
provider : externs . AuthProvider ,
48
37
resolverExtern : externs . PopupRedirectResolver
49
38
) : Promise < UserCredential > {
50
39
const auth = authExtern as Auth ;
51
- const resolver = resolverExtern as PopupRedirectResolver ;
40
+ const resolver : PopupRedirectResolver = _getInstance ( resolverExtern ) ;
52
41
53
42
const action = new PopupAction (
54
43
auth ,
55
44
AuthEventType . SIGN_IN_VIA_POPUP ,
56
- _signIn ,
57
45
provider ,
58
46
resolver
59
47
) ;
60
- const cred = await action . execute ( ) ;
61
-
62
- await auth . updateCurrentUser ( cred . user ) ;
63
- return cred ;
48
+ return action . execute ( ) ;
64
49
}
65
50
66
51
export async function reauthenticateWithPopup (
@@ -69,12 +54,11 @@ export async function reauthenticateWithPopup(
69
54
resolverExtern : externs . PopupRedirectResolver
70
55
) : Promise < UserCredential > {
71
56
const user = userExtern as User ;
72
- const resolver = resolverExtern as PopupRedirectResolver ;
57
+ const resolver : PopupRedirectResolver = _getInstance ( resolverExtern ) ;
73
58
74
59
const action = new PopupAction (
75
60
user . auth ,
76
61
AuthEventType . REAUTH_VIA_POPUP ,
77
- _reauth ,
78
62
provider ,
79
63
resolver ,
80
64
user
@@ -88,12 +72,11 @@ export async function linkWithPopup(
88
72
resolverExtern : externs . PopupRedirectResolver
89
73
) : Promise < UserCredential > {
90
74
const user = userExtern as User ;
91
- const resolver = resolverExtern as PopupRedirectResolver ;
75
+ const resolver : PopupRedirectResolver = _getInstance ( resolverExtern ) ;
92
76
93
77
const action = new PopupAction (
94
78
user . auth ,
95
79
AuthEventType . LINK_VIA_POPUP ,
96
- _link ,
97
80
provider ,
98
81
resolver ,
99
82
user
@@ -105,121 +88,66 @@ export async function linkWithPopup(
105
88
* Popup event manager. Handles the popup's entire lifecycle; listens to auth
106
89
* events
107
90
*/
108
- class PopupAction implements AuthEventConsumer {
91
+ class PopupAction extends AbstractPopupRedirectAction {
109
92
// Only one popup is ever shown at once. The lifecycle of the current popup
110
93
// can be managed / cancelled by the constructor.
111
94
private static currentPopupAction : PopupAction | null = null ;
112
- private pendingPromise : PendingPromise | null = null ;
113
95
private authWindow : AuthPopup | null = null ;
114
96
private pollId : number | null = null ;
115
- private eventManager : EventManager | null = null ;
116
97
117
98
constructor (
118
- private readonly auth : Auth ,
99
+ auth : Auth ,
119
100
readonly filter : AuthEventType ,
120
- private readonly idpTask : IdpTask ,
121
101
private readonly provider : externs . AuthProvider ,
122
- private readonly resolver : PopupRedirectResolver ,
123
- private readonly user ?: User
102
+ resolver : PopupRedirectResolver ,
103
+ user ?: User
124
104
) {
105
+ super ( auth , filter , resolver , user )
125
106
if ( PopupAction . currentPopupAction ) {
126
107
PopupAction . currentPopupAction . cancel ( ) ;
127
108
}
128
109
129
110
PopupAction . currentPopupAction = this ;
130
111
}
131
112
132
- execute ( ) : Promise < UserCredential > {
133
- return new Promise < UserCredential > ( async ( resolve , reject ) => {
134
- this . pendingPromise = { resolve, reject } ;
135
-
136
- this . eventManager = await this . resolver . _initialize ( this . auth ) ;
137
- const eventId = _generateEventId ( ) ;
138
- this . authWindow = await this . resolver . _openPopup (
139
- this . auth ,
140
- this . provider ,
141
- this . filter ,
142
- eventId
143
- ) ;
144
- this . authWindow . associatedEvent = eventId ;
145
-
146
- this . eventManager . registerConsumer ( this ) ;
147
-
148
- // Handle user closure. Notice this does *not* use await
149
- this . pollUserCancellation ( this . auth . name ) ;
150
- } ) ;
151
- }
152
-
153
- isMatchingEvent ( eventId : string | null ) : boolean {
154
- return ! ! eventId && this . authWindow ?. associatedEvent === eventId ;
113
+ protected async onExecution ( ) : Promise < void > {
114
+ const eventId = _generateEventId ( ) ;
115
+ this . authWindow = await this . resolver . _openPopup (
116
+ this . auth ,
117
+ this . provider ,
118
+ this . filter ,
119
+ eventId
120
+ ) ;
121
+ this . authWindow . associatedEvent = eventId ;
122
+
123
+ // Handle user closure. Notice this does *not* use await
124
+ this . pollUserCancellation ( this . auth . name ) ;
155
125
}
156
126
157
- async onAuthEvent ( event : AuthEvent ) : Promise < void > {
158
- const { urlResponse, sessionId, postBody, tenantId, error } = event ;
159
- if ( error ) {
160
- this . broadcastResult ( null , error ) ;
161
- return ;
162
- }
163
-
164
- const params : IdpTaskParams = {
165
- auth : this . auth ,
166
- requestUri : urlResponse ! ,
167
- sessionId : sessionId ! ,
168
- tenantId : tenantId || undefined ,
169
- postBody : postBody || undefined ,
170
- user : this . user
171
- } ;
172
-
173
- try {
174
- this . broadcastResult ( await this . idpTask ( params ) ) ;
175
- } catch ( e ) {
176
- this . broadcastResult ( null , e ) ;
177
- }
178
- }
179
-
180
- onError ( error : FirebaseError ) : void {
181
- this . broadcastResult ( null , error ) ;
127
+ get eventId ( ) : string | null {
128
+ return this . authWindow ?. associatedEvent || null ;
182
129
}
183
130
184
131
cancel ( ) : void {
185
- if ( this . pendingPromise ) {
186
- // There was already a pending promise. Expire it.
187
- this . broadcastResult (
188
- null ,
189
- AUTH_ERROR_FACTORY . create ( AuthErrorCode . EXPIRED_POPUP_REQUEST , {
190
- appName : this . auth . name
191
- } )
192
- ) ;
193
- }
132
+ this . broadcastResult (
133
+ null ,
134
+ AUTH_ERROR_FACTORY . create ( AuthErrorCode . EXPIRED_POPUP_REQUEST , {
135
+ appName : this . auth . name
136
+ } )
137
+ ) ;
194
138
}
195
139
196
- private broadcastResult ( cred : UserCredential | null , error ?: Error ) : void {
140
+ protected cleanUp ( ) : void {
197
141
if ( this . authWindow ) {
198
142
this . authWindow . close ( ) ;
199
143
}
200
144
201
145
if ( this . pollId ) {
202
146
window . clearTimeout ( this . pollId ) ;
203
147
}
204
-
205
- if ( this . pendingPromise ) {
206
- if ( error ) {
207
- this . pendingPromise . reject ( error ) ;
208
- } else {
209
- this . pendingPromise . resolve ( cred ! ) ;
210
- }
211
- }
212
-
213
- this . cleanUp ( ) ;
214
- }
215
-
216
- private cleanUp ( ) : void {
148
+
217
149
this . authWindow = null ;
218
- this . pendingPromise = null ;
219
150
this . pollId = null ;
220
- if ( this . eventManager ) {
221
- this . eventManager . unregisterConsumer ( this ) ;
222
- }
223
151
PopupAction . currentPopupAction = null ;
224
152
}
225
153
0 commit comments