PageSourceSearch

https://ramkumar-2705.web.app/__/firebase/9.6.4/firebase-performance.js

js ramkumar-2705.web.app collected 2026-10-03 12:33:58 UTC 118,735 bytes, 3,194 lines download raw bytes

1import { registerVersion, _registerComponent, _getProvider, getApp } from 'https://www.gstatic.com/firebasejs/9.6.4/firebase-app.js';
2
3/**
4 * @license
5 * Copyright 2017 Google LLC
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *   http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19/**
20 * This method checks if indexedDB is supported by current browser/service worker context
21 * @return true if indexedDB is supported by current browser/service worker context
22 */
23function isIndexedDBAvailable() {
24    return typeof indexedDB === 'object';
25}
26/**
27 * This method validates browser/sw context for indexedDB by opening a dummy indexedDB database and reject
28 * if errors occur during the database open operation.
29 *
30 * @throws exception if current browser/sw context can't run idb.open (ex: Safari iframe, Firefox
31 * private browsing)
32 */
33function validateIndexedDBOpenable() {
34    return new Promise((resolve, reject) => {
35        try {
36            let preExist = true;
37            const DB_CHECK_NAME = 'validate-browser-context-for-indexeddb-analytics-module';
38            const request = self.indexedDB.open(DB_CHECK_NAME);
39            request.onsuccess = () => {
40                request.result.close();
41                // delete database only when it doesn't pre-exist
42                if (!preExist) {
43                    self.indexedDB.deleteDatabase(DB_CHECK_NAME);
44                }
45                resolve(true);
46            };
47            request.onupgradeneeded = () => {
48                preExist = false;
49            };
50            request.onerror = () => {
51                var _a;
52                reject(((_a = request.error) === null || _a === void 0 ? void 0 : _a.message) || '');
53            };
54        }
55        catch (error) {
56            reject(error);
57        }
58    });
59}
60/**
61 *
62 * This method checks whether cookie is enabled within current browser
63 * @return true if cookie is enabled within current browser
64 */
65function areCookiesEnabled() {
66    if (typeof navigator === 'undefined' || !navigator.cookieEnabled) {
67        return false;
68    }
69    return true;
70}
71
72/**
73 * @license
74 * Copyright 2017 Google LLC
75 *
76 * Licensed under the Apache License, Version 2.0 (the "License");
77 * you may not use this file except in compliance with the License.
78 * You may obtain a copy of the License at
79 *
80 *   http://www.apache.org/licenses/LICENSE-2.0
81 *
82 * Unless required by applicable law or agreed to in writing, software
83 * distributed under the License is distributed on an "AS IS" BASIS,
84 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
85 * See the License for the specific language governing permissions and
86 * limitations under the License.
87 */
88/**
89 * @fileoverview Standardized Firebase Error.
90 *
91 * Usage:
92 *
93 *   // Typescript string literals for type-safe codes
94 *   type Err =
95 *     'unknown' |
96 *     'object-not-found'
97 *     ;
98 *
99 *   // Closure enum for type-safe error codes
100 *   // at-enum {string}
101 *   var Err = {
102 *     UNKNOWN: 'unknown',
103 *     OBJECT_NOT_FOUND: 'object-not-found',
104 *   }
105 *
106 *   let errors: Map<Err, string> = {
107 *     'generic-error': "Unknown error",
108 *     'file-not-found': "Could not find file: {$file}",
109 *   };
110 *
111 *   // Type-safe function - must pass a valid error code as param.
112 *   let error = new ErrorFactory<Err>('service', 'Service', errors);
113 *
114 *   ...
115 *   throw error.create(Err.GENERIC);
116 *   ...
117 *   throw error.create(Err.FILE_NOT_FOUND, {'file': fileName});
118 *   ...
119 *   // Service: Could not file file: foo.txt (service/file-not-found).
120 *
121 *   catch (e) {
122 *     assert(e.message === "Could not find file: foo.txt.");
123 *     if (e.code === 'service/file-not-found') {
124 *       console.log("Could not read file: " + e['file']);
125 *     }
126 *   }
127 */
128const ERROR_NAME = 'FirebaseError';
129// Based on code from:
130// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error#Custom_Error_Types
131class FirebaseError extends Error {
132    constructor(
133    /** The error code for this error. */
134    code, message, 
135    /** Custom data for this error. */
136    customData) {
137        super(message);
138        this.code = code;
139        this.customData = customData;
140        /** The custom name for all FirebaseErrors. */
141        this.name = ERROR_NAME;
142        // Fix For ES5
143        // https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work
144        Object.setPrototypeOf(this, FirebaseError.prototype);
145        // Maintains proper stack trace for where our error was thrown.
146        // Only available on V8.
147        if (Error.captureStackTrace) {
148            Error.captureStackTrace(this, ErrorFactory.prototype.create);
149        }
150    }
151}
152class ErrorFactory {
153    constructor(service, serviceName, errors) {
154        this.service = service;
155        this.serviceName = serviceName;
156        this.errors = errors;
157    }
158    create(code, ...data) {
159        const customData = data[0] || {};
160        const fullCode = `${this.service}/${code}`;
161        const template = this.errors[code];
162        const message = template ? replaceTemplate(template, customData) : 'Error';
163        // Service Name: Error message (service/code).
164        const fullMessage = `${this.serviceName}: ${message} (${fullCode}).`;
165        const error = new FirebaseError(fullCode, fullMessage, customData);
166        return error;
167    }
168}
169function replaceTemplate(template, data) {
170    return template.replace(PATTERN, (_, key) => {
171        const value = data[key];
172        return value != null ? String(value) : `<${key}?>`;
173    });
174}
175const PATTERN = /\{\$([^}]+)}/g;
176/**
177 * Deep equal two objects. Support Arrays and Objects.
178 */
179function deepEqual(a, b) {
180    if (a === b) {
181        return true;
182    }
183    const aKeys = Object.keys(a);
184    const bKeys = Object.keys(b);
185    for (const k of aKeys) {
186        if (!bKeys.includes(k)) {
187            return false;
188        }
189        const aProp = a[k];
190        const bProp = b[k];
191        if (isObject(aProp) && isObject(bProp)) {
192            if (!deepEqual(aProp, bProp)) {
193                return false;
194            }
195        }
196        else if (aProp !== bProp) {
197            return false;
198        }
199    }
200    for (const k of bKeys) {
201        if (!aKeys.includes(k)) {
202            return false;
203        }
204    }
205    return true;
206}
207function isObject(thing) {
208    return thing !== null && typeof thing === 'object';
209}
210
211/**
212 * @license
213 * Copyright 2021 Google LLC
214 *
215 * Licensed under the Apache License, Version 2.0 (the "License");
216 * you may not use this file except in compliance with the License.
217 * You may obtain a copy of the License at
218 *
219 *   http://www.apache.org/licenses/LICENSE-2.0
220 *
221 * Unless required by applicable law or agreed to in writing, software
222 * distributed under the License is distributed on an "AS IS" BASIS,
223 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
224 * See the License for the specific language governing permissions and
225 * limitations under the License.
226 */
227function getModularInstance(service) {
228    if (service && service._delegate) {
229        return service._delegate;
230    }
231    else {
232        return service;
233    }
234}
235
236/**
237 * @license
238 * Copyright 2017 Google LLC
239 *
240 * Licensed under the Apache License, Version 2.0 (the "License");
241 * you may not use this file except in compliance with the License.
242 * You may obtain a copy of the License at
243 *
244 *   http://www.apache.org/licenses/LICENSE-2.0
245 *
246 * Unless required by applicable law or agreed to in writing, software
247 * distributed under the License is distributed on an "AS IS" BASIS,
248 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
249 * See the License for the specific language governing permissions and
250 * limitations under the License.
251 */
252/**
253 * The JS SDK supports 5 log levels and also allows a user the ability to
254 * silence the logs altogether.
255 *
256 * The order is a follows:
257 * DEBUG < VERBOSE < INFO < WARN < ERROR
258 *
259 * All of the log types above the current log level will be captured (i.e. if
260 * you set the log level to `INFO`, errors will still be logged, but `DEBUG` and
261 * `VERBOSE` logs will not)
262 */
263var LogLevel;
264(function (LogLevel) {
265    LogLevel[LogLevel["DEBUG"] = 0] = "DEBUG";
266    LogLevel[LogLevel["VERBOSE"] = 1] = "VERBOSE";
267    LogLevel[LogLevel["INFO"] = 2] = "INFO";
268    LogLevel[LogLevel["WARN"] = 3] = "WARN";
vendor: 4,622 bytes, lines 269-404
269    LogLevel[LogLevel["ERROR"] = 4] = "ERROR";
270    LogLevel[LogLevel["SILENT"] = 5] = "SILENT";
271})(LogLevel || (LogLevel = {}));
272const levelStringToEnum = {
273    'debug': LogLevel.DEBUG,
274    'verbose': LogLevel.VERBOSE,
275    'info': LogLevel.INFO,
276    'warn': LogLevel.WARN,
277    'error': LogLevel.ERROR,
278    'silent': LogLevel.SILENT
279};
280/**
281 * The default log level
282 */
283const defaultLogLevel = LogLevel.INFO;
284/**
285 * By default, `console.debug` is not displayed in the developer console (in
286 * chrome). To avoid forcing users to have to opt-in to these logs twice
287 * (i.e. once for firebase, and once in the console), we are sending `DEBUG`
288 * logs to the `console.log` function.
289 */
290const ConsoleMethod = {
291    [LogLevel.DEBUG]: 'log',
292    [LogLevel.VERBOSE]: 'log',
293    [LogLevel.INFO]: 'info',
294    [LogLevel.WARN]: 'warn',
295    [LogLevel.ERROR]: 'error'
296};
297/**
298 * The default log handler will forward DEBUG, VERBOSE, INFO, WARN, and ERROR
299 * messages on to their corresponding console counterparts (if the log method
300 * is supported by the current log level)
301 */
302const defaultLogHandler = (instance, logType, ...args) => {
303    if (logType < instance.logLevel) {
304        return;
305    }
306    const now = new Date().toISOString();
307    const method = ConsoleMethod[logType];
308    if (method) {
309        console[method](`[${now}]  ${instance.name}:`, ...args);
310    }
311    else {
312        throw new Error(`Attempted to log a message with an invalid logType (value: ${logType})`);
313    }
314};
315class Logger {
316    /**
317     * Gives you an instance of a Logger to capture messages according to
318     * Firebase's logging scheme.
319     *
320     * @param name The name that the logs will be associated with
321     */
322    constructor(name) {
323        this.name = name;
324        /**
325         * The log level of the given Logger instance.
326         */
327        this._logLevel = defaultLogLevel;
328        /**
329         * The main (internal) log handler for the Logger instance.
330         * Can be set to a new function in internal package code but not by user.
331         */
332        this._logHandler = defaultLogHandler;
333        /**
334         * The optional, additional, user-defined log handler for the Logger instance.
335         */
336        this._userLogHandler = null;
337    }
338    get logLevel() {
339        return this._logLevel;
340    }
341    set logLevel(val) {
342        if (!(val in LogLevel)) {
343            throw new TypeError(`Invalid value "${val}" assigned to \`logLevel\``);
344        }
345        this._logLevel = val;
346    }
347    // Workaround for setter/getter having to be the same type.
348    setLogLevel(val) {
349        this._logLevel = typeof val === 'string' ? levelStringToEnum[val] : val;
350    }
351    get logHandler() {
352        return this._logHandler;
353    }
354    set logHandler(val) {
355        if (typeof val !== 'function') {
356            throw new TypeError('Value assigned to `logHandler` must be a function');
357        }
358        this._logHandler = val;
359    }
360    get userLogHandler() {
361        return this._userLogHandler;
362    }
363    set userLogHandler(val) {
364        this._userLogHandler = val;
365    }
366    /**
367     * The functions below are all based on the `console` interface
368     */
369    debug(...args) {
370        this._userLogHandler && this._userLogHandler(this, LogLevel.DEBUG, ...args);
371        this._logHandler(this, LogLevel.DEBUG, ...args);
372    }
373    log(...args) {
374        this._userLogHandler &&
375            this._userLogHandler(this, LogLevel.VERBOSE, ...args);
376        this._logHandler(this, LogLevel.VERBOSE, ...args);
377    }
378    info(...args) {
379        this._userLogHandler && this._userLogHandler(this, LogLevel.INFO, ...args);
380        this._logHandler(this, LogLevel.INFO, ...args);
381    }
382    warn(...args) {
383        this._userLogHandler && this._userLogHandler(this, LogLevel.WARN, ...args);
384        this._logHandler(this, LogLevel.WARN, ...args);
385    }
386    error(...args) {
387        this._userLogHandler && this._userLogHandler(this, LogLevel.ERROR, ...args);
388        this._logHandler(this, LogLevel.ERROR, ...args);
389    }
390}
391
392/**
393 * Component for service name T, e.g. `auth`, `auth-internal`
394 */
395class Component {
396    /**
397     *
398     * @param name The public service name, e.g. app, auth, firestore, database
399     * @param instanceFactory Service factory responsible for creating the public interface
400     * @param type whether the service provided by the component is public or private
401     */
402    constructor(name, instanceFactory, type) {
403        this.name = name;
404        this.instanceFactory = instanceFactory;
vendor: 6,182 bytes, lines 405-673
405        this.type = type;
406        this.multipleInstances = false;
407        /**
408         * Properties to be added to the service namespace
409         */
410        this.serviceProps = {};
411        this.instantiationMode = "LAZY" /* LAZY */;
412        this.onInstanceCreated = null;
413    }
414    setInstantiationMode(mode) {
415        this.instantiationMode = mode;
416        return this;
417    }
418    setMultipleInstances(multipleInstances) {
419        this.multipleInstances = multipleInstances;
420        return this;
421    }
422    setServiceProps(props) {
423        this.serviceProps = props;
424        return this;
425    }
426    setInstanceCreatedCallback(callback) {
427        this.onInstanceCreated = callback;
428        return this;
429    }
430}
431
432function toArray(arr) {
433  return Array.prototype.slice.call(arr);
434}
435
436function promisifyRequest(request) {
437  return new Promise(function(resolve, reject) {
438    request.onsuccess = function() {
439      resolve(request.result);
440    };
441
442    request.onerror = function() {
443      reject(request.error);
444    };
445  });
446}
447
448function promisifyRequestCall(obj, method, args) {
449  var request;
450  var p = new Promise(function(resolve, reject) {
451    request = obj[method].apply(obj, args);
452    promisifyRequest(request).then(resolve, reject);
453  });
454
455  p.request = request;
456  return p;
457}
458
459function promisifyCursorRequestCall(obj, method, args) {
460  var p = promisifyRequestCall(obj, method, args);
461  return p.then(function(value) {
462    if (!value) return;
463    return new Cursor(value, p.request);
464  });
465}
466
467function proxyProperties(ProxyClass, targetProp, properties) {
468  properties.forEach(function(prop) {
469    Object.defineProperty(ProxyClass.prototype, prop, {
470      get: function() {
471        return this[targetProp][prop];
472      },
473      set: function(val) {
474        this[targetProp][prop] = val;
475      }
476    });
477  });
478}
479
480function proxyRequestMethods(ProxyClass, targetProp, Constructor, properties) {
481  properties.forEach(function(prop) {
482    if (!(prop in Constructor.prototype)) return;
483    ProxyClass.prototype[prop] = function() {
484      return promisifyRequestCall(this[targetProp], prop, arguments);
485    };
486  });
487}
488
489function proxyMethods(ProxyClass, targetProp, Constructor, properties) {
490  properties.forEach(function(prop) {
491    if (!(prop in Constructor.prototype)) return;
492    ProxyClass.prototype[prop] = function() {
493      return this[targetProp][prop].apply(this[targetProp], arguments);
494    };
495  });
496}
497
498function proxyCursorRequestMethods(ProxyClass, targetProp, Constructor, properties) {
499  properties.forEach(function(prop) {
500    if (!(prop in Constructor.prototype)) return;
501    ProxyClass.prototype[prop] = function() {
502      return promisifyCursorRequestCall(this[targetProp], prop, arguments);
503    };
504  });
505}
506
507function Index(index) {
508  this._index = index;
509}
510
511proxyProperties(Index, '_index', [
512  'name',
513  'keyPath',
514  'multiEntry',
515  'unique'
516]);
517
518proxyRequestMethods(Index, '_index', IDBIndex, [
519  'get',
520  'getKey',
521  'getAll',
522  'getAllKeys',
523  'count'
524]);
525
526proxyCursorRequestMethods(Index, '_index', IDBIndex, [
527  'openCursor',
528  'openKeyCursor'
529]);
530
531function Cursor(cursor, request) {
532  this._cursor = cursor;
533  this._request = request;
534}
535
536proxyProperties(Cursor, '_cursor', [
537  'direction',
538  'key',
539  'primaryKey',
540  'value'
541]);
542
543proxyRequestMethods(Cursor, '_cursor', IDBCursor, [
544  'update',
545  'delete'
546]);
547
548// proxy 'next' methods
549['advance', 'continue', 'continuePrimaryKey'].forEach(function(methodName) {
550  if (!(methodName in IDBCursor.prototype)) return;
551  Cursor.prototype[methodName] = function() {
552    var cursor = this;
553    var args = arguments;
554    return Promise.resolve().then(function() {
555      cursor._cursor[methodName].apply(cursor._cursor, args);
556      return promisifyRequest(cursor._request).then(function(value) {
557        if (!value) return;
558        return new Cursor(value, cursor._request);
559      });
560    });
561  };
562});
563
564function ObjectStore(store) {
565  this._store = store;
566}
567
568ObjectStore.prototype.createIndex = function() {
569  return new Index(this._store.createIndex.apply(this._store, arguments));
570};
571
572ObjectStore.prototype.index = function() {
573  return new Index(this._store.index.apply(this._store, arguments));
574};
575
576proxyProperties(ObjectStore, '_store', [
577  'name',
578  'keyPath',
579  'indexNames',
580  'autoIncrement'
581]);
582
583proxyRequestMethods(ObjectStore, '_store', IDBObjectStore, [
584  'put',
585  'add',
586  'delete',
587  'clear',
588  'get',
589  'getAll',
590  'getKey',
591  'getAllKeys',
592  'count'
593]);
594
595proxyCursorRequestMethods(ObjectStore, '_store', IDBObjectStore, [
596  'openCursor',
597  'openKeyCursor'
598]);
599
600proxyMethods(ObjectStore, '_store', IDBObjectStore, [
601  'deleteIndex'
602]);
603
604function Transaction(idbTransaction) {
605  this._tx = idbTransaction;
606  this.complete = new Promise(function(resolve, reject) {
607    idbTransaction.oncomplete = function() {
608      resolve();
609    };
610    idbTransaction.onerror = function() {
611      reject(idbTransaction.error);
612    };
613    idbTransaction.onabort = function() {
614      reject(idbTransaction.error);
615    };
616  });
617}
618
619Transaction.prototype.objectStore = function() {
620  return new ObjectStore(this._tx.objectStore.apply(this._tx, arguments));
621};
622
623proxyProperties(Transaction, '_tx', [
624  'objectStoreNames',
625  'mode'
626]);
627
628proxyMethods(Transaction, '_tx', IDBTransaction, [
629  'abort'
630]);
631
632function UpgradeDB(db, oldVersion, transaction) {
633  this._db = db;
634  this.oldVersion = oldVersion;
635  this.transaction = new Transaction(transaction);
636}
637
638UpgradeDB.prototype.createObjectStore = function() {
639  return new ObjectStore(this._db.createObjectStore.apply(this._db, arguments));
640};
641
642proxyProperties(UpgradeDB, '_db', [
643  'name',
644  'version',
645  'objectStoreNames'
646]);
647
648proxyMethods(UpgradeDB, '_db', IDBDatabase, [
649  'deleteObjectStore',
650  'close'
651]);
652
653function DB(db) {
654  this._db = db;
655}
656
657DB.prototype.transaction = function() {
658  return new Transaction(this._db.transaction.apply(this._db, arguments));
659};
660
661proxyProperties(DB, '_db', [
662  'name',
663  'version',
664  'objectStoreNames'
665]);
666
667proxyMethods(DB, '_db', IDBDatabase, [
668  'close'
669]);
670
671// Add cursor iterators
672// TODO: remove this once browsers do the right thing with promises
673['openCursor', 'openKeyCursor'].forEach(function(funcName) {
674  [ObjectStore, Index].forEach(function(Constructor) {
675    // Don't create iterateKeyCursor if openKeyCursor doesn't exist.
676    if (!(funcName in Constructor.prototype)) return;
677
678    Constructor.prototype[funcName.replace('open', 'iterate')] = function() {
679      var args = toArray(arguments);
680      var callback = args[args.length - 1];
681      var nativeObject = this._store || this._index;
682      var request = nativeObject[funcName].apply(nativeObject, args.slice(0, -1));
683      request.onsuccess = function() {
684        callback(request.result);
685      };
686    };
687  });
688});
689
690// polyfill getAll
691[Index, ObjectStore].forEach(function(Constructor) {
692  if (Constructor.prototype.getAll) return;
693  Constructor.prototype.getAll = function(query, count) {
694    var instance = this;
695    var items = [];
696
697    return new Promise(function(resolve) {
698      instance.iterateCursor(query, function(cursor) {
699        if (!cursor) {
700          resolve(items);
701          return;
702        }
703        items.push(cursor.value);
704
705        if (count !== undefined && items.length == count) {
706          resolve(items);
707          return;
708        }
709        cursor.continue();
710      });
711    });
712  };
713});
714
715function openDb(name, version, upgradeCallback) {
716  var p = promisifyRequestCall(indexedDB, 'open', [name, version]);
717  var request = p.request;
718
719  if (request) {
720    request.onupgradeneeded = function(event) {
721      if (upgradeCallback) {
722        upgradeCallback(new UpgradeDB(request.result, event.oldVersion, request.transaction));
723      }
724    };
725  }
726
727  return p.then(function(db) {
728    return new DB(db);
729  });
730}
731
732const name$1 = "@firebase/installations";
733const version$1 = "0.5.5";
734
735/**
736 * @license
737 * Copyright 2019 Google LLC
738 *
739 * Licensed under the Apache License, Version 2.0 (the "License");
740 * you may not use this file except in compliance with the License.
741 * You may obtain a copy of the License at
742 *
743 *   http://www.apache.org/licenses/LICENSE-2.0
744 *
745 * Unless required by applicable law or agreed to in writing, software
746 * distributed under the License is distributed on an "AS IS" BASIS,
747 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
748 * See the License for the specific language governing permissions and
749 * limitations under the License.
750 */
751const PENDING_TIMEOUT_MS = 10000;
752const PACKAGE_VERSION = `w:${version$1}`;
753const INTERNAL_AUTH_VERSION = 'FIS_v2';
754const INSTALLATIONS_API_URL = 'https://firebaseinstallations.googleapis.com/v1';
755const TOKEN_EXPIRATION_BUFFER = 60 * 60 * 1000; // One hour
756const SERVICE$1 = 'installations';
757const SERVICE_NAME$1 = 'Installations';
758
759/**
760 * @license
761 * Copyright 2019 Google LLC
762 *
763 * Licensed under the Apache License, Version 2.0 (the "License");
764 * you may not use this file except in compliance with the License.
765 * You may obtain a copy of the License at
766 *
767 *   http://www.apache.org/licenses/LICENSE-2.0
768 *
769 * Unless required by applicable law or agreed to in writing, software
770 * distributed under the License is distributed on an "AS IS" BASIS,
771 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
772 * See the License for the specific language governing permissions and
773 * limitations under the License.
774 */
775const ERROR_DESCRIPTION_MAP$1 = {
776    ["missing-app-config-values" /* MISSING_APP_CONFIG_VALUES */]: 'Missing App configuration value: "{$valueName}"',
777    ["not-registered" /* NOT_REGISTERED */]: 'Firebase Installation is not registered.',
778    ["installation-not-found" /* INSTALLATION_NOT_FOUND */]: 'Firebase Installation not found.',
779    ["request-failed" /* REQUEST_FAILED */]: '{$requestName} request failed with error "{$serverCode} {$serverStatus}: {$serverMessage}"',
780    ["app-offline" /* APP_OFFLINE */]: 'Could not process request. Application offline.',
781    ["delete-pending-registration" /* DELETE_PENDING_REGISTRATION */]: "Can't delete installation while there is a pending registration request."
782};
783const ERROR_FACTORY$1 = new ErrorFactory(SERVICE$1, SERVICE_NAME$1, ERROR_DESCRIPTION_MAP$1);
784/** Returns true if error is a FirebaseError that is based on an error from the server. */
785function isServerError(error) {
786    return (error instanceof FirebaseError &&
787        error.code.includes("request-failed" /* REQUEST_FAILED */)
vendor: 8,416 bytes, lines 787-1017
787);
788}
789
790/**
791 * @license
792 * Copyright 2019 Google LLC
793 *
794 * Licensed under the Apache License, Version 2.0 (the "License");
795 * you may not use this file except in compliance with the License.
796 * You may obtain a copy of the License at
797 *
798 *   http://www.apache.org/licenses/LICENSE-2.0
799 *
800 * Unless required by applicable law or agreed to in writing, software
801 * distributed under the License is distributed on an "AS IS" BASIS,
802 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
803 * See the License for the specific language governing permissions and
804 * limitations under the License.
805 */
806function getInstallationsEndpoint({ projectId }) {
807    return `${INSTALLATIONS_API_URL}/projects/${projectId}/installations`;
808}
809function extractAuthTokenInfoFromResponse(response) {
810    return {
811        token: response.token,
812        requestStatus: 2 /* COMPLETED */,
813        expiresIn: getExpiresInFromResponseExpiresIn(response.expiresIn),
814        creationTime: Date.now()
815    };
816}
817async function getErrorFromResponse(requestName, response) {
818    const responseJson = await response.json();
819    const errorData = responseJson.error;
820    return ERROR_FACTORY$1.create("request-failed" /* REQUEST_FAILED */, {
821        requestName,
822        serverCode: errorData.code,
823        serverMessage: errorData.message,
824        serverStatus: errorData.status
825    });
826}
827function getHeaders({ apiKey }) {
828    return new Headers({
829        'Content-Type': 'application/json',
830        Accept: 'application/json',
831        'x-goog-api-key': apiKey
832    });
833}
834function getHeadersWithAuth(appConfig, { refreshToken }) {
835    const headers = getHeaders(appConfig);
836    headers.append('Authorization', getAuthorizationHeader(refreshToken));
837    return headers;
838}
839/**
840 * Calls the passed in fetch wrapper and returns the response.
841 * If the returned response has a status of 5xx, re-runs the function once and
842 * returns the response.
843 */
844async function retryIfServerError(fn) {
845    const result = await fn();
846    if (result.status >= 500 && result.status < 600) {
847        // Internal Server Error. Retry request.
848        return fn();
849    }
850    return result;
851}
852function getExpiresInFromResponseExpiresIn(responseExpiresIn) {
853    // This works because the server will never respond with fractions of a second.
854    return Number(responseExpiresIn.replace('s', '000'));
855}
856function getAuthorizationHeader(refreshToken) {
857    return `${INTERNAL_AUTH_VERSION} ${refreshToken}`;
858}
859
860/**
861 * @license
862 * Copyright 2019 Google LLC
863 *
864 * Licensed under the Apache License, Version 2.0 (the "License");
865 * you may not use this file except in compliance with the License.
866 * You may obtain a copy of the License at
867 *
868 *   http://www.apache.org/licenses/LICENSE-2.0
869 *
870 * Unless required by applicable law or agreed to in writing, software
871 * distributed under the License is distributed on an "AS IS" BASIS,
872 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
873 * See the License for the specific language governing permissions and
874 * limitations under the License.
875 */
876async function createInstallationRequest(appConfig, { fid }) {
877    const endpoint = getInstallationsEndpoint(appConfig);
878    const headers = getHeaders(appConfig);
879    const body = {
880        fid,
881        authVersion: INTERNAL_AUTH_VERSION,
882        appId: appConfig.appId,
883        sdkVersion: PACKAGE_VERSION
884    };
885    const request = {
886        method: 'POST',
887        headers,
888        body: JSON.stringify(body)
889    };
890    const response = await retryIfServerError(() => fetch(endpoint, request));
891    if (response.ok) {
892        const responseValue = await response.json();
893        const registeredInstallationEntry = {
894            fid: responseValue.fid || fid,
895            registrationStatus: 2 /* COMPLETED */,
896            refreshToken: responseValue.refreshToken,
897            authToken: extractAuthTokenInfoFromResponse(responseValue.authToken)
898        };
899        return registeredInstallationEntry;
900    }
901    else {
902        throw await getErrorFromResponse('Create Installation', response);
903    }
904}
905
906/**
907 * @license
908 * Copyright 2019 Google LLC
909 *
910 * Licensed under the Apache License, Version 2.0 (the "License");
911 * you may not use this file except in compliance with the License.
912 * You may obtain a copy of the License at
913 *
914 *   http://www.apache.org/licenses/LICENSE-2.0
915 *
916 * Unless required by applicable law or agreed to in writing, software
917 * distributed under the License is distributed on an "AS IS" BASIS,
918 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
919 * See the License for the specific language governing permissions and
920 * limitations under the License.
921 */
922/** Returns a promise that resolves after given time passes. */
923function sleep(ms) {
924    return new Promise(resolve => {
925        setTimeout(resolve, ms);
926    });
927}
928
929/**
930 * @license
931 * Copyright 2019 Google LLC
932 *
933 * Licensed under the Apache License, Version 2.0 (the "License");
934 * you may not use this file except in compliance with the License.
935 * You may obtain a copy of the License at
936 *
937 *   http://www.apache.org/licenses/LICENSE-2.0
938 *
939 * Unless required by applicable law or agreed to in writing, software
940 * distributed under the License is distributed on an "AS IS" BASIS,
941 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
942 * See the License for the specific language governing permissions and
943 * limitations under the License.
944 */
945function bufferToBase64UrlSafe(array) {
946    const b64 = btoa(String.fromCharCode(...array));
947    return b64.replace(/\+/g, '-').replace(/\//g, '_');
948}
949
950/**
951 * @license
952 * Copyright 2019 Google LLC
953 *
954 * Licensed under the Apache License, Version 2.0 (the "License");
955 * you may not use this file except in compliance with the License.
956 * You may obtain a copy of the License at
957 *
958 *   http://www.apache.org/licenses/LICENSE-2.0
959 *
960 * Unless required by applicable law or agreed to in writing, software
961 * distributed under the License is distributed on an "AS IS" BASIS,
962 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
963 * See the License for the specific language governing permissions and
964 * limitations under the License.
965 */
966const VALID_FID_PATTERN = /^[cdef][\w-]{21}$/;
967const INVALID_FID = '';
968/**
969 * Generates a new FID using random values from Web Crypto API.
970 * Returns an empty string if FID generation fails for any reason.
971 */
972function generateFid() {
973    try {
974        // A valid FID has exactly 22 base64 characters, which is 132 bits, or 16.5
975        // bytes. our implementation generates a 17 byte array instead.
976        const fidByteArray = new Uint8Array(17);
977        const crypto = self.crypto || self.msCrypto;
978        crypto.getRandomValues(fidByteArray);
979        // Replace the first 4 random bits with the constant FID header of 0b0111.
980        fidByteArray[0] = 0b01110000 + (fidByteArray[0] % 0b00010000);
981        const fid = encode(fidByteArray);
982        return VALID_FID_PATTERN.test(fid) ? fid : INVALID_FID;
983    }
984    catch (_a) {
985        // FID generation errored
986        return INVALID_FID;
987    }
988}
989/** Converts a FID Uint8Array to a base64 string representation. */
990function encode(fidByteArray) {
991    const b64String = bufferToBase64UrlSafe(fidByteArray);
992    // Remove the 23rd character that was added because of the extra 4 bits at the
993    // end of our 17 byte array, and the '=' padding.
994    return b64String.substr(0, 22);
995}
996
997/**
998 * @license
999 * Copyright 2019 Google LLC
1000 *
1001 * Licensed under the Apache License, Version 2.0 (the "License");
1002 * you may not use this file except in compliance with the License.
1003 * You may obtain a copy of the License at
1004 *
1005 *   http://www.apache.org/licenses/LICENSE-2.0
1006 *
1007 * Unless required by applicable law or agreed to in writing, software
1008 * distributed under the License is distributed on an "AS IS" BASIS,
1009 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1010 * See the License for the specific language governing permissions and
1011 * limitations under the License.
1012 */
1013/** Returns a string key that can be used to identify the app. */
1014function getKey(appConfig) {
1015    return `${appConfig.appName}!${appConfig.appId}`;
1016}
1017
1018/**
1019 * @license
1020 * Copyright 2019 Google LLC
1021 *
1022 * Licensed under the Apache License, Version 2.0 (the "License");
1023 * you may not use this file except in compliance with the License.
1024 * You may obtain a copy of the License at
1025 *
1026 *   http://www.apache.org/licenses/LICENSE-2.0
1027 *
1028 * Unless required by applicable law or agreed to in writing, software
1029 * distributed under the License is distributed on an "AS IS" BASIS,
1030 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1031 * See the License for the specific language governing permissions and
1032 * limitations under the License.
1033 */
1034const fidChangeCallbacks = new Map();
1035/**
1036 * Calls the onIdChange callbacks with the new FID value, and broadcasts the
1037 * change to other tabs.
1038 */
1039function fidChanged(appConfig, fid) {
1040    const key = getKey(appConfig);
1041    callFidChangeCallbacks(key, fid);
1042    broadcastFidChange(key, fid);
1043}
1044function callFidChangeCallbacks(key, fid) {
1045    const callbacks = fidChangeCallbacks.get(key);
1046    if (!callbacks) {
1047        return;
1048    }
1049    for (const callback of callbacks) {
1050        callback(fid);
1051    }
1052}
1053function broadcastFidChange(key, fid) {
1054    const channel = getBroadcastChannel();
1055    if (channel) {
1056        channel.postMessage({ key, fid });
1057    }
1058    closeBroadcastChannel();
1059}
1060let broadcastChannel = null;
1061/** Opens and returns a BroadcastChannel if it is supported by the browser. */
1062function getBroadcastChannel() {
1063    if (!broadcastChannel && 'BroadcastChannel' in self) {
1064        broadcastChannel = new BroadcastChannel('[Firebase] FID Change');
1065        broadcastChannel.onmessage = e => {
1066            callFidChangeCallbacks(e.data.key, e.data.fid);
1067        };
1068    }
1069    return broadcastChannel;
1070}
1071function closeBroadcastChannel() {
1072    if (fidChangeCallbacks.size === 0 && broadcastChannel) {
1073        broadcastChannel.close();
1074        broadcastChannel = null;
1075    }
1076}
1077
1078/**
1079 * @license
1080 * Copyright 2019 Google LLC
1081 *
1082 * Licensed under the Apache License, Version 2.0 (the "License");
1083 * you may not use this file except in compliance with the License.
1084 * You may obtain a copy of the License at
1085 *
1086 *   http://www.apache.org/licenses/LICENSE-2.0
1087 *
1088 * Unless required by applicable law or agreed to in writing, software
1089 * distributed under the License is distributed on an "AS IS" BASIS,
1090 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1091 * See the License for the specific language governing permissions and
1092 * limitations under the License.
1093 */
1094const DATABASE_NAME = 'firebase-installations-database';
1095const DATABASE_VERSION = 1;
1096const OBJECT_STORE_NAME = 'firebase-installations-store';
1097let dbPromise = null;
1098function getDbPromise() {
1099    if (!dbPromise) {
1100        dbPromise = openDb(DATABASE_NAME, DATABASE_VERSION, upgradeDB => {
1101            // We don't use 'break' in this switch statement, the fall-through
1102            // behavior is what we want, because if there are multiple versions between
1103            // the old version and the current version, we want ALL the migrations
1104            // that correspond to those versions to run, not only the last one.
1105            // eslint-disable-next-line default-case
1106            switch (upgradeDB.oldVersion) {
1107                case 0:
1108                    upgradeDB.createObjectStore(OBJECT_STORE_NAME);
1109            }
1110        });
1111    }
1112    return dbPromise;
1113}
1114/** Assigns or overwrites the record for the given key with the given value. */
1115async function set(appConfig, value) {
1116    const key = getKey(appConfig);
1117    const db = await getDbPromise();
1118    const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite');
1119    const objectStore = tx.objectStore(OBJECT_STORE_NAME);
1120    const oldValue = await objectStore.get(key);
1121    await objectStore.put(value, key);
1122    await tx.complete;
1123    if (!oldValue || oldValue.fid !== value.fid) {
1124        fidChanged(appConfig, value.fid);
1125    }
1126    return value;
1127}
1128/** Removes record(s) from the objectStore that match the given key. */
1129async function remove(appConfig) {
vendor: 6,733 bytes, lines 1130-1304
1130    const key = getKey(appConfig);
1131    const db = await getDbPromise();
1132    const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite');
1133    await tx.objectStore(OBJECT_STORE_NAME).delete(key);
1134    await tx.complete;
1135}
1136/**
1137 * Atomically updates a record with the result of updateFn, which gets
1138 * called with the current value. If newValue is undefined, the record is
1139 * deleted instead.
1140 * @return Updated value
1141 */
1142async function update(appConfig, updateFn) {
1143    const key = getKey(appConfig);
1144    const db = await getDbPromise();
1145    const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite');
1146    const store = tx.objectStore(OBJECT_STORE_NAME);
1147    const oldValue = await store.get(key);
1148    const newValue = updateFn(oldValue);
1149    if (newValue === undefined) {
1150        await store.delete(key);
1151    }
1152    else {
1153        await store.put(newValue, key);
1154    }
1155    await tx.complete;
1156    if (newValue && (!oldValue || oldValue.fid !== newValue.fid)) {
1157        fidChanged(appConfig, newValue.fid);
1158    }
1159    return newValue;
1160}
1161
1162/**
1163 * @license
1164 * Copyright 2019 Google LLC
1165 *
1166 * Licensed under the Apache License, Version 2.0 (the "License");
1167 * you may not use this file except in compliance with the License.
1168 * You may obtain a copy of the License at
1169 *
1170 *   http://www.apache.org/licenses/LICENSE-2.0
1171 *
1172 * Unless required by applicable law or agreed to in writing, software
1173 * distributed under the License is distributed on an "AS IS" BASIS,
1174 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1175 * See the License for the specific language governing permissions and
1176 * limitations under the License.
1177 */
1178/**
1179 * Updates and returns the InstallationEntry from the database.
1180 * Also triggers a registration request if it is necessary and possible.
1181 */
1182async function getInstallationEntry(appConfig) {
1183    let registrationPromise;
1184    const installationEntry = await update(appConfig, oldEntry => {
1185        const installationEntry = updateOrCreateInstallationEntry(oldEntry);
1186        const entryWithPromise = triggerRegistrationIfNecessary(appConfig, installationEntry);
1187        registrationPromise = entryWithPromise.registrationPromise;
1188        return entryWithPromise.installationEntry;
1189    });
1190    if (installationEntry.fid === INVALID_FID) {
1191        // FID generation failed. Waiting for the FID from the server.
1192        return { installationEntry: await registrationPromise };
1193    }
1194    return {
1195        installationEntry,
1196        registrationPromise
1197    };
1198}
1199/**
1200 * Creates a new Installation Entry if one does not exist.
1201 * Also clears timed out pending requests.
1202 */
1203function updateOrCreateInstallationEntry(oldEntry) {
1204    const entry = oldEntry || {
1205        fid: generateFid(),
1206        registrationStatus: 0 /* NOT_STARTED */
1207    };
1208    return clearTimedOutRequest(entry);
1209}
1210/**
1211 * If the Firebase Installation is not registered yet, this will trigger the
1212 * registration and return an InProgressInstallationEntry.
1213 *
1214 * If registrationPromise does not exist, the installationEntry is guaranteed
1215 * to be registered.
1216 */
1217function triggerRegistrationIfNecessary(appConfig, installationEntry) {
1218    if (installationEntry.registrationStatus === 0 /* NOT_STARTED */) {
1219        if (!navigator.onLine) {
1220            // Registration required but app is offline.
1221            const registrationPromiseWithError = Promise.reject(ERROR_FACTORY$1.create("app-offline" /* APP_OFFLINE */));
1222            return {
1223                installationEntry,
1224                registrationPromise: registrationPromiseWithError
1225            };
1226        }
1227        // Try registering. Change status to IN_PROGRESS.
1228        const inProgressEntry = {
1229            fid: installationEntry.fid,
1230            registrationStatus: 1 /* IN_PROGRESS */,
1231            registrationTime: Date.now()
1232        };
1233        const registrationPromise = registerInstallation(appConfig, inProgressEntry);
1234        return { installationEntry: inProgressEntry, registrationPromise };
1235    }
1236    else if (installationEntry.registrationStatus === 1 /* IN_PROGRESS */) {
1237        return {
1238            installationEntry,
1239            registrationPromise: waitUntilFidRegistration(appConfig)
1240        };
1241    }
1242    else {
1243        return { installationEntry };
1244    }
1245}
1246/** This will be executed only once for each new Firebase Installation. */
1247async function registerInstallation(appConfig, installationEntry) {
1248    try {
1249        const registeredInstallationEntry = await createInstallationRequest(appConfig, installationEntry);
1250        return set(appConfig, registeredInstallationEntry);
1251    }
1252    catch (e) {
1253        if (isServerError(e) && e.customData.serverCode === 409) {
1254            // Server returned a "FID can not be used" error.
1255            // Generate a new ID next time.
1256            await remove(appConfig);
1257        }
1258        else {
1259            // Registration failed. Set FID as not registered.
1260            await set(appConfig, {
1261                fid: installationEntry.fid,
1262                registrationStatus: 0 /* NOT_STARTED */
1263            });
1264        }
1265        throw e;
1266    }
1267}
1268/** Call if FID registration is pending in another request. */
1269async function waitUntilFidRegistration(appConfig) {
1270    // Unfortunately, there is no way of reliably observing when a value in
1271    // IndexedDB changes (yet, see https://github.com/WICG/indexed-db-observers),
1272    // so we need to poll.
1273    let entry = await updateInstallationRequest(appConfig);
1274    while (entry.registrationStatus === 1 /* IN_PROGRESS */) {
1275        // createInstallation request still in progress.
1276        await sleep(100);
1277        entry = await updateInstallationRequest(appConfig);
1278    }
1279    if (entry.registrationStatus === 0 /* NOT_STARTED */) {
1280        // The request timed out or failed in a different call. Try again.
1281        const { installationEntry, registrationPromise } = await getInstallationEntry(appConfig);
1282        if (registrationPromise) {
1283            return registrationPromise;
1284        }
1285        else {
1286            // if there is no registrationPromise, entry is registered.
1287            return installationEntry;
1288        }
1289    }
1290    return entry;
1291}
1292/**
1293 * Called only if there is a CreateInstallation request in progress.
1294 *
1295 * Updates the InstallationEntry in the DB based on the status of the
1296 * CreateInstallation request.
1297 *
1298 * Returns the updated InstallationEntry.
1299 */
1300function updateInstallationRequest(appConfig) {
1301    return update(appConfig, oldEntry => {
1302        if (!oldEntry) {
1303            throw ERROR_FACTORY$1.create("installation-not-found" /* INSTALLATION_NOT_FOUND */);
1304        }
1305        return clearTimedOutRequest(oldEntry);
1306    });
1307}
1308function clearTimedOutRequest(entry) {
1309    if (hasInstallationRequestTimedOut(entry)) {
1310        return {
1311            fid: entry.fid,
1312            registrationStatus: 0 /* NOT_STARTED */
1313        };
1314    }
1315    return entry;
1316}
1317function hasInstallationRequestTimedOut(installationEntry) {
1318    return (installationEntry.registrationStatus === 1 /* IN_PROGRESS */ &&
1319        installationEntry.registrationTime + PENDING_TIMEOUT_MS < Date.now());
1320}
1321
1322/**
1323 * @license
1324 * Copyright 2019 Google LLC
1325 *
1326 * Licensed under the Apache License, Version 2.0 (the "License");
1327 * you may not use this file except in compliance with the License.
1328 * You may obtain a copy of the License at
1329 *
1330 *   http://www.apache.org/licenses/LICENSE-2.0
1331 *
1332 * Unless required by applicable law or agreed to in writing, software
1333 * distributed under the License is distributed on an "AS IS" BASIS,
1334 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1335 * See the License for the specific language governing permissions and
1336 * limitations under the License.
1337 */
1338async function generateAuthTokenRequest({ appConfig, platformLoggerProvider }, installationEntry) {
1339    const endpoint = getGenerateAuthTokenEndpoint(appConfig, installationEntry);
1340    const headers = getHeadersWithAuth(appConfig, installationEntry);
1341    // If platform logger exists, add the platform info string to the header.
1342    const platformLogger = platformLoggerProvider.getImmediate({
1343        optional: true
1344    });
1345    if (platformLogger) {
1346        headers.append('x-firebase-client', platformLogger.getPlatformInfoString());
1347    }
1348    const body = {
1349        installation: {
1350            sdkVersion: PACKAGE_VERSION
1351        }
1352    };
1353    const request = {
1354        method: 'POST',
1355        headers,
1356        body: JSON.stringify(body)
1357    };
1358    const response = await retryIfServerError(() => fetch(endpoint, request));
1359    if (response.ok) {
1360        const responseValue = await response.json();
vendor: 4,317 bytes, lines 1361-1468
1361        const completedAuthToken = extractAuthTokenInfoFromResponse(responseValue);
1362        return completedAuthToken;
1363    }
1364    else {
1365        throw await getErrorFromResponse('Generate Auth Token', response);
1366    }
1367}
1368function getGenerateAuthTokenEndpoint(appConfig, { fid }) {
1369    return `${getInstallationsEndpoint(appConfig)}/${fid}/authTokens:generate`;
1370}
1371
1372/**
1373 * @license
1374 * Copyright 2019 Google LLC
1375 *
1376 * Licensed under the Apache License, Version 2.0 (the "License");
1377 * you may not use this file except in compliance with the License.
1378 * You may obtain a copy of the License at
1379 *
1380 *   http://www.apache.org/licenses/LICENSE-2.0
1381 *
1382 * Unless required by applicable law or agreed to in writing, software
1383 * distributed under the License is distributed on an "AS IS" BASIS,
1384 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1385 * See the License for the specific language governing permissions and
1386 * limitations under the License.
1387 */
1388/**
1389 * Returns a valid authentication token for the installation. Generates a new
1390 * token if one doesn't exist, is expired or about to expire.
1391 *
1392 * Should only be called if the Firebase Installation is registered.
1393 */
1394async function refreshAuthToken(installations, forceRefresh = false) {
1395    let tokenPromise;
1396    const entry = await update(installations.appConfig, oldEntry => {
1397        if (!isEntryRegistered(oldEntry)) {
1398            throw ERROR_FACTORY$1.create("not-registered" /* NOT_REGISTERED */);
1399        }
1400        const oldAuthToken = oldEntry.authToken;
1401        if (!forceRefresh && isAuthTokenValid(oldAuthToken)) {
1402            // There is a valid token in the DB.
1403            return oldEntry;
1404        }
1405        else if (oldAuthToken.requestStatus === 1 /* IN_PROGRESS */) {
1406            // There already is a token request in progress.
1407            tokenPromise = waitUntilAuthTokenRequest(installations, forceRefresh);
1408            return oldEntry;
1409        }
1410        else {
1411            // No token or token expired.
1412            if (!navigator.onLine) {
1413                throw ERROR_FACTORY$1.create("app-offline" /* APP_OFFLINE */);
1414            }
1415            const inProgressEntry = makeAuthTokenRequestInProgressEntry(oldEntry);
1416            tokenPromise = fetchAuthTokenFromServer(installations, inProgressEntry);
1417            return inProgressEntry;
1418        }
1419    });
1420    const authToken = tokenPromise
1421        ? await tokenPromise
1422        : entry.authToken;
1423    return authToken;
1424}
1425/**
1426 * Call only if FID is registered and Auth Token request is in progress.
1427 *
1428 * Waits until the current pending request finishes. If the request times out,
1429 * tries once in this thread as well.
1430 */
1431async function waitUntilAuthTokenRequest(installations, forceRefresh) {
1432    // Unfortunately, there is no way of reliably observing when a value in
1433    // IndexedDB changes (yet, see https://github.com/WICG/indexed-db-observers),
1434    // so we need to poll.
1435    let entry = await updateAuthTokenRequest(installations.appConfig);
1436    while (entry.authToken.requestStatus === 1 /* IN_PROGRESS */) {
1437        // generateAuthToken still in progress.
1438        await sleep(100);
1439        entry = await updateAuthTokenRequest(installations.appConfig);
1440    }
1441    const authToken = entry.authToken;
1442    if (authToken.requestStatus === 0 /* NOT_STARTED */) {
1443        // The request timed out or failed in a different call. Try again.
1444        return refreshAuthToken(installations, forceRefresh);
1445    }
1446    else {
1447        return authToken;
1448    }
1449}
1450/**
1451 * Called only if there is a GenerateAuthToken request in progress.
1452 *
1453 * Updates the InstallationEntry in the DB based on the status of the
1454 * GenerateAuthToken request.
1455 *
1456 * Returns the updated InstallationEntry.
1457 */
1458function updateAuthTokenRequest(appConfig) {
1459    return update(appConfig, oldEntry => {
1460        if (!isEntryRegistered(oldEntry)) {
1461            throw ERROR_FACTORY$1.create("not-registered" /* NOT_REGISTERED */);
1462        }
1463        const oldAuthToken = oldEntry.authToken;
1464        if (hasAuthTokenRequestTimedOut(oldAuthToken)) {
1465            return Object.assign(Object.assign({}, oldEntry), { authToken: { requestStatus: 0 /* NOT_STARTED */ } });
1466        }
1467        return oldEntry;
1468    });
1469}
1470async function fetchAuthTokenFromServer(installations, installationEntry) {
1471    try {
1472        const authToken = await generateAuthTokenRequest(installations, installationEntry);
1473        const updatedInstallationEntry = Object.assign(Object.assign({}, installationEntry), { authToken });
1474        await set(installations.appConfig, updatedInstallationEntry);
1475        return authToken;
1476    }
1477    catch (e) {
1478        if (isServerError(e) &&
1479            (e.customData.serverCode === 401 || e.customData.serverCode === 404)) {
1480            // Server returned a "FID not found" or a "Invalid authentication" error.
1481            // Generate a new ID next time.
1482            await remove(installations.appConfig);
1483        }
1484        else {
1485            const updatedInstallationEntry = Object.assign(Object.assign({}, installationEntry), { authToken: { requestStatus: 0 /* NOT_STARTED */ } });
1486            await set(installations.appConfig, updatedInstallationEntry);
1487        }
1488        throw e;
1489    }
1490}
1491function isEntryRegistered(installationEntry) {
1492    return (installationEntry !== undefined &&
1493        installationEntry.registrationStatus === 2 /* COMPLETED */);
1494}
1495function isAuthTokenValid(authToken) {
1496    return (authToken.requestStatus === 2 /* COMPLETED */ &&
1497        !isAuthTokenExpired(authToken));
1498}
1499function isAuthTokenExpired(authToken) {
1500    const now = Date.now();
1501    return (now < authToken.creationTime ||
1502        authToken.creationTime + authToken.expiresIn < now + TOKEN_EXPIRATION_BUFFER);
1503}
1504/** Returns an updated InstallationEntry with an InProgressAuthToken. */
1505function makeAuthTokenRequestInProgressEntry(oldEntry) {
1506    const inProgressAuthToken = {
1507        requestStatus: 1 /* IN_PROGRESS */,
1508        requestTime: Date.now()
1509    };
1510    return Object.assign(Object.assign({}, oldEntry), { authToken: inProgressAuthToken });
1511}
1512function hasAuthTokenRequestTimedOut(authToken) {
1513    return (authToken.requestStatus === 1 /* IN_PROGRESS */ &&
1514        authToken.requestTime + PENDING_TIMEOUT_MS < Date.now());
1515}
1516
1517/**
1518 * @license
1519 * Copyright 2019 Google LLC
1520 *
1521 * Licensed under the Apache License, Version 2.0 (the "License");
1522 * you may not use this file except in compliance with the License.
1523 * You may obtain a copy of the License at
1524 *
1525 *   http://www.apache.org/licenses/LICENSE-2.0
1526 *
1527 * Unless required by applicable law or agreed to in writing, software
1528 * distributed under the License is distributed on an "AS IS" BASIS,
1529 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1530 * See the License for the specific language governing permissions and
1531 * limitations under the License.
1532 */
1533/**
1534 * Creates a Firebase Installation if there isn't one for the app and
1535 * returns the Installation ID.
1536 * @param installations - The `Installations` instance.
1537 *
1538 * @public
1539 */
1540async function getId(installations) {
1541    const installationsImpl = installations;
1542    const { installationEntry, registrationPromise } = await getInstallationEntry(installationsImpl.appConfig);
1543    if (registrationPromise) {
1544        registrationPromise.catch(console.error);
1545    }
1546    else {
1547        // If the installation is already registered, update the authentication
1548        // token if needed.
1549        refreshAuthToken(installationsImpl).catch(console.error);
1550    }
1551    return installationEntry.fid;
1552}
1553
1554/**
1555 * @license
1556 * Copyright 2019 Google LLC
1557 *
1558 * Licensed under the Apache License, Version 2.0 (the "License");
1559 * you may not use this file except in compliance with the License.
1560 * You may obtain a copy of the License at
1561 *
1562 *   http://www.apache.org/licenses/LICENSE-2.0
1563 *
1564 * Unless required by applicable law or agreed to in writing, software
1565 * distributed under the License is distributed on an "AS IS" BASIS,
1566 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1567 * See the License for the specific language governing permissions and
1568 * limitations under the License.
1569 */
1570/**
1571 * Returns a Firebase Installations auth token, identifying the current
1572 * Firebase Installation.
1573 * @param installations - The `Installations` instance.
1574 * @param forceRefresh - Force refresh regardless of token expiration.
1575 *
1576 * @public
1577 */
1578async function getToken(installations, forceRefresh = false) {
1579    const installationsImpl = installations;
1580    await completeInstallationRegistration(installationsImpl.appConfig);
1581    // At this point we either have a Registered Installation in the DB, or we've
1582    // already thrown an error.
1583    const authToken = await refreshAuthToken(installationsImpl, forceRefresh);
1584    return authToken.token;
1585}
1586async function completeInstallationRegistration(appConfig) {
1587    const { registrationPromise } = await getInstallationEntry(appConfig);
1588    if (registrationPromise) {
1589        // A createInstallation request is in progress. Wait until it finishes.
1590        await registrationPromise;
1591    }
1592}
1593
1594/**
1595 * @license
1596 * Copyright 2019 Google LLC
1597 *
1598 * Licensed under the Apache License, Version 2.0 (the "License");
1599 * you may not use this file except in compliance with the License.
1600 * You may obtain a copy of the License at
1601 *
1602 *   http://www.apache.org/licenses/LICENSE-2.0
1603 *
1604 * Unless required by applicable law or agreed to in writing, software
1605 * distributed under the License is distributed on an "AS IS" BASIS,
1606 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1607 * See the License for the specific language governing permissions and
1608 * limitations under the License.
1609 */
1610function extractAppConfig(app) {
1611    if (!app || !app.options) {
1612        throw getMissingValueError('App Configuration');
1613    }
1614    if (!app.name) {
1615        throw getMissingValueError('App Name');
1616    }
1617    // Required app config keys
1618    const configKeys = [
1619        'projectId',
1620        'apiKey',
1621        'appId'
1622    ];
1623    for (const keyName of configKeys) {
1624        if (!app.options[keyName]) {
1625            throw getMissingValueError(keyName);
1626        }
1627    }
1628    return {
1629        appName: app.name,
1630        projectId: app.options.projectId,
1631        apiKey: app.options.apiKey,
1632        appId: app.options.appId
1633    };
1634}
1635function getMissingValueError(valueName) {
1636    return ERROR_FACTORY$1.create("missing-app-config-values" /* MISSING_APP_CONFIG_VALUES */, {
1637        valueName
1638    });
1639}
1640
1641/**
1642 * @license
1643 * Copyright 2020 Google LLC
1644 *
1645 * Licensed under the Apache License, Version 2.0 (the "License");
1646 * you may not use this file except in compliance with the License.
1647 * You may obtain a copy of the License at
1648 *
1649 *   http://www.apache.org/licenses/LICENSE-2.0
1650 *
1651 * Unless required by applicable law or agreed to in writing, software
1652 * distributed under the License is distributed on an "AS IS" BASIS,
1653 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1654 * See the License for the specific language governing permissions and
1655 * limitations under the License.
1656 */
1657const INSTALLATIONS_NAME = 'installations';
1658const INSTALLATIONS_NAME_INTERNAL = 'installations-internal';
1659const publicFactory = (container) => {
1660    const app = container.getProvider('app').getImmediate();
1661    // Throws if app isn't configured properly.
1662    const appConfig = extractAppConfig(app);
1663    const platformLoggerProvider = _getProvider(app, 'platform-logger');
1664    const installationsImpl = {
1665        app,
1666        appConfig,
1667        platformLoggerProvider,
1668        _delete: () => Promise.resolve()
1669    };
1670    return installationsImpl;
1671};
1672const internalFactory = (container) => {
1673    const app = container.getProvider('app').getImmediate();
1674    // Internal FIS instance relies on public FIS instance.
1675    const installations = _getProvider(app, INSTALLATIONS_NAME).getImmediate();
1676    const installationsInternal = {
1677        getId: () => getId(installations),
1678        getToken: (forceRefresh) => getToken(installations, forceRefresh)
1679    };
1680    return installationsInternal;
1681};
1682function registerInstallations() {
1683    _registerComponent(new Component(INSTALLATIONS_NAME, publicFactory, "PUBLIC" /* PUBLIC */));
1684    _registerComponent(new Component(INSTALLATIONS_NAME_INTERNAL, internalFactory, "PRIVATE" /* PRIVATE */));
1685}
1686
1687/**
1688 * Firebase Installations
1689 *
1690 * @packageDocumentation
1691 */
1692registerInstallations();
1693registerVersion(name$1, version$1);
1694// BUILD_TARGET will be replaced by values like esm5, esm2017, cjs5, etc during the compilation
1695registerVersion(name$1, version$1, 'esm2017');
1696
1697const name = "@firebase/performance";
1698const version = "0.5.5";
1699
1700/**
1701 * @license
1702 * Copyright 2020 Google LLC
1703 *
1704 * Licensed under the Apache License, Version 2.0 (the "License");
1705 * you may not use this file except in compliance with the License.
1706 * You may obtain a copy of the License at
1707 *
1708 *   http://www.apache.org/licenses/LICENSE-2.0
1709 *
1710 * Unless required by applicable law or agreed to in writing, software
1711 * distributed under the License is distributed on an "AS IS" BASIS,
1712 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1713 * See the License for the specific language governing permissions and
1714 * limitations under the License.
1715 */
1716const SDK_VERSION = version;
1717/** The prefix for start User Timing marks used for creating Traces. */
1718const TRACE_START_MARK_PREFIX = 'FB-PERF-TRACE-START';
1719/** The prefix for stop User Timing marks used for creating Traces. */
1720const TRACE_STOP_MARK_PREFIX = 'FB-PERF-TRACE-STOP';
1721/** The prefix for User Timing measure used for creating Traces. */
1722const TRACE_MEASURE_PREFIX = 'FB-PERF-TRACE-MEASURE';
1723/** The prefix for out of the box page load Trace name. */
1724const OOB_TRACE_PAGE_LOAD_PREFIX = '_wt_';
1725const FIRST_PAINT_COUNTER_NAME = '_fp';
1726const FIRST_CONTENTFUL_PAINT_COUNTER_NAME = '_fcp';
1727const FIRST_INPUT_DELAY_COUNTER_NAME = '_fid';
1728const CONFIG_LOCAL_STORAGE_KEY = '@firebase/performance/config';
1729const CONFIG_EXPIRY_LOCAL_STORAGE_KEY = '@firebase/performance/configexpire';
1730const SERVICE = 'performance';
vendor: 21,815 bytes, lines 1731-2277
1731const SERVICE_NAME = 'Performance';
1732
1733/**
1734 * @license
1735 * Copyright 2020 Google LLC
1736 *
1737 * Licensed under the Apache License, Version 2.0 (the "License");
1738 * you may not use this file except in compliance with the License.
1739 * You may obtain a copy of the License at
1740 *
1741 *   http://www.apache.org/licenses/LICENSE-2.0
1742 *
1743 * Unless required by applicable law or agreed to in writing, software
1744 * distributed under the License is distributed on an "AS IS" BASIS,
1745 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1746 * See the License for the specific language governing permissions and
1747 * limitations under the License.
1748 */
1749const ERROR_DESCRIPTION_MAP = {
1750    ["trace started" /* TRACE_STARTED_BEFORE */]: 'Trace {$traceName} was started before.',
1751    ["trace stopped" /* TRACE_STOPPED_BEFORE */]: 'Trace {$traceName} is not running.',
1752    ["nonpositive trace startTime" /* NONPOSITIVE_TRACE_START_TIME */]: 'Trace {$traceName} startTime should be positive.',
1753    ["nonpositive trace duration" /* NONPOSITIVE_TRACE_DURATION */]: 'Trace {$traceName} duration should be positive.',
1754    ["no window" /* NO_WINDOW */]: 'Window is not available.',
1755    ["no app id" /* NO_APP_ID */]: 'App id is not available.',
1756    ["no project id" /* NO_PROJECT_ID */]: 'Project id is not available.',
1757    ["no api key" /* NO_API_KEY */]: 'Api key is not available.',
1758    ["invalid cc log" /* INVALID_CC_LOG */]: 'Attempted to queue invalid cc event',
1759    ["FB not default" /* FB_NOT_DEFAULT */]: 'Performance can only start when Firebase app instance is the default one.',
1760    ["RC response not ok" /* RC_NOT_OK */]: 'RC response is not ok',
1761    ["invalid attribute name" /* INVALID_ATTRIBUTE_NAME */]: 'Attribute name {$attributeName} is invalid.',
1762    ["invalid attribute value" /* INVALID_ATTRIBUTE_VALUE */]: 'Attribute value {$attributeValue} is invalid.',
1763    ["invalid custom metric name" /* INVALID_CUSTOM_METRIC_NAME */]: 'Custom metric name {$customMetricName} is invalid',
1764    ["invalid String merger input" /* INVALID_STRING_MERGER_PARAMETER */]: 'Input for String merger is invalid, contact support team to resolve.',
1765    ["already initialized" /* ALREADY_INITIALIZED */]: 'initializePerformance() has already been called with ' +
1766        'different options. To avoid this error, call initializePerformance() with the ' +
1767        'same options as when it was originally called, or call getPerformance() to return the' +
1768        ' already initialized instance.'
1769};
1770const ERROR_FACTORY = new ErrorFactory(SERVICE, SERVICE_NAME, ERROR_DESCRIPTION_MAP);
1771
1772/**
1773 * @license
1774 * Copyright 2020 Google LLC
1775 *
1776 * Licensed under the Apache License, Version 2.0 (the "License");
1777 * you may not use this file except in compliance with the License.
1778 * You may obtain a copy of the License at
1779 *
1780 *   http://www.apache.org/licenses/LICENSE-2.0
1781 *
1782 * Unless required by applicable law or agreed to in writing, software
1783 * distributed under the License is distributed on an "AS IS" BASIS,
1784 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1785 * See the License for the specific language governing permissions and
1786 * limitations under the License.
1787 */
1788const consoleLogger = new Logger(SERVICE_NAME);
1789consoleLogger.logLevel = LogLevel.INFO;
1790
1791/**
1792 * @license
1793 * Copyright 2020 Google LLC
1794 *
1795 * Licensed under the Apache License, Version 2.0 (the "License");
1796 * you may not use this file except in compliance with the License.
1797 * You may obtain a copy of the License at
1798 *
1799 *   http://www.apache.org/licenses/LICENSE-2.0
1800 *
1801 * Unless required by applicable law or agreed to in writing, software
1802 * distributed under the License is distributed on an "AS IS" BASIS,
1803 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1804 * See the License for the specific language governing permissions and
1805 * limitations under the License.
1806 */
1807let apiInstance;
1808let windowInstance;
1809/**
1810 * This class holds a reference to various browser related objects injected by
1811 * set methods.
1812 */
1813class Api {
1814    constructor(window) {
1815        this.window = window;
1816        if (!window) {
1817            throw ERROR_FACTORY.create("no window" /* NO_WINDOW */);
1818        }
1819        this.performance = window.performance;
1820        this.PerformanceObserver = window.PerformanceObserver;
1821        this.windowLocation = window.location;
1822        this.navigator = window.navigator;
1823        this.document = window.document;
1824        if (this.navigator && this.navigator.cookieEnabled) {
1825            // If user blocks cookies on the browser, accessing localStorage will
1826            // throw an exception.
1827            this.localStorage = window.localStorage;
1828        }
1829        if (window.perfMetrics && window.perfMetrics.onFirstInputDelay) {
1830            this.onFirstInputDelay = window.perfMetrics.onFirstInputDelay;
1831        }
1832    }
1833    getUrl() {
1834        // Do not capture the string query part of url.
1835        return this.windowLocation.href.split('?')[0];
1836    }
1837    mark(name) {
1838        if (!this.performance || !this.performance.mark) {
1839            return;
1840        }
1841        this.performance.mark(name);
1842    }
1843    measure(measureName, mark1, mark2) {
1844        if (!this.performance || !this.performance.measure) {
1845            return;
1846        }
1847        this.performance.measure(measureName, mark1, mark2);
1848    }
1849    getEntriesByType(type) {
1850        if (!this.performance || !this.performance.getEntriesByType) {
1851            return [];
1852        }
1853        return this.performance.getEntriesByType(type);
1854    }
1855    getEntriesByName(name) {
1856        if (!this.performance || !this.performance.getEntriesByName) {
1857            return [];
1858        }
1859        return this.performance.getEntriesByName(name);
1860    }
1861    getTimeOrigin() {
1862        // Polyfill the time origin with performance.timing.navigationStart.
1863        return (this.performance &&
1864            (this.performance.timeOrigin || this.performance.timing.navigationStart));
1865    }
1866    requiredApisAvailable() {
1867        if (!fetch || !Promise || !areCookiesEnabled()) {
1868            consoleLogger.info('Firebase Performance cannot start if browser does not support fetch and Promise or cookie is disabled.');
1869            return false;
1870        }
1871        if (!isIndexedDBAvailable()) {
1872            consoleLogger.info('IndexedDB is not supported by current browswer');
1873            return false;
1874        }
1875        return true;
1876    }
1877    setupObserver(entryType, callback) {
1878        if (!this.PerformanceObserver) {
1879            return;
1880        }
1881        const observer = new this.PerformanceObserver(list => {
1882            for (const entry of list.getEntries()) {
1883                // `entry` is a PerformanceEntry instance.
1884                callback(entry);
1885            }
1886        });
1887        // Start observing the entry types you care about.
1888        observer.observe({ entryTypes: [entryType] });
1889    }
1890    static getInstance() {
1891        if (apiInstance === undefined) {
1892            apiInstance = new Api(windowInstance);
1893        }
1894        return apiInstance;
1895    }
1896}
1897function setupApi(window) {
1898    windowInstance = window;
1899}
1900
1901/**
1902 * @license
1903 * Copyright 2020 Google LLC
1904 *
1905 * Licensed under the Apache License, Version 2.0 (the "License");
1906 * you may not use this file except in compliance with the License.
1907 * You may obtain a copy of the License at
1908 *
1909 *   http://www.apache.org/licenses/LICENSE-2.0
1910 *
1911 * Unless required by applicable law or agreed to in writing, software
1912 * distributed under the License is distributed on an "AS IS" BASIS,
1913 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1914 * See the License for the specific language governing permissions and
1915 * limitations under the License.
1916 */
1917let iid;
1918function getIidPromise(installationsService) {
1919    const iidPromise = installationsService.getId();
1920    // eslint-disable-next-line @typescript-eslint/no-floating-promises
1921    iidPromise.then((iidVal) => {
1922        iid = iidVal;
1923    });
1924    return iidPromise;
1925}
1926// This method should be used after the iid is retrieved by getIidPromise method.
1927function getIid() {
1928    return iid;
1929}
1930function getAuthTokenPromise(installationsService) {
1931    const authTokenPromise = installationsService.getToken();
1932    // eslint-disable-next-line @typescript-eslint/no-floating-promises
1933    authTokenPromise.then((authTokenVal) => {
1934    });
1935    return authTokenPromise;
1936}
1937
1938/**
1939 * @license
1940 * Copyright 2020 Google LLC
1941 *
1942 * Licensed under the Apache License, Version 2.0 (the "License");
1943 * you may not use this file except in compliance with the License.
1944 * You may obtain a copy of the License at
1945 *
1946 *   http://www.apache.org/licenses/LICENSE-2.0
1947 *
1948 * Unless required by applicable law or agreed to in writing, software
1949 * distributed under the License is distributed on an "AS IS" BASIS,
1950 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1951 * See the License for the specific language governing permissions and
1952 * limitations under the License.
1953 */
1954function mergeStrings(part1, part2) {
1955    const sizeDiff = part1.length - part2.length;
1956    if (sizeDiff < 0 || sizeDiff > 1) {
1957        throw ERROR_FACTORY.create("invalid String merger input" /* INVALID_STRING_MERGER_PARAMETER */);
1958    }
1959    const resultArray = [];
1960    for (let i = 0; i < part1.length; i++) {
1961        resultArray.push(part1.charAt(i));
1962        if (part2.length > i) {
1963            resultArray.push(part2.charAt(i));
1964        }
1965    }
1966    return resultArray.join('');
1967}
1968
1969/**
1970 * @license
1971 * Copyright 2019 Google LLC
1972 *
1973 * Licensed under the Apache License, Version 2.0 (the "License");
1974 * you may not use this file except in compliance with the License.
1975 * You may obtain a copy of the License at
1976 *
1977 *   http://www.apache.org/licenses/LICENSE-2.0
1978 *
1979 * Unless required by applicable law or agreed to in writing, software
1980 * distributed under the License is distributed on an "AS IS" BASIS,
1981 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1982 * See the License for the specific language governing permissions and
1983 * limitations under the License.
1984 */
1985let settingsServiceInstance;
1986class SettingsService {
1987    constructor() {
1988        // The variable which controls logging of automatic traces and HTTP/S network monitoring.
1989        this.instrumentationEnabled = true;
1990        // The variable which controls logging of custom traces.
1991        this.dataCollectionEnabled = true;
1992        // Configuration flags set through remote config.
1993        this.loggingEnabled = false;
1994        // Sampling rate between 0 and 1.
1995        this.tracesSamplingRate = 1;
1996        this.networkRequestsSamplingRate = 1;
1997        // Address of logging service.
1998        this.logEndPointUrl = 'https://firebaselogging.googleapis.com/v0cc/log?format=json_proto';
1999        // Performance event transport endpoint URL which should be compatible with proto3.
2000        // New Address for transport service, not configurable via Remote Config.
2001        this.flTransportEndpointUrl = mergeStrings('hts/frbslgigp.ogepscmv/ieo/eaylg', 'tp:/ieaeogn-agolai.o/1frlglgc/o');
2002        this.transportKey = mergeStrings('AzSC8r6ReiGqFMyfvgow', 'Iayx0u-XT3vksVM-pIV');
2003        // Source type for performance event logs.
2004        this.logSource = 462;
2005        // Flags which control per session logging of traces and network requests.
2006        this.logTraceAfterSampling = false;
2007        this.logNetworkAfterSampling = false;
2008        // TTL of config retrieved from remote config in hours.
2009        this.configTimeToLive = 12;
2010    }
2011    getFlTransportFullUrl() {
2012        return this.flTransportEndpointUrl.concat('?key=', this.transportKey);
2013    }
2014    static getInstance() {
2015        if (settingsServiceInstance === undefined) {
2016            settingsServiceInstance = new SettingsService();
2017        }
2018        return settingsServiceInstance;
2019    }
2020}
2021
2022/**
2023 * @license
2024 * Copyright 2020 Google LLC
2025 *
2026 * Licensed under the Apache License, Version 2.0 (the "License");
2027 * you may not use this file except in compliance with the License.
2028 * You may obtain a copy of the License at
2029 *
2030 *   http://www.apache.org/licenses/LICENSE-2.0
2031 *
2032 * Unless required by applicable law or agreed to in writing, software
2033 * distributed under the License is distributed on an "AS IS" BASIS,
2034 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2035 * See the License for the specific language governing permissions and
2036 * limitations under the License.
2037 */
2038var VisibilityState;
2039(function (VisibilityState) {
2040    VisibilityState[VisibilityState["UNKNOWN"] = 0] = "UNKNOWN";
2041    VisibilityState[VisibilityState["VISIBLE"] = 1] = "VISIBLE";
2042    VisibilityState[VisibilityState["HIDDEN"] = 2] = "HIDDEN";
2043})(VisibilityState || (VisibilityState = {}));
2044const RESERVED_ATTRIBUTE_PREFIXES = ['firebase_', 'google_', 'ga_'];
2045const ATTRIBUTE_FORMAT_REGEX = new RegExp('^[a-zA-Z]\\w*$');
2046const MAX_ATTRIBUTE_NAME_LENGTH = 40;
2047const MAX_ATTRIBUTE_VALUE_LENGTH = 100;
2048function getServiceWorkerStatus() {
2049    const navigator = Api.getInstance().navigator;
2050    if ('serviceWorker' in navigator) {
2051        if (navigator.serviceWorker.controller) {
2052            return 2 /* CONTROLLED */;
2053        }
2054        else {
2055            return 3 /* UNCONTROLLED */;
2056        }
2057    }
2058    else {
2059        return 1 /* UNSUPPORTED */;
2060    }
2061}
2062function getVisibilityState() {
2063    const document = Api.getInstance().document;
2064    const visibilityState = document.visibilityState;
2065    switch (visibilityState) {
2066        case 'visible':
2067            return VisibilityState.VISIBLE;
2068        case 'hidden':
2069            return VisibilityState.HIDDEN;
2070        default:
2071            return VisibilityState.UNKNOWN;
2072    }
2073}
2074function getEffectiveConnectionType() {
2075    const navigator = Api.getInstance().navigator;
2076    const navigatorConnection = navigator.connection;
2077    const effectiveType = navigatorConnection && navigatorConnection.effectiveType;
2078    switch (effectiveType) {
2079        case 'slow-2g':
2080            return 1 /* CONNECTION_SLOW_2G */;
2081        case '2g':
2082            return 2 /* CONNECTION_2G */;
2083        case '3g':
2084            return 3 /* CONNECTION_3G */;
2085        case '4g':
2086            return 4 /* CONNECTION_4G */;
2087        default:
2088            return 0 /* UNKNOWN */;
2089    }
2090}
2091function isValidCustomAttributeName(name) {
2092    if (name.length === 0 || name.length > MAX_ATTRIBUTE_NAME_LENGTH) {
2093        return false;
2094    }
2095    const matchesReservedPrefix = RESERVED_ATTRIBUTE_PREFIXES.some(prefix => name.startsWith(prefix));
2096    return !matchesReservedPrefix && !!name.match(ATTRIBUTE_FORMAT_REGEX);
2097}
2098function isValidCustomAttributeValue(value) {
2099    return value.length !== 0 && value.length <= MAX_ATTRIBUTE_VALUE_LENGTH;
2100}
2101
2102/**
2103 * @license
2104 * Copyright 2020 Google LLC
2105 *
2106 * Licensed under the Apache License, Version 2.0 (the "License");
2107 * you may not use this file except in compliance with the License.
2108 * You may obtain a copy of the License at
2109 *
2110 *   http://www.apache.org/licenses/LICENSE-2.0
2111 *
2112 * Unless required by applicable law or agreed to in writing, software
2113 * distributed under the License is distributed on an "AS IS" BASIS,
2114 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2115 * See the License for the specific language governing permissions and
2116 * limitations under the License.
2117 */
2118function getAppId(firebaseApp) {
2119    var _a;
2120    const appId = (_a = firebaseApp.options) === null || _a === void 0 ? void 0 : _a.appId;
2121    if (!appId) {
2122        throw ERROR_FACTORY.create("no app id" /* NO_APP_ID */);
2123    }
2124    return appId;
2125}
2126function getProjectId(firebaseApp) {
2127    var _a;
2128    const projectId = (_a = firebaseApp.options) === null || _a === void 0 ? void 0 : _a.projectId;
2129    if (!projectId) {
2130        throw ERROR_FACTORY.create("no project id" /* NO_PROJECT_ID */);
2131    }
2132    return projectId;
2133}
2134function getApiKey(firebaseApp) {
2135    var _a;
2136    const apiKey = (_a = firebaseApp.options) === null || _a === void 0 ? void 0 : _a.apiKey;
2137    if (!apiKey) {
2138        throw ERROR_FACTORY.create("no api key" /* NO_API_KEY */);
2139    }
2140    return apiKey;
2141}
2142
2143/**
2144 * @license
2145 * Copyright 2020 Google LLC
2146 *
2147 * Licensed under the Apache License, Version 2.0 (the "License");
2148 * you may not use this file except in compliance with the License.
2149 * You may obtain a copy of the License at
2150 *
2151 *   http://www.apache.org/licenses/LICENSE-2.0
2152 *
2153 * Unless required by applicable law or agreed to in writing, software
2154 * distributed under the License is distributed on an "AS IS" BASIS,
2155 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2156 * See the License for the specific language governing permissions and
2157 * limitations under the License.
2158 */
2159const REMOTE_CONFIG_SDK_VERSION = '0.0.1';
2160// These values will be used if the remote config object is successfully
2161// retrieved, but the template does not have these fields.
2162const DEFAULT_CONFIGS = {
2163    loggingEnabled: true
2164};
2165const FIS_AUTH_PREFIX = 'FIREBASE_INSTALLATIONS_AUTH';
2166function getConfig(performanceController, iid) {
2167    const config = getStoredConfig();
2168    if (config) {
2169        processConfig(config);
2170        return Promise.resolve();
2171    }
2172    return getRemoteConfig(performanceController, iid)
2173        .then(processConfig)
2174        .then(config => storeConfig(config), 
2175    /** Do nothing for error, use defaults set in settings service. */
2176    () => { });
2177}
2178function getStoredConfig() {
2179    const localStorage = Api.getInstance().localStorage;
2180    if (!localStorage) {
2181        return;
2182    }
2183    const expiryString = localStorage.getItem(CONFIG_EXPIRY_LOCAL_STORAGE_KEY);
2184    if (!expiryString || !configValid(expiryString)) {
2185        return;
2186    }
2187    const configStringified = localStorage.getItem(CONFIG_LOCAL_STORAGE_KEY);
2188    if (!configStringified) {
2189        return;
2190    }
2191    try {
2192        const configResponse = JSON.parse(configStringified);
2193        return configResponse;
2194    }
2195    catch (_a) {
2196        return;
2197    }
2198}
2199function storeConfig(config) {
2200    const localStorage = Api.getInstance().localStorage;
2201    if (!config || !localStorage) {
2202        return;
2203    }
2204    localStorage.setItem(CONFIG_LOCAL_STORAGE_KEY, JSON.stringify(config));
2205    localStorage.setItem(CONFIG_EXPIRY_LOCAL_STORAGE_KEY, String(Date.now() +
2206        SettingsService.getInstance().configTimeToLive * 60 * 60 * 1000));
2207}
2208const COULD_NOT_GET_CONFIG_MSG = 'Could not fetch config, will use default configs';
2209function getRemoteConfig(performanceController, iid) {
2210    // Perf needs auth token only to retrieve remote config.
2211    return getAuthTokenPromise(performanceController.installations)
2212        .then(authToken => {
2213        const projectId = getProjectId(performanceController.app);
2214        const apiKey = getApiKey(performanceController.app);
2215        const configEndPoint = `https://firebaseremoteconfig.googleapis.com/v1/projects/${projectId}/namespaces/fireperf:fetch?key=${apiKey}`;
2216        const request = new Request(configEndPoint, {
2217            method: 'POST',
2218            headers: { Authorization: `${FIS_AUTH_PREFIX} ${authToken}` },
2219            /* eslint-disable camelcase */
2220            body: JSON.stringify({
2221                app_instance_id: iid,
2222                app_instance_id_token: authToken,
2223                app_id: getAppId(performanceController.app),
2224                app_version: SDK_VERSION,
2225                sdk_version: REMOTE_CONFIG_SDK_VERSION
2226            })
2227            /* eslint-enable camelcase */
2228        });
2229        return fetch(request).then(response => {
2230            if (response.ok) {
2231                return response.json();
2232            }
2233            // In case response is not ok. This will be caught by catch.
2234            throw ERROR_FACTORY.create("RC response not ok" /* RC_NOT_OK */);
2235        });
2236    })
2237        .catch(() => {
2238        consoleLogger.info(COULD_NOT_GET_CONFIG_MSG);
2239        return undefined;
2240    });
2241}
2242/**
2243 * Processes config coming either from calling RC or from local storage.
2244 * This method only runs if call is successful or config in storage
2245 * is valid.
2246 */
2247function processConfig(config) {
2248    if (!config) {
2249        return config;
2250    }
2251    const settingsServiceInstance = SettingsService.getInstance();
2252    const entries = config.entries || {};
2253    if (entries.fpr_enabled !== undefined) {
2254        // TODO: Change the assignment of loggingEnabled once the received type is
2255        // known.
2256        settingsServiceInstance.loggingEnabled =
2257            String(entries.fpr_enabled) === 'true';
2258    }
2259    else {
2260        // Config retrieved successfully, but there is no fpr_enabled in template.
2261        // Use secondary configs value.
2262        settingsServiceInstance.loggingEnabled = DEFAULT_CONFIGS.loggingEnabled;
2263    }
2264    if (entries.fpr_log_source) {
2265        settingsServiceInstance.logSource = Number(entries.fpr_log_source);
2266    }
2267    if (entries.fpr_log_endpoint_url) {
2268        settingsServiceInstance.logEndPointUrl = entries.fpr_log_endpoint_url;
2269    }
2270    // Key from Remote Config has to be non-empty string, otherwsie use local value.
2271    if (entries.fpr_log_transport_key) {
2272        settingsServiceInstance.transportKey = entries.fpr_log_transport_key;
2273    }
2274    if (entries.fpr_vc_network_request_sampling_rate !== undefined) {
2275        settingsServiceInstance.networkRequestsSamplingRate = Number(entries.fpr_vc_network_request_sampling_rate);
2276    }
2277    if (entries.fpr_vc_trace_sampling_rate !== undefined) {
2278        settingsServiceInstance.tracesSamplingRate = Number(entries.fpr_vc_trace_sampling_rate);
2279    }
2280    // Set the per session trace and network logging flags.
2281    settingsServiceInstance.logTraceAfterSampling = shouldLogAfterSampling(settingsServiceInstance.tracesSamplingRate);
2282    settingsServiceInstance.logNetworkAfterSampling = shouldLogAfterSampling(settingsServiceInstance.networkRequestsSamplingRate);
2283    return config;
2284}
2285function configValid(expiry) {
2286    return Number(expiry) > Date.now();
2287}
2288function shouldLogAfterSampling(samplingRate) {
2289    return Math.random() <= samplingRate;
2290}
2291
2292/**
2293 * @license
2294 * Copyright 2020 Google LLC
2295 *
2296 * Licensed under the Apache License, Version 2.0 (the "License");
2297 * you may not use this file except in compliance with the License.
2298 * You may obtain a copy of the License at
2299 *
2300 *   http://www.apache.org/licenses/LICENSE-2.0
2301 *
2302 * Unless required by applicable law or agreed to in writing, software
2303 * distributed under the License is distributed on an "AS IS" BASIS,
2304 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2305 * See the License for the specific language governing permissions and
2306 * limitations under the License.
2307 */
2308let initializationStatus = 1 /* notInitialized */;
2309let initializationPromise;
2310function getInitializationPromise(performanceController) {
2311    initializationStatus = 2 /* initializationPending */;
2312    initializationPromise =
2313        initializationPromise || initializePerf(performanceController);
2314    return initializationPromise;
2315}
2316function isPerfInitialized() {
2317    return initializationStatus === 3 /* initialized */;
2318}
2319function initializePerf(performanceController) {
2320    return getDocumentReadyComplete()
2321        .then(() => getIidPromise(performanceController.installations))
2322        .then(iid => getConfig(performanceController, iid))
2323        .then(() => changeInitializationStatus(), () => changeInitializationStatus());
2324}
2325/**
2326 * Returns a promise which resolves whenever the document readystate is complete or
2327 * immediately if it is called after page load complete.
2328 */
2329function getDocumentReadyComplete() {
2330    const document = Api.getInstance().document;
2331    return new Promise(resolve => {
2332        if (document && document.readyState !== 'complete') {
2333            const handler = () => {
2334                if (document.readyState === 'complete') {
2335                    document.removeEventListener('readystatechange', handler);
2336                    resolve();
2337                }
2338            };
2339            document.addEventListener('readystatechange', handler);
2340        }
2341        else {
2342            resolve();
2343        }
2344    });
2345}
2346function changeInitializationStatus() {
2347    initializationStatus = 3 /* initialized */;
2348}
2349
2350/**
2351 * @license
2352 * Copyright 2020 Google LLC
2353 *
2354 * Licensed under the Apache License, Version 2.0 (the "License");
2355 * you may not use this file except in compliance with the License.
2356 * You may obtain a copy of the License at
2357 *
2358 *   http://www.apache.org/licenses/LICENSE-2.0
2359 *
2360 * Unless required by applicable law or agreed to in writing, software
2361 * distributed under the License is distributed on an "AS IS" BASIS,
2362 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2363 * See the License for the specific language governing permissions and
2364 * limitations under the License.
2365 */
2366const DEFAULT_SEND_INTERVAL_MS = 10 * 1000;
2367const INITIAL_SEND_TIME_DELAY_MS = 5.5 * 1000;
2368// If end point does not work, the call will be tried for these many times.
2369const DEFAULT_REMAINING_TRIES = 3;
2370const MAX_EVENT_COUNT_PER_REQUEST = 1000;
2371let remainingTries = DEFAULT_REMAINING_TRIES;
2372/* eslint-enable camelcase */
2373let queue = [];
2374let isTransportSetup = false;
2375function setupTransportService() {
2376    if (!isTransportSetup) {
2377        processQueue(INITIAL_SEND_TIME_DELAY_MS);
2378        isTransportSetup = true;
2379    }
2380}
2381function processQueue(timeOffset) {
2382    setTimeout(() => {
2383        // If there is no remainingTries left, stop retrying.
2384        if (remainingTries === 0) {
2385            return;
2386        }
2387        // If there are no events to process, wait for DEFAULT_SEND_INTERVAL_MS and try again.
2388        if (!queue.length) {
2389            return processQueue(DEFAULT_SEND_INTERVAL_MS);
2390        }
2391        dispatchQueueEvents();
2392    }, timeOffset);
2393}
2394function dispatchQueueEvents() {
2395    // Extract events up to the maximum cap of single logRequest from top of "official queue".
2396    // The staged events will be used for current logRequest attempt, remaining events will be kept
2397    // for next attempt.
2398    const staged = queue.splice(0, MAX_EVENT_COUNT_PER_REQUEST);
2399    /* eslint-disable camelcase */
2400    // We will pass the JSON serialized event to the backend.
2401    const log_event = staged.map(evt => ({
2402        source_extension_json_proto3: evt.message,
2403        event_time_ms: String(evt.eventTime)
2404    }));
2405    const data = {
2406        request_time_ms: String(Date.now()),
2407        client_info: {
2408            client_type: 1,
2409            js_client_info: {}
2410        },
2411        log_source: SettingsService.getInstance().logSource,
2412        log_event
2413    };
2414    /* eslint-enable camelcase */
2415    sendEventsToFl(data, staged).catch(() => {
2416        // If the request fails for some reason, add the events that were attempted
2417        // back to the primary queue to retry later.
2418        queue = [...staged, ...queue];
2419        remainingTries--;
2420        consoleLogger.info(`Tries left: ${remainingTries}.`);
2421        processQueue(DEFAULT_SEND_INTERVAL_MS);
2422    });
2423}
2424function sendEventsToFl(data, staged) {
2425    return postToFlEndpoint(data)
2426        .then(res => {
2427        if (!res.ok) {
2428            consoleLogger.info('Call to Firebase backend failed.');
2429        }
2430        return res.json();
2431    })
2432        .then(res => {
2433        // Find the next call wait time from the response.
2434        const transportWait = Number(res.nextRequestWaitMillis);
2435        let requestOffset = DEFAULT_SEND_INTERVAL_MS;
2436        if (!isNaN(transportWait)) {
2437            requestOffset = Math.max(transportWait, requestOffset);
2438        }
2439        // Delete request if response include RESPONSE_ACTION_UNKNOWN or DELETE_REQUEST action.
2440        // Otherwise, retry request using normal scheduling if response include RETRY_REQUEST_LATER.
2441        const logResponseDetails = res.logResponseDetails;
2442        if (Array.isArray(logResponseDetails) &&
2443            logResponseDetails.length > 0 &&
2444            logResponseDetails[0].responseAction === 'RETRY_REQUEST_LATER') {
2445            queue = [...staged, ...queue];
2446            consoleLogger.info(`Retry transport request later.`);
2447        }
2448        remainingTries = DEFAULT_REMAINING_TRIES;
2449        // Schedule the next process.
2450        processQueue(requestOffset);
2451    });
2452}
2453function postToFlEndpoint(data) {
2454    const flTransportFullUrl = SettingsService.getInstance().getFlTransportFullUrl();
2455    return fetch(flTransportFullUrl, {
2456        method: 'POST',
2457        body: JSON.stringify(data)
2458    });
2459}
2460function addToQueue(evt) {
2461    if (!evt.eventTime || !evt.message) {
2462        throw ERROR_FACTORY.create("invalid cc log" /* INVALID_CC_LOG */);
2463    }
2464    // Add the new event to the queue.
2465    queue = [...queue, evt];
2466}
2467/** Log handler for cc service to send the performance logs to the server. */
2468function transportHandler(
2469// eslint-disable-next-line @typescript-eslint/no-explicit-any
2470serializer) {
2471    return (...args) => {
2472        const message = serializer(...args);
2473        addToQueue({
2474            message,
2475            eventTime: Date.now()
2476        });
2477    };
2478}
2479
2480/**
2481 * @license
2482 * Copyright 2020 Google LLC
2483 *
2484 * Licensed under the Apache License, Version 2.0 (the "License");
2485 * you may not use this file except in compliance with the License.
2486 * You may obtain a copy of the License at
2487 *
2488 *   http://www.apache.org/licenses/LICENSE-2.0
2489 *
2490 * Unless required by applicable law or agreed to in writing, software
2491 * distributed under the License is distributed on an "AS IS" BASIS,
2492 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2493 * See the License for the specific language governing permissions and
2494 * limitations under the License.
2495 */
2496/* eslint-enble camelcase */
2497let logger;
2498// This method is not called before initialization.
2499function sendLog(resource, resourceType) {
2500    if (!logger) {
2501        logger = transportHandler(serializer);
2502    }
2503    logger(resource, resourceType);
2504}
2505function logTrace(trace) {
2506    const settingsService = SettingsService.getInstance();
2507    // Do not log if trace is auto generated and instrumentation is disabled.
2508    if (!settingsService.instrumentationEnabled && trace.isAuto) {
2509        return;
2510    }
2511    // Do not log if trace is custom and data collection is disabled.
2512    if (!settingsService.dataCollectionEnabled && !trace.isAuto) {
2513        return;
2514    }
2515    // Do not log if required apis are not available.
2516    if (!Api.getInstance().requiredApisAvailable()) {
2517        return;
2518    }
2519    // Only log the page load auto traces if page is visible.
2520    if (trace.isAuto && getVisibilityState() !== VisibilityState.VISIBLE) {
2521        return;
2522    }
2523    if (isPerfInitialized()) {
2524        sendTraceLog(trace);
2525    }
2526    else {
2527        // Custom traces can be used before the initialization but logging
2528        // should wait until after.
2529        getInitializationPromise(trace.performanceController).then(() => sendTraceLog(trace), () => sendTraceLog(trace));
2530    }
2531}
2532function sendTraceLog(trace) {
2533    if (!getIid()) {
2534        return;
2535    }
2536    const settingsService = SettingsService.getInstance();
2537    if (!settingsService.loggingEnabled ||
2538        !settingsService.logTraceAfterSampling) {
2539        return;
2540    }
2541    setTimeout(() => sendLog(trace, 1 /* Trace */), 0);
2542}
2543function logNetworkRequest(networkRequest) {
2544    const settingsService = SettingsService.getInstance();
2545    // Do not log network requests if instrumentation is disabled.
2546    if (!settingsService.instrumentationEnabled) {
2547        return;
2548    }
2549    // Do not log the js sdk's call to transport service domain to avoid unnecessary cycle.
2550    // Need to blacklist both old and new endpoints to avoid migration gap.
2551    const networkRequestUrl = networkRequest.url;
2552    // Blacklist old log endpoint and new transport endpoint.
2553    // Because Performance SDK doesn't instrument requests sent from SDK itself.
2554    const logEndpointUrl = settingsService.logEndPointUrl.split('?')[0];
2555    const flEndpointUrl = settingsService.flTransportEndpointUrl.split('?')[0];
2556    if (networkRequestUrl === logEndpointUrl ||
2557        networkRequestUrl === flEndpointUrl) {
2558        return;
2559    }
2560    if (!settingsService.loggingEnabled ||
2561        !settingsService.logNetworkAfterSampling) {
2562        return;
2563    }
2564    setTimeout(() => sendLog(networkRequest, 0 /* NetworkRequest */), 0);
2565}
2566function serializer(resource, resourceType) {
2567    if (resourceType === 0 /* NetworkRequest */) {
2568        return serializeNetworkRequest(resource);
2569    }
2570    return serializeTrace(resource);
2571}
2572function serializeNetworkRequest(networkRequest) {
2573    const networkRequestMetric = {
2574        url: networkRequest.url,
2575        http_method: networkRequest.httpMethod || 0,
2576        http_response_code: 200,
2577        response_payload_bytes: networkRequest.responsePayloadBytes,
2578        client_start_time_us: networkRequest.startTimeUs,
2579        time_to_response_initiated_us: networkRequest.timeToResponseInitiatedUs,
2580        time_to_response_completed_us: networkRequest.timeToResponseCompletedUs
2581    };
2582    const perfMetric = {
2583        application_info: getApplicationInfo(networkRequest.performanceController.app),
2584        network_request_metric: networkRequestMetric
2585    };
2586    return JSON.stringify(perfMetric);
2587}
2588function serializeTrace(trace) {
2589    const traceMetric = {
2590        name: trace.name,
2591        is_auto: trace.isAuto,
2592        client_start_time_us: trace.startTimeUs,
2593        duration_us: trace.durationUs
2594    };
2595    if (Object.keys(trace.counters).length !== 0) {
2596        traceMetric.counters = trace.counters;
2597    }
2598    const customAttributes = trace.getAttributes();
2599    if (Object.keys(customAttributes).length !== 0) {
2600        traceMetric.custom_attributes = customAttributes;
2601    }
2602    const perfMetric = {
2603        application_info: getApplicationInfo(trace.performanceController.app),
2604        trace_metric: traceMetric
2605    };
2606    return JSON.stringify(perfMetric);
2607}
2608function getApplicationInfo(firebaseApp) {
2609    return {
2610        google_app_id: getAppId(firebaseApp),
2611        app_instance_id: getIid(),
2612        web_app_info: {
2613            sdk_version: SDK_VERSION,
2614            page_url: Api.getInstance().getUrl(),
2615            service_worker_status: getServiceWorkerStatus(),
2616            visibility_state: getVisibilityState(),
2617            effective_connection_type: getEffectiveConnectionType()
2618        },
2619        application_process_state: 0
2620    };
2621}
2622
2623/**
2624 * @license
2625 * Copyright 2020 Google LLC
2626 *
2627 * Licensed under the Apache License, Version 2.0 (the "License");
2628 * you may not use this file except in compliance with the License.
2629 * You may obtain a copy of the License at
2630 *
2631 *   http://www.apache.org/licenses/LICENSE-2.0
2632 *
2633 * Unless required by applicable law or agreed to in writing, software
2634 * distributed under the License is distributed on an "AS IS" BASIS,
2635 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2636 * See the License for the specific language governing permissions and
2637 * limitations under the License.
2638 */
2639const MAX_METRIC_NAME_LENGTH = 100;
2640const RESERVED_AUTO_PREFIX = '_';
2641const oobMetrics = [
2642    FIRST_PAINT_COUNTER_NAME,
2643    FIRST_CONTENTFUL_PAINT_COUNTER_NAME,
2644    FIRST_INPUT_DELAY_COUNTER_NAME
2645];
2646/**
2647 * Returns true if the metric is custom and does not start with reserved prefix, or if
2648 * the metric is one of out of the box page load trace metrics.
2649 */
2650function isValidMetricName(name, traceName) {
2651    if (name.length === 0 || name.length > MAX_METRIC_NAME_LENGTH) {
2652        return false;
2653    }
2654    return ((traceName &&
2655        traceName.startsWith(OOB_TRACE_PAGE_LOAD_PREFIX) &&
2656        oobMetrics.indexOf(name) > -1) ||
2657        !name.startsWith(RESERVED_AUTO_PREFIX));
2658}
2659/**
2660 * Converts the provided value to an integer value to be used in case of a metric.
2661 * @param providedValue Provided number value of the metric that needs to be converted to an integer.
2662 *
2663 * @returns Converted integer number to be set for the metric.
2664 */
2665function convertMetricValueToInteger(providedValue) {
2666    const valueAsInteger = Math.floor(providedValue);
2667    if (valueAsInteger < providedValue) {
2668        consoleLogger.info(`Metric value should be an Integer, setting the value as : ${valueAsInteger}.`);
2669    }
2670    return valueAsInteger;
2671}
2672
2673/**
2674 * @license
2675 * Copyright 2020 Google LLC
2676 *
2677 * Licensed under the Apache License, Version 2.0 (the "License");
2678 * you may not use this file except in compliance with the License.
2679 * You may obtain a copy of the License at
2680 *
2681 *   http://www.apache.org/licenses/LICENSE-2.0
2682 *
2683 * Unless required by applicable law or agreed to in writing, software
2684 * distributed under the License is distributed on an "AS IS" BASIS,
2685 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2686 * See the License for the specific language governing permissions and
2687 * limitations under the License.
2688 */
2689class Trace {
2690    /**
2691     * @param performanceController The performance controller running.
2692     * @param name The name of the trace.
2693     * @param isAuto If the trace is auto-instrumented.
2694     * @param traceMeasureName The name of the measure marker in user timing specification. This field
2695     * is only set when the trace is built for logging when the user directly uses the user timing
2696     * api (performance.mark and performance.measure).
2697     */
2698    constructor(performanceController, name, isAuto = false, traceMeasureName) {
2699        this.performanceController = performanceController;
2700        this.name = name;
2701        this.isAuto = isAuto;
2702        this.state = 1 /* UNINITIALIZED */;
2703        this.customAttributes = {};
2704        this.counters = {};
2705        this.api = Api.getInstance();
2706        this.randomId = Math.floor(Math.random() * 1000000);
2707        if (!this.isAuto) {
2708            this.traceStartMark = `${TRACE_START_MARK_PREFIX}-${this.randomId}-${this.name}`;
2709            this.traceStopMark = `${TRACE_STOP_MARK_PREFIX}-${this.randomId}-${this.name}`;
2710            this.traceMeasure =
2711                traceMeasureName ||
2712                    `${TRACE_MEASURE_PREFIX}-${this.randomId}-${this.name}`;
2713            if (traceMeasureName) {
2714                // For the case of direct user timing traces, no start stop will happen. The measure object
2715                // is already available.
2716                this.calculateTraceMetrics();
2717            }
2718        }
2719    }
2720    /**
2721     * Starts a trace. The measurement of the duration starts at this point.
2722     */
2723    start() {
2724        if (this.state !== 1 /* UNINITIALIZED */) {
2725            throw ERROR_FACTORY.create("trace started" /* TRACE_STARTED_BEFORE */, {
2726                traceName: this.name
2727            });
2728        }
2729        this.api.mark(this.traceStartMark);
2730        this.state = 2 /* RUNNING */;
2731    }
2732    /**
2733     * Stops the trace. The measurement of the duration of the trace stops at this point and trace
2734     * is logged.
2735     */
2736    stop() {
2737        if (this.state !== 2 /* RUNNING */) {
2738            throw ERROR_FACTORY.create("trace stopped" /* TRACE_STOPPED_BEFORE */, {
2739                traceName: this.name
2740            });
2741        }
2742        this.state = 3 /* TERMINATED */;
2743        this.api.mark(this.traceStopMark);
2744        this.api.measure(this.traceMeasure, this.traceStartMark, this.traceStopMark);
2745        this.calculateTraceMetrics();
2746        logTrace(this);
2747    }
2748    /**
2749     * Records a trace with predetermined values. If this method is used a trace is created and logged
2750     * directly. No need to use start and stop methods.
2751     * @param startTime Trace start time since epoch in millisec
2752     * @param duration The duraction of the trace in millisec
2753     * @param options An object which can optionally hold maps of custom metrics and custom attributes
2754     */
2755    record(startTime, duration, options) {
2756        if (startTime <= 0) {
2757            throw ERROR_FACTORY.create("nonpositive trace startTime" /* NONPOSITIVE_TRACE_START_TIME */, {
2758                traceName: this.name
2759            });
2760        }
2761        if (duration <= 0) {
2762            throw ERROR_FACTORY.create("nonpositive trace duration" /* NONPOSITIVE_TRACE_DURATION */, {
2763                traceName: this.name
2764            });
2765        }
2766        this.durationUs = Math.floor(duration * 1000);
2767        this.startTimeUs = Math.floor(startTime * 1000);
2768        if (options && options.attributes) {
2769            this.customAttributes = Object.assign({}, options.attributes);
2770        }
2771        if (options && options.metrics) {
2772            for (const metric of Object.keys(options.metrics)) {
2773                if (!isNaN(Number(options.metrics[metric]))) {
2774                    this.counters[metric] = Number(Math.floor(options.metrics[metric]));
2775                }
2776            }
2777        }
2778        logTrace(this);
2779    }
2780    /**
2781     * Increments a custom metric by a certain number or 1 if number not specified. Will create a new
2782     * custom metric if one with the given name does not exist. The value will be floored down to an
2783     * integer.
2784     * @param counter Name of the custom metric
2785     * @param numAsInteger Increment by value
2786     */
2787    incrementMetric(counter, numAsInteger = 1) {
2788        if (this.counters[counter] === undefined) {
2789            this.putMetric(counter, numAsInteger);
2790        }
2791        else {
2792            this.putMetric(counter, this.counters[counter] + numAsInteger);
2793        }
2794    }
2795    /**
2796     * Sets a custom metric to a specified value. Will create a new custom metric if one with the
2797     * given name does not exist. The value will be floored down to an integer.
2798     * @param counter Name of the custom metric
2799     * @param numAsInteger Set custom metric to this value
2800     */
2801    putMetric(counter, numAsInteger) {
2802        if (isValidMetricName(counter, this.name)) {
2803            this.counters[counter] = convertMetricValueToInteger(numAsInteger);
2804        }
2805        else {
2806            throw ERROR_FACTORY.create("invalid custom metric name" /* INVALID_CUSTOM_METRIC_NAME */, {
2807                customMetricName: counter
2808            });
2809        }
2810    }
2811    /**
2812     * Returns the value of the custom metric by that name. If a custom metric with that name does
2813     * not exist will return zero.
2814     * @param counter
2815     */
2816    getMetric(counter) {
2817        return this.counters[counter] || 0;
2818    }
2819    /**
2820     * Sets a custom attribute of a trace to a certain value.
2821     * @param attr
2822     * @param value
2823     */
2824    putAttribute(attr, value) {
2825        const isValidName = isValidCustomAttributeName(attr);
2826        const isValidValue = isValidCustomAttributeValue(value);
2827        if (isValidName && isValidValue) {
2828            this.customAttributes[attr] = value;
2829            return;
2830        }
2831        // Throw appropriate error when the attribute name or value is invalid.
2832        if (!isValidName) {
2833            throw ERROR_FACTORY.create("invalid attribute name" /* INVALID_ATTRIBUTE_NAME */, {
2834                attributeName: attr
2835            });
2836        }
2837        if (!isValidValue) {
2838            throw ERROR_FACTORY.create("invalid attribute value" /* INVALID_ATTRIBUTE_VALUE */, {
2839                attributeValue: value
2840            });
2841        }
2842    }
2843    /**
2844     * Retrieves the value a custom attribute of a trace is set to.
2845     * @param attr
2846     */
2847    getAttribute(attr) {
2848        return this.customAttributes[attr];
2849    }
2850    removeAttribute(attr) {
2851        if (this.customAttributes[attr] === undefined) {
2852            return;
2853        }
2854        delete this.customAttributes[attr];
2855    }
2856    getAttributes() {
2857        return Object.assign({}, this.customAttributes);
2858    }
2859    setStartTime(startTime) {
2860        this.startTimeUs = startTime;
2861    }
2862    setDuration(duration) {
2863        this.durationUs = duration;
2864    }
2865    /**
2866     * Calculates and assigns the duration and start time of the trace using the measure performance
2867     * entry.
2868     */
2869    calculateTraceMetrics() {
2870        const perfMeasureEntries = this.api.getEntriesByName(this.traceMeasure);
2871        const perfMeasureEntry = perfMeasureEntries && perfMeasureEntries[0];
2872        if (perfMeasureEntry) {
2873            this.durationUs = Math.floor(perfMeasureEntry.duration * 1000);
2874            this.startTimeUs = Math.floor((perfMeasureEntry.startTime + this.api.getTimeOrigin()) * 1000);
2875        }
2876    }
2877    /**
2878     * @param navigationTimings A single element array which contains the navigationTIming object of
2879     * the page load
2880     * @param paintTimings A array which contains paintTiming object of the page load
2881     * @param firstInputDelay First input delay in millisec
2882     */
2883    static createOobTrace(performanceController, navigationTimings, paintTimings, firstInputDelay) {
2884        const route = Api.getInstance().getUrl();
2885        if (!route) {
2886            return;
2887        }
2888        const trace = new Trace(performanceController, OOB_TRACE_PAGE_LOAD_PREFIX + route, true);
2889        const timeOriginUs = Math.floor(Api.getInstance().getTimeOrigin() * 1000);
2890        trace.setStartTime(timeOriginUs);
2891        // navigationTimings includes only one element.
2892        if (navigationTimings && navigationTimings[0]) {
2893            trace.setDuration(Math.floor(navigationTimings[0].duration * 1000));
2894            trace.putMetric('domInteractive', Math.floor(navigationTimings[0].domInteractive * 1000));
2895            trace.putMetric('domContentLoadedEventEnd', Math.floor(navigationTimings[0].domContentLoadedEventEnd * 1000));
2896            trace.putMetric('loadEventEnd', Math.floor(navigationTimings[0].loadEventEnd * 1000));
2897        }
2898        const FIRST_PAINT = 'first-paint';
2899        const FIRST_CONTENTFUL_PAINT = 'first-contentful-paint';
2900        if (paintTimings) {
2901            const firstPaint = paintTimings.find(paintObject => paintObject.name === FIRST_PAINT);
2902            if (firstPaint && firstPaint.startTime) {
2903                trace.putMetric(FIRST_PAINT_COUNTER_NAME, Math.floor(firstPaint.startTime * 1000));
2904            }
2905            const firstContentfulPaint = paintTimings.find(paintObject => paintObject.name === FIRST_CONTENTFUL_PAINT);
2906            if (firstContentfulPaint && firstContentfulPaint.startTime) {
2907                trace.putMetric(FIRST_CONTENTFUL_PAINT_COUNTER_NAME, Math.floor(firstContentfulPaint.startTime * 1000));
2908            }
2909            if (firstInputDelay) {
2910                trace.putMetric(FIRST_INPUT_DELAY_COUNTER_NAME, Math.floor(firstInputDelay * 1000));
2911            }
2912        }
2913        logTrace(trace);
2914    }
2915    static createUserTimingTrace(performanceController, measureName) {
2916        const trace = new Trace(performanceController, measureName, false, measureName);
2917        logTrace(trace);
2918    }
2919}
2920
2921/**
2922 * @license
2923 * Copyright 2020 Google LLC
2924 *
2925 * Licensed under the Apache License, Version 2.0 (the "License");
2926 * you may not use this file except in compliance with the License.
2927 * You may obtain a copy of the License at
2928 *
2929 *   http://www.apache.org/licenses/LICENSE-2.0
2930 *
2931 * Unless required by applicable law or agreed to in writing, software
2932 * distributed under the License is distributed on an "AS IS" BASIS,
2933 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2934 * See the License for the specific language governing permissions and
2935 * limitations under the License.
2936 */
2937function createNetworkRequestEntry(performanceController, entry) {
2938    const performanceEntry = entry;
2939    if (!performanceEntry || performanceEntry.responseStart === undefined) {
2940        return;
2941    }
2942    const timeOrigin = Api.getInstance().getTimeOrigin();
2943    const startTimeUs = Math.floor((performanceEntry.startTime + timeOrigin) * 1000);
2944    const timeToResponseInitiatedUs = performanceEntry.responseStart
2945        ? Math.floor((performanceEntry.responseStart - performanceEntry.startTime) * 1000)
2946        : undefined;
2947    const timeToResponseCompletedUs = Math.floor((performanceEntry.responseEnd - performanceEntry.startTime) * 1000);
2948    // Remove the query params from logged network request url.
2949    const url = performanceEntry.name && performanceEntry.name.split('?')[0];
2950    const networkRequest = {
2951        performanceController,
2952        url,
2953        responsePayloadBytes: performanceEntry.transferSize,
2954        startTimeUs,
2955        timeToResponseInitiatedUs,
2956        timeToResponseCompletedUs
2957    };
2958    logNetworkRequest(networkRequest);
2959}
2960
2961/**
2962 * @license
2963 * Copyright 2020 Google LLC
2964 *
2965 * Licensed under the Apache License, Version 2.0 (the "License");
2966 * you may not use this file except in compliance with the License.
2967 * You may obtain a copy of the License at
2968 *
2969 *   http://www.apache.org/licenses/LICENSE-2.0
2970 *
2971 * Unless required by applicable law or agreed to in writing, software
2972 * distributed under the License is distributed on an "AS IS" BASIS,
2973 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2974 * See the License for the specific language governing permissions and
2975 * limitations under the License.
2976 */
2977const FID_WAIT_TIME_MS = 5000;
2978function setupOobResources(performanceController) {
2979    // Do not initialize unless iid is available.
2980    if (!getIid()) {
2981        return;
2982    }
2983    // The load event might not have fired yet, and that means performance navigation timing
2984    // object has a duration of 0. The setup should run after all current tasks in js queue.
2985    setTimeout(() => setupOobTraces(performanceController), 0);
2986    setTimeout(() => setupNetworkRequests(performanceController), 0);
2987    setTimeout(() => setupUserTimingTraces(performanceController), 0);
2988}
2989function setupNetworkRequests(performanceController) {
2990    const api = Api.getInstance();
2991    const resources = api.getEntriesByType('resource');
2992    for (const resource of resources) {
2993        createNetworkRequestEntry(performanceController, resource);
2994    }
2995    api.setupObserver('resource', entry => createNetworkRequestEntry(performanceController, entry));
2996}
2997function setupOobTraces(performanceController) {
2998    const api = Api.getInstance();
2999    const navigationTimings = api.getEntriesByType('navigation');
3000    const paintTimings = api.getEntriesByType('paint');
3001    // If First Input Desly polyfill is added to the page, report the fid value.
3002    // https://github.com/GoogleChromeLabs/first-input-delay
3003    if (api.onFirstInputDelay) {
3004        // If the fid call back is not called for certain time, continue without it.
3005        // eslint-disable-next-line @typescript-eslint/no-explicit-any
3006        let timeoutId = setTimeout(() => {
3007            Trace.createOobTrace(performanceController, navigationTimings, paintTimings);
3008            timeoutId = undefined;
3009        }, FID_WAIT_TIME_MS);
3010        api.onFirstInputDelay((fid) => {
3011            if (timeoutId) {
3012                clearTimeout(timeoutId);
3013                Trace.createOobTrace(performanceController, navigationTimings, paintTimings, fid);
3014            }
3015        });
3016    }
3017    else {
3018        Trace.createOobTrace(performanceController, navigationTimings, paintTimings);
3019    }
3020}
3021function setupUserTimingTraces(performanceController) {
3022    const api = Api.getInstance();
3023    // Run through the measure performance entries collected up to this point.
3024    const measures = api.getEntriesByType('measure');
3025    for (const measure of measures) {
3026        createUserTimingTrace(performanceController, measure);
3027    }
3028    // Setup an observer to capture the measures from this point on.
3029    api.setupObserver('measure', entry => createUserTimingTrace(performanceController, entry));
3030}
3031function createUserTimingTrace(performanceController, measure) {
3032    const measureName = measure.name;
3033    // Do not create a trace, if the user timing marks and measures are created by the sdk itself.
3034    if (measureName.substring(0, TRACE_MEASURE_PREFIX.length) ===
3035        TRACE_MEASURE_PREFIX) {
3036        return;
3037    }
3038    Trace.createUserTimingTrace(performanceController, measureName);
3039}
3040
3041/**
3042 * @license
3043 * Copyright 2020 Google LLC
3044 *
3045 * Licensed under the Apache License, Version 2.0 (the "License");
3046 * you may not use this file except in compliance with the License.
3047 * You may obtain a copy of the License at
3048 *
3049 *   http://www.apache.org/licenses/LICENSE-2.0
3050 *
3051 * Unless required by applicable law or agreed to in writing, software
3052 * distributed under the License is distributed on an "AS IS" BASIS,
3053 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3054 * See the License for the specific language governing permissions and
3055 * limitations under the License.
3056 */
3057class PerformanceController {
3058    constructor(app, installations) {
3059        this.app = app;
3060        this.installations = installations;
3061        this.initialized = false;
3062    }
3063    /**
3064     * This method *must* be called internally as part of creating a
3065     * PerformanceController instance.
3066     *
3067     * Currently it's not possible to pass the settings object through the
3068     * constructor using Components, so this method exists to be called with the
3069     * desired settings, to ensure nothing is collected without the user's
3070     * consent.
3071     */
3072    _init(settings) {
3073        if (this.initialized) {
3074            return;
3075        }
3076        if ((settings === null || settings === void 0 ? void 0 : settings.dataCollectionEnabled) !== undefined) {
3077            this.dataCollectionEnabled = settings.dataCollectionEnabled;
3078        }
3079        if ((settings === null || settings === void 0 ? void 0 : settings.instrumentationEnabled) !== undefined) {
3080            this.instrumentationEnabled = settings.instrumentationEnabled;
3081        }
3082        if (Api.getInstance().requiredApisAvailable()) {
3083            validateIndexedDBOpenable()
3084                .then(isAvailable => {
3085                if (isAvailable) {
3086                    setupTransportService();
3087                    getInitializationPromise(this).then(() => setupOobResources(this), () => setupOobResources(this));
3088                    this.initialized = true;
3089                }
3090            })
3091                .catch(error => {
3092                consoleLogger.info(`Environment doesn't support IndexedDB: ${error}`);
3093            });
3094        }
3095        else {
3096            consoleLogger.info('Firebase Performance cannot start if the browser does not support ' +
3097                '"Fetch" and "Promise", or cookies are disabled.');
3098        }
3099    }
3100    set instrumentationEnabled(val) {
3101        SettingsService.getInstance().instrumentationEnabled = val;
3102    }
3103    get instrumentationEnabled() {
3104        return SettingsService.getInstance().instrumentationEnabled;
3105    }
3106    set dataCollectionEnabled(val) {
3107        SettingsService.getInstance().dataCollectionEnabled = val;
3108    }
3109    get dataCollectionEnabled() {
3110        return SettingsService.getInstance().dataCollectionEnabled;
3111    }
3112}
3113
3114/**
3115 * Firebase Performance Monitoring
3116 *
3117 * @packageDocumentation
3118 */
3119const DEFAULT_ENTRY_NAME = '[DEFAULT]';
3120/**
3121 * Returns a {@link FirebasePerformance} instance for the given app.
3122 * @param app - The {@link https://www.gstatic.com/firebasejs/9.6.4/firebase-app.js#FirebaseApp} to use.
3123 * @public
3124 */
3125function getPerformance(app = getApp()) {
3126    app = getModularInstance(app);
3127    const provider = _getProvider(app, 'performance');
3128    const perfInstance = provider.getImmediate();
3129    return perfInstance;
3130}
3131/**
3132 * Returns a {@link FirebasePerformance} instance for the given app. Can only be called once.
3133 * @param app - The {@link https://www.gstatic.com/firebasejs/9.6.4/firebase-app.js#FirebaseApp} to use.
3134 * @param settings - Optional settings for the {@link FirebasePerformance} instance.
3135 * @public
3136 */
3137function initializePerformance(app, settings) {
3138    app = getModularInstance(app);
3139    const provider = _getProvider(app, 'performance');
3140    // throw if an instance was already created.
3141    // It could happen if initializePerformance() is called more than once, or getPerformance() is called first.
3142    if (provider.isInitialized()) {
3143        const existingInstance = provider.getImmediate();
3144        const initialSettings = provider.getOptions();
3145        if (deepEqual(initialSettings, settings !== null && settings !== void 0 ? settings : {})) {
3146            return existingInstance;
3147        }
3148        else {
3149            throw ERROR_FACTORY.create("already initialized" /* ALREADY_INITIALIZED */);
3150        }
3151    }
3152    const perfInstance = provider.initialize({
3153        options: settings
3154    });
vendor: 1,443 bytes, lines 3155-3194
3155    return perfInstance;
3156}
3157/**
3158 * Returns a new `PerformanceTrace` instance.
3159 * @param performance - The {@link FirebasePerformance} instance to use.
3160 * @param name - The name of the trace.
3161 * @public
3162 */
3163function trace(performance, name) {
3164    performance = getModularInstance(performance);
3165    return new Trace(performance, name);
3166}
3167const factory = (container, { options: settings }) => {
3168    // Dependencies
3169    const app = container.getProvider('app').getImmediate();
3170    const installations = container
3171        .getProvider('installations-internal')
3172        .getImmediate();
3173    if (app.name !== DEFAULT_ENTRY_NAME) {
3174        throw ERROR_FACTORY.create("FB not default" /* FB_NOT_DEFAULT */);
3175    }
3176    if (typeof window === 'undefined') {
3177        throw ERROR_FACTORY.create("no window" /* NO_WINDOW */);
3178    }
3179    setupApi(window);
3180    const perfInstance = new PerformanceController(app, installations);
3181    perfInstance._init(settings);
3182    return perfInstance;
3183};
3184function registerPerformance() {
3185    _registerComponent(new Component('performance', factory, "PUBLIC" /* PUBLIC */));
3186    registerVersion(name, version);
3187    // BUILD_TARGET will be replaced by values like esm5, esm2017, cjs5, etc during the compilation
3188    registerVersion(name, version, 'esm2017');
3189}
3190registerPerformance();
3191
3192export { getPerformance, initializePerformance, trace };
3193
3194//# sourceMappingURL=firebase-performance.js.map

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.