UNPKG

161 kBJavaScriptView Raw
1'use strict';
2
3Object.defineProperty(exports, '__esModule', { value: true });
4
5var phone = require('./phone-cf00e1ee.js');
6var tslib = require('tslib');
7var util = require('@firebase/util');
8var app = require('@firebase/app');
9require('@firebase/component');
10require('@firebase/logger');
11
12/**
13 * @license
14 * Copyright 2019 Google LLC
15 *
16 * Licensed under the Apache License, Version 2.0 (the "License");
17 * you may not use this file except in compliance with the License.
18 * You may obtain a copy of the License at
19 *
20 * http://www.apache.org/licenses/LICENSE-2.0
21 *
22 * Unless required by applicable law or agreed to in writing, software
23 * distributed under the License is distributed on an "AS IS" BASIS,
24 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
25 * See the License for the specific language governing permissions and
26 * limitations under the License.
27 */
28// There are two different browser persistence types: local and session.
29// Both have the same implementation but use a different underlying storage
30// object.
31var BrowserPersistenceClass = /** @class */ (function () {
32 function BrowserPersistenceClass(storageRetriever, type) {
33 this.storageRetriever = storageRetriever;
34 this.type = type;
35 }
36 BrowserPersistenceClass.prototype._isAvailable = function () {
37 try {
38 if (!this.storage) {
39 return Promise.resolve(false);
40 }
41 this.storage.setItem(phone.STORAGE_AVAILABLE_KEY, '1');
42 this.storage.removeItem(phone.STORAGE_AVAILABLE_KEY);
43 return Promise.resolve(true);
44 }
45 catch (_a) {
46 return Promise.resolve(false);
47 }
48 };
49 BrowserPersistenceClass.prototype._set = function (key, value) {
50 this.storage.setItem(key, JSON.stringify(value));
51 return Promise.resolve();
52 };
53 BrowserPersistenceClass.prototype._get = function (key) {
54 var json = this.storage.getItem(key);
55 return Promise.resolve(json ? JSON.parse(json) : null);
56 };
57 BrowserPersistenceClass.prototype._remove = function (key) {
58 this.storage.removeItem(key);
59 return Promise.resolve();
60 };
61 Object.defineProperty(BrowserPersistenceClass.prototype, "storage", {
62 get: function () {
63 return this.storageRetriever();
64 },
65 enumerable: false,
66 configurable: true
67 });
68 return BrowserPersistenceClass;
69}());
70
71/**
72 * @license
73 * Copyright 2020 Google LLC
74 *
75 * Licensed under the Apache License, Version 2.0 (the "License");
76 * you may not use this file except in compliance with the License.
77 * You may obtain a copy of the License at
78 *
79 * http://www.apache.org/licenses/LICENSE-2.0
80 *
81 * Unless required by applicable law or agreed to in writing, software
82 * distributed under the License is distributed on an "AS IS" BASIS,
83 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
84 * See the License for the specific language governing permissions and
85 * limitations under the License.
86 */
87function _iframeCannotSyncWebStorage() {
88 var ua = util.getUA();
89 return phone._isSafari(ua) || phone._isIOS(ua);
90}
91// The polling period in case events are not supported
92var _POLLING_INTERVAL_MS$1 = 1000;
93// The IE 10 localStorage cross tab synchronization delay in milliseconds
94var IE10_LOCAL_STORAGE_SYNC_DELAY = 10;
95var BrowserLocalPersistence = /** @class */ (function (_super) {
96 tslib.__extends(BrowserLocalPersistence, _super);
97 function BrowserLocalPersistence() {
98 var _this = _super.call(this, function () { return window.localStorage; }, "LOCAL" /* LOCAL */) || this;
99 _this.boundEventHandler = function (event, poll) { return _this.onStorageEvent(event, poll); };
100 _this.listeners = {};
101 _this.localCache = {};
102 // setTimeout return value is platform specific
103 // eslint-disable-next-line @typescript-eslint/no-explicit-any
104 _this.pollTimer = null;
105 // Safari or iOS browser and embedded in an iframe.
106 _this.safariLocalStorageNotSynced = _iframeCannotSyncWebStorage() && phone._isIframe();
107 // Whether to use polling instead of depending on window events
108 _this.fallbackToPolling = phone._isMobileBrowser();
109 _this._shouldAllowMigration = true;
110 return _this;
111 }
112 BrowserLocalPersistence.prototype.forAllChangedKeys = function (cb) {
113 // Check all keys with listeners on them.
114 for (var _i = 0, _a = Object.keys(this.listeners); _i < _a.length; _i++) {
115 var key = _a[_i];
116 // Get value from localStorage.
117 var newValue = this.storage.getItem(key);
118 var oldValue = this.localCache[key];
119 // If local map value does not match, trigger listener with storage event.
120 // Differentiate this simulated event from the real storage event.
121 if (newValue !== oldValue) {
122 cb(key, oldValue, newValue);
123 }
124 }
125 };
126 BrowserLocalPersistence.prototype.onStorageEvent = function (event, poll) {
127 var _this = this;
128 if (poll === void 0) { poll = false; }
129 // Key would be null in some situations, like when localStorage is cleared
130 if (!event.key) {
131 this.forAllChangedKeys(function (key, _oldValue, newValue) {
132 _this.notifyListeners(key, newValue);
133 });
134 return;
135 }
136 var key = event.key;
137 // Check the mechanism how this event was detected.
138 // The first event will dictate the mechanism to be used.
139 if (poll) {
140 // Environment detects storage changes via polling.
141 // Remove storage event listener to prevent possible event duplication.
142 this.detachListener();
143 }
144 else {
145 // Environment detects storage changes via storage event listener.
146 // Remove polling listener to prevent possible event duplication.
147 this.stopPolling();
148 }
149 // Safari embedded iframe. Storage event will trigger with the delta
150 // changes but no changes will be applied to the iframe localStorage.
151 if (this.safariLocalStorageNotSynced) {
152 // Get current iframe page value.
153 var storedValue_1 = this.storage.getItem(key);
154 // Value not synchronized, synchronize manually.
155 if (event.newValue !== storedValue_1) {
156 if (event.newValue !== null) {
157 // Value changed from current value.
158 this.storage.setItem(key, event.newValue);
159 }
160 else {
161 // Current value deleted.
162 this.storage.removeItem(key);
163 }
164 }
165 else if (this.localCache[key] === event.newValue && !poll) {
166 // Already detected and processed, do not trigger listeners again.
167 return;
168 }
169 }
170 var triggerListeners = function () {
171 // Keep local map up to date in case storage event is triggered before
172 // poll.
173 var storedValue = _this.storage.getItem(key);
174 if (!poll && _this.localCache[key] === storedValue) {
175 // Real storage event which has already been detected, do nothing.
176 // This seems to trigger in some IE browsers for some reason.
177 return;
178 }
179 _this.notifyListeners(key, storedValue);
180 };
181 var storedValue = this.storage.getItem(key);
182 if (phone._isIE10() &&
183 storedValue !== event.newValue &&
184 event.newValue !== event.oldValue) {
185 // IE 10 has this weird bug where a storage event would trigger with the
186 // correct key, oldValue and newValue but localStorage.getItem(key) does
187 // not yield the updated value until a few milliseconds. This ensures
188 // this recovers from that situation.
189 setTimeout(triggerListeners, IE10_LOCAL_STORAGE_SYNC_DELAY);
190 }
191 else {
192 triggerListeners();
193 }
194 };
195 BrowserLocalPersistence.prototype.notifyListeners = function (key, value) {
196 this.localCache[key] = value;
197 var listeners = this.listeners[key];
198 if (listeners) {
199 for (var _i = 0, _a = Array.from(listeners); _i < _a.length; _i++) {
200 var listener = _a[_i];
201 listener(value ? JSON.parse(value) : value);
202 }
203 }
204 };
205 BrowserLocalPersistence.prototype.startPolling = function () {
206 var _this = this;
207 this.stopPolling();
208 this.pollTimer = setInterval(function () {
209 _this.forAllChangedKeys(function (key, oldValue, newValue) {
210 _this.onStorageEvent(new StorageEvent('storage', {
211 key: key,
212 oldValue: oldValue,
213 newValue: newValue
214 }),
215 /* poll */ true);
216 });
217 }, _POLLING_INTERVAL_MS$1);
218 };
219 BrowserLocalPersistence.prototype.stopPolling = function () {
220 if (this.pollTimer) {
221 clearInterval(this.pollTimer);
222 this.pollTimer = null;
223 }
224 };
225 BrowserLocalPersistence.prototype.attachListener = function () {
226 window.addEventListener('storage', this.boundEventHandler);
227 };
228 BrowserLocalPersistence.prototype.detachListener = function () {
229 window.removeEventListener('storage', this.boundEventHandler);
230 };
231 BrowserLocalPersistence.prototype._addListener = function (key, listener) {
232 if (Object.keys(this.listeners).length === 0) {
233 // Whether browser can detect storage event when it had already been pushed to the background.
234 // This may happen in some mobile browsers. A localStorage change in the foreground window
235 // will not be detected in the background window via the storage event.
236 // This was detected in iOS 7.x mobile browsers
237 if (this.fallbackToPolling) {
238 this.startPolling();
239 }
240 else {
241 this.attachListener();
242 }
243 }
244 if (!this.listeners[key]) {
245 this.listeners[key] = new Set();
246 // Populate the cache to avoid spuriously triggering on first poll.
247 this.localCache[key] = this.storage.getItem(key);
248 }
249 this.listeners[key].add(listener);
250 };
251 BrowserLocalPersistence.prototype._removeListener = function (key, listener) {
252 if (this.listeners[key]) {
253 this.listeners[key].delete(listener);
254 if (this.listeners[key].size === 0) {
255 delete this.listeners[key];
256 }
257 }
258 if (Object.keys(this.listeners).length === 0) {
259 this.detachListener();
260 this.stopPolling();
261 }
262 };
263 // Update local cache on base operations:
264 BrowserLocalPersistence.prototype._set = function (key, value) {
265 return tslib.__awaiter(this, void 0, void 0, function () {
266 return tslib.__generator(this, function (_a) {
267 switch (_a.label) {
268 case 0: return [4 /*yield*/, _super.prototype._set.call(this, key, value)];
269 case 1:
270 _a.sent();
271 this.localCache[key] = JSON.stringify(value);
272 return [2 /*return*/];
273 }
274 });
275 });
276 };
277 BrowserLocalPersistence.prototype._get = function (key) {
278 return tslib.__awaiter(this, void 0, void 0, function () {
279 var value;
280 return tslib.__generator(this, function (_a) {
281 switch (_a.label) {
282 case 0: return [4 /*yield*/, _super.prototype._get.call(this, key)];
283 case 1:
284 value = _a.sent();
285 this.localCache[key] = JSON.stringify(value);
286 return [2 /*return*/, value];
287 }
288 });
289 });
290 };
291 BrowserLocalPersistence.prototype._remove = function (key) {
292 return tslib.__awaiter(this, void 0, void 0, function () {
293 return tslib.__generator(this, function (_a) {
294 switch (_a.label) {
295 case 0: return [4 /*yield*/, _super.prototype._remove.call(this, key)];
296 case 1:
297 _a.sent();
298 delete this.localCache[key];
299 return [2 /*return*/];
300 }
301 });
302 });
303 };
304 BrowserLocalPersistence.type = 'LOCAL';
305 return BrowserLocalPersistence;
306}(BrowserPersistenceClass));
307/**
308 * An implementation of {@link Persistence} of type `LOCAL` using `localStorage`
309 * for the underlying storage.
310 *
311 * @public
312 */
313var browserLocalPersistence = BrowserLocalPersistence;
314
315/**
316 * @license
317 * Copyright 2020 Google LLC
318 *
319 * Licensed under the Apache License, Version 2.0 (the "License");
320 * you may not use this file except in compliance with the License.
321 * You may obtain a copy of the License at
322 *
323 * http://www.apache.org/licenses/LICENSE-2.0
324 *
325 * Unless required by applicable law or agreed to in writing, software
326 * distributed under the License is distributed on an "AS IS" BASIS,
327 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
328 * See the License for the specific language governing permissions and
329 * limitations under the License.
330 */
331var BrowserSessionPersistence = /** @class */ (function (_super) {
332 tslib.__extends(BrowserSessionPersistence, _super);
333 function BrowserSessionPersistence() {
334 return _super.call(this, function () { return window.sessionStorage; }, "SESSION" /* SESSION */) || this;
335 }
336 BrowserSessionPersistence.prototype._addListener = function (_key, _listener) {
337 // Listeners are not supported for session storage since it cannot be shared across windows
338 return;
339 };
340 BrowserSessionPersistence.prototype._removeListener = function (_key, _listener) {
341 // Listeners are not supported for session storage since it cannot be shared across windows
342 return;
343 };
344 BrowserSessionPersistence.type = 'SESSION';
345 return BrowserSessionPersistence;
346}(BrowserPersistenceClass));
347/**
348 * An implementation of {@link Persistence} of `SESSION` using `sessionStorage`
349 * for the underlying storage.
350 *
351 * @public
352 */
353var browserSessionPersistence = BrowserSessionPersistence;
354
355/**
356 * @license
357 * Copyright 2019 Google LLC
358 *
359 * Licensed under the Apache License, Version 2.0 (the "License");
360 * you may not use this file except in compliance with the License.
361 * You may obtain a copy of the License at
362 *
363 * http://www.apache.org/licenses/LICENSE-2.0
364 *
365 * Unless required by applicable law or agreed to in writing, software
366 * distributed under the License is distributed on an "AS IS" BASIS,
367 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
368 * See the License for the specific language governing permissions and
369 * limitations under the License.
370 */
371/**
372 * Shim for Promise.allSettled, note the slightly different format of `fulfilled` vs `status`.
373 *
374 * @param promises - Array of promises to wait on.
375 */
376function _allSettled(promises) {
377 var _this = this;
378 return Promise.all(promises.map(function (promise) { return tslib.__awaiter(_this, void 0, void 0, function () {
379 var value, reason_1;
380 return tslib.__generator(this, function (_a) {
381 switch (_a.label) {
382 case 0:
383 _a.trys.push([0, 2, , 3]);
384 return [4 /*yield*/, promise];
385 case 1:
386 value = _a.sent();
387 return [2 /*return*/, {
388 fulfilled: true,
389 value: value
390 }];
391 case 2:
392 reason_1 = _a.sent();
393 return [2 /*return*/, {
394 fulfilled: false,
395 reason: reason_1
396 }];
397 case 3: return [2 /*return*/];
398 }
399 });
400 }); }));
401}
402
403/**
404 * @license
405 * Copyright 2019 Google LLC
406 *
407 * Licensed under the Apache License, Version 2.0 (the "License");
408 * you may not use this file except in compliance with the License.
409 * You may obtain a copy of the License at
410 *
411 * http://www.apache.org/licenses/LICENSE-2.0
412 *
413 * Unless required by applicable law or agreed to in writing, software
414 * distributed under the License is distributed on an "AS IS" BASIS,
415 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
416 * See the License for the specific language governing permissions and
417 * limitations under the License.
418 */
419/**
420 * Interface class for receiving messages.
421 *
422 */
423var Receiver = /** @class */ (function () {
424 function Receiver(eventTarget) {
425 this.eventTarget = eventTarget;
426 this.handlersMap = {};
427 this.boundEventHandler = this.handleEvent.bind(this);
428 }
429 /**
430 * Obtain an instance of a Receiver for a given event target, if none exists it will be created.
431 *
432 * @param eventTarget - An event target (such as window or self) through which the underlying
433 * messages will be received.
434 */
435 Receiver._getInstance = function (eventTarget) {
436 // The results are stored in an array since objects can't be keys for other
437 // objects. In addition, setting a unique property on an event target as a
438 // hash map key may not be allowed due to CORS restrictions.
439 var existingInstance = this.receivers.find(function (receiver) {
440 return receiver.isListeningto(eventTarget);
441 });
442 if (existingInstance) {
443 return existingInstance;
444 }
445 var newInstance = new Receiver(eventTarget);
446 this.receivers.push(newInstance);
447 return newInstance;
448 };
449 Receiver.prototype.isListeningto = function (eventTarget) {
450 return this.eventTarget === eventTarget;
451 };
452 /**
453 * Fans out a MessageEvent to the appropriate listeners.
454 *
455 * @remarks
456 * Sends an {@link Status.ACK} upon receipt and a {@link Status.DONE} once all handlers have
457 * finished processing.
458 *
459 * @param event - The MessageEvent.
460 *
461 */
462 Receiver.prototype.handleEvent = function (event) {
463 return tslib.__awaiter(this, void 0, void 0, function () {
464 var messageEvent, _a, eventId, eventType, data, handlers, promises, response;
465 var _this = this;
466 return tslib.__generator(this, function (_b) {
467 switch (_b.label) {
468 case 0:
469 messageEvent = event;
470 _a = messageEvent.data, eventId = _a.eventId, eventType = _a.eventType, data = _a.data;
471 handlers = this.handlersMap[eventType];
472 if (!(handlers === null || handlers === void 0 ? void 0 : handlers.size)) {
473 return [2 /*return*/];
474 }
475 messageEvent.ports[0].postMessage({
476 status: "ack" /* ACK */,
477 eventId: eventId,
478 eventType: eventType
479 });
480 promises = Array.from(handlers).map(function (handler) { return tslib.__awaiter(_this, void 0, void 0, function () { return tslib.__generator(this, function (_a) {
481 return [2 /*return*/, handler(messageEvent.origin, data)];
482 }); }); });
483 return [4 /*yield*/, _allSettled(promises)];
484 case 1:
485 response = _b.sent();
486 messageEvent.ports[0].postMessage({
487 status: "done" /* DONE */,
488 eventId: eventId,
489 eventType: eventType,
490 response: response
491 });
492 return [2 /*return*/];
493 }
494 });
495 });
496 };
497 /**
498 * Subscribe an event handler for a particular event.
499 *
500 * @param eventType - Event name to subscribe to.
501 * @param eventHandler - The event handler which should receive the events.
502 *
503 */
504 Receiver.prototype._subscribe = function (eventType, eventHandler) {
505 if (Object.keys(this.handlersMap).length === 0) {
506 this.eventTarget.addEventListener('message', this.boundEventHandler);
507 }
508 if (!this.handlersMap[eventType]) {
509 this.handlersMap[eventType] = new Set();
510 }
511 this.handlersMap[eventType].add(eventHandler);
512 };
513 /**
514 * Unsubscribe an event handler from a particular event.
515 *
516 * @param eventType - Event name to unsubscribe from.
517 * @param eventHandler - Optinoal event handler, if none provided, unsubscribe all handlers on this event.
518 *
519 */
520 Receiver.prototype._unsubscribe = function (eventType, eventHandler) {
521 if (this.handlersMap[eventType] && eventHandler) {
522 this.handlersMap[eventType].delete(eventHandler);
523 }
524 if (!eventHandler || this.handlersMap[eventType].size === 0) {
525 delete this.handlersMap[eventType];
526 }
527 if (Object.keys(this.handlersMap).length === 0) {
528 this.eventTarget.removeEventListener('message', this.boundEventHandler);
529 }
530 };
531 Receiver.receivers = [];
532 return Receiver;
533}());
534
535/**
536 * @license
537 * Copyright 2020 Google LLC
538 *
539 * Licensed under the Apache License, Version 2.0 (the "License");
540 * you may not use this file except in compliance with the License.
541 * You may obtain a copy of the License at
542 *
543 * http://www.apache.org/licenses/LICENSE-2.0
544 *
545 * Unless required by applicable law or agreed to in writing, software
546 * distributed under the License is distributed on an "AS IS" BASIS,
547 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
548 * See the License for the specific language governing permissions and
549 * limitations under the License.
550 */
551function _generateEventId(prefix, digits) {
552 if (prefix === void 0) { prefix = ''; }
553 if (digits === void 0) { digits = 10; }
554 var random = '';
555 for (var i = 0; i < digits; i++) {
556 random += Math.floor(Math.random() * 10);
557 }
558 return prefix + random;
559}
560
561/**
562 * @license
563 * Copyright 2019 Google LLC
564 *
565 * Licensed under the Apache License, Version 2.0 (the "License");
566 * you may not use this file except in compliance with the License.
567 * You may obtain a copy of the License at
568 *
569 * http://www.apache.org/licenses/LICENSE-2.0
570 *
571 * Unless required by applicable law or agreed to in writing, software
572 * distributed under the License is distributed on an "AS IS" BASIS,
573 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
574 * See the License for the specific language governing permissions and
575 * limitations under the License.
576 */
577/**
578 * Interface for sending messages and waiting for a completion response.
579 *
580 */
581var Sender = /** @class */ (function () {
582 function Sender(target) {
583 this.target = target;
584 this.handlers = new Set();
585 }
586 /**
587 * Unsubscribe the handler and remove it from our tracking Set.
588 *
589 * @param handler - The handler to unsubscribe.
590 */
591 Sender.prototype.removeMessageHandler = function (handler) {
592 if (handler.messageChannel) {
593 handler.messageChannel.port1.removeEventListener('message', handler.onMessage);
594 handler.messageChannel.port1.close();
595 }
596 this.handlers.delete(handler);
597 };
598 /**
599 * Send a message to the Receiver located at {@link target}.
600 *
601 * @remarks
602 * We'll first wait a bit for an ACK , if we get one we will wait significantly longer until the
603 * receiver has had a chance to fully process the event.
604 *
605 * @param eventType - Type of event to send.
606 * @param data - The payload of the event.
607 * @param timeout - Timeout for waiting on an ACK from the receiver.
608 *
609 * @returns An array of settled promises from all the handlers that were listening on the receiver.
610 */
611 Sender.prototype._send = function (eventType, data, timeout) {
612 if (timeout === void 0) { timeout = 50 /* ACK */; }
613 return tslib.__awaiter(this, void 0, void 0, function () {
614 var messageChannel, completionTimer, handler;
615 var _this = this;
616 return tslib.__generator(this, function (_a) {
617 messageChannel = typeof MessageChannel !== 'undefined' ? new MessageChannel() : null;
618 if (!messageChannel) {
619 throw new Error("connection_unavailable" /* CONNECTION_UNAVAILABLE */);
620 }
621 return [2 /*return*/, new Promise(function (resolve, reject) {
622 var eventId = _generateEventId('', 20);
623 messageChannel.port1.start();
624 var ackTimer = setTimeout(function () {
625 reject(new Error("unsupported_event" /* UNSUPPORTED_EVENT */));
626 }, timeout);
627 handler = {
628 messageChannel: messageChannel,
629 onMessage: function (event) {
630 var messageEvent = event;
631 if (messageEvent.data.eventId !== eventId) {
632 return;
633 }
634 switch (messageEvent.data.status) {
635 case "ack" /* ACK */:
636 // The receiver should ACK first.
637 clearTimeout(ackTimer);
638 completionTimer = setTimeout(function () {
639 reject(new Error("timeout" /* TIMEOUT */));
640 }, 3000 /* COMPLETION */);
641 break;
642 case "done" /* DONE */:
643 // Once the receiver's handlers are finished we will get the results.
644 clearTimeout(completionTimer);
645 resolve(messageEvent.data.response);
646 break;
647 default:
648 clearTimeout(ackTimer);
649 clearTimeout(completionTimer);
650 reject(new Error("invalid_response" /* INVALID_RESPONSE */));
651 break;
652 }
653 }
654 };
655 _this.handlers.add(handler);
656 messageChannel.port1.addEventListener('message', handler.onMessage);
657 _this.target.postMessage({
658 eventType: eventType,
659 eventId: eventId,
660 data: data
661 }, [messageChannel.port2]);
662 }).finally(function () {
663 if (handler) {
664 _this.removeMessageHandler(handler);
665 }
666 })];
667 });
668 });
669 };
670 return Sender;
671}());
672
673/**
674 * @license
675 * Copyright 2019 Google LLC
676 *
677 * Licensed under the Apache License, Version 2.0 (the "License");
678 * you may not use this file except in compliance with the License.
679 * You may obtain a copy of the License at
680 *
681 * http://www.apache.org/licenses/LICENSE-2.0
682 *
683 * Unless required by applicable law or agreed to in writing, software
684 * distributed under the License is distributed on an "AS IS" BASIS,
685 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
686 * See the License for the specific language governing permissions and
687 * limitations under the License.
688 */
689var DB_NAME = 'firebaseLocalStorageDb';
690var DB_VERSION = 1;
691var DB_OBJECTSTORE_NAME = 'firebaseLocalStorage';
692var DB_DATA_KEYPATH = 'fbase_key';
693/**
694 * Promise wrapper for IDBRequest
695 *
696 * Unfortunately we can't cleanly extend Promise<T> since promises are not callable in ES6
697 *
698 */
699var DBPromise = /** @class */ (function () {
700 function DBPromise(request) {
701 this.request = request;
702 }
703 DBPromise.prototype.toPromise = function () {
704 var _this = this;
705 return new Promise(function (resolve, reject) {
706 _this.request.addEventListener('success', function () {
707 resolve(_this.request.result);
708 });
709 _this.request.addEventListener('error', function () {
710 reject(_this.request.error);
711 });
712 });
713 };
714 return DBPromise;
715}());
716function getObjectStore(db, isReadWrite) {
717 return db
718 .transaction([DB_OBJECTSTORE_NAME], isReadWrite ? 'readwrite' : 'readonly')
719 .objectStore(DB_OBJECTSTORE_NAME);
720}
721function _deleteDatabase() {
722 var request = indexedDB.deleteDatabase(DB_NAME);
723 return new DBPromise(request).toPromise();
724}
725function _openDatabase() {
726 var _this = this;
727 var request = indexedDB.open(DB_NAME, DB_VERSION);
728 return new Promise(function (resolve, reject) {
729 request.addEventListener('error', function () {
730 reject(request.error);
731 });
732 request.addEventListener('upgradeneeded', function () {
733 var db = request.result;
734 try {
735 db.createObjectStore(DB_OBJECTSTORE_NAME, { keyPath: DB_DATA_KEYPATH });
736 }
737 catch (e) {
738 reject(e);
739 }
740 });
741 request.addEventListener('success', function () { return tslib.__awaiter(_this, void 0, void 0, function () {
742 var db, _a;
743 return tslib.__generator(this, function (_b) {
744 switch (_b.label) {
745 case 0:
746 db = request.result;
747 if (!!db.objectStoreNames.contains(DB_OBJECTSTORE_NAME)) return [3 /*break*/, 3];
748 // Need to close the database or else you get a `blocked` event
749 db.close();
750 return [4 /*yield*/, _deleteDatabase()];
751 case 1:
752 _b.sent();
753 _a = resolve;
754 return [4 /*yield*/, _openDatabase()];
755 case 2:
756 _a.apply(void 0, [_b.sent()]);
757 return [3 /*break*/, 4];
758 case 3:
759 resolve(db);
760 _b.label = 4;
761 case 4: return [2 /*return*/];
762 }
763 });
764 }); });
765 });
766}
767function _putObject(db, key, value) {
768 return tslib.__awaiter(this, void 0, void 0, function () {
769 var request;
770 var _a;
771 return tslib.__generator(this, function (_b) {
772 request = getObjectStore(db, true).put((_a = {},
773 _a[DB_DATA_KEYPATH] = key,
774 _a.value = value,
775 _a));
776 return [2 /*return*/, new DBPromise(request).toPromise()];
777 });
778 });
779}
780function getObject(db, key) {
781 return tslib.__awaiter(this, void 0, void 0, function () {
782 var request, data;
783 return tslib.__generator(this, function (_a) {
784 switch (_a.label) {
785 case 0:
786 request = getObjectStore(db, false).get(key);
787 return [4 /*yield*/, new DBPromise(request).toPromise()];
788 case 1:
789 data = _a.sent();
790 return [2 /*return*/, data === undefined ? null : data.value];
791 }
792 });
793 });
794}
795function _deleteObject(db, key) {
796 var request = getObjectStore(db, true).delete(key);
797 return new DBPromise(request).toPromise();
798}
799var _POLLING_INTERVAL_MS = 800;
800var _TRANSACTION_RETRY_COUNT = 3;
801var IndexedDBLocalPersistence = /** @class */ (function () {
802 function IndexedDBLocalPersistence() {
803 this.type = "LOCAL" /* LOCAL */;
804 this._shouldAllowMigration = true;
805 this.listeners = {};
806 this.localCache = {};
807 // setTimeout return value is platform specific
808 // eslint-disable-next-line @typescript-eslint/no-explicit-any
809 this.pollTimer = null;
810 this.pendingWrites = 0;
811 this.receiver = null;
812 this.sender = null;
813 this.serviceWorkerReceiverAvailable = false;
814 this.activeServiceWorker = null;
815 // Fire & forget the service worker registration as it may never resolve
816 this._workerInitializationPromise =
817 this.initializeServiceWorkerMessaging().then(function () { }, function () { });
818 }
819 IndexedDBLocalPersistence.prototype._openDb = function () {
820 return tslib.__awaiter(this, void 0, void 0, function () {
821 var _a;
822 return tslib.__generator(this, function (_b) {
823 switch (_b.label) {
824 case 0:
825 if (this.db) {
826 return [2 /*return*/, this.db];
827 }
828 _a = this;
829 return [4 /*yield*/, _openDatabase()];
830 case 1:
831 _a.db = _b.sent();
832 return [2 /*return*/, this.db];
833 }
834 });
835 });
836 };
837 IndexedDBLocalPersistence.prototype._withRetries = function (op) {
838 return tslib.__awaiter(this, void 0, void 0, function () {
839 var numAttempts, db, e_1;
840 return tslib.__generator(this, function (_a) {
841 switch (_a.label) {
842 case 0:
843 numAttempts = 0;
844 _a.label = 1;
845 case 1:
846 _a.label = 2;
847 case 2:
848 _a.trys.push([2, 5, , 6]);
849 return [4 /*yield*/, this._openDb()];
850 case 3:
851 db = _a.sent();
852 return [4 /*yield*/, op(db)];
853 case 4: return [2 /*return*/, _a.sent()];
854 case 5:
855 e_1 = _a.sent();
856 if (numAttempts++ > _TRANSACTION_RETRY_COUNT) {
857 throw e_1;
858 }
859 if (this.db) {
860 this.db.close();
861 this.db = undefined;
862 }
863 return [3 /*break*/, 6];
864 case 6: return [3 /*break*/, 1];
865 case 7: return [2 /*return*/];
866 }
867 });
868 });
869 };
870 /**
871 * IndexedDB events do not propagate from the main window to the worker context. We rely on a
872 * postMessage interface to send these events to the worker ourselves.
873 */
874 IndexedDBLocalPersistence.prototype.initializeServiceWorkerMessaging = function () {
875 return tslib.__awaiter(this, void 0, void 0, function () {
876 return tslib.__generator(this, function (_a) {
877 return [2 /*return*/, phone._isWorker() ? this.initializeReceiver() : this.initializeSender()];
878 });
879 });
880 };
881 /**
882 * As the worker we should listen to events from the main window.
883 */
884 IndexedDBLocalPersistence.prototype.initializeReceiver = function () {
885 return tslib.__awaiter(this, void 0, void 0, function () {
886 var _this = this;
887 return tslib.__generator(this, function (_a) {
888 this.receiver = Receiver._getInstance(phone._getWorkerGlobalScope());
889 // Refresh from persistence if we receive a KeyChanged message.
890 this.receiver._subscribe("keyChanged" /* KEY_CHANGED */, function (_origin, data) { return tslib.__awaiter(_this, void 0, void 0, function () {
891 var keys;
892 return tslib.__generator(this, function (_a) {
893 switch (_a.label) {
894 case 0: return [4 /*yield*/, this._poll()];
895 case 1:
896 keys = _a.sent();
897 return [2 /*return*/, {
898 keyProcessed: keys.includes(data.key)
899 }];
900 }
901 });
902 }); });
903 // Let the sender know that we are listening so they give us more timeout.
904 this.receiver._subscribe("ping" /* PING */, function (_origin, _data) { return tslib.__awaiter(_this, void 0, void 0, function () {
905 return tslib.__generator(this, function (_a) {
906 return [2 /*return*/, ["keyChanged" /* KEY_CHANGED */]];
907 });
908 }); });
909 return [2 /*return*/];
910 });
911 });
912 };
913 /**
914 * As the main window, we should let the worker know when keys change (set and remove).
915 *
916 * @remarks
917 * {@link https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerContainer/ready | ServiceWorkerContainer.ready}
918 * may not resolve.
919 */
920 IndexedDBLocalPersistence.prototype.initializeSender = function () {
921 var _a, _b;
922 return tslib.__awaiter(this, void 0, void 0, function () {
923 var _c, results;
924 return tslib.__generator(this, function (_d) {
925 switch (_d.label) {
926 case 0:
927 // Check to see if there's an active service worker.
928 _c = this;
929 return [4 /*yield*/, phone._getActiveServiceWorker()];
930 case 1:
931 // Check to see if there's an active service worker.
932 _c.activeServiceWorker = _d.sent();
933 if (!this.activeServiceWorker) {
934 return [2 /*return*/];
935 }
936 this.sender = new Sender(this.activeServiceWorker);
937 return [4 /*yield*/, this.sender._send("ping" /* PING */, {}, 800 /* LONG_ACK */)];
938 case 2:
939 results = _d.sent();
940 if (!results) {
941 return [2 /*return*/];
942 }
943 if (((_a = results[0]) === null || _a === void 0 ? void 0 : _a.fulfilled) &&
944 ((_b = results[0]) === null || _b === void 0 ? void 0 : _b.value.includes("keyChanged" /* KEY_CHANGED */))) {
945 this.serviceWorkerReceiverAvailable = true;
946 }
947 return [2 /*return*/];
948 }
949 });
950 });
951 };
952 /**
953 * Let the worker know about a changed key, the exact key doesn't technically matter since the
954 * worker will just trigger a full sync anyway.
955 *
956 * @remarks
957 * For now, we only support one service worker per page.
958 *
959 * @param key - Storage key which changed.
960 */
961 IndexedDBLocalPersistence.prototype.notifyServiceWorker = function (key) {
962 return tslib.__awaiter(this, void 0, void 0, function () {
963 return tslib.__generator(this, function (_b) {
964 switch (_b.label) {
965 case 0:
966 if (!this.sender ||
967 !this.activeServiceWorker ||
968 phone._getServiceWorkerController() !== this.activeServiceWorker) {
969 return [2 /*return*/];
970 }
971 _b.label = 1;
972 case 1:
973 _b.trys.push([1, 3, , 4]);
974 return [4 /*yield*/, this.sender._send("keyChanged" /* KEY_CHANGED */, { key: key },
975 // Use long timeout if receiver has previously responded to a ping from us.
976 this.serviceWorkerReceiverAvailable
977 ? 800 /* LONG_ACK */
978 : 50 /* ACK */)];
979 case 2:
980 _b.sent();
981 return [3 /*break*/, 4];
982 case 3:
983 _b.sent();
984 return [3 /*break*/, 4];
985 case 4: return [2 /*return*/];
986 }
987 });
988 });
989 };
990 IndexedDBLocalPersistence.prototype._isAvailable = function () {
991 return tslib.__awaiter(this, void 0, void 0, function () {
992 var db;
993 return tslib.__generator(this, function (_b) {
994 switch (_b.label) {
995 case 0:
996 _b.trys.push([0, 4, , 5]);
997 if (!indexedDB) {
998 return [2 /*return*/, false];
999 }
1000 return [4 /*yield*/, _openDatabase()];
1001 case 1:
1002 db = _b.sent();
1003 return [4 /*yield*/, _putObject(db, phone.STORAGE_AVAILABLE_KEY, '1')];
1004 case 2:
1005 _b.sent();
1006 return [4 /*yield*/, _deleteObject(db, phone.STORAGE_AVAILABLE_KEY)];
1007 case 3:
1008 _b.sent();
1009 return [2 /*return*/, true];
1010 case 4:
1011 _b.sent();
1012 return [3 /*break*/, 5];
1013 case 5: return [2 /*return*/, false];
1014 }
1015 });
1016 });
1017 };
1018 IndexedDBLocalPersistence.prototype._withPendingWrite = function (write) {
1019 return tslib.__awaiter(this, void 0, void 0, function () {
1020 return tslib.__generator(this, function (_a) {
1021 switch (_a.label) {
1022 case 0:
1023 this.pendingWrites++;
1024 _a.label = 1;
1025 case 1:
1026 _a.trys.push([1, , 3, 4]);
1027 return [4 /*yield*/, write()];
1028 case 2:
1029 _a.sent();
1030 return [3 /*break*/, 4];
1031 case 3:
1032 this.pendingWrites--;
1033 return [7 /*endfinally*/];
1034 case 4: return [2 /*return*/];
1035 }
1036 });
1037 });
1038 };
1039 IndexedDBLocalPersistence.prototype._set = function (key, value) {
1040 return tslib.__awaiter(this, void 0, void 0, function () {
1041 var _this = this;
1042 return tslib.__generator(this, function (_a) {
1043 return [2 /*return*/, this._withPendingWrite(function () { return tslib.__awaiter(_this, void 0, void 0, function () {
1044 return tslib.__generator(this, function (_a) {
1045 switch (_a.label) {
1046 case 0: return [4 /*yield*/, this._withRetries(function (db) { return _putObject(db, key, value); })];
1047 case 1:
1048 _a.sent();
1049 this.localCache[key] = value;
1050 return [2 /*return*/, this.notifyServiceWorker(key)];
1051 }
1052 });
1053 }); })];
1054 });
1055 });
1056 };
1057 IndexedDBLocalPersistence.prototype._get = function (key) {
1058 return tslib.__awaiter(this, void 0, void 0, function () {
1059 var obj;
1060 return tslib.__generator(this, function (_a) {
1061 switch (_a.label) {
1062 case 0: return [4 /*yield*/, this._withRetries(function (db) {
1063 return getObject(db, key);
1064 })];
1065 case 1:
1066 obj = (_a.sent());
1067 this.localCache[key] = obj;
1068 return [2 /*return*/, obj];
1069 }
1070 });
1071 });
1072 };
1073 IndexedDBLocalPersistence.prototype._remove = function (key) {
1074 return tslib.__awaiter(this, void 0, void 0, function () {
1075 var _this = this;
1076 return tslib.__generator(this, function (_a) {
1077 return [2 /*return*/, this._withPendingWrite(function () { return tslib.__awaiter(_this, void 0, void 0, function () {
1078 return tslib.__generator(this, function (_a) {
1079 switch (_a.label) {
1080 case 0: return [4 /*yield*/, this._withRetries(function (db) { return _deleteObject(db, key); })];
1081 case 1:
1082 _a.sent();
1083 delete this.localCache[key];
1084 return [2 /*return*/, this.notifyServiceWorker(key)];
1085 }
1086 });
1087 }); })];
1088 });
1089 });
1090 };
1091 IndexedDBLocalPersistence.prototype._poll = function () {
1092 return tslib.__awaiter(this, void 0, void 0, function () {
1093 var result, keys, keysInResult, _i, result_1, _a, key, value, _b, _c, localKey;
1094 return tslib.__generator(this, function (_d) {
1095 switch (_d.label) {
1096 case 0: return [4 /*yield*/, this._withRetries(function (db) {
1097 var getAllRequest = getObjectStore(db, false).getAll();
1098 return new DBPromise(getAllRequest).toPromise();
1099 })];
1100 case 1:
1101 result = _d.sent();
1102 if (!result) {
1103 return [2 /*return*/, []];
1104 }
1105 // If we have pending writes in progress abort, we'll get picked up on the next poll
1106 if (this.pendingWrites !== 0) {
1107 return [2 /*return*/, []];
1108 }
1109 keys = [];
1110 keysInResult = new Set();
1111 for (_i = 0, result_1 = result; _i < result_1.length; _i++) {
1112 _a = result_1[_i], key = _a.fbase_key, value = _a.value;
1113 keysInResult.add(key);
1114 if (JSON.stringify(this.localCache[key]) !== JSON.stringify(value)) {
1115 this.notifyListeners(key, value);
1116 keys.push(key);
1117 }
1118 }
1119 for (_b = 0, _c = Object.keys(this.localCache); _b < _c.length; _b++) {
1120 localKey = _c[_b];
1121 if (this.localCache[localKey] && !keysInResult.has(localKey)) {
1122 // Deleted
1123 this.notifyListeners(localKey, null);
1124 keys.push(localKey);
1125 }
1126 }
1127 return [2 /*return*/, keys];
1128 }
1129 });
1130 });
1131 };
1132 IndexedDBLocalPersistence.prototype.notifyListeners = function (key, newValue) {
1133 this.localCache[key] = newValue;
1134 var listeners = this.listeners[key];
1135 if (listeners) {
1136 for (var _i = 0, _a = Array.from(listeners); _i < _a.length; _i++) {
1137 var listener = _a[_i];
1138 listener(newValue);
1139 }
1140 }
1141 };
1142 IndexedDBLocalPersistence.prototype.startPolling = function () {
1143 var _this = this;
1144 this.stopPolling();
1145 this.pollTimer = setInterval(function () { return tslib.__awaiter(_this, void 0, void 0, function () { return tslib.__generator(this, function (_a) {
1146 return [2 /*return*/, this._poll()];
1147 }); }); }, _POLLING_INTERVAL_MS);
1148 };
1149 IndexedDBLocalPersistence.prototype.stopPolling = function () {
1150 if (this.pollTimer) {
1151 clearInterval(this.pollTimer);
1152 this.pollTimer = null;
1153 }
1154 };
1155 IndexedDBLocalPersistence.prototype._addListener = function (key, listener) {
1156 if (Object.keys(this.listeners).length === 0) {
1157 this.startPolling();
1158 }
1159 if (!this.listeners[key]) {
1160 this.listeners[key] = new Set();
1161 // Populate the cache to avoid spuriously triggering on first poll.
1162 void this._get(key); // This can happen in the background async and we can return immediately.
1163 }
1164 this.listeners[key].add(listener);
1165 };
1166 IndexedDBLocalPersistence.prototype._removeListener = function (key, listener) {
1167 if (this.listeners[key]) {
1168 this.listeners[key].delete(listener);
1169 if (this.listeners[key].size === 0) {
1170 delete this.listeners[key];
1171 }
1172 }
1173 if (Object.keys(this.listeners).length === 0) {
1174 this.stopPolling();
1175 }
1176 };
1177 IndexedDBLocalPersistence.type = 'LOCAL';
1178 return IndexedDBLocalPersistence;
1179}());
1180/**
1181 * An implementation of {@link Persistence} of type `LOCAL` using `indexedDB`
1182 * for the underlying storage.
1183 *
1184 * @public
1185 */
1186var indexedDBLocalPersistence = IndexedDBLocalPersistence;
1187
1188/**
1189 * @license
1190 * Copyright 2021 Google LLC
1191 *
1192 * Licensed under the Apache License, Version 2.0 (the "License");
1193 * you may not use this file except in compliance with the License.
1194 * You may obtain a copy of the License at
1195 *
1196 * http://www.apache.org/licenses/LICENSE-2.0
1197 *
1198 * Unless required by applicable law or agreed to in writing, software
1199 * distributed under the License is distributed on an "AS IS" BASIS,
1200 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1201 * See the License for the specific language governing permissions and
1202 * limitations under the License.
1203 */
1204/**
1205 * Chooses a popup/redirect resolver to use. This prefers the override (which
1206 * is directly passed in), and falls back to the property set on the auth
1207 * object. If neither are available, this function errors w/ an argument error.
1208 */
1209function _withDefaultResolver(auth, resolverOverride) {
1210 if (resolverOverride) {
1211 return phone._getInstance(resolverOverride);
1212 }
1213 phone._assert(auth._popupRedirectResolver, auth, "argument-error" /* ARGUMENT_ERROR */);
1214 return auth._popupRedirectResolver;
1215}
1216
1217/**
1218 * @license
1219 * Copyright 2019 Google LLC
1220 *
1221 * Licensed under the Apache License, Version 2.0 (the "License");
1222 * you may not use this file except in compliance with the License.
1223 * You may obtain a copy of the License at
1224 *
1225 * http://www.apache.org/licenses/LICENSE-2.0
1226 *
1227 * Unless required by applicable law or agreed to in writing, software
1228 * distributed under the License is distributed on an "AS IS" BASIS,
1229 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1230 * See the License for the specific language governing permissions and
1231 * limitations under the License.
1232 */
1233var IdpCredential = /** @class */ (function (_super) {
1234 tslib.__extends(IdpCredential, _super);
1235 function IdpCredential(params) {
1236 var _this = _super.call(this, "custom" /* CUSTOM */, "custom" /* CUSTOM */) || this;
1237 _this.params = params;
1238 return _this;
1239 }
1240 IdpCredential.prototype._getIdTokenResponse = function (auth) {
1241 return phone.signInWithIdp(auth, this._buildIdpRequest());
1242 };
1243 IdpCredential.prototype._linkToIdToken = function (auth, idToken) {
1244 return phone.signInWithIdp(auth, this._buildIdpRequest(idToken));
1245 };
1246 IdpCredential.prototype._getReauthenticationResolver = function (auth) {
1247 return phone.signInWithIdp(auth, this._buildIdpRequest());
1248 };
1249 IdpCredential.prototype._buildIdpRequest = function (idToken) {
1250 var request = {
1251 requestUri: this.params.requestUri,
1252 sessionId: this.params.sessionId,
1253 postBody: this.params.postBody,
1254 tenantId: this.params.tenantId,
1255 pendingToken: this.params.pendingToken,
1256 returnSecureToken: true,
1257 returnIdpCredential: true
1258 };
1259 if (idToken) {
1260 request.idToken = idToken;
1261 }
1262 return request;
1263 };
1264 return IdpCredential;
1265}(phone.AuthCredential));
1266function _signIn(params) {
1267 return phone._signInWithCredential(params.auth, new IdpCredential(params), params.bypassAuthState);
1268}
1269function _reauth(params) {
1270 var auth = params.auth, user = params.user;
1271 phone._assert(user, auth, "internal-error" /* INTERNAL_ERROR */);
1272 return phone._reauthenticate(user, new IdpCredential(params), params.bypassAuthState);
1273}
1274function _link(params) {
1275 return tslib.__awaiter(this, void 0, void 0, function () {
1276 var auth, user;
1277 return tslib.__generator(this, function (_a) {
1278 auth = params.auth, user = params.user;
1279 phone._assert(user, auth, "internal-error" /* INTERNAL_ERROR */);
1280 return [2 /*return*/, phone._link(user, new IdpCredential(params), params.bypassAuthState)];
1281 });
1282 });
1283}
1284
1285/**
1286 * @license
1287 * Copyright 2020 Google LLC
1288 *
1289 * Licensed under the Apache License, Version 2.0 (the "License");
1290 * you may not use this file except in compliance with the License.
1291 * You may obtain a copy of the License at
1292 *
1293 * http://www.apache.org/licenses/LICENSE-2.0
1294 *
1295 * Unless required by applicable law or agreed to in writing, software
1296 * distributed under the License is distributed on an "AS IS" BASIS,
1297 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1298 * See the License for the specific language governing permissions and
1299 * limitations under the License.
1300 */
1301/**
1302 * Popup event manager. Handles the popup's entire lifecycle; listens to auth
1303 * events
1304 */
1305var AbstractPopupRedirectOperation = /** @class */ (function () {
1306 function AbstractPopupRedirectOperation(auth, filter, resolver, user, bypassAuthState) {
1307 if (bypassAuthState === void 0) { bypassAuthState = false; }
1308 this.auth = auth;
1309 this.resolver = resolver;
1310 this.user = user;
1311 this.bypassAuthState = bypassAuthState;
1312 this.pendingPromise = null;
1313 this.eventManager = null;
1314 this.filter = Array.isArray(filter) ? filter : [filter];
1315 }
1316 AbstractPopupRedirectOperation.prototype.execute = function () {
1317 var _this = this;
1318 return new Promise(function (resolve, reject) { return tslib.__awaiter(_this, void 0, void 0, function () {
1319 var _a, e_1;
1320 return tslib.__generator(this, function (_b) {
1321 switch (_b.label) {
1322 case 0:
1323 this.pendingPromise = { resolve: resolve, reject: reject };
1324 _b.label = 1;
1325 case 1:
1326 _b.trys.push([1, 4, , 5]);
1327 _a = this;
1328 return [4 /*yield*/, this.resolver._initialize(this.auth)];
1329 case 2:
1330 _a.eventManager = _b.sent();
1331 return [4 /*yield*/, this.onExecution()];
1332 case 3:
1333 _b.sent();
1334 this.eventManager.registerConsumer(this);
1335 return [3 /*break*/, 5];
1336 case 4:
1337 e_1 = _b.sent();
1338 this.reject(e_1);
1339 return [3 /*break*/, 5];
1340 case 5: return [2 /*return*/];
1341 }
1342 });
1343 }); });
1344 };
1345 AbstractPopupRedirectOperation.prototype.onAuthEvent = function (event) {
1346 return tslib.__awaiter(this, void 0, void 0, function () {
1347 var urlResponse, sessionId, postBody, tenantId, error, type, params, _a, e_2;
1348 return tslib.__generator(this, function (_b) {
1349 switch (_b.label) {
1350 case 0:
1351 urlResponse = event.urlResponse, sessionId = event.sessionId, postBody = event.postBody, tenantId = event.tenantId, error = event.error, type = event.type;
1352 if (error) {
1353 this.reject(error);
1354 return [2 /*return*/];
1355 }
1356 params = {
1357 auth: this.auth,
1358 requestUri: urlResponse,
1359 sessionId: sessionId,
1360 tenantId: tenantId || undefined,
1361 postBody: postBody || undefined,
1362 user: this.user,
1363 bypassAuthState: this.bypassAuthState
1364 };
1365 _b.label = 1;
1366 case 1:
1367 _b.trys.push([1, 3, , 4]);
1368 _a = this.resolve;
1369 return [4 /*yield*/, this.getIdpTask(type)(params)];
1370 case 2:
1371 _a.apply(this, [_b.sent()]);
1372 return [3 /*break*/, 4];
1373 case 3:
1374 e_2 = _b.sent();
1375 this.reject(e_2);
1376 return [3 /*break*/, 4];
1377 case 4: return [2 /*return*/];
1378 }
1379 });
1380 });
1381 };
1382 AbstractPopupRedirectOperation.prototype.onError = function (error) {
1383 this.reject(error);
1384 };
1385 AbstractPopupRedirectOperation.prototype.getIdpTask = function (type) {
1386 switch (type) {
1387 case "signInViaPopup" /* SIGN_IN_VIA_POPUP */:
1388 case "signInViaRedirect" /* SIGN_IN_VIA_REDIRECT */:
1389 return _signIn;
1390 case "linkViaPopup" /* LINK_VIA_POPUP */:
1391 case "linkViaRedirect" /* LINK_VIA_REDIRECT */:
1392 return _link;
1393 case "reauthViaPopup" /* REAUTH_VIA_POPUP */:
1394 case "reauthViaRedirect" /* REAUTH_VIA_REDIRECT */:
1395 return _reauth;
1396 default:
1397 phone._fail(this.auth, "internal-error" /* INTERNAL_ERROR */);
1398 }
1399 };
1400 AbstractPopupRedirectOperation.prototype.resolve = function (cred) {
1401 phone.debugAssert(this.pendingPromise, 'Pending promise was never set');
1402 this.pendingPromise.resolve(cred);
1403 this.unregisterAndCleanUp();
1404 };
1405 AbstractPopupRedirectOperation.prototype.reject = function (error) {
1406 phone.debugAssert(this.pendingPromise, 'Pending promise was never set');
1407 this.pendingPromise.reject(error);
1408 this.unregisterAndCleanUp();
1409 };
1410 AbstractPopupRedirectOperation.prototype.unregisterAndCleanUp = function () {
1411 if (this.eventManager) {
1412 this.eventManager.unregisterConsumer(this);
1413 }
1414 this.pendingPromise = null;
1415 this.cleanUp();
1416 };
1417 return AbstractPopupRedirectOperation;
1418}());
1419
1420/**
1421 * @license
1422 * Copyright 2020 Google LLC
1423 *
1424 * Licensed under the Apache License, Version 2.0 (the "License");
1425 * you may not use this file except in compliance with the License.
1426 * You may obtain a copy of the License at
1427 *
1428 * http://www.apache.org/licenses/LICENSE-2.0
1429 *
1430 * Unless required by applicable law or agreed to in writing, software
1431 * distributed under the License is distributed on an "AS IS" BASIS,
1432 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1433 * See the License for the specific language governing permissions and
1434 * limitations under the License.
1435 */
1436var _POLL_WINDOW_CLOSE_TIMEOUT = new phone.Delay(2000, 10000);
1437/**
1438 * Authenticates a Firebase client using a popup-based OAuth authentication flow.
1439 *
1440 * @remarks
1441 * If succeeds, returns the signed in user along with the provider's credential. If sign in was
1442 * unsuccessful, returns an error object containing additional information about the error.
1443 *
1444 * @example
1445 * ```javascript
1446 * // Sign in using a popup.
1447 * const provider = new FacebookAuthProvider();
1448 * const result = await signInWithPopup(auth, provider);
1449 *
1450 * // The signed-in user info.
1451 * const user = result.user;
1452 * // This gives you a Facebook Access Token.
1453 * const credential = provider.credentialFromResult(auth, result);
1454 * const token = credential.accessToken;
1455 * ```
1456 *
1457 * @param auth - The {@link Auth} instance.
1458 * @param provider - The provider to authenticate. The provider has to be an {@link OAuthProvider}.
1459 * Non-OAuth providers like {@link EmailAuthProvider} will throw an error.
1460 * @param resolver - An instance of {@link PopupRedirectResolver}, optional
1461 * if already supplied to {@link initializeAuth} or provided by {@link getAuth}.
1462 *
1463 *
1464 * @public
1465 */
1466function signInWithPopup(auth, provider, resolver) {
1467 return tslib.__awaiter(this, void 0, void 0, function () {
1468 var authInternal, resolverInternal, action;
1469 return tslib.__generator(this, function (_a) {
1470 authInternal = phone._castAuth(auth);
1471 phone._assertInstanceOf(auth, provider, phone.FederatedAuthProvider);
1472 resolverInternal = _withDefaultResolver(authInternal, resolver);
1473 action = new PopupOperation(authInternal, "signInViaPopup" /* SIGN_IN_VIA_POPUP */, provider, resolverInternal);
1474 return [2 /*return*/, action.executeNotNull()];
1475 });
1476 });
1477}
1478/**
1479 * Reauthenticates the current user with the specified {@link OAuthProvider} using a pop-up based
1480 * OAuth flow.
1481 *
1482 * @remarks
1483 * If the reauthentication is successful, the returned result will contain the user and the
1484 * provider's credential.
1485 *
1486 * @example
1487 * ```javascript
1488 * // Sign in using a popup.
1489 * const provider = new FacebookAuthProvider();
1490 * const result = await signInWithPopup(auth, provider);
1491 * // Reauthenticate using a popup.
1492 * await reauthenticateWithPopup(result.user, provider);
1493 * ```
1494 *
1495 * @param user - The user.
1496 * @param provider - The provider to authenticate. The provider has to be an {@link OAuthProvider}.
1497 * Non-OAuth providers like {@link EmailAuthProvider} will throw an error.
1498 * @param resolver - An instance of {@link PopupRedirectResolver}, optional
1499 * if already supplied to {@link initializeAuth} or provided by {@link getAuth}.
1500 *
1501 * @public
1502 */
1503function reauthenticateWithPopup(user, provider, resolver) {
1504 return tslib.__awaiter(this, void 0, void 0, function () {
1505 var userInternal, resolverInternal, action;
1506 return tslib.__generator(this, function (_a) {
1507 userInternal = util.getModularInstance(user);
1508 phone._assertInstanceOf(userInternal.auth, provider, phone.FederatedAuthProvider);
1509 resolverInternal = _withDefaultResolver(userInternal.auth, resolver);
1510 action = new PopupOperation(userInternal.auth, "reauthViaPopup" /* REAUTH_VIA_POPUP */, provider, resolverInternal, userInternal);
1511 return [2 /*return*/, action.executeNotNull()];
1512 });
1513 });
1514}
1515/**
1516 * Links the authenticated provider to the user account using a pop-up based OAuth flow.
1517 *
1518 * @remarks
1519 * If the linking is successful, the returned result will contain the user and the provider's credential.
1520 *
1521 *
1522 * @example
1523 * ```javascript
1524 * // Sign in using some other provider.
1525 * const result = await signInWithEmailAndPassword(auth, email, password);
1526 * // Link using a popup.
1527 * const provider = new FacebookAuthProvider();
1528 * await linkWithPopup(result.user, provider);
1529 * ```
1530 *
1531 * @param user - The user.
1532 * @param provider - The provider to authenticate. The provider has to be an {@link OAuthProvider}.
1533 * Non-OAuth providers like {@link EmailAuthProvider} will throw an error.
1534 * @param resolver - An instance of {@link PopupRedirectResolver}, optional
1535 * if already supplied to {@link initializeAuth} or provided by {@link getAuth}.
1536 *
1537 * @public
1538 */
1539function linkWithPopup(user, provider, resolver) {
1540 return tslib.__awaiter(this, void 0, void 0, function () {
1541 var userInternal, resolverInternal, action;
1542 return tslib.__generator(this, function (_a) {
1543 userInternal = util.getModularInstance(user);
1544 phone._assertInstanceOf(userInternal.auth, provider, phone.FederatedAuthProvider);
1545 resolverInternal = _withDefaultResolver(userInternal.auth, resolver);
1546 action = new PopupOperation(userInternal.auth, "linkViaPopup" /* LINK_VIA_POPUP */, provider, resolverInternal, userInternal);
1547 return [2 /*return*/, action.executeNotNull()];
1548 });
1549 });
1550}
1551/**
1552 * Popup event manager. Handles the popup's entire lifecycle; listens to auth
1553 * events
1554 *
1555 */
1556var PopupOperation = /** @class */ (function (_super) {
1557 tslib.__extends(PopupOperation, _super);
1558 function PopupOperation(auth, filter, provider, resolver, user) {
1559 var _this = _super.call(this, auth, filter, resolver, user) || this;
1560 _this.provider = provider;
1561 _this.authWindow = null;
1562 _this.pollId = null;
1563 if (PopupOperation.currentPopupAction) {
1564 PopupOperation.currentPopupAction.cancel();
1565 }
1566 PopupOperation.currentPopupAction = _this;
1567 return _this;
1568 }
1569 PopupOperation.prototype.executeNotNull = function () {
1570 return tslib.__awaiter(this, void 0, void 0, function () {
1571 var result;
1572 return tslib.__generator(this, function (_a) {
1573 switch (_a.label) {
1574 case 0: return [4 /*yield*/, this.execute()];
1575 case 1:
1576 result = _a.sent();
1577 phone._assert(result, this.auth, "internal-error" /* INTERNAL_ERROR */);
1578 return [2 /*return*/, result];
1579 }
1580 });
1581 });
1582 };
1583 PopupOperation.prototype.onExecution = function () {
1584 return tslib.__awaiter(this, void 0, void 0, function () {
1585 var eventId, _a;
1586 var _this = this;
1587 return tslib.__generator(this, function (_b) {
1588 switch (_b.label) {
1589 case 0:
1590 phone.debugAssert(this.filter.length === 1, 'Popup operations only handle one event');
1591 eventId = _generateEventId();
1592 _a = this;
1593 return [4 /*yield*/, this.resolver._openPopup(this.auth, this.provider, this.filter[0], // There's always one, see constructor
1594 eventId)];
1595 case 1:
1596 _a.authWindow = _b.sent();
1597 this.authWindow.associatedEvent = eventId;
1598 // Check for web storage support and origin validation _after_ the popup is
1599 // loaded. These operations are slow (~1 second or so) Rather than
1600 // waiting on them before opening the window, optimistically open the popup
1601 // and check for storage support at the same time. If storage support is
1602 // not available, this will cause the whole thing to reject properly. It
1603 // will also close the popup, but since the promise has already rejected,
1604 // the popup closed by user poll will reject into the void.
1605 this.resolver._originValidation(this.auth).catch(function (e) {
1606 _this.reject(e);
1607 });
1608 this.resolver._isIframeWebStorageSupported(this.auth, function (isSupported) {
1609 if (!isSupported) {
1610 _this.reject(phone._createError(_this.auth, "web-storage-unsupported" /* WEB_STORAGE_UNSUPPORTED */));
1611 }
1612 });
1613 // Handle user closure. Notice this does *not* use await
1614 this.pollUserCancellation();
1615 return [2 /*return*/];
1616 }
1617 });
1618 });
1619 };
1620 Object.defineProperty(PopupOperation.prototype, "eventId", {
1621 get: function () {
1622 var _a;
1623 return ((_a = this.authWindow) === null || _a === void 0 ? void 0 : _a.associatedEvent) || null;
1624 },
1625 enumerable: false,
1626 configurable: true
1627 });
1628 PopupOperation.prototype.cancel = function () {
1629 this.reject(phone._createError(this.auth, "cancelled-popup-request" /* EXPIRED_POPUP_REQUEST */));
1630 };
1631 PopupOperation.prototype.cleanUp = function () {
1632 if (this.authWindow) {
1633 this.authWindow.close();
1634 }
1635 if (this.pollId) {
1636 window.clearTimeout(this.pollId);
1637 }
1638 this.authWindow = null;
1639 this.pollId = null;
1640 PopupOperation.currentPopupAction = null;
1641 };
1642 PopupOperation.prototype.pollUserCancellation = function () {
1643 var _this = this;
1644 var poll = function () {
1645 var _a, _b;
1646 if ((_b = (_a = _this.authWindow) === null || _a === void 0 ? void 0 : _a.window) === null || _b === void 0 ? void 0 : _b.closed) {
1647 // Make sure that there is sufficient time for whatever action to
1648 // complete. The window could have closed but the sign in network
1649 // call could still be in flight.
1650 _this.pollId = window.setTimeout(function () {
1651 _this.pollId = null;
1652 _this.reject(phone._createError(_this.auth, "popup-closed-by-user" /* POPUP_CLOSED_BY_USER */));
1653 }, 2000 /* AUTH_EVENT */);
1654 return;
1655 }
1656 _this.pollId = window.setTimeout(poll, _POLL_WINDOW_CLOSE_TIMEOUT.get());
1657 };
1658 poll();
1659 };
1660 // Only one popup is ever shown at once. The lifecycle of the current popup
1661 // can be managed / cancelled by the constructor.
1662 PopupOperation.currentPopupAction = null;
1663 return PopupOperation;
1664}(AbstractPopupRedirectOperation));
1665
1666/**
1667 * @license
1668 * Copyright 2020 Google LLC
1669 *
1670 * Licensed under the Apache License, Version 2.0 (the "License");
1671 * you may not use this file except in compliance with the License.
1672 * You may obtain a copy of the License at
1673 *
1674 * http://www.apache.org/licenses/LICENSE-2.0
1675 *
1676 * Unless required by applicable law or agreed to in writing, software
1677 * distributed under the License is distributed on an "AS IS" BASIS,
1678 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1679 * See the License for the specific language governing permissions and
1680 * limitations under the License.
1681 */
1682var PENDING_REDIRECT_KEY = 'pendingRedirect';
1683// We only get one redirect outcome for any one auth, so just store it
1684// in here.
1685var redirectOutcomeMap = new Map();
1686var RedirectAction = /** @class */ (function (_super) {
1687 tslib.__extends(RedirectAction, _super);
1688 function RedirectAction(auth, resolver, bypassAuthState) {
1689 if (bypassAuthState === void 0) { bypassAuthState = false; }
1690 var _this = _super.call(this, auth, [
1691 "signInViaRedirect" /* SIGN_IN_VIA_REDIRECT */,
1692 "linkViaRedirect" /* LINK_VIA_REDIRECT */,
1693 "reauthViaRedirect" /* REAUTH_VIA_REDIRECT */,
1694 "unknown" /* UNKNOWN */
1695 ], resolver, undefined, bypassAuthState) || this;
1696 _this.eventId = null;
1697 return _this;
1698 }
1699 /**
1700 * Override the execute function; if we already have a redirect result, then
1701 * just return it.
1702 */
1703 RedirectAction.prototype.execute = function () {
1704 return tslib.__awaiter(this, void 0, void 0, function () {
1705 var readyOutcome, hasPendingRedirect, result_1, _a, e_1;
1706 return tslib.__generator(this, function (_b) {
1707 switch (_b.label) {
1708 case 0:
1709 readyOutcome = redirectOutcomeMap.get(this.auth._key());
1710 if (!!readyOutcome) return [3 /*break*/, 8];
1711 _b.label = 1;
1712 case 1:
1713 _b.trys.push([1, 6, , 7]);
1714 return [4 /*yield*/, _getAndClearPendingRedirectStatus(this.resolver, this.auth)];
1715 case 2:
1716 hasPendingRedirect = _b.sent();
1717 if (!hasPendingRedirect) return [3 /*break*/, 4];
1718 return [4 /*yield*/, _super.prototype.execute.call(this)];
1719 case 3:
1720 _a = _b.sent();
1721 return [3 /*break*/, 5];
1722 case 4:
1723 _a = null;
1724 _b.label = 5;
1725 case 5:
1726 result_1 = _a;
1727 readyOutcome = function () { return Promise.resolve(result_1); };
1728 return [3 /*break*/, 7];
1729 case 6:
1730 e_1 = _b.sent();
1731 readyOutcome = function () { return Promise.reject(e_1); };
1732 return [3 /*break*/, 7];
1733 case 7:
1734 redirectOutcomeMap.set(this.auth._key(), readyOutcome);
1735 _b.label = 8;
1736 case 8:
1737 // If we're not bypassing auth state, the ready outcome should be set to
1738 // null.
1739 if (!this.bypassAuthState) {
1740 redirectOutcomeMap.set(this.auth._key(), function () { return Promise.resolve(null); });
1741 }
1742 return [2 /*return*/, readyOutcome()];
1743 }
1744 });
1745 });
1746 };
1747 RedirectAction.prototype.onAuthEvent = function (event) {
1748 return tslib.__awaiter(this, void 0, void 0, function () {
1749 var user;
1750 return tslib.__generator(this, function (_a) {
1751 switch (_a.label) {
1752 case 0:
1753 if (event.type === "signInViaRedirect" /* SIGN_IN_VIA_REDIRECT */) {
1754 return [2 /*return*/, _super.prototype.onAuthEvent.call(this, event)];
1755 }
1756 else if (event.type === "unknown" /* UNKNOWN */) {
1757 // This is a sentinel value indicating there's no pending redirect
1758 this.resolve(null);
1759 return [2 /*return*/];
1760 }
1761 if (!event.eventId) return [3 /*break*/, 2];
1762 return [4 /*yield*/, this.auth._redirectUserForId(event.eventId)];
1763 case 1:
1764 user = _a.sent();
1765 if (user) {
1766 this.user = user;
1767 return [2 /*return*/, _super.prototype.onAuthEvent.call(this, event)];
1768 }
1769 else {
1770 this.resolve(null);
1771 }
1772 _a.label = 2;
1773 case 2: return [2 /*return*/];
1774 }
1775 });
1776 });
1777 };
1778 RedirectAction.prototype.onExecution = function () {
1779 return tslib.__awaiter(this, void 0, void 0, function () { return tslib.__generator(this, function (_a) {
1780 return [2 /*return*/];
1781 }); });
1782 };
1783 RedirectAction.prototype.cleanUp = function () { };
1784 return RedirectAction;
1785}(AbstractPopupRedirectOperation));
1786function _getAndClearPendingRedirectStatus(resolver, auth) {
1787 return tslib.__awaiter(this, void 0, void 0, function () {
1788 var key, persistence, hasPendingRedirect;
1789 return tslib.__generator(this, function (_a) {
1790 switch (_a.label) {
1791 case 0:
1792 key = pendingRedirectKey(auth);
1793 persistence = resolverPersistence(resolver);
1794 return [4 /*yield*/, persistence._isAvailable()];
1795 case 1:
1796 if (!(_a.sent())) {
1797 return [2 /*return*/, false];
1798 }
1799 return [4 /*yield*/, persistence._get(key)];
1800 case 2:
1801 hasPendingRedirect = (_a.sent()) === 'true';
1802 return [4 /*yield*/, persistence._remove(key)];
1803 case 3:
1804 _a.sent();
1805 return [2 /*return*/, hasPendingRedirect];
1806 }
1807 });
1808 });
1809}
1810function _setPendingRedirectStatus(resolver, auth) {
1811 return tslib.__awaiter(this, void 0, void 0, function () {
1812 return tslib.__generator(this, function (_a) {
1813 return [2 /*return*/, resolverPersistence(resolver)._set(pendingRedirectKey(auth), 'true')];
1814 });
1815 });
1816}
1817function _clearRedirectOutcomes() {
1818 redirectOutcomeMap.clear();
1819}
1820function _overrideRedirectResult(auth, result) {
1821 redirectOutcomeMap.set(auth._key(), result);
1822}
1823function resolverPersistence(resolver) {
1824 return phone._getInstance(resolver._redirectPersistence);
1825}
1826function pendingRedirectKey(auth) {
1827 return phone._persistenceKeyName(PENDING_REDIRECT_KEY, auth.config.apiKey, auth.name);
1828}
1829
1830/**
1831 * @license
1832 * Copyright 2020 Google LLC
1833 *
1834 * Licensed under the Apache License, Version 2.0 (the "License");
1835 * you may not use this file except in compliance with the License.
1836 * You may obtain a copy of the License at
1837 *
1838 * http://www.apache.org/licenses/LICENSE-2.0
1839 *
1840 * Unless required by applicable law or agreed to in writing, software
1841 * distributed under the License is distributed on an "AS IS" BASIS,
1842 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1843 * See the License for the specific language governing permissions and
1844 * limitations under the License.
1845 */
1846/**
1847 * Authenticates a Firebase client using a full-page redirect flow.
1848 *
1849 * @remarks
1850 * To handle the results and errors for this operation, refer to {@link getRedirectResult}.
1851 *
1852 * @example
1853 * ```javascript
1854 * // Sign in using a redirect.
1855 * const provider = new FacebookAuthProvider();
1856 * // You can add additional scopes to the provider:
1857 * provider.addScope('user_birthday');
1858 * // Start a sign in process for an unauthenticated user.
1859 * await signInWithRedirect(auth, provider);
1860 * // This will trigger a full page redirect away from your app
1861 *
1862 * // After returning from the redirect when your app initializes you can obtain the result
1863 * const result = await getRedirectResult(auth);
1864 * if (result) {
1865 * // This is the signed-in user
1866 * const user = result.user;
1867 * // This gives you a Facebook Access Token.
1868 * const credential = provider.credentialFromResult(auth, result);
1869 * const token = credential.accessToken;
1870 * }
1871 * // As this API can be used for sign-in, linking and reauthentication,
1872 * // check the operationType to determine what triggered this redirect
1873 * // operation.
1874 * const operationType = result.operationType;
1875 * ```
1876 *
1877 * @param auth - The {@link Auth} instance.
1878 * @param provider - The provider to authenticate. The provider has to be an {@link OAuthProvider}.
1879 * Non-OAuth providers like {@link EmailAuthProvider} will throw an error.
1880 * @param resolver - An instance of {@link PopupRedirectResolver}, optional
1881 * if already supplied to {@link initializeAuth} or provided by {@link getAuth}.
1882 *
1883 * @public
1884 */
1885function signInWithRedirect(auth, provider, resolver) {
1886 return _signInWithRedirect(auth, provider, resolver);
1887}
1888function _signInWithRedirect(auth, provider, resolver) {
1889 return tslib.__awaiter(this, void 0, void 0, function () {
1890 var authInternal, resolverInternal;
1891 return tslib.__generator(this, function (_a) {
1892 switch (_a.label) {
1893 case 0:
1894 authInternal = phone._castAuth(auth);
1895 phone._assertInstanceOf(auth, provider, phone.FederatedAuthProvider);
1896 resolverInternal = _withDefaultResolver(authInternal, resolver);
1897 return [4 /*yield*/, _setPendingRedirectStatus(resolverInternal, authInternal)];
1898 case 1:
1899 _a.sent();
1900 return [2 /*return*/, resolverInternal._openRedirect(authInternal, provider, "signInViaRedirect" /* SIGN_IN_VIA_REDIRECT */)];
1901 }
1902 });
1903 });
1904}
1905/**
1906 * Reauthenticates the current user with the specified {@link OAuthProvider} using a full-page redirect flow.
1907 *
1908 * @example
1909 * ```javascript
1910 * // Sign in using a redirect.
1911 * const provider = new FacebookAuthProvider();
1912 * const result = await signInWithRedirect(auth, provider);
1913 * // This will trigger a full page redirect away from your app
1914 *
1915 * // After returning from the redirect when your app initializes you can obtain the result
1916 * const result = await getRedirectResult(auth);
1917 * // Link using a redirect.
1918 * await linkWithRedirect(result.user, provider);
1919 * // This will again trigger a full page redirect away from your app
1920 *
1921 * // After returning from the redirect when your app initializes you can obtain the result
1922 * const result = await getRedirectResult(auth);
1923 * ```
1924 *
1925 * @param user - The user.
1926 * @param provider - The provider to authenticate. The provider has to be an {@link OAuthProvider}.
1927 * Non-OAuth providers like {@link EmailAuthProvider} will throw an error.
1928 * @param resolver - An instance of {@link PopupRedirectResolver}, optional
1929 * if already supplied to {@link initializeAuth} or provided by {@link getAuth}.
1930 *
1931 * @public
1932 */
1933function reauthenticateWithRedirect(user, provider, resolver) {
1934 return _reauthenticateWithRedirect(user, provider, resolver);
1935}
1936function _reauthenticateWithRedirect(user, provider, resolver) {
1937 return tslib.__awaiter(this, void 0, void 0, function () {
1938 var userInternal, resolverInternal, eventId;
1939 return tslib.__generator(this, function (_a) {
1940 switch (_a.label) {
1941 case 0:
1942 userInternal = util.getModularInstance(user);
1943 phone._assertInstanceOf(userInternal.auth, provider, phone.FederatedAuthProvider);
1944 resolverInternal = _withDefaultResolver(userInternal.auth, resolver);
1945 return [4 /*yield*/, _setPendingRedirectStatus(resolverInternal, userInternal.auth)];
1946 case 1:
1947 _a.sent();
1948 return [4 /*yield*/, prepareUserForRedirect(userInternal)];
1949 case 2:
1950 eventId = _a.sent();
1951 return [2 /*return*/, resolverInternal._openRedirect(userInternal.auth, provider, "reauthViaRedirect" /* REAUTH_VIA_REDIRECT */, eventId)];
1952 }
1953 });
1954 });
1955}
1956/**
1957 * Links the {@link OAuthProvider} to the user account using a full-page redirect flow.
1958 *
1959 * @example
1960 * ```javascript
1961 * // Sign in using some other provider.
1962 * const result = await signInWithEmailAndPassword(auth, email, password);
1963 * // Link using a redirect.
1964 * const provider = new FacebookAuthProvider();
1965 * await linkWithRedirect(result.user, provider);
1966 * // This will trigger a full page redirect away from your app
1967 *
1968 * // After returning from the redirect when your app initializes you can obtain the result
1969 * const result = await getRedirectResult(auth);
1970 * ```
1971 *
1972 * @param user - The user.
1973 * @param provider - The provider to authenticate. The provider has to be an {@link OAuthProvider}.
1974 * Non-OAuth providers like {@link EmailAuthProvider} will throw an error.
1975 * @param resolver - An instance of {@link PopupRedirectResolver}, optional
1976 * if already supplied to {@link initializeAuth} or provided by {@link getAuth}.
1977 *
1978 *
1979 * @public
1980 */
1981function linkWithRedirect(user, provider, resolver) {
1982 return _linkWithRedirect(user, provider, resolver);
1983}
1984function _linkWithRedirect(user, provider, resolver) {
1985 return tslib.__awaiter(this, void 0, void 0, function () {
1986 var userInternal, resolverInternal, eventId;
1987 return tslib.__generator(this, function (_a) {
1988 switch (_a.label) {
1989 case 0:
1990 userInternal = util.getModularInstance(user);
1991 phone._assertInstanceOf(userInternal.auth, provider, phone.FederatedAuthProvider);
1992 resolverInternal = _withDefaultResolver(userInternal.auth, resolver);
1993 return [4 /*yield*/, phone._assertLinkedStatus(false, userInternal, provider.providerId)];
1994 case 1:
1995 _a.sent();
1996 return [4 /*yield*/, _setPendingRedirectStatus(resolverInternal, userInternal.auth)];
1997 case 2:
1998 _a.sent();
1999 return [4 /*yield*/, prepareUserForRedirect(userInternal)];
2000 case 3:
2001 eventId = _a.sent();
2002 return [2 /*return*/, resolverInternal._openRedirect(userInternal.auth, provider, "linkViaRedirect" /* LINK_VIA_REDIRECT */, eventId)];
2003 }
2004 });
2005 });
2006}
2007/**
2008 * Returns a {@link UserCredential} from the redirect-based sign-in flow.
2009 *
2010 * @remarks
2011 * If sign-in succeeded, returns the signed in user. If sign-in was unsuccessful, fails with an
2012 * error. If no redirect operation was called, returns a {@link UserCredential}
2013 * with a null `user`.
2014 *
2015 * @example
2016 * ```javascript
2017 * // Sign in using a redirect.
2018 * const provider = new FacebookAuthProvider();
2019 * // You can add additional scopes to the provider:
2020 * provider.addScope('user_birthday');
2021 * // Start a sign in process for an unauthenticated user.
2022 * await signInWithRedirect(auth, provider);
2023 * // This will trigger a full page redirect away from your app
2024 *
2025 * // After returning from the redirect when your app initializes you can obtain the result
2026 * const result = await getRedirectResult(auth);
2027 * if (result) {
2028 * // This is the signed-in user
2029 * const user = result.user;
2030 * // This gives you a Facebook Access Token.
2031 * const credential = provider.credentialFromResult(auth, result);
2032 * const token = credential.accessToken;
2033 * }
2034 * // As this API can be used for sign-in, linking and reauthentication,
2035 * // check the operationType to determine what triggered this redirect
2036 * // operation.
2037 * const operationType = result.operationType;
2038 * ```
2039 *
2040 * @param auth - The {@link Auth} instance.
2041 * @param resolver - An instance of {@link PopupRedirectResolver}, optional
2042 * if already supplied to {@link initializeAuth} or provided by {@link getAuth}.
2043 *
2044 * @public
2045 */
2046function getRedirectResult(auth, resolver) {
2047 return tslib.__awaiter(this, void 0, void 0, function () {
2048 return tslib.__generator(this, function (_a) {
2049 switch (_a.label) {
2050 case 0: return [4 /*yield*/, phone._castAuth(auth)._initializationPromise];
2051 case 1:
2052 _a.sent();
2053 return [2 /*return*/, _getRedirectResult(auth, resolver, false)];
2054 }
2055 });
2056 });
2057}
2058function _getRedirectResult(auth, resolverExtern, bypassAuthState) {
2059 if (bypassAuthState === void 0) { bypassAuthState = false; }
2060 return tslib.__awaiter(this, void 0, void 0, function () {
2061 var authInternal, resolver, action, result;
2062 return tslib.__generator(this, function (_a) {
2063 switch (_a.label) {
2064 case 0:
2065 authInternal = phone._castAuth(auth);
2066 resolver = _withDefaultResolver(authInternal, resolverExtern);
2067 action = new RedirectAction(authInternal, resolver, bypassAuthState);
2068 return [4 /*yield*/, action.execute()];
2069 case 1:
2070 result = _a.sent();
2071 if (!(result && !bypassAuthState)) return [3 /*break*/, 4];
2072 delete result.user._redirectEventId;
2073 return [4 /*yield*/, authInternal._persistUserIfCurrent(result.user)];
2074 case 2:
2075 _a.sent();
2076 return [4 /*yield*/, authInternal._setRedirectUser(null, resolverExtern)];
2077 case 3:
2078 _a.sent();
2079 _a.label = 4;
2080 case 4: return [2 /*return*/, result];
2081 }
2082 });
2083 });
2084}
2085function prepareUserForRedirect(user) {
2086 return tslib.__awaiter(this, void 0, void 0, function () {
2087 var eventId;
2088 return tslib.__generator(this, function (_a) {
2089 switch (_a.label) {
2090 case 0:
2091 eventId = _generateEventId(user.uid + ":::");
2092 user._redirectEventId = eventId;
2093 return [4 /*yield*/, user.auth._setRedirectUser(user)];
2094 case 1:
2095 _a.sent();
2096 return [4 /*yield*/, user.auth._persistUserIfCurrent(user)];
2097 case 2:
2098 _a.sent();
2099 return [2 /*return*/, eventId];
2100 }
2101 });
2102 });
2103}
2104
2105/**
2106 * @license
2107 * Copyright 2020 Google LLC
2108 *
2109 * Licensed under the Apache License, Version 2.0 (the "License");
2110 * you may not use this file except in compliance with the License.
2111 * You may obtain a copy of the License at
2112 *
2113 * http://www.apache.org/licenses/LICENSE-2.0
2114 *
2115 * Unless required by applicable law or agreed to in writing, software
2116 * distributed under the License is distributed on an "AS IS" BASIS,
2117 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2118 * See the License for the specific language governing permissions and
2119 * limitations under the License.
2120 */
2121// The amount of time to store the UIDs of seen events; this is
2122// set to 10 min by default
2123var EVENT_DUPLICATION_CACHE_DURATION_MS = 10 * 60 * 1000;
2124var AuthEventManager = /** @class */ (function () {
2125 function AuthEventManager(auth) {
2126 this.auth = auth;
2127 this.cachedEventUids = new Set();
2128 this.consumers = new Set();
2129 this.queuedRedirectEvent = null;
2130 this.hasHandledPotentialRedirect = false;
2131 this.lastProcessedEventTime = Date.now();
2132 }
2133 AuthEventManager.prototype.registerConsumer = function (authEventConsumer) {
2134 this.consumers.add(authEventConsumer);
2135 if (this.queuedRedirectEvent &&
2136 this.isEventForConsumer(this.queuedRedirectEvent, authEventConsumer)) {
2137 this.sendToConsumer(this.queuedRedirectEvent, authEventConsumer);
2138 this.saveEventToCache(this.queuedRedirectEvent);
2139 this.queuedRedirectEvent = null;
2140 }
2141 };
2142 AuthEventManager.prototype.unregisterConsumer = function (authEventConsumer) {
2143 this.consumers.delete(authEventConsumer);
2144 };
2145 AuthEventManager.prototype.onEvent = function (event) {
2146 var _this = this;
2147 // Check if the event has already been handled
2148 if (this.hasEventBeenHandled(event)) {
2149 return false;
2150 }
2151 var handled = false;
2152 this.consumers.forEach(function (consumer) {
2153 if (_this.isEventForConsumer(event, consumer)) {
2154 handled = true;
2155 _this.sendToConsumer(event, consumer);
2156 _this.saveEventToCache(event);
2157 }
2158 });
2159 if (this.hasHandledPotentialRedirect || !isRedirectEvent(event)) {
2160 // If we've already seen a redirect before, or this is a popup event,
2161 // bail now
2162 return handled;
2163 }
2164 this.hasHandledPotentialRedirect = true;
2165 // If the redirect wasn't handled, hang on to it
2166 if (!handled) {
2167 this.queuedRedirectEvent = event;
2168 handled = true;
2169 }
2170 return handled;
2171 };
2172 AuthEventManager.prototype.sendToConsumer = function (event, consumer) {
2173 var _a;
2174 if (event.error && !isNullRedirectEvent(event)) {
2175 var code = ((_a = event.error.code) === null || _a === void 0 ? void 0 : _a.split('auth/')[1]) ||
2176 "internal-error" /* INTERNAL_ERROR */;
2177 consumer.onError(phone._createError(this.auth, code));
2178 }
2179 else {
2180 consumer.onAuthEvent(event);
2181 }
2182 };
2183 AuthEventManager.prototype.isEventForConsumer = function (event, consumer) {
2184 var eventIdMatches = consumer.eventId === null ||
2185 (!!event.eventId && event.eventId === consumer.eventId);
2186 return consumer.filter.includes(event.type) && eventIdMatches;
2187 };
2188 AuthEventManager.prototype.hasEventBeenHandled = function (event) {
2189 if (Date.now() - this.lastProcessedEventTime >=
2190 EVENT_DUPLICATION_CACHE_DURATION_MS) {
2191 this.cachedEventUids.clear();
2192 }
2193 return this.cachedEventUids.has(eventUid(event));
2194 };
2195 AuthEventManager.prototype.saveEventToCache = function (event) {
2196 this.cachedEventUids.add(eventUid(event));
2197 this.lastProcessedEventTime = Date.now();
2198 };
2199 return AuthEventManager;
2200}());
2201function eventUid(e) {
2202 return [e.type, e.eventId, e.sessionId, e.tenantId].filter(function (v) { return v; }).join('-');
2203}
2204function isNullRedirectEvent(_a) {
2205 var type = _a.type, error = _a.error;
2206 return (type === "unknown" /* UNKNOWN */ &&
2207 (error === null || error === void 0 ? void 0 : error.code) === "auth/" + "no-auth-event" /* NO_AUTH_EVENT */);
2208}
2209function isRedirectEvent(event) {
2210 switch (event.type) {
2211 case "signInViaRedirect" /* SIGN_IN_VIA_REDIRECT */:
2212 case "linkViaRedirect" /* LINK_VIA_REDIRECT */:
2213 case "reauthViaRedirect" /* REAUTH_VIA_REDIRECT */:
2214 return true;
2215 case "unknown" /* UNKNOWN */:
2216 return isNullRedirectEvent(event);
2217 default:
2218 return false;
2219 }
2220}
2221
2222/**
2223 * @license
2224 * Copyright 2020 Google LLC
2225 *
2226 * Licensed under the Apache License, Version 2.0 (the "License");
2227 * you may not use this file except in compliance with the License.
2228 * You may obtain a copy of the License at
2229 *
2230 * http://www.apache.org/licenses/LICENSE-2.0
2231 *
2232 * Unless required by applicable law or agreed to in writing, software
2233 * distributed under the License is distributed on an "AS IS" BASIS,
2234 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2235 * See the License for the specific language governing permissions and
2236 * limitations under the License.
2237 */
2238function _getProjectConfig(auth, request) {
2239 if (request === void 0) { request = {}; }
2240 return tslib.__awaiter(this, void 0, void 0, function () {
2241 return tslib.__generator(this, function (_a) {
2242 return [2 /*return*/, phone._performApiRequest(auth, "GET" /* GET */, "/v1/projects" /* GET_PROJECT_CONFIG */, request)];
2243 });
2244 });
2245}
2246
2247/**
2248 * @license
2249 * Copyright 2020 Google LLC
2250 *
2251 * Licensed under the Apache License, Version 2.0 (the "License");
2252 * you may not use this file except in compliance with the License.
2253 * You may obtain a copy of the License at
2254 *
2255 * http://www.apache.org/licenses/LICENSE-2.0
2256 *
2257 * Unless required by applicable law or agreed to in writing, software
2258 * distributed under the License is distributed on an "AS IS" BASIS,
2259 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2260 * See the License for the specific language governing permissions and
2261 * limitations under the License.
2262 */
2263var IP_ADDRESS_REGEX = /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/;
2264var HTTP_REGEX = /^https?/;
2265function _validateOrigin$1(auth) {
2266 return tslib.__awaiter(this, void 0, void 0, function () {
2267 var authorizedDomains, _i, authorizedDomains_1, domain;
2268 return tslib.__generator(this, function (_a) {
2269 switch (_a.label) {
2270 case 0:
2271 // Skip origin validation if we are in an emulated environment
2272 if (auth.config.emulator) {
2273 return [2 /*return*/];
2274 }
2275 return [4 /*yield*/, _getProjectConfig(auth)];
2276 case 1:
2277 authorizedDomains = (_a.sent()).authorizedDomains;
2278 for (_i = 0, authorizedDomains_1 = authorizedDomains; _i < authorizedDomains_1.length; _i++) {
2279 domain = authorizedDomains_1[_i];
2280 try {
2281 if (matchDomain(domain)) {
2282 return [2 /*return*/];
2283 }
2284 }
2285 catch (_b) {
2286 // Do nothing if there's a URL error; just continue searching
2287 }
2288 }
2289 // In the old SDK, this error also provides helpful messages.
2290 phone._fail(auth, "unauthorized-domain" /* INVALID_ORIGIN */);
2291 return [2 /*return*/];
2292 }
2293 });
2294 });
2295}
2296function matchDomain(expected) {
2297 var currentUrl = phone._getCurrentUrl();
2298 var _a = new URL(currentUrl), protocol = _a.protocol, hostname = _a.hostname;
2299 if (expected.startsWith('chrome-extension://')) {
2300 var ceUrl = new URL(expected);
2301 if (ceUrl.hostname === '' && hostname === '') {
2302 // For some reason we're not parsing chrome URLs properly
2303 return (protocol === 'chrome-extension:' &&
2304 expected.replace('chrome-extension://', '') ===
2305 currentUrl.replace('chrome-extension://', ''));
2306 }
2307 return protocol === 'chrome-extension:' && ceUrl.hostname === hostname;
2308 }
2309 if (!HTTP_REGEX.test(protocol)) {
2310 return false;
2311 }
2312 if (IP_ADDRESS_REGEX.test(expected)) {
2313 // The domain has to be exactly equal to the pattern, as an IP domain will
2314 // only contain the IP, no extra character.
2315 return hostname === expected;
2316 }
2317 // Dots in pattern should be escaped.
2318 var escapedDomainPattern = expected.replace(/\./g, '\\.');
2319 // Non ip address domains.
2320 // domain.com = *.domain.com OR domain.com
2321 var re = new RegExp('^(.+\\.' + escapedDomainPattern + '|' + escapedDomainPattern + ')$', 'i');
2322 return re.test(hostname);
2323}
2324
2325/**
2326 * @license
2327 * Copyright 2020 Google LLC.
2328 *
2329 * Licensed under the Apache License, Version 2.0 (the "License");
2330 * you may not use this file except in compliance with the License.
2331 * You may obtain a copy of the License at
2332 *
2333 * http://www.apache.org/licenses/LICENSE-2.0
2334 *
2335 * Unless required by applicable law or agreed to in writing, software
2336 * distributed under the License is distributed on an "AS IS" BASIS,
2337 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2338 * See the License for the specific language governing permissions and
2339 * limitations under the License.
2340 */
2341var NETWORK_TIMEOUT = new phone.Delay(30000, 60000);
2342/**
2343 * Reset unlaoded GApi modules. If gapi.load fails due to a network error,
2344 * it will stop working after a retrial. This is a hack to fix this issue.
2345 */
2346function resetUnloadedGapiModules() {
2347 // Clear last failed gapi.load state to force next gapi.load to first
2348 // load the failed gapi.iframes module.
2349 // Get gapix.beacon context.
2350 var beacon = phone._window().___jsl;
2351 // Get current hint.
2352 if (beacon === null || beacon === void 0 ? void 0 : beacon.H) {
2353 // Get gapi hint.
2354 for (var _i = 0, _a = Object.keys(beacon.H); _i < _a.length; _i++) {
2355 var hint = _a[_i];
2356 // Requested modules.
2357 beacon.H[hint].r = beacon.H[hint].r || [];
2358 // Loaded modules.
2359 beacon.H[hint].L = beacon.H[hint].L || [];
2360 // Set requested modules to a copy of the loaded modules.
2361 beacon.H[hint].r = tslib.__spreadArray([], beacon.H[hint].L);
2362 // Clear pending callbacks.
2363 if (beacon.CP) {
2364 for (var i = 0; i < beacon.CP.length; i++) {
2365 // Remove all failed pending callbacks.
2366 beacon.CP[i] = null;
2367 }
2368 }
2369 }
2370 }
2371}
2372function loadGapi(auth) {
2373 return new Promise(function (resolve, reject) {
2374 var _a, _b, _c;
2375 // Function to run when gapi.load is ready.
2376 function loadGapiIframe() {
2377 // The developer may have tried to previously run gapi.load and failed.
2378 // Run this to fix that.
2379 resetUnloadedGapiModules();
2380 gapi.load('gapi.iframes', {
2381 callback: function () {
2382 resolve(gapi.iframes.getContext());
2383 },
2384 ontimeout: function () {
2385 // The above reset may be sufficient, but having this reset after
2386 // failure ensures that if the developer calls gapi.load after the
2387 // connection is re-established and before another attempt to embed
2388 // the iframe, it would work and would not be broken because of our
2389 // failed attempt.
2390 // Timeout when gapi.iframes.Iframe not loaded.
2391 resetUnloadedGapiModules();
2392 reject(phone._createError(auth, "network-request-failed" /* NETWORK_REQUEST_FAILED */));
2393 },
2394 timeout: NETWORK_TIMEOUT.get()
2395 });
2396 }
2397 if ((_b = (_a = phone._window().gapi) === null || _a === void 0 ? void 0 : _a.iframes) === null || _b === void 0 ? void 0 : _b.Iframe) {
2398 // If gapi.iframes.Iframe available, resolve.
2399 resolve(gapi.iframes.getContext());
2400 }
2401 else if (!!((_c = phone._window().gapi) === null || _c === void 0 ? void 0 : _c.load)) {
2402 // Gapi loader ready, load gapi.iframes.
2403 loadGapiIframe();
2404 }
2405 else {
2406 // Create a new iframe callback when this is called so as not to overwrite
2407 // any previous defined callback. This happens if this method is called
2408 // multiple times in parallel and could result in the later callback
2409 // overwriting the previous one. This would end up with a iframe
2410 // timeout.
2411 var cbName = phone._generateCallbackName('iframefcb');
2412 // GApi loader not available, dynamically load platform.js.
2413 phone._window()[cbName] = function () {
2414 // GApi loader should be ready.
2415 if (!!gapi.load) {
2416 loadGapiIframe();
2417 }
2418 else {
2419 // Gapi loader failed, throw error.
2420 reject(phone._createError(auth, "network-request-failed" /* NETWORK_REQUEST_FAILED */));
2421 }
2422 };
2423 // Load GApi loader.
2424 return phone._loadJS("https://apis.google.com/js/api.js?onload=" + cbName).catch(function (e) { return reject(e); });
2425 }
2426 }).catch(function (error) {
2427 // Reset cached promise to allow for retrial.
2428 cachedGApiLoader = null;
2429 throw error;
2430 });
2431}
2432var cachedGApiLoader = null;
2433function _loadGapi(auth) {
2434 cachedGApiLoader = cachedGApiLoader || loadGapi(auth);
2435 return cachedGApiLoader;
2436}
2437
2438/**
2439 * @license
2440 * Copyright 2020 Google LLC.
2441 *
2442 * Licensed under the Apache License, Version 2.0 (the "License");
2443 * you may not use this file except in compliance with the License.
2444 * You may obtain a copy of the License at
2445 *
2446 * http://www.apache.org/licenses/LICENSE-2.0
2447 *
2448 * Unless required by applicable law or agreed to in writing, software
2449 * distributed under the License is distributed on an "AS IS" BASIS,
2450 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2451 * See the License for the specific language governing permissions and
2452 * limitations under the License.
2453 */
2454var PING_TIMEOUT = new phone.Delay(5000, 15000);
2455var IFRAME_PATH = '__/auth/iframe';
2456var EMULATED_IFRAME_PATH = 'emulator/auth/iframe';
2457var IFRAME_ATTRIBUTES = {
2458 style: {
2459 position: 'absolute',
2460 top: '-100px',
2461 width: '1px',
2462 height: '1px'
2463 },
2464 'aria-hidden': 'true',
2465 tabindex: '-1'
2466};
2467// Map from apiHost to endpoint ID for passing into iframe. In current SDK, apiHost can be set to
2468// anything (not from a list of endpoints with IDs as in legacy), so this is the closest we can get.
2469var EID_FROM_APIHOST = new Map([
2470 ["identitytoolkit.googleapis.com" /* API_HOST */, 'p'],
2471 ['staging-identitytoolkit.sandbox.googleapis.com', 's'],
2472 ['test-identitytoolkit.sandbox.googleapis.com', 't'] // test
2473]);
2474function getIframeUrl(auth) {
2475 var config = auth.config;
2476 phone._assert(config.authDomain, auth, "auth-domain-config-required" /* MISSING_AUTH_DOMAIN */);
2477 var url = config.emulator
2478 ? phone._emulatorUrl(config, EMULATED_IFRAME_PATH)
2479 : "https://" + auth.config.authDomain + "/" + IFRAME_PATH;
2480 var params = {
2481 apiKey: config.apiKey,
2482 appName: auth.name,
2483 v: app.SDK_VERSION
2484 };
2485 var eid = EID_FROM_APIHOST.get(auth.config.apiHost);
2486 if (eid) {
2487 params.eid = eid;
2488 }
2489 var frameworks = auth._getFrameworks();
2490 if (frameworks.length) {
2491 params.fw = frameworks.join(',');
2492 }
2493 return url + "?" + util.querystring(params).slice(1);
2494}
2495function _openIframe(auth) {
2496 return tslib.__awaiter(this, void 0, void 0, function () {
2497 var context, gapi;
2498 var _this = this;
2499 return tslib.__generator(this, function (_a) {
2500 switch (_a.label) {
2501 case 0: return [4 /*yield*/, _loadGapi(auth)];
2502 case 1:
2503 context = _a.sent();
2504 gapi = phone._window().gapi;
2505 phone._assert(gapi, auth, "internal-error" /* INTERNAL_ERROR */);
2506 return [2 /*return*/, context.open({
2507 where: document.body,
2508 url: getIframeUrl(auth),
2509 messageHandlersFilter: gapi.iframes.CROSS_ORIGIN_IFRAMES_FILTER,
2510 attributes: IFRAME_ATTRIBUTES,
2511 dontclear: true
2512 }, function (iframe) {
2513 return new Promise(function (resolve, reject) { return tslib.__awaiter(_this, void 0, void 0, function () {
2514 // Clear timer and resolve pending iframe ready promise.
2515 function clearTimerAndResolve() {
2516 phone._window().clearTimeout(networkErrorTimer);
2517 resolve(iframe);
2518 }
2519 var networkError, networkErrorTimer;
2520 return tslib.__generator(this, function (_a) {
2521 switch (_a.label) {
2522 case 0: return [4 /*yield*/, iframe.restyle({
2523 // Prevent iframe from closing on mouse out.
2524 setHideOnLeave: false
2525 })];
2526 case 1:
2527 _a.sent();
2528 networkError = phone._createError(auth, "network-request-failed" /* NETWORK_REQUEST_FAILED */);
2529 networkErrorTimer = phone._window().setTimeout(function () {
2530 reject(networkError);
2531 }, PING_TIMEOUT.get());
2532 // This returns an IThenable. However the reject part does not call
2533 // when the iframe is not loaded.
2534 iframe.ping(clearTimerAndResolve).then(clearTimerAndResolve, function () {
2535 reject(networkError);
2536 });
2537 return [2 /*return*/];
2538 }
2539 });
2540 }); });
2541 })];
2542 }
2543 });
2544 });
2545}
2546
2547/**
2548 * @license
2549 * Copyright 2020 Google LLC.
2550 *
2551 * Licensed under the Apache License, Version 2.0 (the "License");
2552 * you may not use this file except in compliance with the License.
2553 * You may obtain a copy of the License at
2554 *
2555 * http://www.apache.org/licenses/LICENSE-2.0
2556 *
2557 * Unless required by applicable law or agreed to in writing, software
2558 * distributed under the License is distributed on an "AS IS" BASIS,
2559 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2560 * See the License for the specific language governing permissions and
2561 * limitations under the License.
2562 */
2563var BASE_POPUP_OPTIONS = {
2564 location: 'yes',
2565 resizable: 'yes',
2566 statusbar: 'yes',
2567 toolbar: 'no'
2568};
2569var DEFAULT_WIDTH = 500;
2570var DEFAULT_HEIGHT = 600;
2571var TARGET_BLANK = '_blank';
2572var FIREFOX_EMPTY_URL = 'http://localhost';
2573var AuthPopup = /** @class */ (function () {
2574 function AuthPopup(window) {
2575 this.window = window;
2576 this.associatedEvent = null;
2577 }
2578 AuthPopup.prototype.close = function () {
2579 if (this.window) {
2580 try {
2581 this.window.close();
2582 }
2583 catch (e) { }
2584 }
2585 };
2586 return AuthPopup;
2587}());
2588function _open(auth, url, name, width, height) {
2589 if (width === void 0) { width = DEFAULT_WIDTH; }
2590 if (height === void 0) { height = DEFAULT_HEIGHT; }
2591 var top = Math.max((window.screen.availHeight - height) / 2, 0).toString();
2592 var left = Math.max((window.screen.availWidth - width) / 2, 0).toString();
2593 var target = '';
2594 var options = tslib.__assign(tslib.__assign({}, BASE_POPUP_OPTIONS), { width: width.toString(), height: height.toString(), top: top,
2595 left: left });
2596 // Chrome iOS 7 and 8 is returning an undefined popup win when target is
2597 // specified, even though the popup is not necessarily blocked.
2598 var ua = util.getUA().toLowerCase();
2599 if (name) {
2600 target = phone._isChromeIOS(ua) ? TARGET_BLANK : name;
2601 }
2602 if (phone._isFirefox(ua)) {
2603 // Firefox complains when invalid URLs are popped out. Hacky way to bypass.
2604 url = url || FIREFOX_EMPTY_URL;
2605 // Firefox disables by default scrolling on popup windows, which can create
2606 // issues when the user has many Google accounts, for instance.
2607 options.scrollbars = 'yes';
2608 }
2609 var optionsString = Object.entries(options).reduce(function (accum, _a) {
2610 var key = _a[0], value = _a[1];
2611 return "" + accum + key + "=" + value + ",";
2612 }, '');
2613 if (phone._isIOSStandalone(ua) && target !== '_self') {
2614 openAsNewWindowIOS(url || '', target);
2615 return new AuthPopup(null);
2616 }
2617 // about:blank getting sanitized causing browsers like IE/Edge to display
2618 // brief error message before redirecting to handler.
2619 var newWin = window.open(url || '', target, optionsString);
2620 phone._assert(newWin, auth, "popup-blocked" /* POPUP_BLOCKED */);
2621 // Flaky on IE edge, encapsulate with a try and catch.
2622 try {
2623 newWin.focus();
2624 }
2625 catch (e) { }
2626 return new AuthPopup(newWin);
2627}
2628function openAsNewWindowIOS(url, target) {
2629 var el = document.createElement('a');
2630 el.href = url;
2631 el.target = target;
2632 var click = document.createEvent('MouseEvent');
2633 click.initMouseEvent('click', true, true, window, 1, 0, 0, 0, 0, false, false, false, false, 1, null);
2634 el.dispatchEvent(click);
2635}
2636
2637/**
2638 * @license
2639 * Copyright 2021 Google LLC
2640 *
2641 * Licensed under the Apache License, Version 2.0 (the "License");
2642 * you may not use this file except in compliance with the License.
2643 * You may obtain a copy of the License at
2644 *
2645 * http://www.apache.org/licenses/LICENSE-2.0
2646 *
2647 * Unless required by applicable law or agreed to in writing, software
2648 * distributed under the License is distributed on an "AS IS" BASIS,
2649 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2650 * See the License for the specific language governing permissions and
2651 * limitations under the License.
2652 */
2653/**
2654 * URL for Authentication widget which will initiate the OAuth handshake
2655 *
2656 * @internal
2657 */
2658var WIDGET_PATH = '__/auth/handler';
2659/**
2660 * URL for emulated environment
2661 *
2662 * @internal
2663 */
2664var EMULATOR_WIDGET_PATH = 'emulator/auth/handler';
2665function _getRedirectUrl(auth, provider, authType, redirectUrl, eventId, additionalParams) {
2666 phone._assert(auth.config.authDomain, auth, "auth-domain-config-required" /* MISSING_AUTH_DOMAIN */);
2667 phone._assert(auth.config.apiKey, auth, "invalid-api-key" /* INVALID_API_KEY */);
2668 var params = {
2669 apiKey: auth.config.apiKey,
2670 appName: auth.name,
2671 authType: authType,
2672 redirectUrl: redirectUrl,
2673 v: app.SDK_VERSION,
2674 eventId: eventId
2675 };
2676 if (provider instanceof phone.FederatedAuthProvider) {
2677 provider.setDefaultLanguage(auth.languageCode);
2678 params.providerId = provider.providerId || '';
2679 if (!util.isEmpty(provider.getCustomParameters())) {
2680 params.customParameters = JSON.stringify(provider.getCustomParameters());
2681 }
2682 // TODO set additionalParams from the provider as well?
2683 for (var _i = 0, _a = Object.entries(additionalParams || {}); _i < _a.length; _i++) {
2684 var _b = _a[_i], key = _b[0], value = _b[1];
2685 params[key] = value;
2686 }
2687 }
2688 if (provider instanceof phone.BaseOAuthProvider) {
2689 var scopes = provider.getScopes().filter(function (scope) { return scope !== ''; });
2690 if (scopes.length > 0) {
2691 params.scopes = scopes.join(',');
2692 }
2693 }
2694 if (auth.tenantId) {
2695 params.tid = auth.tenantId;
2696 }
2697 // TODO: maybe set eid as endipointId
2698 // TODO: maybe set fw as Frameworks.join(",")
2699 var paramsDict = params;
2700 for (var _c = 0, _d = Object.keys(paramsDict); _c < _d.length; _c++) {
2701 var key = _d[_c];
2702 if (paramsDict[key] === undefined) {
2703 delete paramsDict[key];
2704 }
2705 }
2706 return getHandlerBase(auth) + "?" + util.querystring(paramsDict).slice(1);
2707}
2708function getHandlerBase(_a) {
2709 var config = _a.config;
2710 if (!config.emulator) {
2711 return "https://" + config.authDomain + "/" + WIDGET_PATH;
2712 }
2713 return phone._emulatorUrl(config, EMULATOR_WIDGET_PATH);
2714}
2715
2716/**
2717 * @license
2718 * Copyright 2020 Google LLC
2719 *
2720 * Licensed under the Apache License, Version 2.0 (the "License");
2721 * you may not use this file except in compliance with the License.
2722 * You may obtain a copy of the License at
2723 *
2724 * http://www.apache.org/licenses/LICENSE-2.0
2725 *
2726 * Unless required by applicable law or agreed to in writing, software
2727 * distributed under the License is distributed on an "AS IS" BASIS,
2728 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2729 * See the License for the specific language governing permissions and
2730 * limitations under the License.
2731 */
2732/**
2733 * The special web storage event
2734 *
2735 */
2736var WEB_STORAGE_SUPPORT_KEY = 'webStorageSupport';
2737var BrowserPopupRedirectResolver = /** @class */ (function () {
2738 function BrowserPopupRedirectResolver() {
2739 this.eventManagers = {};
2740 this.iframes = {};
2741 this.originValidationPromises = {};
2742 this._redirectPersistence = browserSessionPersistence;
2743 this._completeRedirectFn = _getRedirectResult;
2744 this._overrideRedirectResult = _overrideRedirectResult;
2745 }
2746 // Wrapping in async even though we don't await anywhere in order
2747 // to make sure errors are raised as promise rejections
2748 BrowserPopupRedirectResolver.prototype._openPopup = function (auth, provider, authType, eventId) {
2749 var _a;
2750 return tslib.__awaiter(this, void 0, void 0, function () {
2751 var url;
2752 return tslib.__generator(this, function (_b) {
2753 phone.debugAssert((_a = this.eventManagers[auth._key()]) === null || _a === void 0 ? void 0 : _a.manager, '_initialize() not called before _openPopup()');
2754 url = _getRedirectUrl(auth, provider, authType, phone._getCurrentUrl(), eventId);
2755 return [2 /*return*/, _open(auth, url, _generateEventId())];
2756 });
2757 });
2758 };
2759 BrowserPopupRedirectResolver.prototype._openRedirect = function (auth, provider, authType, eventId) {
2760 return tslib.__awaiter(this, void 0, void 0, function () {
2761 return tslib.__generator(this, function (_a) {
2762 switch (_a.label) {
2763 case 0: return [4 /*yield*/, this._originValidation(auth)];
2764 case 1:
2765 _a.sent();
2766 phone._setWindowLocation(_getRedirectUrl(auth, provider, authType, phone._getCurrentUrl(), eventId));
2767 return [2 /*return*/, new Promise(function () { })];
2768 }
2769 });
2770 });
2771 };
2772 BrowserPopupRedirectResolver.prototype._initialize = function (auth) {
2773 var _this = this;
2774 var key = auth._key();
2775 if (this.eventManagers[key]) {
2776 var _a = this.eventManagers[key], manager = _a.manager, promise_1 = _a.promise;
2777 if (manager) {
2778 return Promise.resolve(manager);
2779 }
2780 else {
2781 phone.debugAssert(promise_1, 'If manager is not set, promise should be');
2782 return promise_1;
2783 }
2784 }
2785 var promise = this.initAndGetManager(auth);
2786 this.eventManagers[key] = { promise: promise };
2787 // If the promise is rejected, the key should be removed so that the
2788 // operation can be retried later.
2789 promise.catch(function () {
2790 delete _this.eventManagers[key];
2791 });
2792 return promise;
2793 };
2794 BrowserPopupRedirectResolver.prototype.initAndGetManager = function (auth) {
2795 return tslib.__awaiter(this, void 0, void 0, function () {
2796 var iframe, manager;
2797 return tslib.__generator(this, function (_a) {
2798 switch (_a.label) {
2799 case 0: return [4 /*yield*/, _openIframe(auth)];
2800 case 1:
2801 iframe = _a.sent();
2802 manager = new AuthEventManager(auth);
2803 iframe.register('authEvent', function (iframeEvent) {
2804 phone._assert(iframeEvent === null || iframeEvent === void 0 ? void 0 : iframeEvent.authEvent, auth, "invalid-auth-event" /* INVALID_AUTH_EVENT */);
2805 // TODO: Consider splitting redirect and popup events earlier on
2806 var handled = manager.onEvent(iframeEvent.authEvent);
2807 return { status: handled ? "ACK" /* ACK */ : "ERROR" /* ERROR */ };
2808 }, gapi.iframes.CROSS_ORIGIN_IFRAMES_FILTER);
2809 this.eventManagers[auth._key()] = { manager: manager };
2810 this.iframes[auth._key()] = iframe;
2811 return [2 /*return*/, manager];
2812 }
2813 });
2814 });
2815 };
2816 BrowserPopupRedirectResolver.prototype._isIframeWebStorageSupported = function (auth, cb) {
2817 var iframe = this.iframes[auth._key()];
2818 iframe.send(WEB_STORAGE_SUPPORT_KEY, { type: WEB_STORAGE_SUPPORT_KEY }, function (result) {
2819 var _a;
2820 var isSupported = (_a = result === null || result === void 0 ? void 0 : result[0]) === null || _a === void 0 ? void 0 : _a[WEB_STORAGE_SUPPORT_KEY];
2821 if (isSupported !== undefined) {
2822 cb(!!isSupported);
2823 }
2824 phone._fail(auth, "internal-error" /* INTERNAL_ERROR */);
2825 }, gapi.iframes.CROSS_ORIGIN_IFRAMES_FILTER);
2826 };
2827 BrowserPopupRedirectResolver.prototype._originValidation = function (auth) {
2828 var key = auth._key();
2829 if (!this.originValidationPromises[key]) {
2830 this.originValidationPromises[key] = _validateOrigin$1(auth);
2831 }
2832 return this.originValidationPromises[key];
2833 };
2834 Object.defineProperty(BrowserPopupRedirectResolver.prototype, "_shouldInitProactively", {
2835 get: function () {
2836 // Mobile browsers and Safari need to optimistically initialize
2837 return phone._isMobileBrowser() || phone._isSafari() || phone._isIOS();
2838 },
2839 enumerable: false,
2840 configurable: true
2841 });
2842 return BrowserPopupRedirectResolver;
2843}());
2844/**
2845 * An implementation of {@link PopupRedirectResolver} suitable for browser
2846 * based applications.
2847 *
2848 * @public
2849 */
2850var browserPopupRedirectResolver = BrowserPopupRedirectResolver;
2851
2852/**
2853 * @license
2854 * Copyright 2021 Google LLC
2855 *
2856 * Licensed under the Apache License, Version 2.0 (the "License");
2857 * you may not use this file except in compliance with the License.
2858 * You may obtain a copy of the License at
2859 *
2860 * http://www.apache.org/licenses/LICENSE-2.0
2861 *
2862 * Unless required by applicable law or agreed to in writing, software
2863 * distributed under the License is distributed on an "AS IS" BASIS,
2864 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2865 * See the License for the specific language governing permissions and
2866 * limitations under the License.
2867 */
2868/**
2869 * Returns the Auth instance associated with the provided {@link @firebase/app#FirebaseApp}.
2870 * If no instance exists, initializes an Auth instance with platform-specific default dependencies.
2871 *
2872 * @param app - The Firebase App.
2873 *
2874 * @public
2875 */
2876function getAuth(app$1) {
2877 if (app$1 === void 0) { app$1 = app.getApp(); }
2878 var provider = app._getProvider(app$1, 'auth');
2879 if (provider.isInitialized()) {
2880 return provider.getImmediate();
2881 }
2882 return phone.initializeAuth(app$1, {
2883 popupRedirectResolver: browserPopupRedirectResolver,
2884 persistence: [
2885 indexedDBLocalPersistence,
2886 browserLocalPersistence,
2887 browserSessionPersistence
2888 ]
2889 });
2890}
2891phone.registerAuth("Browser" /* BROWSER */);
2892
2893/**
2894 * @license
2895 * Copyright 2021 Google LLC
2896 *
2897 * Licensed under the Apache License, Version 2.0 (the "License");
2898 * you may not use this file except in compliance with the License.
2899 * You may obtain a copy of the License at
2900 *
2901 * http://www.apache.org/licenses/LICENSE-2.0
2902 *
2903 * Unless required by applicable law or agreed to in writing, software
2904 * distributed under the License is distributed on an "AS IS" BASIS,
2905 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2906 * See the License for the specific language governing permissions and
2907 * limitations under the License.
2908 */
2909function _cordovaWindow() {
2910 return window;
2911}
2912
2913/**
2914 * @license
2915 * Copyright 2020 Google LLC
2916 *
2917 * Licensed under the Apache License, Version 2.0 (the "License");
2918 * you may not use this file except in compliance with the License.
2919 * You may obtain a copy of the License at
2920 *
2921 * http://www.apache.org/licenses/LICENSE-2.0
2922 *
2923 * Unless required by applicable law or agreed to in writing, software
2924 * distributed under the License is distributed on an "AS IS" BASIS,
2925 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2926 * See the License for the specific language governing permissions and
2927 * limitations under the License.
2928 */
2929/**
2930 * How long to wait after the app comes back into focus before concluding that
2931 * the user closed the sign in tab.
2932 */
2933var REDIRECT_TIMEOUT_MS = 2000;
2934/**
2935 * Generates the URL for the OAuth handler.
2936 */
2937function _generateHandlerUrl(auth, event, provider) {
2938 var _a;
2939 return tslib.__awaiter(this, void 0, void 0, function () {
2940 var BuildInfo, sessionDigest, additionalParams;
2941 return tslib.__generator(this, function (_b) {
2942 switch (_b.label) {
2943 case 0:
2944 BuildInfo = _cordovaWindow().BuildInfo;
2945 phone.debugAssert(event.sessionId, 'AuthEvent did not contain a session ID');
2946 return [4 /*yield*/, computeSha256(event.sessionId)];
2947 case 1:
2948 sessionDigest = _b.sent();
2949 additionalParams = {};
2950 if (phone._isIOS()) {
2951 // iOS app identifier
2952 additionalParams['ibi'] = BuildInfo.packageName;
2953 }
2954 else if (phone._isAndroid()) {
2955 // Android app identifier
2956 additionalParams['apn'] = BuildInfo.packageName;
2957 }
2958 else {
2959 phone._fail(auth, "operation-not-supported-in-this-environment" /* OPERATION_NOT_SUPPORTED */);
2960 }
2961 // Add the display name if available
2962 if (BuildInfo.displayName) {
2963 additionalParams['appDisplayName'] = BuildInfo.displayName;
2964 }
2965 // Attached the hashed session ID
2966 additionalParams['sessionId'] = sessionDigest;
2967 return [2 /*return*/, _getRedirectUrl(auth, provider, event.type, undefined, (_a = event.eventId) !== null && _a !== void 0 ? _a : undefined, additionalParams)];
2968 }
2969 });
2970 });
2971}
2972/**
2973 * Validates that this app is valid for this project configuration
2974 */
2975function _validateOrigin(auth) {
2976 return tslib.__awaiter(this, void 0, void 0, function () {
2977 var BuildInfo, request;
2978 return tslib.__generator(this, function (_a) {
2979 switch (_a.label) {
2980 case 0:
2981 BuildInfo = _cordovaWindow().BuildInfo;
2982 request = {};
2983 if (phone._isIOS()) {
2984 request.iosBundleId = BuildInfo.packageName;
2985 }
2986 else if (phone._isAndroid()) {
2987 request.androidPackageName = BuildInfo.packageName;
2988 }
2989 else {
2990 phone._fail(auth, "operation-not-supported-in-this-environment" /* OPERATION_NOT_SUPPORTED */);
2991 }
2992 // Will fail automatically if package name is not authorized
2993 return [4 /*yield*/, _getProjectConfig(auth, request)];
2994 case 1:
2995 // Will fail automatically if package name is not authorized
2996 _a.sent();
2997 return [2 /*return*/];
2998 }
2999 });
3000 });
3001}
3002function _performRedirect(handlerUrl) {
3003 // Get the cordova plugins
3004 var cordova = _cordovaWindow().cordova;
3005 return new Promise(function (resolve) {
3006 cordova.plugins.browsertab.isAvailable(function (browserTabIsAvailable) {
3007 var iabRef = null;
3008 if (browserTabIsAvailable) {
3009 cordova.plugins.browsertab.openUrl(handlerUrl);
3010 }
3011 else {
3012 // TODO: Return the inappbrowser ref that's returned from the open call
3013 iabRef = cordova.InAppBrowser.open(handlerUrl, phone._isIOS7Or8() ? '_blank' : '_system', 'location=yes');
3014 }
3015 resolve(iabRef);
3016 });
3017 });
3018}
3019/**
3020 * This function waits for app activity to be seen before resolving. It does
3021 * this by attaching listeners to various dom events. Once the app is determined
3022 * to be visible, this promise resolves. AFTER that resolution, the listeners
3023 * are detached and any browser tabs left open will be closed.
3024 */
3025function _waitForAppResume(auth, eventListener, iabRef) {
3026 return tslib.__awaiter(this, void 0, void 0, function () {
3027 var cordova, cleanup;
3028 return tslib.__generator(this, function (_a) {
3029 switch (_a.label) {
3030 case 0:
3031 cordova = _cordovaWindow().cordova;
3032 cleanup = function () { };
3033 _a.label = 1;
3034 case 1:
3035 _a.trys.push([1, , 3, 4]);
3036 return [4 /*yield*/, new Promise(function (resolve, reject) {
3037 var onCloseTimer = null;
3038 // DEFINE ALL THE CALLBACKS =====
3039 function authEventSeen() {
3040 var _a;
3041 // Auth event was detected. Resolve this promise and close the extra
3042 // window if it's still open.
3043 resolve();
3044 var closeBrowserTab = (_a = cordova.plugins.browsertab) === null || _a === void 0 ? void 0 : _a.close;
3045 if (typeof closeBrowserTab === 'function') {
3046 closeBrowserTab();
3047 }
3048 // Close inappbrowser emebedded webview in iOS7 and 8 case if still
3049 // open.
3050 if (typeof (iabRef === null || iabRef === void 0 ? void 0 : iabRef.close) === 'function') {
3051 iabRef.close();
3052 }
3053 }
3054 function resumed() {
3055 if (onCloseTimer) {
3056 // This code already ran; do not rerun.
3057 return;
3058 }
3059 onCloseTimer = window.setTimeout(function () {
3060 // Wait two seeconds after resume then reject.
3061 reject(phone._createError(auth, "redirect-cancelled-by-user" /* REDIRECT_CANCELLED_BY_USER */));
3062 }, REDIRECT_TIMEOUT_MS);
3063 }
3064 function visibilityChanged() {
3065 if ((document === null || document === void 0 ? void 0 : document.visibilityState) === 'visible') {
3066 resumed();
3067 }
3068 }
3069 // ATTACH ALL THE LISTENERS =====
3070 // Listen for the auth event
3071 eventListener.addPassiveListener(authEventSeen);
3072 // Listen for resume and visibility events
3073 document.addEventListener('resume', resumed, false);
3074 if (phone._isAndroid()) {
3075 document.addEventListener('visibilitychange', visibilityChanged, false);
3076 }
3077 // SETUP THE CLEANUP FUNCTION =====
3078 cleanup = function () {
3079 eventListener.removePassiveListener(authEventSeen);
3080 document.removeEventListener('resume', resumed, false);
3081 document.removeEventListener('visibilitychange', visibilityChanged, false);
3082 if (onCloseTimer) {
3083 window.clearTimeout(onCloseTimer);
3084 }
3085 };
3086 })];
3087 case 2:
3088 _a.sent();
3089 return [3 /*break*/, 4];
3090 case 3:
3091 cleanup();
3092 return [7 /*endfinally*/];
3093 case 4: return [2 /*return*/];
3094 }
3095 });
3096 });
3097}
3098/**
3099 * Checks the configuration of the Cordova environment. This has no side effect
3100 * if the configuration is correct; otherwise it throws an error with the
3101 * missing plugin.
3102 */
3103function _checkCordovaConfiguration(auth) {
3104 var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
3105 var win = _cordovaWindow();
3106 // Check all dependencies installed.
3107 // https://github.com/nordnet/cordova-universal-links-plugin
3108 // Note that cordova-universal-links-plugin has been abandoned.
3109 // A fork with latest fixes is available at:
3110 // https://www.npmjs.com/package/cordova-universal-links-plugin-fix
3111 phone._assert(typeof ((_a = win === null || win === void 0 ? void 0 : win.universalLinks) === null || _a === void 0 ? void 0 : _a.subscribe) === 'function', auth, "invalid-cordova-configuration" /* INVALID_CORDOVA_CONFIGURATION */, {
3112 missingPlugin: 'cordova-universal-links-plugin-fix'
3113 });
3114 // https://www.npmjs.com/package/cordova-plugin-buildinfo
3115 phone._assert(typeof ((_b = win === null || win === void 0 ? void 0 : win.BuildInfo) === null || _b === void 0 ? void 0 : _b.packageName) !== 'undefined', auth, "invalid-cordova-configuration" /* INVALID_CORDOVA_CONFIGURATION */, {
3116 missingPlugin: 'cordova-plugin-buildInfo'
3117 });
3118 // https://github.com/google/cordova-plugin-browsertab
3119 phone._assert(typeof ((_e = (_d = (_c = win === null || win === void 0 ? void 0 : win.cordova) === null || _c === void 0 ? void 0 : _c.plugins) === null || _d === void 0 ? void 0 : _d.browsertab) === null || _e === void 0 ? void 0 : _e.openUrl) === 'function', auth, "invalid-cordova-configuration" /* INVALID_CORDOVA_CONFIGURATION */, {
3120 missingPlugin: 'cordova-plugin-browsertab'
3121 });
3122 phone._assert(typeof ((_h = (_g = (_f = win === null || win === void 0 ? void 0 : win.cordova) === null || _f === void 0 ? void 0 : _f.plugins) === null || _g === void 0 ? void 0 : _g.browsertab) === null || _h === void 0 ? void 0 : _h.isAvailable) === 'function', auth, "invalid-cordova-configuration" /* INVALID_CORDOVA_CONFIGURATION */, {
3123 missingPlugin: 'cordova-plugin-browsertab'
3124 });
3125 // https://cordova.apache.org/docs/en/latest/reference/cordova-plugin-inappbrowser/
3126 phone._assert(typeof ((_k = (_j = win === null || win === void 0 ? void 0 : win.cordova) === null || _j === void 0 ? void 0 : _j.InAppBrowser) === null || _k === void 0 ? void 0 : _k.open) === 'function', auth, "invalid-cordova-configuration" /* INVALID_CORDOVA_CONFIGURATION */, {
3127 missingPlugin: 'cordova-plugin-inappbrowser'
3128 });
3129}
3130/**
3131 * Computes the SHA-256 of a session ID. The SubtleCrypto interface is only
3132 * available in "secure" contexts, which covers Cordova (which is served on a file
3133 * protocol).
3134 */
3135function computeSha256(sessionId) {
3136 return tslib.__awaiter(this, void 0, void 0, function () {
3137 var bytes, buf, arr;
3138 return tslib.__generator(this, function (_a) {
3139 switch (_a.label) {
3140 case 0:
3141 bytes = stringToArrayBuffer(sessionId);
3142 return [4 /*yield*/, crypto.subtle.digest('SHA-256', bytes)];
3143 case 1:
3144 buf = _a.sent();
3145 arr = Array.from(new Uint8Array(buf));
3146 return [2 /*return*/, arr.map(function (num) { return num.toString(16).padStart(2, '0'); }).join('')];
3147 }
3148 });
3149 });
3150}
3151function stringToArrayBuffer(str) {
3152 // This function is only meant to deal with an ASCII charset and makes
3153 // certain simplifying assumptions.
3154 phone.debugAssert(/[0-9a-zA-Z]+/.test(str), 'Can only convert alpha-numeric strings');
3155 if (typeof TextEncoder !== 'undefined') {
3156 return new TextEncoder().encode(str);
3157 }
3158 var buff = new ArrayBuffer(str.length);
3159 var view = new Uint8Array(buff);
3160 for (var i = 0; i < str.length; i++) {
3161 view[i] = str.charCodeAt(i);
3162 }
3163 return view;
3164}
3165
3166/**
3167 * @license
3168 * Copyright 2020 Google LLC
3169 *
3170 * Licensed under the Apache License, Version 2.0 (the "License");
3171 * you may not use this file except in compliance with the License.
3172 * You may obtain a copy of the License at
3173 *
3174 * http://www.apache.org/licenses/LICENSE-2.0
3175 *
3176 * Unless required by applicable law or agreed to in writing, software
3177 * distributed under the License is distributed on an "AS IS" BASIS,
3178 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3179 * See the License for the specific language governing permissions and
3180 * limitations under the License.
3181 */
3182var SESSION_ID_LENGTH = 20;
3183/** Custom AuthEventManager that adds passive listeners to events */
3184var CordovaAuthEventManager = /** @class */ (function (_super) {
3185 tslib.__extends(CordovaAuthEventManager, _super);
3186 function CordovaAuthEventManager() {
3187 var _this = _super !== null && _super.apply(this, arguments) || this;
3188 _this.passiveListeners = new Set();
3189 _this.initPromise = new Promise(function (resolve) {
3190 _this.resolveInialized = resolve;
3191 });
3192 return _this;
3193 }
3194 CordovaAuthEventManager.prototype.addPassiveListener = function (cb) {
3195 this.passiveListeners.add(cb);
3196 };
3197 CordovaAuthEventManager.prototype.removePassiveListener = function (cb) {
3198 this.passiveListeners.delete(cb);
3199 };
3200 // In a Cordova environment, this manager can live through multiple redirect
3201 // operations
3202 CordovaAuthEventManager.prototype.resetRedirect = function () {
3203 this.queuedRedirectEvent = null;
3204 this.hasHandledPotentialRedirect = false;
3205 };
3206 /** Override the onEvent method */
3207 CordovaAuthEventManager.prototype.onEvent = function (event) {
3208 this.resolveInialized();
3209 this.passiveListeners.forEach(function (cb) { return cb(event); });
3210 return _super.prototype.onEvent.call(this, event);
3211 };
3212 CordovaAuthEventManager.prototype.initialized = function () {
3213 return tslib.__awaiter(this, void 0, void 0, function () {
3214 return tslib.__generator(this, function (_a) {
3215 switch (_a.label) {
3216 case 0: return [4 /*yield*/, this.initPromise];
3217 case 1:
3218 _a.sent();
3219 return [2 /*return*/];
3220 }
3221 });
3222 });
3223 };
3224 return CordovaAuthEventManager;
3225}(AuthEventManager));
3226/**
3227 * Generates a (partial) {@link AuthEvent}.
3228 */
3229function _generateNewEvent(auth, type, eventId) {
3230 if (eventId === void 0) { eventId = null; }
3231 return {
3232 type: type,
3233 eventId: eventId,
3234 urlResponse: null,
3235 sessionId: generateSessionId(),
3236 postBody: null,
3237 tenantId: auth.tenantId,
3238 error: phone._createError(auth, "no-auth-event" /* NO_AUTH_EVENT */)
3239 };
3240}
3241function _savePartialEvent(auth, event) {
3242 return storage()._set(persistenceKey(auth), event);
3243}
3244function _getAndRemoveEvent(auth) {
3245 return tslib.__awaiter(this, void 0, void 0, function () {
3246 var event;
3247 return tslib.__generator(this, function (_a) {
3248 switch (_a.label) {
3249 case 0: return [4 /*yield*/, storage()._get(persistenceKey(auth))];
3250 case 1:
3251 event = (_a.sent());
3252 if (!event) return [3 /*break*/, 3];
3253 return [4 /*yield*/, storage()._remove(persistenceKey(auth))];
3254 case 2:
3255 _a.sent();
3256 _a.label = 3;
3257 case 3: return [2 /*return*/, event];
3258 }
3259 });
3260 });
3261}
3262function _eventFromPartialAndUrl(partialEvent, url) {
3263 var _a, _b;
3264 // Parse the deep link within the dynamic link URL.
3265 var callbackUrl = _getDeepLinkFromCallback(url);
3266 // Confirm it is actually a callback URL.
3267 // Currently the universal link will be of this format:
3268 // https://<AUTH_DOMAIN>/__/auth/callback<OAUTH_RESPONSE>
3269 // This is a fake URL but is not intended to take the user anywhere
3270 // and just redirect to the app.
3271 if (callbackUrl.includes('/__/auth/callback')) {
3272 // Check if there is an error in the URL.
3273 // This mechanism is also used to pass errors back to the app:
3274 // https://<AUTH_DOMAIN>/__/auth/callback?firebaseError=<STRINGIFIED_ERROR>
3275 var params = searchParamsOrEmpty(callbackUrl);
3276 // Get the error object corresponding to the stringified error if found.
3277 var errorObject = params['firebaseError']
3278 ? parseJsonOrNull(decodeURIComponent(params['firebaseError']))
3279 : null;
3280 var code = (_b = (_a = errorObject === null || errorObject === void 0 ? void 0 : errorObject['code']) === null || _a === void 0 ? void 0 : _a.split('auth/')) === null || _b === void 0 ? void 0 : _b[1];
3281 var error = code ? phone._createError(code) : null;
3282 if (error) {
3283 return {
3284 type: partialEvent.type,
3285 eventId: partialEvent.eventId,
3286 tenantId: partialEvent.tenantId,
3287 error: error,
3288 urlResponse: null,
3289 sessionId: null,
3290 postBody: null
3291 };
3292 }
3293 else {
3294 return {
3295 type: partialEvent.type,
3296 eventId: partialEvent.eventId,
3297 tenantId: partialEvent.tenantId,
3298 sessionId: partialEvent.sessionId,
3299 urlResponse: callbackUrl,
3300 postBody: null
3301 };
3302 }
3303 }
3304 return null;
3305}
3306function generateSessionId() {
3307 var chars = [];
3308 var allowedChars = '1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
3309 for (var i = 0; i < SESSION_ID_LENGTH; i++) {
3310 var idx = Math.floor(Math.random() * allowedChars.length);
3311 chars.push(allowedChars.charAt(idx));
3312 }
3313 return chars.join('');
3314}
3315function storage() {
3316 return phone._getInstance(browserLocalPersistence);
3317}
3318function persistenceKey(auth) {
3319 return phone._persistenceKeyName("authEvent" /* AUTH_EVENT */, auth.config.apiKey, auth.name);
3320}
3321function parseJsonOrNull(json) {
3322 try {
3323 return JSON.parse(json);
3324 }
3325 catch (e) {
3326 return null;
3327 }
3328}
3329// Exported for testing
3330function _getDeepLinkFromCallback(url) {
3331 var params = searchParamsOrEmpty(url);
3332 var link = params['link'] ? decodeURIComponent(params['link']) : undefined;
3333 // Double link case (automatic redirect)
3334 var doubleDeepLink = searchParamsOrEmpty(link)['link'];
3335 // iOS custom scheme links.
3336 var iOSDeepLink = params['deep_link_id']
3337 ? decodeURIComponent(params['deep_link_id'])
3338 : undefined;
3339 var iOSDoubleDeepLink = searchParamsOrEmpty(iOSDeepLink)['link'];
3340 return iOSDoubleDeepLink || iOSDeepLink || doubleDeepLink || link || url;
3341}
3342/**
3343 * Optimistically tries to get search params from a string, or else returns an
3344 * empty search params object.
3345 */
3346function searchParamsOrEmpty(url) {
3347 if (!(url === null || url === void 0 ? void 0 : url.includes('?'))) {
3348 return {};
3349 }
3350 var _a = url.split('?'); _a[0]; var rest = _a.slice(1);
3351 return util.querystringDecode(rest.join('?'));
3352}
3353
3354/**
3355 * @license
3356 * Copyright 2021 Google LLC
3357 *
3358 * Licensed under the Apache License, Version 2.0 (the "License");
3359 * you may not use this file except in compliance with the License.
3360 * You may obtain a copy of the License at
3361 *
3362 * http://www.apache.org/licenses/LICENSE-2.0
3363 *
3364 * Unless required by applicable law or agreed to in writing, software
3365 * distributed under the License is distributed on an "AS IS" BASIS,
3366 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3367 * See the License for the specific language governing permissions and
3368 * limitations under the License.
3369 */
3370/**
3371 * How long to wait for the initial auth event before concluding no
3372 * redirect pending
3373 */
3374var INITIAL_EVENT_TIMEOUT_MS = 500;
3375var CordovaPopupRedirectResolver = /** @class */ (function () {
3376 function CordovaPopupRedirectResolver() {
3377 this._redirectPersistence = browserSessionPersistence;
3378 this._shouldInitProactively = true; // This is lightweight for Cordova
3379 this.eventManagers = new Map();
3380 this.originValidationPromises = {};
3381 this._completeRedirectFn = _getRedirectResult;
3382 this._overrideRedirectResult = _overrideRedirectResult;
3383 }
3384 CordovaPopupRedirectResolver.prototype._initialize = function (auth) {
3385 return tslib.__awaiter(this, void 0, void 0, function () {
3386 var key, manager;
3387 return tslib.__generator(this, function (_a) {
3388 key = auth._key();
3389 manager = this.eventManagers.get(key);
3390 if (!manager) {
3391 manager = new CordovaAuthEventManager(auth);
3392 this.eventManagers.set(key, manager);
3393 this.attachCallbackListeners(auth, manager);
3394 }
3395 return [2 /*return*/, manager];
3396 });
3397 });
3398 };
3399 CordovaPopupRedirectResolver.prototype._openPopup = function (auth) {
3400 phone._fail(auth, "operation-not-supported-in-this-environment" /* OPERATION_NOT_SUPPORTED */);
3401 };
3402 CordovaPopupRedirectResolver.prototype._openRedirect = function (auth, provider, authType, eventId) {
3403 return tslib.__awaiter(this, void 0, void 0, function () {
3404 var manager, event, url, iabRef;
3405 return tslib.__generator(this, function (_a) {
3406 switch (_a.label) {
3407 case 0:
3408 _checkCordovaConfiguration(auth);
3409 return [4 /*yield*/, this._initialize(auth)];
3410 case 1:
3411 manager = _a.sent();
3412 return [4 /*yield*/, manager.initialized()];
3413 case 2:
3414 _a.sent();
3415 // Reset the persisted redirect states. This does not matter on Web where
3416 // the redirect always blows away application state entirely. On Cordova,
3417 // the app maintains control flow through the redirect.
3418 manager.resetRedirect();
3419 _clearRedirectOutcomes();
3420 return [4 /*yield*/, this._originValidation(auth)];
3421 case 3:
3422 _a.sent();
3423 event = _generateNewEvent(auth, authType, eventId);
3424 return [4 /*yield*/, _savePartialEvent(auth, event)];
3425 case 4:
3426 _a.sent();
3427 return [4 /*yield*/, _generateHandlerUrl(auth, event, provider)];
3428 case 5:
3429 url = _a.sent();
3430 return [4 /*yield*/, _performRedirect(url)];
3431 case 6:
3432 iabRef = _a.sent();
3433 return [2 /*return*/, _waitForAppResume(auth, manager, iabRef)];
3434 }
3435 });
3436 });
3437 };
3438 CordovaPopupRedirectResolver.prototype._isIframeWebStorageSupported = function (_auth, _cb) {
3439 throw new Error('Method not implemented.');
3440 };
3441 CordovaPopupRedirectResolver.prototype._originValidation = function (auth) {
3442 var key = auth._key();
3443 if (!this.originValidationPromises[key]) {
3444 this.originValidationPromises[key] = _validateOrigin(auth);
3445 }
3446 return this.originValidationPromises[key];
3447 };
3448 CordovaPopupRedirectResolver.prototype.attachCallbackListeners = function (auth, manager) {
3449 var _this = this;
3450 // Get the global plugins
3451 var _a = _cordovaWindow(), universalLinks = _a.universalLinks, handleOpenURL = _a.handleOpenURL, BuildInfo = _a.BuildInfo;
3452 var noEventTimeout = setTimeout(function () { return tslib.__awaiter(_this, void 0, void 0, function () {
3453 return tslib.__generator(this, function (_a) {
3454 switch (_a.label) {
3455 case 0:
3456 // We didn't see that initial event. Clear any pending object and
3457 // dispatch no event
3458 return [4 /*yield*/, _getAndRemoveEvent(auth)];
3459 case 1:
3460 // We didn't see that initial event. Clear any pending object and
3461 // dispatch no event
3462 _a.sent();
3463 manager.onEvent(generateNoEvent());
3464 return [2 /*return*/];
3465 }
3466 });
3467 }); }, INITIAL_EVENT_TIMEOUT_MS);
3468 var universalLinksCb = function (eventData) { return tslib.__awaiter(_this, void 0, void 0, function () {
3469 var partialEvent, finalEvent;
3470 return tslib.__generator(this, function (_a) {
3471 switch (_a.label) {
3472 case 0:
3473 // We have an event so we can clear the no event timeout
3474 clearTimeout(noEventTimeout);
3475 return [4 /*yield*/, _getAndRemoveEvent(auth)];
3476 case 1:
3477 partialEvent = _a.sent();
3478 finalEvent = null;
3479 if (partialEvent && (eventData === null || eventData === void 0 ? void 0 : eventData['url'])) {
3480 finalEvent = _eventFromPartialAndUrl(partialEvent, eventData['url']);
3481 }
3482 // If finalEvent is never filled, trigger with no event
3483 manager.onEvent(finalEvent || generateNoEvent());
3484 return [2 /*return*/];
3485 }
3486 });
3487 }); };
3488 // Universal links subscriber doesn't exist for iOS, so we need to check
3489 if (typeof universalLinks !== 'undefined' &&
3490 typeof universalLinks.subscribe === 'function') {
3491 universalLinks.subscribe(null, universalLinksCb);
3492 }
3493 // iOS 7 or 8 custom URL schemes.
3494 // This is also the current default behavior for iOS 9+.
3495 // For this to work, cordova-plugin-customurlscheme needs to be installed.
3496 // https://github.com/EddyVerbruggen/Custom-URL-scheme
3497 // Do not overwrite the existing developer's URL handler.
3498 var existingHandleOpenURL = handleOpenURL;
3499 var packagePrefix = BuildInfo.packageName.toLowerCase() + "://";
3500 _cordovaWindow().handleOpenURL = function (url) { return tslib.__awaiter(_this, void 0, void 0, function () {
3501 return tslib.__generator(this, function (_a) {
3502 if (url.toLowerCase().startsWith(packagePrefix)) {
3503 // We want this intentionally to float
3504 // eslint-disable-next-line @typescript-eslint/no-floating-promises
3505 universalLinksCb({ url: url });
3506 }
3507 // Call the developer's handler if it is present.
3508 if (typeof existingHandleOpenURL === 'function') {
3509 try {
3510 existingHandleOpenURL(url);
3511 }
3512 catch (e) {
3513 // This is a developer error. Don't stop the flow of the SDK.
3514 console.error(e);
3515 }
3516 }
3517 return [2 /*return*/];
3518 });
3519 }); };
3520 };
3521 return CordovaPopupRedirectResolver;
3522}());
3523/**
3524 * An implementation of {@link PopupRedirectResolver} suitable for Cordova
3525 * based applications.
3526 *
3527 * @public
3528 */
3529var cordovaPopupRedirectResolver = CordovaPopupRedirectResolver;
3530function generateNoEvent() {
3531 return {
3532 type: "unknown" /* UNKNOWN */,
3533 eventId: null,
3534 sessionId: null,
3535 urlResponse: null,
3536 postBody: null,
3537 tenantId: null,
3538 error: phone._createError("no-auth-event" /* NO_AUTH_EVENT */)
3539 };
3540}
3541
3542/**
3543 * @license
3544 * Copyright 2017 Google LLC
3545 *
3546 * Licensed under the Apache License, Version 2.0 (the "License");
3547 * you may not use this file except in compliance with the License.
3548 * You may obtain a copy of the License at
3549 *
3550 * http://www.apache.org/licenses/LICENSE-2.0
3551 *
3552 * Unless required by applicable law or agreed to in writing, software
3553 * distributed under the License is distributed on an "AS IS" BASIS,
3554 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3555 * See the License for the specific language governing permissions and
3556 * limitations under the License.
3557 */
3558// This function should only be called by frameworks (e.g. FirebaseUI-web) to log their usage.
3559// It is not intended for direct use by developer apps. NO jsdoc here to intentionally leave it out
3560// of autogenerated documentation pages to reduce accidental misuse.
3561function addFrameworkForLogging(auth, framework) {
3562 phone._castAuth(auth)._logFramework(framework);
3563}
3564
3565exports.ActionCodeOperation = phone.ActionCodeOperation;
3566exports.ActionCodeURL = phone.ActionCodeURL;
3567exports.AuthCredential = phone.AuthCredential;
3568exports.AuthErrorCodes = phone.AUTH_ERROR_CODES_MAP_DO_NOT_USE_INTERNALLY;
3569exports.AuthImpl = phone.AuthImpl;
3570exports.EmailAuthCredential = phone.EmailAuthCredential;
3571exports.EmailAuthProvider = phone.EmailAuthProvider;
3572exports.FacebookAuthProvider = phone.FacebookAuthProvider;
3573exports.FactorId = phone.FactorId;
3574exports.FetchProvider = phone.FetchProvider;
3575exports.GithubAuthProvider = phone.GithubAuthProvider;
3576exports.GoogleAuthProvider = phone.GoogleAuthProvider;
3577exports.OAuthCredential = phone.OAuthCredential;
3578exports.OAuthProvider = phone.OAuthProvider;
3579exports.OperationType = phone.OperationType;
3580exports.PhoneAuthCredential = phone.PhoneAuthCredential;
3581exports.PhoneAuthProvider = phone.PhoneAuthProvider;
3582exports.PhoneMultiFactorGenerator = phone.PhoneMultiFactorGenerator;
3583exports.ProviderId = phone.ProviderId;
3584exports.RecaptchaVerifier = phone.RecaptchaVerifier;
3585exports.SAMLAuthCredential = phone.SAMLAuthCredential;
3586exports.SAMLAuthProvider = phone.SAMLAuthProvider;
3587exports.SignInMethod = phone.SignInMethod;
3588exports.TwitterAuthProvider = phone.TwitterAuthProvider;
3589exports.UserImpl = phone.UserImpl;
3590exports._assert = phone._assert;
3591exports._castAuth = phone._castAuth;
3592exports._fail = phone._fail;
3593exports._getClientVersion = phone._getClientVersion;
3594exports._getInstance = phone._getInstance;
3595exports._persistenceKeyName = phone._persistenceKeyName;
3596exports.applyActionCode = phone.applyActionCode;
3597exports.beforeAuthStateChanged = phone.beforeAuthStateChanged;
3598exports.checkActionCode = phone.checkActionCode;
3599exports.confirmPasswordReset = phone.confirmPasswordReset;
3600exports.connectAuthEmulator = phone.connectAuthEmulator;
3601exports.createUserWithEmailAndPassword = phone.createUserWithEmailAndPassword;
3602exports.debugErrorMap = phone.debugErrorMap;
3603exports.deleteUser = phone.deleteUser;
3604exports.fetchSignInMethodsForEmail = phone.fetchSignInMethodsForEmail;
3605exports.getAdditionalUserInfo = phone.getAdditionalUserInfo;
3606exports.getIdToken = phone.getIdToken;
3607exports.getIdTokenResult = phone.getIdTokenResult;
3608exports.getMultiFactorResolver = phone.getMultiFactorResolver;
3609exports.inMemoryPersistence = phone.inMemoryPersistence;
3610exports.initializeAuth = phone.initializeAuth;
3611exports.isSignInWithEmailLink = phone.isSignInWithEmailLink;
3612exports.linkWithCredential = phone.linkWithCredential;
3613exports.linkWithPhoneNumber = phone.linkWithPhoneNumber;
3614exports.multiFactor = phone.multiFactor;
3615exports.onAuthStateChanged = phone.onAuthStateChanged;
3616exports.onIdTokenChanged = phone.onIdTokenChanged;
3617exports.parseActionCodeURL = phone.parseActionCodeURL;
3618exports.prodErrorMap = phone.prodErrorMap;
3619exports.reauthenticateWithCredential = phone.reauthenticateWithCredential;
3620exports.reauthenticateWithPhoneNumber = phone.reauthenticateWithPhoneNumber;
3621exports.reload = phone.reload;
3622exports.sendEmailVerification = phone.sendEmailVerification;
3623exports.sendPasswordResetEmail = phone.sendPasswordResetEmail;
3624exports.sendSignInLinkToEmail = phone.sendSignInLinkToEmail;
3625exports.setPersistence = phone.setPersistence;
3626exports.signInAnonymously = phone.signInAnonymously;
3627exports.signInWithCredential = phone.signInWithCredential;
3628exports.signInWithCustomToken = phone.signInWithCustomToken;
3629exports.signInWithEmailAndPassword = phone.signInWithEmailAndPassword;
3630exports.signInWithEmailLink = phone.signInWithEmailLink;
3631exports.signInWithPhoneNumber = phone.signInWithPhoneNumber;
3632exports.signOut = phone.signOut;
3633exports.unlink = phone.unlink;
3634exports.updateCurrentUser = phone.updateCurrentUser;
3635exports.updateEmail = phone.updateEmail;
3636exports.updatePassword = phone.updatePassword;
3637exports.updatePhoneNumber = phone.updatePhoneNumber;
3638exports.updateProfile = phone.updateProfile;
3639exports.useDeviceLanguage = phone.useDeviceLanguage;
3640exports.verifyBeforeUpdateEmail = phone.verifyBeforeUpdateEmail;
3641exports.verifyPasswordResetCode = phone.verifyPasswordResetCode;
3642exports.AuthPopup = AuthPopup;
3643exports._generateEventId = _generateEventId;
3644exports._getRedirectResult = _getRedirectResult;
3645exports._overrideRedirectResult = _overrideRedirectResult;
3646exports.addFrameworkForLogging = addFrameworkForLogging;
3647exports.browserLocalPersistence = browserLocalPersistence;
3648exports.browserPopupRedirectResolver = browserPopupRedirectResolver;
3649exports.browserSessionPersistence = browserSessionPersistence;
3650exports.cordovaPopupRedirectResolver = cordovaPopupRedirectResolver;
3651exports.getAuth = getAuth;
3652exports.getRedirectResult = getRedirectResult;
3653exports.indexedDBLocalPersistence = indexedDBLocalPersistence;
3654exports.linkWithPopup = linkWithPopup;
3655exports.linkWithRedirect = linkWithRedirect;
3656exports.reauthenticateWithPopup = reauthenticateWithPopup;
3657exports.reauthenticateWithRedirect = reauthenticateWithRedirect;
3658exports.signInWithPopup = signInWithPopup;
3659exports.signInWithRedirect = signInWithRedirect;
3660//# sourceMappingURL=internal.js.map