internal.js 174 KB

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