{"version":3,"file":"firebase-performance-compat.js","sources":["../logger/src/logger.ts","../../node_modules/idb/build/index.js","../util/src/errors.ts","../component/src/component.ts","../../node_modules/idb/build/wrap-idb-value.js","../installations/src/util/constants.ts","../installations/src/util/errors.ts","../installations/src/functions/common.ts","../installations/src/util/sleep.ts","../installations/src/helpers/generate-fid.ts","../installations/src/helpers/buffer-to-base64-url-safe.ts","../installations/src/util/get-key.ts","../installations/src/helpers/fid-changed.ts","../installations/src/helpers/idb-manager.ts","../installations/src/helpers/get-installation-entry.ts","../installations/src/functions/create-installation-request.ts","../installations/src/functions/generate-auth-token-request.ts","../installations/src/helpers/refresh-auth-token.ts","../installations/src/api/get-token.ts","../installations/src/helpers/extract-app-config.ts","../installations/src/functions/config.ts","../installations/src/api/get-id.ts","../installations/src/index.ts","../performance/src/constants.ts","../performance/src/utils/attributes_utils.ts","../performance-compat/src/index.ts","../performance/src/utils/errors.ts","../performance/src/utils/console_logger.ts","../performance/src/services/api_service.ts","../util/src/environment.ts","../performance/src/services/iid_service.ts","../performance/src/utils/string_merger.ts","../performance/src/services/settings_service.ts","../performance/src/utils/app_utils.ts","../performance/src/services/remote_config_service.ts","../performance/src/services/initialization_service.ts","../performance/src/services/transport_service.ts","../performance/src/services/perf_logger.ts","../performance/src/utils/metric_utils.ts","../performance/src/resources/trace.ts","../performance/src/resources/network_request.ts","../performance/src/services/oob_resources_service.ts","../performance/src/controllers/perf.ts","../performance/src/index.ts","../performance-compat/src/performance.ts","../util/src/compat.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2017 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport type LogLevelString =\n | 'debug'\n | 'verbose'\n | 'info'\n | 'warn'\n | 'error'\n | 'silent';\n\nexport interface LogOptions {\n level: LogLevelString;\n}\n\nexport type LogCallback = (callbackParams: LogCallbackParams) => void;\n\nexport interface LogCallbackParams {\n level: LogLevelString;\n message: string;\n args: unknown[];\n type: string;\n}\n\n/**\n * A container for all of the Logger instances\n */\nexport const instances: Logger[] = [];\n\n/**\n * The JS SDK supports 5 log levels and also allows a user the ability to\n * silence the logs altogether.\n *\n * The order is a follows:\n * DEBUG < VERBOSE < INFO < WARN < ERROR\n *\n * All of the log types above the current log level will be captured (i.e. if\n * you set the log level to `INFO`, errors will still be logged, but `DEBUG` and\n * `VERBOSE` logs will not)\n */\nexport enum LogLevel {\n DEBUG,\n VERBOSE,\n INFO,\n WARN,\n ERROR,\n SILENT\n}\n\nconst levelStringToEnum: { [key in LogLevelString]: LogLevel } = {\n 'debug': LogLevel.DEBUG,\n 'verbose': LogLevel.VERBOSE,\n 'info': LogLevel.INFO,\n 'warn': LogLevel.WARN,\n 'error': LogLevel.ERROR,\n 'silent': LogLevel.SILENT\n};\n\n/**\n * The default log level\n */\nconst defaultLogLevel: LogLevel = LogLevel.INFO;\n\n/**\n * We allow users the ability to pass their own log handler. We will pass the\n * type of log, the current log level, and any other arguments passed (i.e. the\n * messages that the user wants to log) to this function.\n */\nexport type LogHandler = (\n loggerInstance: Logger,\n logType: LogLevel,\n ...args: unknown[]\n) => void;\n\n/**\n * By default, `console.debug` is not displayed in the developer console (in\n * chrome). To avoid forcing users to have to opt-in to these logs twice\n * (i.e. once for firebase, and once in the console), we are sending `DEBUG`\n * logs to the `console.log` function.\n */\nconst ConsoleMethod = {\n [LogLevel.DEBUG]: 'log',\n [LogLevel.VERBOSE]: 'log',\n [LogLevel.INFO]: 'info',\n [LogLevel.WARN]: 'warn',\n [LogLevel.ERROR]: 'error'\n};\n\n/**\n * The default log handler will forward DEBUG, VERBOSE, INFO, WARN, and ERROR\n * messages on to their corresponding console counterparts (if the log method\n * is supported by the current log level)\n */\nconst defaultLogHandler: LogHandler = (instance, logType, ...args): void => {\n if (logType < instance.logLevel) {\n return;\n }\n const now = new Date().toISOString();\n const method = ConsoleMethod[logType as keyof typeof ConsoleMethod];\n if (method) {\n console[method as 'log' | 'info' | 'warn' | 'error'](\n `[${now}] ${instance.name}:`,\n ...args\n );\n } else {\n throw new Error(\n `Attempted to log a message with an invalid logType (value: ${logType})`\n );\n }\n};\n\nexport class Logger {\n /**\n * Gives you an instance of a Logger to capture messages according to\n * Firebase's logging scheme.\n *\n * @param name The name that the logs will be associated with\n */\n constructor(public name: string) {\n /**\n * Capture the current instance for later use\n */\n instances.push(this);\n }\n\n /**\n * The log level of the given Logger instance.\n */\n private _logLevel = defaultLogLevel;\n\n get logLevel(): LogLevel {\n return this._logLevel;\n }\n\n set logLevel(val: LogLevel) {\n if (!(val in LogLevel)) {\n throw new TypeError(`Invalid value \"${val}\" assigned to \\`logLevel\\``);\n }\n this._logLevel = val;\n }\n\n // Workaround for setter/getter having to be the same type.\n setLogLevel(val: LogLevel | LogLevelString): void {\n this._logLevel = typeof val === 'string' ? levelStringToEnum[val] : val;\n }\n\n /**\n * The main (internal) log handler for the Logger instance.\n * Can be set to a new function in internal package code but not by user.\n */\n private _logHandler: LogHandler = defaultLogHandler;\n get logHandler(): LogHandler {\n return this._logHandler;\n }\n set logHandler(val: LogHandler) {\n if (typeof val !== 'function') {\n throw new TypeError('Value assigned to `logHandler` must be a function');\n }\n this._logHandler = val;\n }\n\n /**\n * The optional, additional, user-defined log handler for the Logger instance.\n */\n private _userLogHandler: LogHandler | null = null;\n get userLogHandler(): LogHandler | null {\n return this._userLogHandler;\n }\n set userLogHandler(val: LogHandler | null) {\n this._userLogHandler = val;\n }\n\n /**\n * The functions below are all based on the `console` interface\n */\n\n debug(...args: unknown[]): void {\n this._userLogHandler && this._userLogHandler(this, LogLevel.DEBUG, ...args);\n this._logHandler(this, LogLevel.DEBUG, ...args);\n }\n log(...args: unknown[]): void {\n this._userLogHandler &&\n this._userLogHandler(this, LogLevel.VERBOSE, ...args);\n this._logHandler(this, LogLevel.VERBOSE, ...args);\n }\n info(...args: unknown[]): void {\n this._userLogHandler && this._userLogHandler(this, LogLevel.INFO, ...args);\n this._logHandler(this, LogLevel.INFO, ...args);\n }\n warn(...args: unknown[]): void {\n this._userLogHandler && this._userLogHandler(this, LogLevel.WARN, ...args);\n this._logHandler(this, LogLevel.WARN, ...args);\n }\n error(...args: unknown[]): void {\n this._userLogHandler && this._userLogHandler(this, LogLevel.ERROR, ...args);\n this._logHandler(this, LogLevel.ERROR, ...args);\n }\n}\n\nexport function setLogLevel(level: LogLevelString | LogLevel): void {\n instances.forEach(inst => {\n inst.setLogLevel(level);\n });\n}\n\nexport function setUserLogHandler(\n logCallback: LogCallback | null,\n options?: LogOptions\n): void {\n for (const instance of instances) {\n let customLogLevel: LogLevel | null = null;\n if (options && options.level) {\n customLogLevel = levelStringToEnum[options.level];\n }\n if (logCallback === null) {\n instance.userLogHandler = null;\n } else {\n instance.userLogHandler = (\n instance: Logger,\n level: LogLevel,\n ...args: unknown[]\n ) => {\n const message = args\n .map(arg => {\n if (arg == null) {\n return null;\n } else if (typeof arg === 'string') {\n return arg;\n } else if (typeof arg === 'number' || typeof arg === 'boolean') {\n return arg.toString();\n } else if (arg instanceof Error) {\n return arg.message;\n } else {\n try {\n return JSON.stringify(arg);\n } catch (ignored) {\n return null;\n }\n }\n })\n .filter(arg => arg)\n .join(' ');\n if (level >= (customLogLevel ?? instance.logLevel)) {\n logCallback({\n level: LogLevel[level].toLowerCase() as LogLevelString,\n message,\n args,\n type: instance.name\n });\n }\n };\n }\n }\n}\n","import { w as wrap, r as replaceTraps } from './wrap-idb-value.js';\nexport { u as unwrap, w as wrap } from './wrap-idb-value.js';\n\n/**\n * Open a database.\n *\n * @param name Name of the database.\n * @param version Schema version.\n * @param callbacks Additional callbacks.\n */\nfunction openDB(name, version, { blocked, upgrade, blocking, terminated } = {}) {\n const request = indexedDB.open(name, version);\n const openPromise = wrap(request);\n if (upgrade) {\n request.addEventListener('upgradeneeded', (event) => {\n upgrade(wrap(request.result), event.oldVersion, event.newVersion, wrap(request.transaction));\n });\n }\n if (blocked)\n request.addEventListener('blocked', () => blocked());\n openPromise\n .then((db) => {\n if (terminated)\n db.addEventListener('close', () => terminated());\n if (blocking)\n db.addEventListener('versionchange', () => blocking());\n })\n .catch(() => { });\n return openPromise;\n}\n/**\n * Delete a database.\n *\n * @param name Name of the database.\n */\nfunction deleteDB(name, { blocked } = {}) {\n const request = indexedDB.deleteDatabase(name);\n if (blocked)\n request.addEventListener('blocked', () => blocked());\n return wrap(request).then(() => undefined);\n}\n\nconst readMethods = ['get', 'getKey', 'getAll', 'getAllKeys', 'count'];\nconst writeMethods = ['put', 'add', 'delete', 'clear'];\nconst cachedMethods = new Map();\nfunction getMethod(target, prop) {\n if (!(target instanceof IDBDatabase &&\n !(prop in target) &&\n typeof prop === 'string')) {\n return;\n }\n if (cachedMethods.get(prop))\n return cachedMethods.get(prop);\n const targetFuncName = prop.replace(/FromIndex$/, '');\n const useIndex = prop !== targetFuncName;\n const isWrite = writeMethods.includes(targetFuncName);\n if (\n // Bail if the target doesn't exist on the target. Eg, getAll isn't in Edge.\n !(targetFuncName in (useIndex ? IDBIndex : IDBObjectStore).prototype) ||\n !(isWrite || readMethods.includes(targetFuncName))) {\n return;\n }\n const method = async function (storeName, ...args) {\n // isWrite ? 'readwrite' : undefined gzipps better, but fails in Edge :(\n const tx = this.transaction(storeName, isWrite ? 'readwrite' : 'readonly');\n let target = tx.store;\n if (useIndex)\n target = target.index(args.shift());\n // Must reject if op rejects.\n // If it's a write operation, must reject if tx.done rejects.\n // Must reject with op rejection first.\n // Must resolve with op value.\n // Must handle both promises (no unhandled rejections)\n return (await Promise.all([\n target[targetFuncName](...args),\n isWrite && tx.done,\n ]))[0];\n };\n cachedMethods.set(prop, method);\n return method;\n}\nreplaceTraps((oldTraps) => ({\n ...oldTraps,\n get: (target, prop, receiver) => getMethod(target, prop) || oldTraps.get(target, prop, receiver),\n has: (target, prop) => !!getMethod(target, prop) || oldTraps.has(target, prop),\n}));\n\nexport { deleteDB, openDB };\n","/**\n * @license\n * Copyright 2017 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * @fileoverview Standardized Firebase Error.\n *\n * Usage:\n *\n * // Typescript string literals for type-safe codes\n * type Err =\n * 'unknown' |\n * 'object-not-found'\n * ;\n *\n * // Closure enum for type-safe error codes\n * // at-enum {string}\n * var Err = {\n * UNKNOWN: 'unknown',\n * OBJECT_NOT_FOUND: 'object-not-found',\n * }\n *\n * let errors: Map = {\n * 'generic-error': \"Unknown error\",\n * 'file-not-found': \"Could not find file: {$file}\",\n * };\n *\n * // Type-safe function - must pass a valid error code as param.\n * let error = new ErrorFactory('service', 'Service', errors);\n *\n * ...\n * throw error.create(Err.GENERIC);\n * ...\n * throw error.create(Err.FILE_NOT_FOUND, {'file': fileName});\n * ...\n * // Service: Could not file file: foo.txt (service/file-not-found).\n *\n * catch (e) {\n * assert(e.message === \"Could not find file: foo.txt.\");\n * if ((e as FirebaseError)?.code === 'service/file-not-found') {\n * console.log(\"Could not read file: \" + e['file']);\n * }\n * }\n */\n\nexport type ErrorMap = {\n readonly [K in ErrorCode]: string;\n};\n\nconst ERROR_NAME = 'FirebaseError';\n\nexport interface StringLike {\n toString(): string;\n}\n\nexport interface ErrorData {\n [key: string]: unknown;\n}\n\n// Based on code from:\n// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error#Custom_Error_Types\nexport class FirebaseError extends Error {\n /** The custom name for all FirebaseErrors. */\n readonly name: string = ERROR_NAME;\n\n constructor(\n /** The error code for this error. */\n readonly code: string,\n message: string,\n /** Custom data for this error. */\n public customData?: Record\n ) {\n super(message);\n\n // Fix For ES5\n // https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work\n Object.setPrototypeOf(this, FirebaseError.prototype);\n\n // Maintains proper stack trace for where our error was thrown.\n // Only available on V8.\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, ErrorFactory.prototype.create);\n }\n }\n}\n\nexport class ErrorFactory<\n ErrorCode extends string,\n ErrorParams extends { readonly [K in ErrorCode]?: ErrorData } = {}\n> {\n constructor(\n private readonly service: string,\n private readonly serviceName: string,\n private readonly errors: ErrorMap\n ) {}\n\n create(\n code: K,\n ...data: K extends keyof ErrorParams ? [ErrorParams[K]] : []\n ): FirebaseError {\n const customData = (data[0] as ErrorData) || {};\n const fullCode = `${this.service}/${code}`;\n const template = this.errors[code];\n\n const message = template ? replaceTemplate(template, customData) : 'Error';\n // Service Name: Error message (service/code).\n const fullMessage = `${this.serviceName}: ${message} (${fullCode}).`;\n\n const error = new FirebaseError(fullCode, fullMessage, customData);\n\n return error;\n }\n}\n\nfunction replaceTemplate(template: string, data: ErrorData): string {\n return template.replace(PATTERN, (_, key) => {\n const value = data[key];\n return value != null ? String(value) : `<${key}?>`;\n });\n}\n\nconst PATTERN = /\\{\\$([^}]+)}/g;\n","/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport {\n InstantiationMode,\n InstanceFactory,\n ComponentType,\n Dictionary,\n Name,\n onInstanceCreatedCallback\n} from './types';\n\n/**\n * Component for service name T, e.g. `auth`, `auth-internal`\n */\nexport class Component {\n multipleInstances = false;\n /**\n * Properties to be added to the service namespace\n */\n serviceProps: Dictionary = {};\n\n instantiationMode = InstantiationMode.LAZY;\n\n onInstanceCreated: onInstanceCreatedCallback | null = null;\n\n /**\n *\n * @param name The public service name, e.g. app, auth, firestore, database\n * @param instanceFactory Service factory responsible for creating the public interface\n * @param type whether the service provided by the component is public or private\n */\n constructor(\n readonly name: T,\n readonly instanceFactory: InstanceFactory,\n readonly type: ComponentType\n ) {}\n\n setInstantiationMode(mode: InstantiationMode): this {\n this.instantiationMode = mode;\n return this;\n }\n\n setMultipleInstances(multipleInstances: boolean): this {\n this.multipleInstances = multipleInstances;\n return this;\n }\n\n setServiceProps(props: Dictionary): this {\n this.serviceProps = props;\n return this;\n }\n\n setInstanceCreatedCallback(callback: onInstanceCreatedCallback): this {\n this.onInstanceCreated = callback;\n return this;\n }\n}\n","const instanceOfAny = (object, constructors) => constructors.some((c) => object instanceof c);\n\nlet idbProxyableTypes;\nlet cursorAdvanceMethods;\n// This is a function to prevent it throwing up in node environments.\nfunction getIdbProxyableTypes() {\n return (idbProxyableTypes ||\n (idbProxyableTypes = [\n IDBDatabase,\n IDBObjectStore,\n IDBIndex,\n IDBCursor,\n IDBTransaction,\n ]));\n}\n// This is a function to prevent it throwing up in node environments.\nfunction getCursorAdvanceMethods() {\n return (cursorAdvanceMethods ||\n (cursorAdvanceMethods = [\n IDBCursor.prototype.advance,\n IDBCursor.prototype.continue,\n IDBCursor.prototype.continuePrimaryKey,\n ]));\n}\nconst cursorRequestMap = new WeakMap();\nconst transactionDoneMap = new WeakMap();\nconst transactionStoreNamesMap = new WeakMap();\nconst transformCache = new WeakMap();\nconst reverseTransformCache = new WeakMap();\nfunction promisifyRequest(request) {\n const promise = new Promise((resolve, reject) => {\n const unlisten = () => {\n request.removeEventListener('success', success);\n request.removeEventListener('error', error);\n };\n const success = () => {\n resolve(wrap(request.result));\n unlisten();\n };\n const error = () => {\n reject(request.error);\n unlisten();\n };\n request.addEventListener('success', success);\n request.addEventListener('error', error);\n });\n promise\n .then((value) => {\n // Since cursoring reuses the IDBRequest (*sigh*), we cache it for later retrieval\n // (see wrapFunction).\n if (value instanceof IDBCursor) {\n cursorRequestMap.set(value, request);\n }\n // Catching to avoid \"Uncaught Promise exceptions\"\n })\n .catch(() => { });\n // This mapping exists in reverseTransformCache but doesn't doesn't exist in transformCache. This\n // is because we create many promises from a single IDBRequest.\n reverseTransformCache.set(promise, request);\n return promise;\n}\nfunction cacheDonePromiseForTransaction(tx) {\n // Early bail if we've already created a done promise for this transaction.\n if (transactionDoneMap.has(tx))\n return;\n const done = new Promise((resolve, reject) => {\n const unlisten = () => {\n tx.removeEventListener('complete', complete);\n tx.removeEventListener('error', error);\n tx.removeEventListener('abort', error);\n };\n const complete = () => {\n resolve();\n unlisten();\n };\n const error = () => {\n reject(tx.error || new DOMException('AbortError', 'AbortError'));\n unlisten();\n };\n tx.addEventListener('complete', complete);\n tx.addEventListener('error', error);\n tx.addEventListener('abort', error);\n });\n // Cache it for later retrieval.\n transactionDoneMap.set(tx, done);\n}\nlet idbProxyTraps = {\n get(target, prop, receiver) {\n if (target instanceof IDBTransaction) {\n // Special handling for transaction.done.\n if (prop === 'done')\n return transactionDoneMap.get(target);\n // Polyfill for objectStoreNames because of Edge.\n if (prop === 'objectStoreNames') {\n return target.objectStoreNames || transactionStoreNamesMap.get(target);\n }\n // Make tx.store return the only store in the transaction, or undefined if there are many.\n if (prop === 'store') {\n return receiver.objectStoreNames[1]\n ? undefined\n : receiver.objectStore(receiver.objectStoreNames[0]);\n }\n }\n // Else transform whatever we get back.\n return wrap(target[prop]);\n },\n set(target, prop, value) {\n target[prop] = value;\n return true;\n },\n has(target, prop) {\n if (target instanceof IDBTransaction &&\n (prop === 'done' || prop === 'store')) {\n return true;\n }\n return prop in target;\n },\n};\nfunction replaceTraps(callback) {\n idbProxyTraps = callback(idbProxyTraps);\n}\nfunction wrapFunction(func) {\n // Due to expected object equality (which is enforced by the caching in `wrap`), we\n // only create one new func per func.\n // Edge doesn't support objectStoreNames (booo), so we polyfill it here.\n if (func === IDBDatabase.prototype.transaction &&\n !('objectStoreNames' in IDBTransaction.prototype)) {\n return function (storeNames, ...args) {\n const tx = func.call(unwrap(this), storeNames, ...args);\n transactionStoreNamesMap.set(tx, storeNames.sort ? storeNames.sort() : [storeNames]);\n return wrap(tx);\n };\n }\n // Cursor methods are special, as the behaviour is a little more different to standard IDB. In\n // IDB, you advance the cursor and wait for a new 'success' on the IDBRequest that gave you the\n // cursor. It's kinda like a promise that can resolve with many values. That doesn't make sense\n // with real promises, so each advance methods returns a new promise for the cursor object, or\n // undefined if the end of the cursor has been reached.\n if (getCursorAdvanceMethods().includes(func)) {\n return function (...args) {\n // Calling the original function with the proxy as 'this' causes ILLEGAL INVOCATION, so we use\n // the original object.\n func.apply(unwrap(this), args);\n return wrap(cursorRequestMap.get(this));\n };\n }\n return function (...args) {\n // Calling the original function with the proxy as 'this' causes ILLEGAL INVOCATION, so we use\n // the original object.\n return wrap(func.apply(unwrap(this), args));\n };\n}\nfunction transformCachableValue(value) {\n if (typeof value === 'function')\n return wrapFunction(value);\n // This doesn't return, it just creates a 'done' promise for the transaction,\n // which is later returned for transaction.done (see idbObjectHandler).\n if (value instanceof IDBTransaction)\n cacheDonePromiseForTransaction(value);\n if (instanceOfAny(value, getIdbProxyableTypes()))\n return new Proxy(value, idbProxyTraps);\n // Return the same value back if we're not going to transform it.\n return value;\n}\nfunction wrap(value) {\n // We sometimes generate multiple promises from a single IDBRequest (eg when cursoring), because\n // IDB is weird and a single IDBRequest can yield many responses, so these can't be cached.\n if (value instanceof IDBRequest)\n return promisifyRequest(value);\n // If we've already transformed this value before, reuse the transformed value.\n // This is faster, but it also provides object equality.\n if (transformCache.has(value))\n return transformCache.get(value);\n const newValue = transformCachableValue(value);\n // Not all types are transformed.\n // These may be primitive types, so they can't be WeakMap keys.\n if (newValue !== value) {\n transformCache.set(value, newValue);\n reverseTransformCache.set(newValue, value);\n }\n return newValue;\n}\nconst unwrap = (value) => reverseTransformCache.get(value);\n\nexport { reverseTransformCache as a, instanceOfAny as i, replaceTraps as r, unwrap as u, wrap as w };\n","/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { version } from '../../package.json';\n\nexport const PENDING_TIMEOUT_MS = 10000;\n\nexport const PACKAGE_VERSION = `w:${version}`;\nexport const INTERNAL_AUTH_VERSION = 'FIS_v2';\n\nexport const INSTALLATIONS_API_URL =\n 'https://firebaseinstallations.googleapis.com/v1';\n\nexport const TOKEN_EXPIRATION_BUFFER = 60 * 60 * 1000; // One hour\n\nexport const SERVICE = 'installations';\nexport const SERVICE_NAME = 'Installations';\n","/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ErrorFactory, FirebaseError } from '@firebase/util';\nimport { SERVICE, SERVICE_NAME } from './constants';\n\nexport const enum ErrorCode {\n MISSING_APP_CONFIG_VALUES = 'missing-app-config-values',\n NOT_REGISTERED = 'not-registered',\n INSTALLATION_NOT_FOUND = 'installation-not-found',\n REQUEST_FAILED = 'request-failed',\n APP_OFFLINE = 'app-offline',\n DELETE_PENDING_REGISTRATION = 'delete-pending-registration'\n}\n\nconst ERROR_DESCRIPTION_MAP: { readonly [key in ErrorCode]: string } = {\n [ErrorCode.MISSING_APP_CONFIG_VALUES]:\n 'Missing App configuration value: \"{$valueName}\"',\n [ErrorCode.NOT_REGISTERED]: 'Firebase Installation is not registered.',\n [ErrorCode.INSTALLATION_NOT_FOUND]: 'Firebase Installation not found.',\n [ErrorCode.REQUEST_FAILED]:\n '{$requestName} request failed with error \"{$serverCode} {$serverStatus}: {$serverMessage}\"',\n [ErrorCode.APP_OFFLINE]: 'Could not process request. Application offline.',\n [ErrorCode.DELETE_PENDING_REGISTRATION]:\n \"Can't delete installation while there is a pending registration request.\"\n};\n\ninterface ErrorParams {\n [ErrorCode.MISSING_APP_CONFIG_VALUES]: {\n valueName: string;\n };\n [ErrorCode.REQUEST_FAILED]: {\n requestName: string;\n [index: string]: string | number; // to make Typescript 3.8 happy\n } & ServerErrorData;\n}\n\nexport const ERROR_FACTORY = new ErrorFactory(\n SERVICE,\n SERVICE_NAME,\n ERROR_DESCRIPTION_MAP\n);\n\nexport interface ServerErrorData {\n serverCode: number;\n serverMessage: string;\n serverStatus: string;\n}\n\nexport type ServerError = FirebaseError & { customData: ServerErrorData };\n\n/** Returns true if error is a FirebaseError that is based on an error from the server. */\nexport function isServerError(error: unknown): error is ServerError {\n return (\n error instanceof FirebaseError &&\n error.code.includes(ErrorCode.REQUEST_FAILED)\n );\n}\n","/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { FirebaseError } from '@firebase/util';\nimport { GenerateAuthTokenResponse } from '../interfaces/api-response';\nimport {\n CompletedAuthToken,\n RegisteredInstallationEntry,\n RequestStatus\n} from '../interfaces/installation-entry';\nimport {\n INSTALLATIONS_API_URL,\n INTERNAL_AUTH_VERSION\n} from '../util/constants';\nimport { ERROR_FACTORY, ErrorCode } from '../util/errors';\nimport { AppConfig } from '../interfaces/installation-impl';\n\nexport function getInstallationsEndpoint({ projectId }: AppConfig): string {\n return `${INSTALLATIONS_API_URL}/projects/${projectId}/installations`;\n}\n\nexport function extractAuthTokenInfoFromResponse(\n response: GenerateAuthTokenResponse\n): CompletedAuthToken {\n return {\n token: response.token,\n requestStatus: RequestStatus.COMPLETED,\n expiresIn: getExpiresInFromResponseExpiresIn(response.expiresIn),\n creationTime: Date.now()\n };\n}\n\nexport async function getErrorFromResponse(\n requestName: string,\n response: Response\n): Promise {\n const responseJson: ErrorResponse = await response.json();\n const errorData = responseJson.error;\n return ERROR_FACTORY.create(ErrorCode.REQUEST_FAILED, {\n requestName,\n serverCode: errorData.code,\n serverMessage: errorData.message,\n serverStatus: errorData.status\n });\n}\n\nexport function getHeaders({ apiKey }: AppConfig): Headers {\n return new Headers({\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n 'x-goog-api-key': apiKey\n });\n}\n\nexport function getHeadersWithAuth(\n appConfig: AppConfig,\n { refreshToken }: RegisteredInstallationEntry\n): Headers {\n const headers = getHeaders(appConfig);\n headers.append('Authorization', getAuthorizationHeader(refreshToken));\n return headers;\n}\n\nexport interface ErrorResponse {\n error: {\n code: number;\n message: string;\n status: string;\n };\n}\n\n/**\n * Calls the passed in fetch wrapper and returns the response.\n * If the returned response has a status of 5xx, re-runs the function once and\n * returns the response.\n */\nexport async function retryIfServerError(\n fn: () => Promise\n): Promise {\n const result = await fn();\n\n if (result.status >= 500 && result.status < 600) {\n // Internal Server Error. Retry request.\n return fn();\n }\n\n return result;\n}\n\nfunction getExpiresInFromResponseExpiresIn(responseExpiresIn: string): number {\n // This works because the server will never respond with fractions of a second.\n return Number(responseExpiresIn.replace('s', '000'));\n}\n\nfunction getAuthorizationHeader(refreshToken: string): string {\n return `${INTERNAL_AUTH_VERSION} ${refreshToken}`;\n}\n","/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/** Returns a promise that resolves after given time passes. */\nexport function sleep(ms: number): Promise {\n return new Promise(resolve => {\n setTimeout(resolve, ms);\n });\n}\n","/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { bufferToBase64UrlSafe } from './buffer-to-base64-url-safe';\n\nexport const VALID_FID_PATTERN = /^[cdef][\\w-]{21}$/;\nexport const INVALID_FID = '';\n\n/**\n * Generates a new FID using random values from Web Crypto API.\n * Returns an empty string if FID generation fails for any reason.\n */\nexport function generateFid(): string {\n try {\n // A valid FID has exactly 22 base64 characters, which is 132 bits, or 16.5\n // bytes. our implementation generates a 17 byte array instead.\n const fidByteArray = new Uint8Array(17);\n const crypto =\n self.crypto || (self as unknown as { msCrypto: Crypto }).msCrypto;\n crypto.getRandomValues(fidByteArray);\n\n // Replace the first 4 random bits with the constant FID header of 0b0111.\n fidByteArray[0] = 0b01110000 + (fidByteArray[0] % 0b00010000);\n\n const fid = encode(fidByteArray);\n\n return VALID_FID_PATTERN.test(fid) ? fid : INVALID_FID;\n } catch {\n // FID generation errored\n return INVALID_FID;\n }\n}\n\n/** Converts a FID Uint8Array to a base64 string representation. */\nfunction encode(fidByteArray: Uint8Array): string {\n const b64String = bufferToBase64UrlSafe(fidByteArray);\n\n // Remove the 23rd character that was added because of the extra 4 bits at the\n // end of our 17 byte array, and the '=' padding.\n return b64String.substr(0, 22);\n}\n","/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport function bufferToBase64UrlSafe(array: Uint8Array): string {\n const b64 = btoa(String.fromCharCode(...array));\n return b64.replace(/\\+/g, '-').replace(/\\//g, '_');\n}\n","/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { AppConfig } from '../interfaces/installation-impl';\n\n/** Returns a string key that can be used to identify the app. */\nexport function getKey(appConfig: AppConfig): string {\n return `${appConfig.appName}!${appConfig.appId}`;\n}\n","/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { getKey } from '../util/get-key';\nimport { AppConfig } from '../interfaces/installation-impl';\nimport { IdChangeCallbackFn } from '../api';\n\nconst fidChangeCallbacks: Map> = new Map();\n\n/**\n * Calls the onIdChange callbacks with the new FID value, and broadcasts the\n * change to other tabs.\n */\nexport function fidChanged(appConfig: AppConfig, fid: string): void {\n const key = getKey(appConfig);\n\n callFidChangeCallbacks(key, fid);\n broadcastFidChange(key, fid);\n}\n\nexport function addCallback(\n appConfig: AppConfig,\n callback: IdChangeCallbackFn\n): void {\n // Open the broadcast channel if it's not already open,\n // to be able to listen to change events from other tabs.\n getBroadcastChannel();\n\n const key = getKey(appConfig);\n\n let callbackSet = fidChangeCallbacks.get(key);\n if (!callbackSet) {\n callbackSet = new Set();\n fidChangeCallbacks.set(key, callbackSet);\n }\n callbackSet.add(callback);\n}\n\nexport function removeCallback(\n appConfig: AppConfig,\n callback: IdChangeCallbackFn\n): void {\n const key = getKey(appConfig);\n\n const callbackSet = fidChangeCallbacks.get(key);\n\n if (!callbackSet) {\n return;\n }\n\n callbackSet.delete(callback);\n if (callbackSet.size === 0) {\n fidChangeCallbacks.delete(key);\n }\n\n // Close broadcast channel if there are no more callbacks.\n closeBroadcastChannel();\n}\n\nfunction callFidChangeCallbacks(key: string, fid: string): void {\n const callbacks = fidChangeCallbacks.get(key);\n if (!callbacks) {\n return;\n }\n\n for (const callback of callbacks) {\n callback(fid);\n }\n}\n\nfunction broadcastFidChange(key: string, fid: string): void {\n const channel = getBroadcastChannel();\n if (channel) {\n channel.postMessage({ key, fid });\n }\n closeBroadcastChannel();\n}\n\nlet broadcastChannel: BroadcastChannel | null = null;\n/** Opens and returns a BroadcastChannel if it is supported by the browser. */\nfunction getBroadcastChannel(): BroadcastChannel | null {\n if (!broadcastChannel && 'BroadcastChannel' in self) {\n broadcastChannel = new BroadcastChannel('[Firebase] FID Change');\n broadcastChannel.onmessage = e => {\n callFidChangeCallbacks(e.data.key, e.data.fid);\n };\n }\n return broadcastChannel;\n}\n\nfunction closeBroadcastChannel(): void {\n if (fidChangeCallbacks.size === 0 && broadcastChannel) {\n broadcastChannel.close();\n broadcastChannel = null;\n }\n}\n","/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { DBSchema, IDBPDatabase, openDB } from 'idb';\nimport { AppConfig } from '../interfaces/installation-impl';\nimport { InstallationEntry } from '../interfaces/installation-entry';\nimport { getKey } from '../util/get-key';\nimport { fidChanged } from './fid-changed';\n\nconst DATABASE_NAME = 'firebase-installations-database';\nconst DATABASE_VERSION = 1;\nconst OBJECT_STORE_NAME = 'firebase-installations-store';\n\ninterface InstallationsDB extends DBSchema {\n 'firebase-installations-store': {\n key: string;\n value: InstallationEntry | undefined;\n };\n}\n\nlet dbPromise: Promise> | null = null;\nfunction getDbPromise(): Promise> {\n if (!dbPromise) {\n dbPromise = openDB(DATABASE_NAME, DATABASE_VERSION, {\n upgrade: (db, oldVersion) => {\n // We don't use 'break' in this switch statement, the fall-through\n // behavior is what we want, because if there are multiple versions between\n // the old version and the current version, we want ALL the migrations\n // that correspond to those versions to run, not only the last one.\n // eslint-disable-next-line default-case\n switch (oldVersion) {\n case 0:\n db.createObjectStore(OBJECT_STORE_NAME);\n }\n }\n });\n }\n return dbPromise;\n}\n\n/** Gets record(s) from the objectStore that match the given key. */\nexport async function get(\n appConfig: AppConfig\n): Promise {\n const key = getKey(appConfig);\n const db = await getDbPromise();\n return db\n .transaction(OBJECT_STORE_NAME)\n .objectStore(OBJECT_STORE_NAME)\n .get(key) as Promise;\n}\n\n/** Assigns or overwrites the record for the given key with the given value. */\nexport async function set(\n appConfig: AppConfig,\n value: ValueType\n): Promise {\n const key = getKey(appConfig);\n const db = await getDbPromise();\n const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite');\n const objectStore = tx.objectStore(OBJECT_STORE_NAME);\n const oldValue = (await objectStore.get(key)) as InstallationEntry;\n await objectStore.put(value, key);\n await tx.done;\n\n if (!oldValue || oldValue.fid !== value.fid) {\n fidChanged(appConfig, value.fid);\n }\n\n return value;\n}\n\n/** Removes record(s) from the objectStore that match the given key. */\nexport async function remove(appConfig: AppConfig): Promise {\n const key = getKey(appConfig);\n const db = await getDbPromise();\n const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite');\n await tx.objectStore(OBJECT_STORE_NAME).delete(key);\n await tx.done;\n}\n\n/**\n * Atomically updates a record with the result of updateFn, which gets\n * called with the current value. If newValue is undefined, the record is\n * deleted instead.\n * @return Updated value\n */\nexport async function update(\n appConfig: AppConfig,\n updateFn: (previousValue: InstallationEntry | undefined) => ValueType\n): Promise {\n const key = getKey(appConfig);\n const db = await getDbPromise();\n const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite');\n const store = tx.objectStore(OBJECT_STORE_NAME);\n const oldValue: InstallationEntry | undefined = (await store.get(\n key\n )) as InstallationEntry;\n const newValue = updateFn(oldValue);\n\n if (newValue === undefined) {\n await store.delete(key);\n } else {\n await store.put(newValue, key);\n }\n await tx.done;\n\n if (newValue && (!oldValue || oldValue.fid !== newValue.fid)) {\n fidChanged(appConfig, newValue.fid);\n }\n\n return newValue;\n}\n\nexport async function clear(): Promise {\n const db = await getDbPromise();\n const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite');\n await tx.objectStore(OBJECT_STORE_NAME).clear();\n await tx.done;\n}\n","/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { createInstallationRequest } from '../functions/create-installation-request';\nimport {\n AppConfig,\n FirebaseInstallationsImpl\n} from '../interfaces/installation-impl';\nimport {\n InProgressInstallationEntry,\n InstallationEntry,\n RegisteredInstallationEntry,\n RequestStatus\n} from '../interfaces/installation-entry';\nimport { PENDING_TIMEOUT_MS } from '../util/constants';\nimport { ERROR_FACTORY, ErrorCode, isServerError } from '../util/errors';\nimport { sleep } from '../util/sleep';\nimport { generateFid, INVALID_FID } from './generate-fid';\nimport { remove, set, update } from './idb-manager';\n\nexport interface InstallationEntryWithRegistrationPromise {\n installationEntry: InstallationEntry;\n /** Exist iff the installationEntry is not registered. */\n registrationPromise?: Promise;\n}\n\n/**\n * Updates and returns the InstallationEntry from the database.\n * Also triggers a registration request if it is necessary and possible.\n */\nexport async function getInstallationEntry(\n installations: FirebaseInstallationsImpl\n): Promise {\n let registrationPromise: Promise | undefined;\n\n const installationEntry = await update(installations.appConfig, oldEntry => {\n const installationEntry = updateOrCreateInstallationEntry(oldEntry);\n const entryWithPromise = triggerRegistrationIfNecessary(\n installations,\n installationEntry\n );\n registrationPromise = entryWithPromise.registrationPromise;\n return entryWithPromise.installationEntry;\n });\n\n if (installationEntry.fid === INVALID_FID) {\n // FID generation failed. Waiting for the FID from the server.\n return { installationEntry: await registrationPromise! };\n }\n\n return {\n installationEntry,\n registrationPromise\n };\n}\n\n/**\n * Creates a new Installation Entry if one does not exist.\n * Also clears timed out pending requests.\n */\nfunction updateOrCreateInstallationEntry(\n oldEntry: InstallationEntry | undefined\n): InstallationEntry {\n const entry: InstallationEntry = oldEntry || {\n fid: generateFid(),\n registrationStatus: RequestStatus.NOT_STARTED\n };\n\n return clearTimedOutRequest(entry);\n}\n\n/**\n * If the Firebase Installation is not registered yet, this will trigger the\n * registration and return an InProgressInstallationEntry.\n *\n * If registrationPromise does not exist, the installationEntry is guaranteed\n * to be registered.\n */\nfunction triggerRegistrationIfNecessary(\n installations: FirebaseInstallationsImpl,\n installationEntry: InstallationEntry\n): InstallationEntryWithRegistrationPromise {\n if (installationEntry.registrationStatus === RequestStatus.NOT_STARTED) {\n if (!navigator.onLine) {\n // Registration required but app is offline.\n const registrationPromiseWithError = Promise.reject(\n ERROR_FACTORY.create(ErrorCode.APP_OFFLINE)\n );\n return {\n installationEntry,\n registrationPromise: registrationPromiseWithError\n };\n }\n\n // Try registering. Change status to IN_PROGRESS.\n const inProgressEntry: InProgressInstallationEntry = {\n fid: installationEntry.fid,\n registrationStatus: RequestStatus.IN_PROGRESS,\n registrationTime: Date.now()\n };\n const registrationPromise = registerInstallation(\n installations,\n inProgressEntry\n );\n return { installationEntry: inProgressEntry, registrationPromise };\n } else if (\n installationEntry.registrationStatus === RequestStatus.IN_PROGRESS\n ) {\n return {\n installationEntry,\n registrationPromise: waitUntilFidRegistration(installations)\n };\n } else {\n return { installationEntry };\n }\n}\n\n/** This will be executed only once for each new Firebase Installation. */\nasync function registerInstallation(\n installations: FirebaseInstallationsImpl,\n installationEntry: InProgressInstallationEntry\n): Promise {\n try {\n const registeredInstallationEntry = await createInstallationRequest(\n installations,\n installationEntry\n );\n return set(installations.appConfig, registeredInstallationEntry);\n } catch (e) {\n if (isServerError(e) && e.customData.serverCode === 409) {\n // Server returned a \"FID can not be used\" error.\n // Generate a new ID next time.\n await remove(installations.appConfig);\n } else {\n // Registration failed. Set FID as not registered.\n await set(installations.appConfig, {\n fid: installationEntry.fid,\n registrationStatus: RequestStatus.NOT_STARTED\n });\n }\n throw e;\n }\n}\n\n/** Call if FID registration is pending in another request. */\nasync function waitUntilFidRegistration(\n installations: FirebaseInstallationsImpl\n): Promise {\n // Unfortunately, there is no way of reliably observing when a value in\n // IndexedDB changes (yet, see https://github.com/WICG/indexed-db-observers),\n // so we need to poll.\n\n let entry: InstallationEntry = await updateInstallationRequest(\n installations.appConfig\n );\n while (entry.registrationStatus === RequestStatus.IN_PROGRESS) {\n // createInstallation request still in progress.\n await sleep(100);\n\n entry = await updateInstallationRequest(installations.appConfig);\n }\n\n if (entry.registrationStatus === RequestStatus.NOT_STARTED) {\n // The request timed out or failed in a different call. Try again.\n const { installationEntry, registrationPromise } =\n await getInstallationEntry(installations);\n\n if (registrationPromise) {\n return registrationPromise;\n } else {\n // if there is no registrationPromise, entry is registered.\n return installationEntry as RegisteredInstallationEntry;\n }\n }\n\n return entry;\n}\n\n/**\n * Called only if there is a CreateInstallation request in progress.\n *\n * Updates the InstallationEntry in the DB based on the status of the\n * CreateInstallation request.\n *\n * Returns the updated InstallationEntry.\n */\nfunction updateInstallationRequest(\n appConfig: AppConfig\n): Promise {\n return update(appConfig, oldEntry => {\n if (!oldEntry) {\n throw ERROR_FACTORY.create(ErrorCode.INSTALLATION_NOT_FOUND);\n }\n return clearTimedOutRequest(oldEntry);\n });\n}\n\nfunction clearTimedOutRequest(entry: InstallationEntry): InstallationEntry {\n if (hasInstallationRequestTimedOut(entry)) {\n return {\n fid: entry.fid,\n registrationStatus: RequestStatus.NOT_STARTED\n };\n }\n\n return entry;\n}\n\nfunction hasInstallationRequestTimedOut(\n installationEntry: InstallationEntry\n): boolean {\n return (\n installationEntry.registrationStatus === RequestStatus.IN_PROGRESS &&\n installationEntry.registrationTime + PENDING_TIMEOUT_MS < Date.now()\n );\n}\n","/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { CreateInstallationResponse } from '../interfaces/api-response';\nimport {\n InProgressInstallationEntry,\n RegisteredInstallationEntry,\n RequestStatus\n} from '../interfaces/installation-entry';\nimport { INTERNAL_AUTH_VERSION, PACKAGE_VERSION } from '../util/constants';\nimport {\n extractAuthTokenInfoFromResponse,\n getErrorFromResponse,\n getHeaders,\n getInstallationsEndpoint,\n retryIfServerError\n} from './common';\nimport { FirebaseInstallationsImpl } from '../interfaces/installation-impl';\n\nexport async function createInstallationRequest(\n { appConfig, heartbeatServiceProvider }: FirebaseInstallationsImpl,\n { fid }: InProgressInstallationEntry\n): Promise {\n const endpoint = getInstallationsEndpoint(appConfig);\n\n const headers = getHeaders(appConfig);\n\n // If heartbeat service exists, add the heartbeat string to the header.\n const heartbeatService = heartbeatServiceProvider.getImmediate({\n optional: true\n });\n if (heartbeatService) {\n const heartbeatsHeader = await heartbeatService.getHeartbeatsHeader();\n if (heartbeatsHeader) {\n headers.append('x-firebase-client', heartbeatsHeader);\n }\n }\n\n const body = {\n fid,\n authVersion: INTERNAL_AUTH_VERSION,\n appId: appConfig.appId,\n sdkVersion: PACKAGE_VERSION\n };\n\n const request: RequestInit = {\n method: 'POST',\n headers,\n body: JSON.stringify(body)\n };\n\n const response = await retryIfServerError(() => fetch(endpoint, request));\n if (response.ok) {\n const responseValue: CreateInstallationResponse = await response.json();\n const registeredInstallationEntry: RegisteredInstallationEntry = {\n fid: responseValue.fid || fid,\n registrationStatus: RequestStatus.COMPLETED,\n refreshToken: responseValue.refreshToken,\n authToken: extractAuthTokenInfoFromResponse(responseValue.authToken)\n };\n return registeredInstallationEntry;\n } else {\n throw await getErrorFromResponse('Create Installation', response);\n }\n}\n","/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { GenerateAuthTokenResponse } from '../interfaces/api-response';\nimport {\n CompletedAuthToken,\n RegisteredInstallationEntry\n} from '../interfaces/installation-entry';\nimport { PACKAGE_VERSION } from '../util/constants';\nimport {\n extractAuthTokenInfoFromResponse,\n getErrorFromResponse,\n getHeadersWithAuth,\n getInstallationsEndpoint,\n retryIfServerError\n} from './common';\nimport {\n FirebaseInstallationsImpl,\n AppConfig\n} from '../interfaces/installation-impl';\n\nexport async function generateAuthTokenRequest(\n { appConfig, heartbeatServiceProvider }: FirebaseInstallationsImpl,\n installationEntry: RegisteredInstallationEntry\n): Promise {\n const endpoint = getGenerateAuthTokenEndpoint(appConfig, installationEntry);\n\n const headers = getHeadersWithAuth(appConfig, installationEntry);\n\n // If heartbeat service exists, add the heartbeat string to the header.\n const heartbeatService = heartbeatServiceProvider.getImmediate({\n optional: true\n });\n if (heartbeatService) {\n const heartbeatsHeader = await heartbeatService.getHeartbeatsHeader();\n if (heartbeatsHeader) {\n headers.append('x-firebase-client', heartbeatsHeader);\n }\n }\n\n const body = {\n installation: {\n sdkVersion: PACKAGE_VERSION,\n appId: appConfig.appId\n }\n };\n\n const request: RequestInit = {\n method: 'POST',\n headers,\n body: JSON.stringify(body)\n };\n\n const response = await retryIfServerError(() => fetch(endpoint, request));\n if (response.ok) {\n const responseValue: GenerateAuthTokenResponse = await response.json();\n const completedAuthToken: CompletedAuthToken =\n extractAuthTokenInfoFromResponse(responseValue);\n return completedAuthToken;\n } else {\n throw await getErrorFromResponse('Generate Auth Token', response);\n }\n}\n\nfunction getGenerateAuthTokenEndpoint(\n appConfig: AppConfig,\n { fid }: RegisteredInstallationEntry\n): string {\n return `${getInstallationsEndpoint(appConfig)}/${fid}/authTokens:generate`;\n}\n","/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { generateAuthTokenRequest } from '../functions/generate-auth-token-request';\nimport {\n AppConfig,\n FirebaseInstallationsImpl\n} from '../interfaces/installation-impl';\nimport {\n AuthToken,\n CompletedAuthToken,\n InProgressAuthToken,\n InstallationEntry,\n RegisteredInstallationEntry,\n RequestStatus\n} from '../interfaces/installation-entry';\nimport { PENDING_TIMEOUT_MS, TOKEN_EXPIRATION_BUFFER } from '../util/constants';\nimport { ERROR_FACTORY, ErrorCode, isServerError } from '../util/errors';\nimport { sleep } from '../util/sleep';\nimport { remove, set, update } from './idb-manager';\n\n/**\n * Returns a valid authentication token for the installation. Generates a new\n * token if one doesn't exist, is expired or about to expire.\n *\n * Should only be called if the Firebase Installation is registered.\n */\nexport async function refreshAuthToken(\n installations: FirebaseInstallationsImpl,\n forceRefresh = false\n): Promise {\n let tokenPromise: Promise | undefined;\n const entry = await update(installations.appConfig, oldEntry => {\n if (!isEntryRegistered(oldEntry)) {\n throw ERROR_FACTORY.create(ErrorCode.NOT_REGISTERED);\n }\n\n const oldAuthToken = oldEntry.authToken;\n if (!forceRefresh && isAuthTokenValid(oldAuthToken)) {\n // There is a valid token in the DB.\n return oldEntry;\n } else if (oldAuthToken.requestStatus === RequestStatus.IN_PROGRESS) {\n // There already is a token request in progress.\n tokenPromise = waitUntilAuthTokenRequest(installations, forceRefresh);\n return oldEntry;\n } else {\n // No token or token expired.\n if (!navigator.onLine) {\n throw ERROR_FACTORY.create(ErrorCode.APP_OFFLINE);\n }\n\n const inProgressEntry = makeAuthTokenRequestInProgressEntry(oldEntry);\n tokenPromise = fetchAuthTokenFromServer(installations, inProgressEntry);\n return inProgressEntry;\n }\n });\n\n const authToken = tokenPromise\n ? await tokenPromise\n : (entry.authToken as CompletedAuthToken);\n return authToken;\n}\n\n/**\n * Call only if FID is registered and Auth Token request is in progress.\n *\n * Waits until the current pending request finishes. If the request times out,\n * tries once in this thread as well.\n */\nasync function waitUntilAuthTokenRequest(\n installations: FirebaseInstallationsImpl,\n forceRefresh: boolean\n): Promise {\n // Unfortunately, there is no way of reliably observing when a value in\n // IndexedDB changes (yet, see https://github.com/WICG/indexed-db-observers),\n // so we need to poll.\n\n let entry = await updateAuthTokenRequest(installations.appConfig);\n while (entry.authToken.requestStatus === RequestStatus.IN_PROGRESS) {\n // generateAuthToken still in progress.\n await sleep(100);\n\n entry = await updateAuthTokenRequest(installations.appConfig);\n }\n\n const authToken = entry.authToken;\n if (authToken.requestStatus === RequestStatus.NOT_STARTED) {\n // The request timed out or failed in a different call. Try again.\n return refreshAuthToken(installations, forceRefresh);\n } else {\n return authToken;\n }\n}\n\n/**\n * Called only if there is a GenerateAuthToken request in progress.\n *\n * Updates the InstallationEntry in the DB based on the status of the\n * GenerateAuthToken request.\n *\n * Returns the updated InstallationEntry.\n */\nfunction updateAuthTokenRequest(\n appConfig: AppConfig\n): Promise {\n return update(appConfig, oldEntry => {\n if (!isEntryRegistered(oldEntry)) {\n throw ERROR_FACTORY.create(ErrorCode.NOT_REGISTERED);\n }\n\n const oldAuthToken = oldEntry.authToken;\n if (hasAuthTokenRequestTimedOut(oldAuthToken)) {\n return {\n ...oldEntry,\n authToken: { requestStatus: RequestStatus.NOT_STARTED }\n };\n }\n\n return oldEntry;\n });\n}\n\nasync function fetchAuthTokenFromServer(\n installations: FirebaseInstallationsImpl,\n installationEntry: RegisteredInstallationEntry\n): Promise {\n try {\n const authToken = await generateAuthTokenRequest(\n installations,\n installationEntry\n );\n const updatedInstallationEntry: RegisteredInstallationEntry = {\n ...installationEntry,\n authToken\n };\n await set(installations.appConfig, updatedInstallationEntry);\n return authToken;\n } catch (e) {\n if (\n isServerError(e) &&\n (e.customData.serverCode === 401 || e.customData.serverCode === 404)\n ) {\n // Server returned a \"FID not found\" or a \"Invalid authentication\" error.\n // Generate a new ID next time.\n await remove(installations.appConfig);\n } else {\n const updatedInstallationEntry: RegisteredInstallationEntry = {\n ...installationEntry,\n authToken: { requestStatus: RequestStatus.NOT_STARTED }\n };\n await set(installations.appConfig, updatedInstallationEntry);\n }\n throw e;\n }\n}\n\nfunction isEntryRegistered(\n installationEntry: InstallationEntry | undefined\n): installationEntry is RegisteredInstallationEntry {\n return (\n installationEntry !== undefined &&\n installationEntry.registrationStatus === RequestStatus.COMPLETED\n );\n}\n\nfunction isAuthTokenValid(authToken: AuthToken): boolean {\n return (\n authToken.requestStatus === RequestStatus.COMPLETED &&\n !isAuthTokenExpired(authToken)\n );\n}\n\nfunction isAuthTokenExpired(authToken: CompletedAuthToken): boolean {\n const now = Date.now();\n return (\n now < authToken.creationTime ||\n authToken.creationTime + authToken.expiresIn < now + TOKEN_EXPIRATION_BUFFER\n );\n}\n\n/** Returns an updated InstallationEntry with an InProgressAuthToken. */\nfunction makeAuthTokenRequestInProgressEntry(\n oldEntry: RegisteredInstallationEntry\n): RegisteredInstallationEntry {\n const inProgressAuthToken: InProgressAuthToken = {\n requestStatus: RequestStatus.IN_PROGRESS,\n requestTime: Date.now()\n };\n return {\n ...oldEntry,\n authToken: inProgressAuthToken\n };\n}\n\nfunction hasAuthTokenRequestTimedOut(authToken: AuthToken): boolean {\n return (\n authToken.requestStatus === RequestStatus.IN_PROGRESS &&\n authToken.requestTime + PENDING_TIMEOUT_MS < Date.now()\n );\n}\n","/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { getInstallationEntry } from '../helpers/get-installation-entry';\nimport { refreshAuthToken } from '../helpers/refresh-auth-token';\nimport { FirebaseInstallationsImpl } from '../interfaces/installation-impl';\nimport { Installations } from '../interfaces/public-types';\n\n/**\n * Returns a Firebase Installations auth token, identifying the current\n * Firebase Installation.\n * @param installations - The `Installations` instance.\n * @param forceRefresh - Force refresh regardless of token expiration.\n *\n * @public\n */\nexport async function getToken(\n installations: Installations,\n forceRefresh = false\n): Promise {\n const installationsImpl = installations as FirebaseInstallationsImpl;\n await completeInstallationRegistration(installationsImpl);\n\n // At this point we either have a Registered Installation in the DB, or we've\n // already thrown an error.\n const authToken = await refreshAuthToken(installationsImpl, forceRefresh);\n return authToken.token;\n}\n\nasync function completeInstallationRegistration(\n installations: FirebaseInstallationsImpl\n): Promise {\n const { registrationPromise } = await getInstallationEntry(installations);\n\n if (registrationPromise) {\n // A createInstallation request is in progress. Wait until it finishes.\n await registrationPromise;\n }\n}\n","/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { FirebaseApp, FirebaseOptions } from '@firebase/app';\nimport { FirebaseError } from '@firebase/util';\nimport { AppConfig } from '../interfaces/installation-impl';\nimport { ERROR_FACTORY, ErrorCode } from '../util/errors';\n\nexport function extractAppConfig(app: FirebaseApp): AppConfig {\n if (!app || !app.options) {\n throw getMissingValueError('App Configuration');\n }\n\n if (!app.name) {\n throw getMissingValueError('App Name');\n }\n\n // Required app config keys\n const configKeys: Array = [\n 'projectId',\n 'apiKey',\n 'appId'\n ];\n\n for (const keyName of configKeys) {\n if (!app.options[keyName]) {\n throw getMissingValueError(keyName);\n }\n }\n\n return {\n appName: app.name,\n projectId: app.options.projectId!,\n apiKey: app.options.apiKey!,\n appId: app.options.appId!\n };\n}\n\nfunction getMissingValueError(valueName: string): FirebaseError {\n return ERROR_FACTORY.create(ErrorCode.MISSING_APP_CONFIG_VALUES, {\n valueName\n });\n}\n","/**\n * @license\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { _registerComponent, _getProvider } from '@firebase/app';\nimport {\n Component,\n ComponentType,\n InstanceFactory,\n ComponentContainer\n} from '@firebase/component';\nimport { getId, getToken } from '../api/index';\nimport { _FirebaseInstallationsInternal } from '../interfaces/public-types';\nimport { FirebaseInstallationsImpl } from '../interfaces/installation-impl';\nimport { extractAppConfig } from '../helpers/extract-app-config';\n\nconst INSTALLATIONS_NAME = 'installations';\nconst INSTALLATIONS_NAME_INTERNAL = 'installations-internal';\n\nconst publicFactory: InstanceFactory<'installations'> = (\n container: ComponentContainer\n) => {\n const app = container.getProvider('app').getImmediate();\n // Throws if app isn't configured properly.\n const appConfig = extractAppConfig(app);\n const heartbeatServiceProvider = _getProvider(app, 'heartbeat');\n\n const installationsImpl: FirebaseInstallationsImpl = {\n app,\n appConfig,\n heartbeatServiceProvider,\n _delete: () => Promise.resolve()\n };\n return installationsImpl;\n};\n\nconst internalFactory: InstanceFactory<'installations-internal'> = (\n container: ComponentContainer\n) => {\n const app = container.getProvider('app').getImmediate();\n // Internal FIS instance relies on public FIS instance.\n const installations = _getProvider(app, INSTALLATIONS_NAME).getImmediate();\n\n const installationsInternal: _FirebaseInstallationsInternal = {\n getId: () => getId(installations),\n getToken: (forceRefresh?: boolean) => getToken(installations, forceRefresh)\n };\n return installationsInternal;\n};\n\nexport function registerInstallations(): void {\n _registerComponent(\n new Component(INSTALLATIONS_NAME, publicFactory, ComponentType.PUBLIC)\n );\n _registerComponent(\n new Component(\n INSTALLATIONS_NAME_INTERNAL,\n internalFactory,\n ComponentType.PRIVATE\n )\n );\n}\n","/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { getInstallationEntry } from '../helpers/get-installation-entry';\nimport { refreshAuthToken } from '../helpers/refresh-auth-token';\nimport { FirebaseInstallationsImpl } from '../interfaces/installation-impl';\nimport { Installations } from '../interfaces/public-types';\n\n/**\n * Creates a Firebase Installation if there isn't one for the app and\n * returns the Installation ID.\n * @param installations - The `Installations` instance.\n *\n * @public\n */\nexport async function getId(installations: Installations): Promise {\n const installationsImpl = installations as FirebaseInstallationsImpl;\n const { installationEntry, registrationPromise } = await getInstallationEntry(\n installationsImpl\n );\n\n if (registrationPromise) {\n registrationPromise.catch(console.error);\n } else {\n // If the installation is already registered, update the authentication\n // token if needed.\n refreshAuthToken(installationsImpl).catch(console.error);\n }\n\n return installationEntry.fid;\n}\n","/**\n * Firebase Installations\n *\n * @packageDocumentation\n */\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { registerInstallations } from './functions/config';\nimport { registerVersion } from '@firebase/app';\nimport { name, version } from '../package.json';\n\nexport * from './api';\nexport * from './interfaces/public-types';\n\nregisterInstallations();\nregisterVersion(name, version);\n// BUILD_TARGET will be replaced by values like esm5, esm2017, cjs5, etc during the compilation\nregisterVersion(name, version, '__BUILD_TARGET__');\n","/**\n * @license\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { version } from '../package.json';\n\nexport const SDK_VERSION = version;\n/** The prefix for start User Timing marks used for creating Traces. */\nexport const TRACE_START_MARK_PREFIX = 'FB-PERF-TRACE-START';\n/** The prefix for stop User Timing marks used for creating Traces. */\nexport const TRACE_STOP_MARK_PREFIX = 'FB-PERF-TRACE-STOP';\n/** The prefix for User Timing measure used for creating Traces. */\nexport const TRACE_MEASURE_PREFIX = 'FB-PERF-TRACE-MEASURE';\n/** The prefix for out of the box page load Trace name. */\nexport const OOB_TRACE_PAGE_LOAD_PREFIX = '_wt_';\n\nexport const FIRST_PAINT_COUNTER_NAME = '_fp';\n\nexport const FIRST_CONTENTFUL_PAINT_COUNTER_NAME = '_fcp';\n\nexport const FIRST_INPUT_DELAY_COUNTER_NAME = '_fid';\n\nexport const CONFIG_LOCAL_STORAGE_KEY = '@firebase/performance/config';\n\nexport const CONFIG_EXPIRY_LOCAL_STORAGE_KEY =\n '@firebase/performance/configexpire';\n\nexport const SERVICE = 'performance';\nexport const SERVICE_NAME = 'Performance';\n","/**\n * @license\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Api } from '../services/api_service';\n\n// The values and orders of the following enums should not be changed.\nconst enum ServiceWorkerStatus {\n UNKNOWN = 0,\n UNSUPPORTED = 1,\n CONTROLLED = 2,\n UNCONTROLLED = 3\n}\n\nexport enum VisibilityState {\n UNKNOWN = 0,\n VISIBLE = 1,\n HIDDEN = 2\n}\n\nconst enum EffectiveConnectionType {\n UNKNOWN = 0,\n CONNECTION_SLOW_2G = 1,\n CONNECTION_2G = 2,\n CONNECTION_3G = 3,\n CONNECTION_4G = 4\n}\n\n/**\n * NetworkInformation\n *\n * ref: https://developer.mozilla.org/en-US/docs/Web/API/NetworkInformation\n */\ninterface NetworkInformationWithEffectiveType extends NetworkInformation {\n // `effectiveType` is an experimental property and not included in\n // TypeScript's typings for the native NetworkInformation interface\n readonly effectiveType?: 'slow-2g' | '2g' | '3g' | '4g';\n}\n\ninterface NavigatorWithConnection extends Navigator {\n readonly connection: NetworkInformationWithEffectiveType;\n}\n\nconst RESERVED_ATTRIBUTE_PREFIXES = ['firebase_', 'google_', 'ga_'];\nconst ATTRIBUTE_FORMAT_REGEX = new RegExp('^[a-zA-Z]\\\\w*$');\nconst MAX_ATTRIBUTE_NAME_LENGTH = 40;\nconst MAX_ATTRIBUTE_VALUE_LENGTH = 100;\n\nexport function getServiceWorkerStatus(): ServiceWorkerStatus {\n const navigator = Api.getInstance().navigator;\n if (navigator?.serviceWorker) {\n if (navigator.serviceWorker.controller) {\n return ServiceWorkerStatus.CONTROLLED;\n } else {\n return ServiceWorkerStatus.UNCONTROLLED;\n }\n } else {\n return ServiceWorkerStatus.UNSUPPORTED;\n }\n}\n\nexport function getVisibilityState(): VisibilityState {\n const document = Api.getInstance().document;\n const visibilityState = document.visibilityState;\n switch (visibilityState) {\n case 'visible':\n return VisibilityState.VISIBLE;\n case 'hidden':\n return VisibilityState.HIDDEN;\n default:\n return VisibilityState.UNKNOWN;\n }\n}\n\nexport function getEffectiveConnectionType(): EffectiveConnectionType {\n const navigator = Api.getInstance().navigator;\n const navigatorConnection = (navigator as NavigatorWithConnection).connection;\n const effectiveType =\n navigatorConnection && navigatorConnection.effectiveType;\n switch (effectiveType) {\n case 'slow-2g':\n return EffectiveConnectionType.CONNECTION_SLOW_2G;\n case '2g':\n return EffectiveConnectionType.CONNECTION_2G;\n case '3g':\n return EffectiveConnectionType.CONNECTION_3G;\n case '4g':\n return EffectiveConnectionType.CONNECTION_4G;\n default:\n return EffectiveConnectionType.UNKNOWN;\n }\n}\n\nexport function isValidCustomAttributeName(name: string): boolean {\n if (name.length === 0 || name.length > MAX_ATTRIBUTE_NAME_LENGTH) {\n return false;\n }\n const matchesReservedPrefix = RESERVED_ATTRIBUTE_PREFIXES.some(prefix =>\n name.startsWith(prefix)\n );\n return !matchesReservedPrefix && !!name.match(ATTRIBUTE_FORMAT_REGEX);\n}\n\nexport function isValidCustomAttributeValue(value: string): boolean {\n return value.length !== 0 && value.length <= MAX_ATTRIBUTE_VALUE_LENGTH;\n}\n","/**\n * @license\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport firebase, { _FirebaseNamespace } from '@firebase/app-compat';\nimport {\n Component,\n ComponentContainer,\n ComponentType\n} from '@firebase/component';\nimport { PerformanceCompatImpl } from './performance';\nimport { name as packageName, version } from '../package.json';\nimport { FirebasePerformance as FirebasePerformanceCompat } from '@firebase/performance-types';\n\nfunction registerPerformanceCompat(firebaseInstance: _FirebaseNamespace): void {\n firebaseInstance.INTERNAL.registerComponent(\n new Component(\n 'performance-compat',\n performanceFactory,\n ComponentType.PUBLIC\n )\n );\n\n firebaseInstance.registerVersion(packageName, version);\n}\n\nfunction performanceFactory(\n container: ComponentContainer\n): PerformanceCompatImpl {\n const app = container.getProvider('app-compat').getImmediate();\n // The following call will always succeed.\n const performance = container.getProvider('performance').getImmediate();\n\n return new PerformanceCompatImpl(app, performance);\n}\n\nregisterPerformanceCompat(firebase as _FirebaseNamespace);\n\ndeclare module '@firebase/app-compat' {\n interface FirebaseNamespace {\n performance: {\n (app?: FirebaseApp): FirebasePerformanceCompat;\n };\n }\n interface FirebaseApp {\n performance(): FirebasePerformanceCompat;\n }\n}\n","/**\n * @license\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ErrorFactory } from '@firebase/util';\nimport { SERVICE, SERVICE_NAME } from '../constants';\n\nexport const enum ErrorCode {\n TRACE_STARTED_BEFORE = 'trace started',\n TRACE_STOPPED_BEFORE = 'trace stopped',\n NONPOSITIVE_TRACE_START_TIME = 'nonpositive trace startTime',\n NONPOSITIVE_TRACE_DURATION = 'nonpositive trace duration',\n NO_WINDOW = 'no window',\n NO_APP_ID = 'no app id',\n NO_PROJECT_ID = 'no project id',\n NO_API_KEY = 'no api key',\n INVALID_CC_LOG = 'invalid cc log',\n FB_NOT_DEFAULT = 'FB not default',\n RC_NOT_OK = 'RC response not ok',\n INVALID_ATTRIBUTE_NAME = 'invalid attribute name',\n INVALID_ATTRIBUTE_VALUE = 'invalid attribute value',\n INVALID_CUSTOM_METRIC_NAME = 'invalid custom metric name',\n INVALID_STRING_MERGER_PARAMETER = 'invalid String merger input',\n ALREADY_INITIALIZED = 'already initialized'\n}\n\nconst ERROR_DESCRIPTION_MAP: { readonly [key in ErrorCode]: string } = {\n [ErrorCode.TRACE_STARTED_BEFORE]: 'Trace {$traceName} was started before.',\n [ErrorCode.TRACE_STOPPED_BEFORE]: 'Trace {$traceName} is not running.',\n [ErrorCode.NONPOSITIVE_TRACE_START_TIME]:\n 'Trace {$traceName} startTime should be positive.',\n [ErrorCode.NONPOSITIVE_TRACE_DURATION]:\n 'Trace {$traceName} duration should be positive.',\n [ErrorCode.NO_WINDOW]: 'Window is not available.',\n [ErrorCode.NO_APP_ID]: 'App id is not available.',\n [ErrorCode.NO_PROJECT_ID]: 'Project id is not available.',\n [ErrorCode.NO_API_KEY]: 'Api key is not available.',\n [ErrorCode.INVALID_CC_LOG]: 'Attempted to queue invalid cc event',\n [ErrorCode.FB_NOT_DEFAULT]:\n 'Performance can only start when Firebase app instance is the default one.',\n [ErrorCode.RC_NOT_OK]: 'RC response is not ok',\n [ErrorCode.INVALID_ATTRIBUTE_NAME]:\n 'Attribute name {$attributeName} is invalid.',\n [ErrorCode.INVALID_ATTRIBUTE_VALUE]:\n 'Attribute value {$attributeValue} is invalid.',\n [ErrorCode.INVALID_CUSTOM_METRIC_NAME]:\n 'Custom metric name {$customMetricName} is invalid',\n [ErrorCode.INVALID_STRING_MERGER_PARAMETER]:\n 'Input for String merger is invalid, contact support team to resolve.',\n [ErrorCode.ALREADY_INITIALIZED]:\n 'initializePerformance() has already been called with ' +\n 'different options. To avoid this error, call initializePerformance() with the ' +\n 'same options as when it was originally called, or call getPerformance() to return the' +\n ' already initialized instance.'\n};\n\ninterface ErrorParams {\n [ErrorCode.TRACE_STARTED_BEFORE]: { traceName: string };\n [ErrorCode.TRACE_STOPPED_BEFORE]: { traceName: string };\n [ErrorCode.NONPOSITIVE_TRACE_START_TIME]: { traceName: string };\n [ErrorCode.NONPOSITIVE_TRACE_DURATION]: { traceName: string };\n [ErrorCode.INVALID_ATTRIBUTE_NAME]: { attributeName: string };\n [ErrorCode.INVALID_ATTRIBUTE_VALUE]: { attributeValue: string };\n [ErrorCode.INVALID_CUSTOM_METRIC_NAME]: { customMetricName: string };\n}\n\nexport const ERROR_FACTORY = new ErrorFactory(\n SERVICE,\n SERVICE_NAME,\n ERROR_DESCRIPTION_MAP\n);\n","/**\n * @license\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Logger, LogLevel } from '@firebase/logger';\nimport { SERVICE_NAME } from '../constants';\n\nexport const consoleLogger = new Logger(SERVICE_NAME);\nconsoleLogger.logLevel = LogLevel.INFO;\n","/**\n * @license\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ERROR_FACTORY, ErrorCode } from '../utils/errors';\nimport { isIndexedDBAvailable, areCookiesEnabled } from '@firebase/util';\nimport { consoleLogger } from '../utils/console_logger';\n\ndeclare global {\n interface Window {\n PerformanceObserver: typeof PerformanceObserver;\n perfMetrics?: { onFirstInputDelay(fn: (fid: number) => void): void };\n }\n}\n\nlet apiInstance: Api | undefined;\nlet windowInstance: Window | undefined;\n\nexport type EntryType =\n | 'mark'\n | 'measure'\n | 'paint'\n | 'resource'\n | 'frame'\n | 'navigation';\n\n/**\n * This class holds a reference to various browser related objects injected by\n * set methods.\n */\nexport class Api {\n private readonly performance: Performance;\n /** PreformanceObserver constructor function. */\n private readonly PerformanceObserver: typeof PerformanceObserver;\n private readonly windowLocation: Location;\n readonly onFirstInputDelay?: (fn: (fid: number) => void) => void;\n readonly localStorage?: Storage;\n readonly document: Document;\n readonly navigator: Navigator;\n\n constructor(readonly window?: Window) {\n if (!window) {\n throw ERROR_FACTORY.create(ErrorCode.NO_WINDOW);\n }\n this.performance = window.performance;\n this.PerformanceObserver = window.PerformanceObserver;\n this.windowLocation = window.location;\n this.navigator = window.navigator;\n this.document = window.document;\n if (this.navigator && this.navigator.cookieEnabled) {\n // If user blocks cookies on the browser, accessing localStorage will\n // throw an exception.\n this.localStorage = window.localStorage;\n }\n if (window.perfMetrics && window.perfMetrics.onFirstInputDelay) {\n this.onFirstInputDelay = window.perfMetrics.onFirstInputDelay;\n }\n }\n\n getUrl(): string {\n // Do not capture the string query part of url.\n return this.windowLocation.href.split('?')[0];\n }\n\n mark(name: string): void {\n if (!this.performance || !this.performance.mark) {\n return;\n }\n this.performance.mark(name);\n }\n\n measure(measureName: string, mark1: string, mark2: string): void {\n if (!this.performance || !this.performance.measure) {\n return;\n }\n this.performance.measure(measureName, mark1, mark2);\n }\n\n getEntriesByType(type: EntryType): PerformanceEntry[] {\n if (!this.performance || !this.performance.getEntriesByType) {\n return [];\n }\n return this.performance.getEntriesByType(type);\n }\n\n getEntriesByName(name: string): PerformanceEntry[] {\n if (!this.performance || !this.performance.getEntriesByName) {\n return [];\n }\n return this.performance.getEntriesByName(name);\n }\n\n getTimeOrigin(): number {\n // Polyfill the time origin with performance.timing.navigationStart.\n return (\n this.performance &&\n (this.performance.timeOrigin || this.performance.timing.navigationStart)\n );\n }\n\n requiredApisAvailable(): boolean {\n if (!fetch || !Promise || !areCookiesEnabled()) {\n consoleLogger.info(\n 'Firebase Performance cannot start if browser does not support fetch and Promise or cookie is disabled.'\n );\n return false;\n }\n\n if (!isIndexedDBAvailable()) {\n consoleLogger.info('IndexedDB is not supported by current browswer');\n return false;\n }\n return true;\n }\n\n setupObserver(\n entryType: EntryType,\n callback: (entry: PerformanceEntry) => void\n ): void {\n if (!this.PerformanceObserver) {\n return;\n }\n const observer = new this.PerformanceObserver(list => {\n for (const entry of list.getEntries()) {\n // `entry` is a PerformanceEntry instance.\n callback(entry);\n }\n });\n\n // Start observing the entry types you care about.\n observer.observe({ entryTypes: [entryType] });\n }\n\n static getInstance(): Api {\n if (apiInstance === undefined) {\n apiInstance = new Api(windowInstance);\n }\n return apiInstance;\n }\n}\n\nexport function setupApi(window: Window): void {\n windowInstance = window;\n}\n","/**\n * @license\n * Copyright 2017 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { CONSTANTS } from './constants';\nimport { getDefaults } from './defaults';\n\n/**\n * Returns navigator.userAgent string or '' if it's not defined.\n * @return user agent string\n */\nexport function getUA(): string {\n if (\n typeof navigator !== 'undefined' &&\n typeof navigator['userAgent'] === 'string'\n ) {\n return navigator['userAgent'];\n } else {\n return '';\n }\n}\n\n/**\n * Detect Cordova / PhoneGap / Ionic frameworks on a mobile device.\n *\n * Deliberately does not rely on checking `file://` URLs (as this fails PhoneGap\n * in the Ripple emulator) nor Cordova `onDeviceReady`, which would normally\n * wait for a callback.\n */\nexport function isMobileCordova(): boolean {\n return (\n typeof window !== 'undefined' &&\n // @ts-ignore Setting up an broadly applicable index signature for Window\n // just to deal with this case would probably be a bad idea.\n !!(window['cordova'] || window['phonegap'] || window['PhoneGap']) &&\n /ios|iphone|ipod|ipad|android|blackberry|iemobile/i.test(getUA())\n );\n}\n\n/**\n * Detect Node.js.\n *\n * @return true if Node.js environment is detected or specified.\n */\n// Node detection logic from: https://github.com/iliakan/detect-node/\nexport function isNode(): boolean {\n const forceEnvironment = getDefaults()?.forceEnvironment;\n if (forceEnvironment === 'node') {\n return true;\n } else if (forceEnvironment === 'browser') {\n return false;\n }\n\n try {\n return (\n Object.prototype.toString.call(global.process) === '[object process]'\n );\n } catch (e) {\n return false;\n }\n}\n\n/**\n * Detect Browser Environment\n */\nexport function isBrowser(): boolean {\n return typeof self === 'object' && self.self === self;\n}\n\n/**\n * Detect browser extensions (Chrome and Firefox at least).\n */\ninterface BrowserRuntime {\n id?: unknown;\n}\ndeclare const chrome: { runtime?: BrowserRuntime };\ndeclare const browser: { runtime?: BrowserRuntime };\nexport function isBrowserExtension(): boolean {\n const runtime =\n typeof chrome === 'object'\n ? chrome.runtime\n : typeof browser === 'object'\n ? browser.runtime\n : undefined;\n return typeof runtime === 'object' && runtime.id !== undefined;\n}\n\n/**\n * Detect React Native.\n *\n * @return true if ReactNative environment is detected.\n */\nexport function isReactNative(): boolean {\n return (\n typeof navigator === 'object' && navigator['product'] === 'ReactNative'\n );\n}\n\n/** Detects Electron apps. */\nexport function isElectron(): boolean {\n return getUA().indexOf('Electron/') >= 0;\n}\n\n/** Detects Internet Explorer. */\nexport function isIE(): boolean {\n const ua = getUA();\n return ua.indexOf('MSIE ') >= 0 || ua.indexOf('Trident/') >= 0;\n}\n\n/** Detects Universal Windows Platform apps. */\nexport function isUWP(): boolean {\n return getUA().indexOf('MSAppHost/') >= 0;\n}\n\n/**\n * Detect whether the current SDK build is the Node version.\n *\n * @return true if it's the Node SDK build.\n */\nexport function isNodeSdk(): boolean {\n return CONSTANTS.NODE_CLIENT === true || CONSTANTS.NODE_ADMIN === true;\n}\n\n/** Returns true if we are running in Safari. */\nexport function isSafari(): boolean {\n return (\n !isNode() &&\n navigator.userAgent.includes('Safari') &&\n !navigator.userAgent.includes('Chrome')\n );\n}\n\n/**\n * This method checks if indexedDB is supported by current browser/service worker context\n * @return true if indexedDB is supported by current browser/service worker context\n */\nexport function isIndexedDBAvailable(): boolean {\n try {\n return typeof indexedDB === 'object';\n } catch (e) {\n return false;\n }\n}\n\n/**\n * This method validates browser/sw context for indexedDB by opening a dummy indexedDB database and reject\n * if errors occur during the database open operation.\n *\n * @throws exception if current browser/sw context can't run idb.open (ex: Safari iframe, Firefox\n * private browsing)\n */\nexport function validateIndexedDBOpenable(): Promise {\n return new Promise((resolve, reject) => {\n try {\n let preExist: boolean = true;\n const DB_CHECK_NAME =\n 'validate-browser-context-for-indexeddb-analytics-module';\n const request = self.indexedDB.open(DB_CHECK_NAME);\n request.onsuccess = () => {\n request.result.close();\n // delete database only when it doesn't pre-exist\n if (!preExist) {\n self.indexedDB.deleteDatabase(DB_CHECK_NAME);\n }\n resolve(true);\n };\n request.onupgradeneeded = () => {\n preExist = false;\n };\n\n request.onerror = () => {\n reject(request.error?.message || '');\n };\n } catch (error) {\n reject(error);\n }\n });\n}\n\n/**\n *\n * This method checks whether cookie is enabled within current browser\n * @return true if cookie is enabled within current browser\n */\nexport function areCookiesEnabled(): boolean {\n if (typeof navigator === 'undefined' || !navigator.cookieEnabled) {\n return false;\n }\n return true;\n}\n","/**\n * @license\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { _FirebaseInstallationsInternal } from '@firebase/installations';\n\nlet iid: string | undefined;\nlet authToken: string | undefined;\n\nexport function getIidPromise(\n installationsService: _FirebaseInstallationsInternal\n): Promise {\n const iidPromise = installationsService.getId();\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n iidPromise.then((iidVal: string) => {\n iid = iidVal;\n });\n return iidPromise;\n}\n\n// This method should be used after the iid is retrieved by getIidPromise method.\nexport function getIid(): string | undefined {\n return iid;\n}\n\nexport function getAuthTokenPromise(\n installationsService: _FirebaseInstallationsInternal\n): Promise {\n const authTokenPromise = installationsService.getToken();\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n authTokenPromise.then((authTokenVal: string) => {\n authToken = authTokenVal;\n });\n return authTokenPromise;\n}\n\nexport function getAuthenticationToken(): string | undefined {\n return authToken;\n}\n","/**\n * @license\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ERROR_FACTORY, ErrorCode } from './errors';\n\nexport function mergeStrings(part1: string, part2: string): string {\n const sizeDiff = part1.length - part2.length;\n if (sizeDiff < 0 || sizeDiff > 1) {\n throw ERROR_FACTORY.create(ErrorCode.INVALID_STRING_MERGER_PARAMETER);\n }\n\n const resultArray = [];\n for (let i = 0; i < part1.length; i++) {\n resultArray.push(part1.charAt(i));\n if (part2.length > i) {\n resultArray.push(part2.charAt(i));\n }\n }\n\n return resultArray.join('');\n}\n","/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { mergeStrings } from '../utils/string_merger';\n\nlet settingsServiceInstance: SettingsService | undefined;\n\nexport class SettingsService {\n // The variable which controls logging of automatic traces and HTTP/S network monitoring.\n instrumentationEnabled = true;\n\n // The variable which controls logging of custom traces.\n dataCollectionEnabled = true;\n\n // Configuration flags set through remote config.\n loggingEnabled = false;\n // Sampling rate between 0 and 1.\n tracesSamplingRate = 1;\n networkRequestsSamplingRate = 1;\n\n // Address of logging service.\n logEndPointUrl =\n 'https://firebaselogging.googleapis.com/v0cc/log?format=json_proto';\n // Performance event transport endpoint URL which should be compatible with proto3.\n // New Address for transport service, not configurable via Remote Config.\n flTransportEndpointUrl = mergeStrings(\n 'hts/frbslgigp.ogepscmv/ieo/eaylg',\n 'tp:/ieaeogn-agolai.o/1frlglgc/o'\n );\n\n transportKey = mergeStrings('AzSC8r6ReiGqFMyfvgow', 'Iayx0u-XT3vksVM-pIV');\n\n // Source type for performance event logs.\n logSource = 462;\n\n // Flags which control per session logging of traces and network requests.\n logTraceAfterSampling = false;\n logNetworkAfterSampling = false;\n\n // TTL of config retrieved from remote config in hours.\n configTimeToLive = 12;\n\n getFlTransportFullUrl(): string {\n return this.flTransportEndpointUrl.concat('?key=', this.transportKey);\n }\n\n static getInstance(): SettingsService {\n if (settingsServiceInstance === undefined) {\n settingsServiceInstance = new SettingsService();\n }\n return settingsServiceInstance;\n }\n}\n","/**\n * @license\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ERROR_FACTORY, ErrorCode } from './errors';\nimport { FirebaseApp } from '@firebase/app';\n\nexport function getAppId(firebaseApp: FirebaseApp): string {\n const appId = firebaseApp.options?.appId;\n if (!appId) {\n throw ERROR_FACTORY.create(ErrorCode.NO_APP_ID);\n }\n return appId;\n}\n\nexport function getProjectId(firebaseApp: FirebaseApp): string {\n const projectId = firebaseApp.options?.projectId;\n if (!projectId) {\n throw ERROR_FACTORY.create(ErrorCode.NO_PROJECT_ID);\n }\n return projectId;\n}\n\nexport function getApiKey(firebaseApp: FirebaseApp): string {\n const apiKey = firebaseApp.options?.apiKey;\n if (!apiKey) {\n throw ERROR_FACTORY.create(ErrorCode.NO_API_KEY);\n }\n return apiKey;\n}\n","/**\n * @license\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n CONFIG_EXPIRY_LOCAL_STORAGE_KEY,\n CONFIG_LOCAL_STORAGE_KEY,\n SDK_VERSION\n} from '../constants';\nimport { consoleLogger } from '../utils/console_logger';\nimport { ERROR_FACTORY, ErrorCode } from '../utils/errors';\n\nimport { Api } from './api_service';\nimport { getAuthTokenPromise } from './iid_service';\nimport { SettingsService } from './settings_service';\nimport { PerformanceController } from '../controllers/perf';\nimport { getProjectId, getApiKey, getAppId } from '../utils/app_utils';\n\nconst REMOTE_CONFIG_SDK_VERSION = '0.0.1';\n\ninterface SecondaryConfig {\n loggingEnabled?: boolean;\n logSource?: number;\n logEndPointUrl?: string;\n transportKey?: string;\n tracesSamplingRate?: number;\n networkRequestsSamplingRate?: number;\n}\n\n// These values will be used if the remote config object is successfully\n// retrieved, but the template does not have these fields.\nconst DEFAULT_CONFIGS: SecondaryConfig = {\n loggingEnabled: true\n};\n\n/* eslint-disable camelcase */\ninterface RemoteConfigTemplate {\n fpr_enabled?: string;\n fpr_log_source?: string;\n fpr_log_endpoint_url?: string;\n fpr_log_transport_key?: string;\n fpr_log_transport_web_percent?: string;\n fpr_vc_network_request_sampling_rate?: string;\n fpr_vc_trace_sampling_rate?: string;\n fpr_vc_session_sampling_rate?: string;\n}\n/* eslint-enable camelcase */\n\ninterface RemoteConfigResponse {\n entries?: RemoteConfigTemplate;\n state?: string;\n}\n\nconst FIS_AUTH_PREFIX = 'FIREBASE_INSTALLATIONS_AUTH';\n\nexport function getConfig(\n performanceController: PerformanceController,\n iid: string\n): Promise {\n const config = getStoredConfig();\n if (config) {\n processConfig(config);\n return Promise.resolve();\n }\n\n return getRemoteConfig(performanceController, iid)\n .then(processConfig)\n .then(\n config => storeConfig(config),\n /** Do nothing for error, use defaults set in settings service. */\n () => {}\n );\n}\n\nfunction getStoredConfig(): RemoteConfigResponse | undefined {\n const localStorage = Api.getInstance().localStorage;\n if (!localStorage) {\n return;\n }\n const expiryString = localStorage.getItem(CONFIG_EXPIRY_LOCAL_STORAGE_KEY);\n if (!expiryString || !configValid(expiryString)) {\n return;\n }\n\n const configStringified = localStorage.getItem(CONFIG_LOCAL_STORAGE_KEY);\n if (!configStringified) {\n return;\n }\n try {\n const configResponse: RemoteConfigResponse = JSON.parse(configStringified);\n return configResponse;\n } catch {\n return;\n }\n}\n\nfunction storeConfig(config: RemoteConfigResponse | undefined): void {\n const localStorage = Api.getInstance().localStorage;\n if (!config || !localStorage) {\n return;\n }\n\n localStorage.setItem(CONFIG_LOCAL_STORAGE_KEY, JSON.stringify(config));\n localStorage.setItem(\n CONFIG_EXPIRY_LOCAL_STORAGE_KEY,\n String(\n Date.now() +\n SettingsService.getInstance().configTimeToLive * 60 * 60 * 1000\n )\n );\n}\n\nconst COULD_NOT_GET_CONFIG_MSG =\n 'Could not fetch config, will use default configs';\n\nfunction getRemoteConfig(\n performanceController: PerformanceController,\n iid: string\n): Promise {\n // Perf needs auth token only to retrieve remote config.\n return getAuthTokenPromise(performanceController.installations)\n .then(authToken => {\n const projectId = getProjectId(performanceController.app);\n const apiKey = getApiKey(performanceController.app);\n const configEndPoint = `https://firebaseremoteconfig.googleapis.com/v1/projects/${projectId}/namespaces/fireperf:fetch?key=${apiKey}`;\n const request = new Request(configEndPoint, {\n method: 'POST',\n headers: { Authorization: `${FIS_AUTH_PREFIX} ${authToken}` },\n /* eslint-disable camelcase */\n body: JSON.stringify({\n app_instance_id: iid,\n app_instance_id_token: authToken,\n app_id: getAppId(performanceController.app),\n app_version: SDK_VERSION,\n sdk_version: REMOTE_CONFIG_SDK_VERSION\n })\n /* eslint-enable camelcase */\n });\n return fetch(request).then(response => {\n if (response.ok) {\n return response.json() as RemoteConfigResponse;\n }\n // In case response is not ok. This will be caught by catch.\n throw ERROR_FACTORY.create(ErrorCode.RC_NOT_OK);\n });\n })\n .catch(() => {\n consoleLogger.info(COULD_NOT_GET_CONFIG_MSG);\n return undefined;\n });\n}\n\n/**\n * Processes config coming either from calling RC or from local storage.\n * This method only runs if call is successful or config in storage\n * is valid.\n */\nfunction processConfig(\n config?: RemoteConfigResponse\n): RemoteConfigResponse | undefined {\n if (!config) {\n return config;\n }\n const settingsServiceInstance = SettingsService.getInstance();\n const entries = config.entries || {};\n if (entries.fpr_enabled !== undefined) {\n // TODO: Change the assignment of loggingEnabled once the received type is\n // known.\n settingsServiceInstance.loggingEnabled =\n String(entries.fpr_enabled) === 'true';\n } else if (DEFAULT_CONFIGS.loggingEnabled !== undefined) {\n // Config retrieved successfully, but there is no fpr_enabled in template.\n // Use secondary configs value.\n settingsServiceInstance.loggingEnabled = DEFAULT_CONFIGS.loggingEnabled;\n }\n if (entries.fpr_log_source) {\n settingsServiceInstance.logSource = Number(entries.fpr_log_source);\n } else if (DEFAULT_CONFIGS.logSource) {\n settingsServiceInstance.logSource = DEFAULT_CONFIGS.logSource;\n }\n\n if (entries.fpr_log_endpoint_url) {\n settingsServiceInstance.logEndPointUrl = entries.fpr_log_endpoint_url;\n } else if (DEFAULT_CONFIGS.logEndPointUrl) {\n settingsServiceInstance.logEndPointUrl = DEFAULT_CONFIGS.logEndPointUrl;\n }\n\n // Key from Remote Config has to be non-empty string, otherwsie use local value.\n if (entries.fpr_log_transport_key) {\n settingsServiceInstance.transportKey = entries.fpr_log_transport_key;\n } else if (DEFAULT_CONFIGS.transportKey) {\n settingsServiceInstance.transportKey = DEFAULT_CONFIGS.transportKey;\n }\n\n if (entries.fpr_vc_network_request_sampling_rate !== undefined) {\n settingsServiceInstance.networkRequestsSamplingRate = Number(\n entries.fpr_vc_network_request_sampling_rate\n );\n } else if (DEFAULT_CONFIGS.networkRequestsSamplingRate !== undefined) {\n settingsServiceInstance.networkRequestsSamplingRate =\n DEFAULT_CONFIGS.networkRequestsSamplingRate;\n }\n if (entries.fpr_vc_trace_sampling_rate !== undefined) {\n settingsServiceInstance.tracesSamplingRate = Number(\n entries.fpr_vc_trace_sampling_rate\n );\n } else if (DEFAULT_CONFIGS.tracesSamplingRate !== undefined) {\n settingsServiceInstance.tracesSamplingRate =\n DEFAULT_CONFIGS.tracesSamplingRate;\n }\n // Set the per session trace and network logging flags.\n settingsServiceInstance.logTraceAfterSampling = shouldLogAfterSampling(\n settingsServiceInstance.tracesSamplingRate\n );\n settingsServiceInstance.logNetworkAfterSampling = shouldLogAfterSampling(\n settingsServiceInstance.networkRequestsSamplingRate\n );\n return config;\n}\n\nfunction configValid(expiry: string): boolean {\n return Number(expiry) > Date.now();\n}\n\nfunction shouldLogAfterSampling(samplingRate: number): boolean {\n return Math.random() <= samplingRate;\n}\n","/**\n * @license\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { getIidPromise } from './iid_service';\nimport { getConfig } from './remote_config_service';\nimport { Api } from './api_service';\nimport { PerformanceController } from '../controllers/perf';\n\nconst enum InitializationStatus {\n notInitialized = 1,\n initializationPending,\n initialized\n}\n\nlet initializationStatus = InitializationStatus.notInitialized;\n\nlet initializationPromise: Promise | undefined;\n\nexport function getInitializationPromise(\n performanceController: PerformanceController\n): Promise {\n initializationStatus = InitializationStatus.initializationPending;\n\n initializationPromise =\n initializationPromise || initializePerf(performanceController);\n\n return initializationPromise;\n}\n\nexport function isPerfInitialized(): boolean {\n return initializationStatus === InitializationStatus.initialized;\n}\n\nfunction initializePerf(\n performanceController: PerformanceController\n): Promise {\n return getDocumentReadyComplete()\n .then(() => getIidPromise(performanceController.installations))\n .then(iid => getConfig(performanceController, iid))\n .then(\n () => changeInitializationStatus(),\n () => changeInitializationStatus()\n );\n}\n\n/**\n * Returns a promise which resolves whenever the document readystate is complete or\n * immediately if it is called after page load complete.\n */\nfunction getDocumentReadyComplete(): Promise {\n const document = Api.getInstance().document;\n return new Promise(resolve => {\n if (document && document.readyState !== 'complete') {\n const handler = (): void => {\n if (document.readyState === 'complete') {\n document.removeEventListener('readystatechange', handler);\n resolve();\n }\n };\n document.addEventListener('readystatechange', handler);\n } else {\n resolve();\n }\n });\n}\n\nfunction changeInitializationStatus(): void {\n initializationStatus = InitializationStatus.initialized;\n}\n","/**\n * @license\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { SettingsService } from './settings_service';\nimport { ERROR_FACTORY, ErrorCode } from '../utils/errors';\nimport { consoleLogger } from '../utils/console_logger';\n\nconst DEFAULT_SEND_INTERVAL_MS = 10 * 1000;\nconst INITIAL_SEND_TIME_DELAY_MS = 5.5 * 1000;\n// If end point does not work, the call will be tried for these many times.\nconst DEFAULT_REMAINING_TRIES = 3;\nconst MAX_EVENT_COUNT_PER_REQUEST = 1000;\nlet remainingTries = DEFAULT_REMAINING_TRIES;\n\ninterface LogResponseDetails {\n responseAction?: string;\n}\n\ninterface BatchEvent {\n message: string;\n eventTime: number;\n}\n\n/* eslint-disable camelcase */\n// CC/Fl accepted log format.\ninterface TransportBatchLogFormat {\n request_time_ms: string;\n client_info: ClientInfo;\n log_source: number;\n log_event: Log[];\n}\n\ninterface ClientInfo {\n client_type: number;\n js_client_info: {};\n}\n\ninterface Log {\n source_extension_json_proto3: string;\n event_time_ms: string;\n}\n/* eslint-enable camelcase */\n\nlet queue: BatchEvent[] = [];\n\nlet isTransportSetup: boolean = false;\n\nexport function setupTransportService(): void {\n if (!isTransportSetup) {\n processQueue(INITIAL_SEND_TIME_DELAY_MS);\n isTransportSetup = true;\n }\n}\n\n/**\n * Utilized by testing to clean up message queue and un-initialize transport service.\n */\nexport function resetTransportService(): void {\n isTransportSetup = false;\n queue = [];\n}\n\nfunction processQueue(timeOffset: number): void {\n setTimeout(() => {\n // If there is no remainingTries left, stop retrying.\n if (remainingTries === 0) {\n return;\n }\n\n // If there are no events to process, wait for DEFAULT_SEND_INTERVAL_MS and try again.\n if (!queue.length) {\n return processQueue(DEFAULT_SEND_INTERVAL_MS);\n }\n\n dispatchQueueEvents();\n }, timeOffset);\n}\n\nfunction dispatchQueueEvents(): void {\n // Extract events up to the maximum cap of single logRequest from top of \"official queue\".\n // The staged events will be used for current logRequest attempt, remaining events will be kept\n // for next attempt.\n const staged = queue.splice(0, MAX_EVENT_COUNT_PER_REQUEST);\n\n /* eslint-disable camelcase */\n // We will pass the JSON serialized event to the backend.\n const log_event: Log[] = staged.map(evt => ({\n source_extension_json_proto3: evt.message,\n event_time_ms: String(evt.eventTime)\n }));\n\n const data: TransportBatchLogFormat = {\n request_time_ms: String(Date.now()),\n client_info: {\n client_type: 1, // 1 is JS\n js_client_info: {}\n },\n log_source: SettingsService.getInstance().logSource,\n log_event\n };\n /* eslint-enable camelcase */\n\n sendEventsToFl(data, staged).catch(() => {\n // If the request fails for some reason, add the events that were attempted\n // back to the primary queue to retry later.\n queue = [...staged, ...queue];\n remainingTries--;\n consoleLogger.info(`Tries left: ${remainingTries}.`);\n processQueue(DEFAULT_SEND_INTERVAL_MS);\n });\n}\n\nfunction sendEventsToFl(\n data: TransportBatchLogFormat,\n staged: BatchEvent[]\n): Promise {\n return postToFlEndpoint(data)\n .then(res => {\n if (!res.ok) {\n consoleLogger.info('Call to Firebase backend failed.');\n }\n return res.json();\n })\n .then(res => {\n // Find the next call wait time from the response.\n const transportWait = Number(res.nextRequestWaitMillis);\n let requestOffset = DEFAULT_SEND_INTERVAL_MS;\n if (!isNaN(transportWait)) {\n requestOffset = Math.max(transportWait, requestOffset);\n }\n\n // Delete request if response include RESPONSE_ACTION_UNKNOWN or DELETE_REQUEST action.\n // Otherwise, retry request using normal scheduling if response include RETRY_REQUEST_LATER.\n const logResponseDetails: LogResponseDetails[] = res.logResponseDetails;\n if (\n Array.isArray(logResponseDetails) &&\n logResponseDetails.length > 0 &&\n logResponseDetails[0].responseAction === 'RETRY_REQUEST_LATER'\n ) {\n queue = [...staged, ...queue];\n consoleLogger.info(`Retry transport request later.`);\n }\n\n remainingTries = DEFAULT_REMAINING_TRIES;\n // Schedule the next process.\n processQueue(requestOffset);\n });\n}\n\nfunction postToFlEndpoint(data: TransportBatchLogFormat): Promise {\n const flTransportFullUrl =\n SettingsService.getInstance().getFlTransportFullUrl();\n return fetch(flTransportFullUrl, {\n method: 'POST',\n body: JSON.stringify(data)\n });\n}\n\nfunction addToQueue(evt: BatchEvent): void {\n if (!evt.eventTime || !evt.message) {\n throw ERROR_FACTORY.create(ErrorCode.INVALID_CC_LOG);\n }\n // Add the new event to the queue.\n queue = [...queue, evt];\n}\n\n/** Log handler for cc service to send the performance logs to the server. */\nexport function transportHandler(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n serializer: (...args: any[]) => string\n): (...args: unknown[]) => void {\n return (...args) => {\n const message = serializer(...args);\n addToQueue({\n message,\n eventTime: Date.now()\n });\n };\n}\n","/**\n * @license\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { getIid } from './iid_service';\nimport { NetworkRequest } from '../resources/network_request';\nimport { Trace } from '../resources/trace';\nimport { Api } from './api_service';\nimport { SettingsService } from './settings_service';\nimport {\n getServiceWorkerStatus,\n getVisibilityState,\n VisibilityState,\n getEffectiveConnectionType\n} from '../utils/attributes_utils';\nimport {\n isPerfInitialized,\n getInitializationPromise\n} from './initialization_service';\nimport { transportHandler } from './transport_service';\nimport { SDK_VERSION } from '../constants';\nimport { FirebaseApp } from '@firebase/app';\nimport { getAppId } from '../utils/app_utils';\n\nconst enum ResourceType {\n NetworkRequest,\n Trace\n}\n\n/* eslint-disable camelcase */\ninterface ApplicationInfo {\n google_app_id: string;\n app_instance_id?: string;\n web_app_info: WebAppInfo;\n application_process_state: number;\n}\n\ninterface WebAppInfo {\n sdk_version: string;\n page_url: string;\n service_worker_status: number;\n visibility_state: number;\n effective_connection_type: number;\n}\n\ninterface PerfNetworkLog {\n application_info: ApplicationInfo;\n network_request_metric: NetworkRequestMetric;\n}\n\ninterface PerfTraceLog {\n application_info: ApplicationInfo;\n trace_metric: TraceMetric;\n}\n\ninterface NetworkRequestMetric {\n url: string;\n http_method: number;\n http_response_code: number;\n response_payload_bytes?: number;\n client_start_time_us?: number;\n time_to_response_initiated_us?: number;\n time_to_response_completed_us?: number;\n}\n\ninterface TraceMetric {\n name: string;\n is_auto: boolean;\n client_start_time_us: number;\n duration_us: number;\n counters?: { [key: string]: number };\n custom_attributes?: { [key: string]: string };\n}\n\n/* eslint-enble camelcase */\n\nlet logger: (\n resource: NetworkRequest | Trace,\n resourceType: ResourceType\n) => void | undefined;\n// This method is not called before initialization.\nfunction sendLog(\n resource: NetworkRequest | Trace,\n resourceType: ResourceType\n): void {\n if (!logger) {\n logger = transportHandler(serializer);\n }\n logger(resource, resourceType);\n}\n\nexport function logTrace(trace: Trace): void {\n const settingsService = SettingsService.getInstance();\n // Do not log if trace is auto generated and instrumentation is disabled.\n if (!settingsService.instrumentationEnabled && trace.isAuto) {\n return;\n }\n // Do not log if trace is custom and data collection is disabled.\n if (!settingsService.dataCollectionEnabled && !trace.isAuto) {\n return;\n }\n // Do not log if required apis are not available.\n if (!Api.getInstance().requiredApisAvailable()) {\n return;\n }\n\n // Only log the page load auto traces if page is visible.\n if (trace.isAuto && getVisibilityState() !== VisibilityState.VISIBLE) {\n return;\n }\n\n if (isPerfInitialized()) {\n sendTraceLog(trace);\n } else {\n // Custom traces can be used before the initialization but logging\n // should wait until after.\n getInitializationPromise(trace.performanceController).then(\n () => sendTraceLog(trace),\n () => sendTraceLog(trace)\n );\n }\n}\n\nfunction sendTraceLog(trace: Trace): void {\n if (!getIid()) {\n return;\n }\n\n const settingsService = SettingsService.getInstance();\n if (\n !settingsService.loggingEnabled ||\n !settingsService.logTraceAfterSampling\n ) {\n return;\n }\n\n setTimeout(() => sendLog(trace, ResourceType.Trace), 0);\n}\n\nexport function logNetworkRequest(networkRequest: NetworkRequest): void {\n const settingsService = SettingsService.getInstance();\n // Do not log network requests if instrumentation is disabled.\n if (!settingsService.instrumentationEnabled) {\n return;\n }\n\n // Do not log the js sdk's call to transport service domain to avoid unnecessary cycle.\n // Need to blacklist both old and new endpoints to avoid migration gap.\n const networkRequestUrl = networkRequest.url;\n\n // Blacklist old log endpoint and new transport endpoint.\n // Because Performance SDK doesn't instrument requests sent from SDK itself.\n const logEndpointUrl = settingsService.logEndPointUrl.split('?')[0];\n const flEndpointUrl = settingsService.flTransportEndpointUrl.split('?')[0];\n if (\n networkRequestUrl === logEndpointUrl ||\n networkRequestUrl === flEndpointUrl\n ) {\n return;\n }\n\n if (\n !settingsService.loggingEnabled ||\n !settingsService.logNetworkAfterSampling\n ) {\n return;\n }\n\n setTimeout(() => sendLog(networkRequest, ResourceType.NetworkRequest), 0);\n}\n\nfunction serializer(\n resource: NetworkRequest | Trace,\n resourceType: ResourceType\n): string {\n if (resourceType === ResourceType.NetworkRequest) {\n return serializeNetworkRequest(resource as NetworkRequest);\n }\n return serializeTrace(resource as Trace);\n}\n\nfunction serializeNetworkRequest(networkRequest: NetworkRequest): string {\n const networkRequestMetric: NetworkRequestMetric = {\n url: networkRequest.url,\n http_method: networkRequest.httpMethod || 0,\n http_response_code: 200,\n response_payload_bytes: networkRequest.responsePayloadBytes,\n client_start_time_us: networkRequest.startTimeUs,\n time_to_response_initiated_us: networkRequest.timeToResponseInitiatedUs,\n time_to_response_completed_us: networkRequest.timeToResponseCompletedUs\n };\n const perfMetric: PerfNetworkLog = {\n application_info: getApplicationInfo(\n networkRequest.performanceController.app\n ),\n network_request_metric: networkRequestMetric\n };\n return JSON.stringify(perfMetric);\n}\n\nfunction serializeTrace(trace: Trace): string {\n const traceMetric: TraceMetric = {\n name: trace.name,\n is_auto: trace.isAuto,\n client_start_time_us: trace.startTimeUs,\n duration_us: trace.durationUs\n };\n\n if (Object.keys(trace.counters).length !== 0) {\n traceMetric.counters = trace.counters;\n }\n const customAttributes = trace.getAttributes();\n if (Object.keys(customAttributes).length !== 0) {\n traceMetric.custom_attributes = customAttributes;\n }\n\n const perfMetric: PerfTraceLog = {\n application_info: getApplicationInfo(trace.performanceController.app),\n trace_metric: traceMetric\n };\n return JSON.stringify(perfMetric);\n}\n\nfunction getApplicationInfo(firebaseApp: FirebaseApp): ApplicationInfo {\n return {\n google_app_id: getAppId(firebaseApp),\n app_instance_id: getIid(),\n web_app_info: {\n sdk_version: SDK_VERSION,\n page_url: Api.getInstance().getUrl(),\n service_worker_status: getServiceWorkerStatus(),\n visibility_state: getVisibilityState(),\n effective_connection_type: getEffectiveConnectionType()\n },\n application_process_state: 0\n };\n}\n","/**\n * @license\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n FIRST_PAINT_COUNTER_NAME,\n FIRST_CONTENTFUL_PAINT_COUNTER_NAME,\n FIRST_INPUT_DELAY_COUNTER_NAME,\n OOB_TRACE_PAGE_LOAD_PREFIX\n} from '../constants';\nimport { consoleLogger } from '../utils/console_logger';\n\nconst MAX_METRIC_NAME_LENGTH = 100;\nconst RESERVED_AUTO_PREFIX = '_';\nconst oobMetrics = [\n FIRST_PAINT_COUNTER_NAME,\n FIRST_CONTENTFUL_PAINT_COUNTER_NAME,\n FIRST_INPUT_DELAY_COUNTER_NAME\n];\n\n/**\n * Returns true if the metric is custom and does not start with reserved prefix, or if\n * the metric is one of out of the box page load trace metrics.\n */\nexport function isValidMetricName(name: string, traceName?: string): boolean {\n if (name.length === 0 || name.length > MAX_METRIC_NAME_LENGTH) {\n return false;\n }\n return (\n (traceName &&\n traceName.startsWith(OOB_TRACE_PAGE_LOAD_PREFIX) &&\n oobMetrics.indexOf(name) > -1) ||\n !name.startsWith(RESERVED_AUTO_PREFIX)\n );\n}\n\n/**\n * Converts the provided value to an integer value to be used in case of a metric.\n * @param providedValue Provided number value of the metric that needs to be converted to an integer.\n *\n * @returns Converted integer number to be set for the metric.\n */\nexport function convertMetricValueToInteger(providedValue: number): number {\n const valueAsInteger: number = Math.floor(providedValue);\n if (valueAsInteger < providedValue) {\n consoleLogger.info(\n `Metric value should be an Integer, setting the value as : ${valueAsInteger}.`\n );\n }\n return valueAsInteger;\n}\n","/**\n * @license\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n TRACE_START_MARK_PREFIX,\n TRACE_STOP_MARK_PREFIX,\n TRACE_MEASURE_PREFIX,\n OOB_TRACE_PAGE_LOAD_PREFIX,\n FIRST_PAINT_COUNTER_NAME,\n FIRST_CONTENTFUL_PAINT_COUNTER_NAME,\n FIRST_INPUT_DELAY_COUNTER_NAME\n} from '../constants';\nimport { Api } from '../services/api_service';\nimport { logTrace } from '../services/perf_logger';\nimport { ERROR_FACTORY, ErrorCode } from '../utils/errors';\nimport {\n isValidCustomAttributeName,\n isValidCustomAttributeValue\n} from '../utils/attributes_utils';\nimport {\n isValidMetricName,\n convertMetricValueToInteger\n} from '../utils/metric_utils';\nimport { PerformanceTrace } from '../public_types';\nimport { PerformanceController } from '../controllers/perf';\n\nconst enum TraceState {\n UNINITIALIZED = 1,\n RUNNING,\n TERMINATED\n}\n\nexport class Trace implements PerformanceTrace {\n private state: TraceState = TraceState.UNINITIALIZED;\n startTimeUs!: number;\n durationUs!: number;\n private customAttributes: { [key: string]: string } = {};\n counters: { [counterName: string]: number } = {};\n private api = Api.getInstance();\n private randomId = Math.floor(Math.random() * 1000000);\n private traceStartMark!: string;\n private traceStopMark!: string;\n private traceMeasure!: string;\n\n /**\n * @param performanceController The performance controller running.\n * @param name The name of the trace.\n * @param isAuto If the trace is auto-instrumented.\n * @param traceMeasureName The name of the measure marker in user timing specification. This field\n * is only set when the trace is built for logging when the user directly uses the user timing\n * api (performance.mark and performance.measure).\n */\n constructor(\n readonly performanceController: PerformanceController,\n readonly name: string,\n readonly isAuto = false,\n traceMeasureName?: string\n ) {\n if (!this.isAuto) {\n this.traceStartMark = `${TRACE_START_MARK_PREFIX}-${this.randomId}-${this.name}`;\n this.traceStopMark = `${TRACE_STOP_MARK_PREFIX}-${this.randomId}-${this.name}`;\n this.traceMeasure =\n traceMeasureName ||\n `${TRACE_MEASURE_PREFIX}-${this.randomId}-${this.name}`;\n\n if (traceMeasureName) {\n // For the case of direct user timing traces, no start stop will happen. The measure object\n // is already available.\n this.calculateTraceMetrics();\n }\n }\n }\n\n /**\n * Starts a trace. The measurement of the duration starts at this point.\n */\n start(): void {\n if (this.state !== TraceState.UNINITIALIZED) {\n throw ERROR_FACTORY.create(ErrorCode.TRACE_STARTED_BEFORE, {\n traceName: this.name\n });\n }\n this.api.mark(this.traceStartMark);\n this.state = TraceState.RUNNING;\n }\n\n /**\n * Stops the trace. The measurement of the duration of the trace stops at this point and trace\n * is logged.\n */\n stop(): void {\n if (this.state !== TraceState.RUNNING) {\n throw ERROR_FACTORY.create(ErrorCode.TRACE_STOPPED_BEFORE, {\n traceName: this.name\n });\n }\n this.state = TraceState.TERMINATED;\n this.api.mark(this.traceStopMark);\n this.api.measure(\n this.traceMeasure,\n this.traceStartMark,\n this.traceStopMark\n );\n this.calculateTraceMetrics();\n logTrace(this);\n }\n\n /**\n * Records a trace with predetermined values. If this method is used a trace is created and logged\n * directly. No need to use start and stop methods.\n * @param startTime Trace start time since epoch in millisec\n * @param duration The duraction of the trace in millisec\n * @param options An object which can optionally hold maps of custom metrics and custom attributes\n */\n record(\n startTime: number,\n duration: number,\n options?: {\n metrics?: { [key: string]: number };\n attributes?: { [key: string]: string };\n }\n ): void {\n if (startTime <= 0) {\n throw ERROR_FACTORY.create(ErrorCode.NONPOSITIVE_TRACE_START_TIME, {\n traceName: this.name\n });\n }\n if (duration <= 0) {\n throw ERROR_FACTORY.create(ErrorCode.NONPOSITIVE_TRACE_DURATION, {\n traceName: this.name\n });\n }\n\n this.durationUs = Math.floor(duration * 1000);\n this.startTimeUs = Math.floor(startTime * 1000);\n if (options && options.attributes) {\n this.customAttributes = { ...options.attributes };\n }\n if (options && options.metrics) {\n for (const metricName of Object.keys(options.metrics)) {\n if (!isNaN(Number(options.metrics[metricName]))) {\n this.counters[metricName] = Math.floor(\n Number(options.metrics[metricName])\n );\n }\n }\n }\n logTrace(this);\n }\n\n /**\n * Increments a custom metric by a certain number or 1 if number not specified. Will create a new\n * custom metric if one with the given name does not exist. The value will be floored down to an\n * integer.\n * @param counter Name of the custom metric\n * @param numAsInteger Increment by value\n */\n incrementMetric(counter: string, numAsInteger = 1): void {\n if (this.counters[counter] === undefined) {\n this.putMetric(counter, numAsInteger);\n } else {\n this.putMetric(counter, this.counters[counter] + numAsInteger);\n }\n }\n\n /**\n * Sets a custom metric to a specified value. Will create a new custom metric if one with the\n * given name does not exist. The value will be floored down to an integer.\n * @param counter Name of the custom metric\n * @param numAsInteger Set custom metric to this value\n */\n putMetric(counter: string, numAsInteger: number): void {\n if (isValidMetricName(counter, this.name)) {\n this.counters[counter] = convertMetricValueToInteger(numAsInteger ?? 0);\n } else {\n throw ERROR_FACTORY.create(ErrorCode.INVALID_CUSTOM_METRIC_NAME, {\n customMetricName: counter\n });\n }\n }\n\n /**\n * Returns the value of the custom metric by that name. If a custom metric with that name does\n * not exist will return zero.\n * @param counter\n */\n getMetric(counter: string): number {\n return this.counters[counter] || 0;\n }\n\n /**\n * Sets a custom attribute of a trace to a certain value.\n * @param attr\n * @param value\n */\n putAttribute(attr: string, value: string): void {\n const isValidName = isValidCustomAttributeName(attr);\n const isValidValue = isValidCustomAttributeValue(value);\n if (isValidName && isValidValue) {\n this.customAttributes[attr] = value;\n return;\n }\n // Throw appropriate error when the attribute name or value is invalid.\n if (!isValidName) {\n throw ERROR_FACTORY.create(ErrorCode.INVALID_ATTRIBUTE_NAME, {\n attributeName: attr\n });\n }\n if (!isValidValue) {\n throw ERROR_FACTORY.create(ErrorCode.INVALID_ATTRIBUTE_VALUE, {\n attributeValue: value\n });\n }\n }\n\n /**\n * Retrieves the value a custom attribute of a trace is set to.\n * @param attr\n */\n getAttribute(attr: string): string | undefined {\n return this.customAttributes[attr];\n }\n\n removeAttribute(attr: string): void {\n if (this.customAttributes[attr] === undefined) {\n return;\n }\n delete this.customAttributes[attr];\n }\n\n getAttributes(): { [key: string]: string } {\n return { ...this.customAttributes };\n }\n\n private setStartTime(startTime: number): void {\n this.startTimeUs = startTime;\n }\n\n private setDuration(duration: number): void {\n this.durationUs = duration;\n }\n\n /**\n * Calculates and assigns the duration and start time of the trace using the measure performance\n * entry.\n */\n private calculateTraceMetrics(): void {\n const perfMeasureEntries = this.api.getEntriesByName(this.traceMeasure);\n const perfMeasureEntry = perfMeasureEntries && perfMeasureEntries[0];\n if (perfMeasureEntry) {\n this.durationUs = Math.floor(perfMeasureEntry.duration * 1000);\n this.startTimeUs = Math.floor(\n (perfMeasureEntry.startTime + this.api.getTimeOrigin()) * 1000\n );\n }\n }\n\n /**\n * @param navigationTimings A single element array which contains the navigationTIming object of\n * the page load\n * @param paintTimings A array which contains paintTiming object of the page load\n * @param firstInputDelay First input delay in millisec\n */\n static createOobTrace(\n performanceController: PerformanceController,\n navigationTimings: PerformanceNavigationTiming[],\n paintTimings: PerformanceEntry[],\n firstInputDelay?: number\n ): void {\n const route = Api.getInstance().getUrl();\n if (!route) {\n return;\n }\n const trace = new Trace(\n performanceController,\n OOB_TRACE_PAGE_LOAD_PREFIX + route,\n true\n );\n const timeOriginUs = Math.floor(Api.getInstance().getTimeOrigin() * 1000);\n trace.setStartTime(timeOriginUs);\n\n // navigationTimings includes only one element.\n if (navigationTimings && navigationTimings[0]) {\n trace.setDuration(Math.floor(navigationTimings[0].duration * 1000));\n trace.putMetric(\n 'domInteractive',\n Math.floor(navigationTimings[0].domInteractive * 1000)\n );\n trace.putMetric(\n 'domContentLoadedEventEnd',\n Math.floor(navigationTimings[0].domContentLoadedEventEnd * 1000)\n );\n trace.putMetric(\n 'loadEventEnd',\n Math.floor(navigationTimings[0].loadEventEnd * 1000)\n );\n }\n\n const FIRST_PAINT = 'first-paint';\n const FIRST_CONTENTFUL_PAINT = 'first-contentful-paint';\n if (paintTimings) {\n const firstPaint = paintTimings.find(\n paintObject => paintObject.name === FIRST_PAINT\n );\n if (firstPaint && firstPaint.startTime) {\n trace.putMetric(\n FIRST_PAINT_COUNTER_NAME,\n Math.floor(firstPaint.startTime * 1000)\n );\n }\n const firstContentfulPaint = paintTimings.find(\n paintObject => paintObject.name === FIRST_CONTENTFUL_PAINT\n );\n if (firstContentfulPaint && firstContentfulPaint.startTime) {\n trace.putMetric(\n FIRST_CONTENTFUL_PAINT_COUNTER_NAME,\n Math.floor(firstContentfulPaint.startTime * 1000)\n );\n }\n\n if (firstInputDelay) {\n trace.putMetric(\n FIRST_INPUT_DELAY_COUNTER_NAME,\n Math.floor(firstInputDelay * 1000)\n );\n }\n }\n\n logTrace(trace);\n }\n\n static createUserTimingTrace(\n performanceController: PerformanceController,\n measureName: string\n ): void {\n const trace = new Trace(\n performanceController,\n measureName,\n false,\n measureName\n );\n logTrace(trace);\n }\n}\n","/**\n * @license\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Api } from '../services/api_service';\nimport { logNetworkRequest } from '../services/perf_logger';\nimport { PerformanceController } from '../controllers/perf';\n\n// The order of values of this enum should not be changed.\nexport const enum HttpMethod {\n HTTP_METHOD_UNKNOWN = 0,\n GET = 1,\n PUT = 2,\n POST = 3,\n DELETE = 4,\n HEAD = 5,\n PATCH = 6,\n OPTIONS = 7,\n TRACE = 8,\n CONNECT = 9\n}\n\n// Durations are in microseconds.\nexport interface NetworkRequest {\n performanceController: PerformanceController;\n url: string;\n httpMethod?: HttpMethod;\n requestPayloadBytes?: number;\n responsePayloadBytes?: number;\n httpResponseCode?: number;\n responseContentType?: string;\n startTimeUs?: number;\n timeToRequestCompletedUs?: number;\n timeToResponseInitiatedUs?: number;\n timeToResponseCompletedUs?: number;\n}\n\nexport function createNetworkRequestEntry(\n performanceController: PerformanceController,\n entry: PerformanceEntry\n): void {\n const performanceEntry = entry as PerformanceResourceTiming;\n if (!performanceEntry || performanceEntry.responseStart === undefined) {\n return;\n }\n const timeOrigin = Api.getInstance().getTimeOrigin();\n const startTimeUs = Math.floor(\n (performanceEntry.startTime + timeOrigin) * 1000\n );\n const timeToResponseInitiatedUs = performanceEntry.responseStart\n ? Math.floor(\n (performanceEntry.responseStart - performanceEntry.startTime) * 1000\n )\n : undefined;\n const timeToResponseCompletedUs = Math.floor(\n (performanceEntry.responseEnd - performanceEntry.startTime) * 1000\n );\n // Remove the query params from logged network request url.\n const url = performanceEntry.name && performanceEntry.name.split('?')[0];\n const networkRequest: NetworkRequest = {\n performanceController,\n url,\n responsePayloadBytes: performanceEntry.transferSize,\n startTimeUs,\n timeToResponseInitiatedUs,\n timeToResponseCompletedUs\n };\n\n logNetworkRequest(networkRequest);\n}\n","/**\n * @license\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Api } from './api_service';\nimport { Trace } from '../resources/trace';\nimport { createNetworkRequestEntry } from '../resources/network_request';\nimport { TRACE_MEASURE_PREFIX } from '../constants';\nimport { getIid } from './iid_service';\nimport { PerformanceController } from '../controllers/perf';\n\nconst FID_WAIT_TIME_MS = 5000;\n\nexport function setupOobResources(\n performanceController: PerformanceController\n): void {\n // Do not initialize unless iid is available.\n if (!getIid()) {\n return;\n }\n // The load event might not have fired yet, and that means performance navigation timing\n // object has a duration of 0. The setup should run after all current tasks in js queue.\n setTimeout(() => setupOobTraces(performanceController), 0);\n setTimeout(() => setupNetworkRequests(performanceController), 0);\n setTimeout(() => setupUserTimingTraces(performanceController), 0);\n}\n\nfunction setupNetworkRequests(\n performanceController: PerformanceController\n): void {\n const api = Api.getInstance();\n const resources = api.getEntriesByType('resource');\n for (const resource of resources) {\n createNetworkRequestEntry(performanceController, resource);\n }\n api.setupObserver('resource', entry =>\n createNetworkRequestEntry(performanceController, entry)\n );\n}\n\nfunction setupOobTraces(performanceController: PerformanceController): void {\n const api = Api.getInstance();\n const navigationTimings = api.getEntriesByType(\n 'navigation'\n ) as PerformanceNavigationTiming[];\n const paintTimings = api.getEntriesByType('paint');\n // If First Input Desly polyfill is added to the page, report the fid value.\n // https://github.com/GoogleChromeLabs/first-input-delay\n if (api.onFirstInputDelay) {\n // If the fid call back is not called for certain time, continue without it.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n let timeoutId: any = setTimeout(() => {\n Trace.createOobTrace(\n performanceController,\n navigationTimings,\n paintTimings\n );\n timeoutId = undefined;\n }, FID_WAIT_TIME_MS);\n api.onFirstInputDelay((fid: number) => {\n if (timeoutId) {\n clearTimeout(timeoutId);\n Trace.createOobTrace(\n performanceController,\n navigationTimings,\n paintTimings,\n fid\n );\n }\n });\n } else {\n Trace.createOobTrace(\n performanceController,\n navigationTimings,\n paintTimings\n );\n }\n}\n\nfunction setupUserTimingTraces(\n performanceController: PerformanceController\n): void {\n const api = Api.getInstance();\n // Run through the measure performance entries collected up to this point.\n const measures = api.getEntriesByType('measure');\n for (const measure of measures) {\n createUserTimingTrace(performanceController, measure);\n }\n // Setup an observer to capture the measures from this point on.\n api.setupObserver('measure', entry =>\n createUserTimingTrace(performanceController, entry)\n );\n}\n\nfunction createUserTimingTrace(\n performanceController: PerformanceController,\n measure: PerformanceEntry\n): void {\n const measureName = measure.name;\n // Do not create a trace, if the user timing marks and measures are created by the sdk itself.\n if (\n measureName.substring(0, TRACE_MEASURE_PREFIX.length) ===\n TRACE_MEASURE_PREFIX\n ) {\n return;\n }\n Trace.createUserTimingTrace(performanceController, measureName);\n}\n","/**\n * @license\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { setupOobResources } from '../services/oob_resources_service';\nimport { SettingsService } from '../services/settings_service';\nimport { getInitializationPromise } from '../services/initialization_service';\nimport { Api } from '../services/api_service';\nimport { FirebaseApp } from '@firebase/app';\nimport { _FirebaseInstallationsInternal } from '@firebase/installations';\nimport { PerformanceSettings, FirebasePerformance } from '../public_types';\nimport { validateIndexedDBOpenable } from '@firebase/util';\nimport { setupTransportService } from '../services/transport_service';\nimport { consoleLogger } from '../utils/console_logger';\n\nexport class PerformanceController implements FirebasePerformance {\n private initialized: boolean = false;\n\n constructor(\n readonly app: FirebaseApp,\n readonly installations: _FirebaseInstallationsInternal\n ) {}\n\n /**\n * This method *must* be called internally as part of creating a\n * PerformanceController instance.\n *\n * Currently it's not possible to pass the settings object through the\n * constructor using Components, so this method exists to be called with the\n * desired settings, to ensure nothing is collected without the user's\n * consent.\n */\n _init(settings?: PerformanceSettings): void {\n if (this.initialized) {\n return;\n }\n\n if (settings?.dataCollectionEnabled !== undefined) {\n this.dataCollectionEnabled = settings.dataCollectionEnabled;\n }\n if (settings?.instrumentationEnabled !== undefined) {\n this.instrumentationEnabled = settings.instrumentationEnabled;\n }\n\n if (Api.getInstance().requiredApisAvailable()) {\n validateIndexedDBOpenable()\n .then(isAvailable => {\n if (isAvailable) {\n setupTransportService();\n getInitializationPromise(this).then(\n () => setupOobResources(this),\n () => setupOobResources(this)\n );\n this.initialized = true;\n }\n })\n .catch(error => {\n consoleLogger.info(`Environment doesn't support IndexedDB: ${error}`);\n });\n } else {\n consoleLogger.info(\n 'Firebase Performance cannot start if the browser does not support ' +\n '\"Fetch\" and \"Promise\", or cookies are disabled.'\n );\n }\n }\n\n set instrumentationEnabled(val: boolean) {\n SettingsService.getInstance().instrumentationEnabled = val;\n }\n get instrumentationEnabled(): boolean {\n return SettingsService.getInstance().instrumentationEnabled;\n }\n\n set dataCollectionEnabled(val: boolean) {\n SettingsService.getInstance().dataCollectionEnabled = val;\n }\n get dataCollectionEnabled(): boolean {\n return SettingsService.getInstance().dataCollectionEnabled;\n }\n}\n","/**\n * Firebase Performance Monitoring\n *\n * @packageDocumentation\n */\n\n/**\n * @license\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n FirebasePerformance,\n PerformanceSettings,\n PerformanceTrace\n} from './public_types';\nimport { ERROR_FACTORY, ErrorCode } from './utils/errors';\nimport { setupApi } from './services/api_service';\nimport { PerformanceController } from './controllers/perf';\nimport {\n _registerComponent,\n _getProvider,\n registerVersion,\n FirebaseApp,\n getApp\n} from '@firebase/app';\nimport {\n InstanceFactory,\n ComponentContainer,\n Component,\n ComponentType\n} from '@firebase/component';\nimport { name, version } from '../package.json';\nimport { Trace } from './resources/trace';\nimport '@firebase/installations';\nimport { deepEqual, getModularInstance } from '@firebase/util';\n\nconst DEFAULT_ENTRY_NAME = '[DEFAULT]';\n\n/**\n * Returns a {@link FirebasePerformance} instance for the given app.\n * @param app - The {@link @firebase/app#FirebaseApp} to use.\n * @public\n */\nexport function getPerformance(\n app: FirebaseApp = getApp()\n): FirebasePerformance {\n app = getModularInstance(app);\n const provider = _getProvider(app, 'performance');\n const perfInstance = provider.getImmediate() as PerformanceController;\n return perfInstance;\n}\n\n/**\n * Returns a {@link FirebasePerformance} instance for the given app. Can only be called once.\n * @param app - The {@link @firebase/app#FirebaseApp} to use.\n * @param settings - Optional settings for the {@link FirebasePerformance} instance.\n * @public\n */\nexport function initializePerformance(\n app: FirebaseApp,\n settings?: PerformanceSettings\n): FirebasePerformance {\n app = getModularInstance(app);\n const provider = _getProvider(app, 'performance');\n\n // throw if an instance was already created.\n // It could happen if initializePerformance() is called more than once, or getPerformance() is called first.\n if (provider.isInitialized()) {\n const existingInstance = provider.getImmediate();\n const initialSettings = provider.getOptions() as PerformanceSettings;\n if (deepEqual(initialSettings, settings ?? {})) {\n return existingInstance;\n } else {\n throw ERROR_FACTORY.create(ErrorCode.ALREADY_INITIALIZED);\n }\n }\n\n const perfInstance = provider.initialize({\n options: settings\n }) as PerformanceController;\n return perfInstance;\n}\n\n/**\n * Returns a new `PerformanceTrace` instance.\n * @param performance - The {@link FirebasePerformance} instance to use.\n * @param name - The name of the trace.\n * @public\n */\nexport function trace(\n performance: FirebasePerformance,\n name: string\n): PerformanceTrace {\n performance = getModularInstance(performance);\n return new Trace(performance as PerformanceController, name);\n}\n\nconst factory: InstanceFactory<'performance'> = (\n container: ComponentContainer,\n { options: settings }: { options?: PerformanceSettings }\n) => {\n // Dependencies\n const app = container.getProvider('app').getImmediate();\n const installations = container\n .getProvider('installations-internal')\n .getImmediate();\n\n if (app.name !== DEFAULT_ENTRY_NAME) {\n throw ERROR_FACTORY.create(ErrorCode.FB_NOT_DEFAULT);\n }\n if (typeof window === 'undefined') {\n throw ERROR_FACTORY.create(ErrorCode.NO_WINDOW);\n }\n setupApi(window);\n const perfInstance = new PerformanceController(app, installations);\n perfInstance._init(settings);\n\n return perfInstance;\n};\n\nfunction registerPerformance(): void {\n _registerComponent(\n new Component('performance', factory, ComponentType.PUBLIC)\n );\n registerVersion(name, version);\n // BUILD_TARGET will be replaced by values like esm5, esm2017, cjs5, etc during the compilation\n registerVersion(name, version, '__BUILD_TARGET__');\n}\n\nregisterPerformance();\n\nexport { FirebasePerformance, PerformanceSettings, PerformanceTrace };\n","/**\n * @license\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n trace,\n FirebasePerformance,\n // The PerformanceTrace type has not changed between modular and non-modular packages.\n PerformanceTrace\n} from '@firebase/performance';\nimport { FirebasePerformance as FirebasePerformanceCompat } from '@firebase/performance-types';\nimport { FirebaseApp, _FirebaseService } from '@firebase/app-compat';\n\nexport class PerformanceCompatImpl\n implements FirebasePerformanceCompat, _FirebaseService\n{\n constructor(\n public app: FirebaseApp,\n readonly _delegate: FirebasePerformance\n ) {}\n\n get instrumentationEnabled(): boolean {\n return this._delegate.instrumentationEnabled;\n }\n\n set instrumentationEnabled(val: boolean) {\n this._delegate.instrumentationEnabled = val;\n }\n\n get dataCollectionEnabled(): boolean {\n return this._delegate.dataCollectionEnabled;\n }\n\n set dataCollectionEnabled(val: boolean) {\n this._delegate.dataCollectionEnabled = val;\n }\n\n trace(traceName: string): PerformanceTrace {\n return trace(this._delegate, traceName);\n }\n}\n","/**\n * @license\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport interface Compat {\n _delegate: T;\n}\n\nexport function getModularInstance(\n service: Compat | ExpService\n): ExpService {\n if (service && (service as Compat)._delegate) {\n return (service as Compat)._delegate;\n } else {\n return service as ExpService;\n }\n}\n"],"names":["LogLevel","FirebaseError","Error","constructor","code","message","customData","super","this","name","Object","setPrototypeOf","prototype","captureStackTrace","ErrorFactory","create","service","serviceName","errors","data","fullCode","template","replace","PATTERN","_","key","value","String","fullMessage","Component","instanceFactory","type","multipleInstances","serviceProps","instantiationMode","onInstanceCreated","setInstantiationMode","mode","setMultipleInstances","setServiceProps","props","setInstanceCreatedCallback","callback","levelStringToEnum","debug","DEBUG","verbose","VERBOSE","info","INFO","warn","WARN","error","ERROR","silent","SILENT","defaultLogLevel","ConsoleMethod","defaultLogHandler","instance","logType","args","logLevel","now","Date","toISOString","method","console","instanceOfAny","object","constructors","some","c","idbProxyableTypes","cursorAdvanceMethods","cursorRequestMap","WeakMap","transactionDoneMap","transactionStoreNamesMap","transformCache","reverseTransformCache","idbProxyTraps","get","target","prop","receiver","IDBTransaction","objectStoreNames","undefined","objectStore","wrap","set","has","wrapFunction","func","IDBDatabase","transaction","IDBCursor","advance","continue","continuePrimaryKey","includes","apply","unwrap","storeNames","tx","call","sort","transformCachableValue","done","Promise","resolve","reject","unlisten","removeEventListener","complete","DOMException","addEventListener","IDBObjectStore","IDBIndex","Proxy","IDBRequest","request","promise","success","result","then","catch","promisifyRequest","newValue","readMethods","writeMethods","cachedMethods","Map","getMethod","targetFuncName","useIndex","isWrite","async","storeName","store","index","shift","all","oldTraps","PENDING_TIMEOUT_MS","PACKAGE_VERSION","version","INTERNAL_AUTH_VERSION","INSTALLATIONS_API_URL","TOKEN_EXPIRATION_BUFFER","ERROR_FACTORY","missing-app-config-values","not-registered","installation-not-found","request-failed","app-offline","delete-pending-registration","isServerError","getInstallationsEndpoint","projectId","extractAuthTokenInfoFromResponse","response","token","requestStatus","expiresIn","responseExpiresIn","Number","creationTime","getErrorFromResponse","requestName","errorData","json","serverCode","serverMessage","serverStatus","status","getHeaders","apiKey","Headers","Content-Type","Accept","x-goog-api-key","getHeadersWithAuth","appConfig","refreshToken","headers","append","retryIfServerError","fn","sleep","ms","setTimeout","VALID_FID_PATTERN","INVALID_FID","generateFid","fidByteArray","Uint8Array","crypto","self","msCrypto","getRandomValues","fid","b64String","array","b64","btoa","fromCharCode","bufferToBase64UrlSafe","substr","encode","test","_a","getKey","appName","appId","fidChangeCallbacks","fidChanged","callFidChangeCallbacks","channel","broadcastChannel","BroadcastChannel","onmessage","e","getBroadcastChannel","postMessage","size","close","broadcastFidChange","callbacks","OBJECT_STORE_NAME","dbPromise","getDbPromise","blocked","upgrade","blocking","terminated","indexedDB","open","openPromise","event","oldVersion","newVersion","db","openDB","createObjectStore","oldValue","put","remove","delete","update","updateFn","getInstallationEntry","installations","registrationPromise","installationEntry","oldEntry","clearTimedOutRequest","registrationStatus","entryWithPromise","entry","updateInstallationRequest","waitUntilFidRegistration","navigator","onLine","registrationPromiseWithError","inProgressEntry","registrationTime","registeredInstallationEntry","heartbeatServiceProvider","endpoint","heartbeatService","getImmediate","optional","heartbeatsHeader","getHeartbeatsHeader","body","authVersion","sdkVersion","JSON","stringify","fetch","ok","responseValue","authToken","createInstallationRequest","registerInstallation","triggerRegistrationIfNecessary","generateAuthTokenRequest","getGenerateAuthTokenEndpoint","installation","refreshAuthToken","forceRefresh","tokenPromise","isEntryRegistered","oldAuthToken","isAuthTokenExpired","updateAuthTokenRequest","waitUntilAuthTokenRequest","inProgressAuthToken","requestTime","assign","updatedInstallationEntry","fetchAuthTokenFromServer","getToken","installationsImpl","getMissingValueError","valueName","INSTALLATIONS_NAME","publicFactory","app","container","getProvider","options","keyName","extractAppConfig","_getProvider","_delete","internalFactory","getId","_registerComponent","registerVersion","SDK_VERSION","TRACE_MEASURE_PREFIX","CONFIG_LOCAL_STORAGE_KEY","CONFIG_EXPIRY_LOCAL_STORAGE_KEY","VisibilityState","firebaseInstance","SERVICE_NAME","trace started","trace stopped","nonpositive trace startTime","nonpositive trace duration","no window","no app id","no project id","no api key","invalid cc log","FB not default","RC response not ok","invalid attribute name","invalid attribute value","invalid custom metric name","invalid String merger input","already initialized","consoleLogger","_logLevel","_logHandler","_userLogHandler","val","TypeError","setLogLevel","logHandler","userLogHandler","log","apiInstance","windowInstance","Api","window","performance","PerformanceObserver","windowLocation","location","document","cookieEnabled","localStorage","perfMetrics","onFirstInputDelay","getUrl","href","split","mark","measure","measureName","mark1","mark2","getEntriesByType","getEntriesByName","getTimeOrigin","timeOrigin","timing","navigationStart","requiredApisAvailable","isIndexedDBAvailable","setupObserver","entryType","observer","list","getEntries","observe","entryTypes","getInstance","iid","mergeStrings","part1","part2","sizeDiff","length","resultArray","i","push","charAt","join","settingsServiceInstance","SettingsService","instrumentationEnabled","dataCollectionEnabled","loggingEnabled","tracesSamplingRate","networkRequestsSamplingRate","logEndPointUrl","flTransportEndpointUrl","transportKey","logSource","logTraceAfterSampling","logNetworkAfterSampling","configTimeToLive","getFlTransportFullUrl","concat","RESERVED_ATTRIBUTE_PREFIXES","ATTRIBUTE_FORMAT_REGEX","RegExp","getVisibilityState","visibilityState","VISIBLE","HIDDEN","UNKNOWN","getAppId","firebaseApp","REMOTE_CONFIG_SDK_VERSION","DEFAULT_CONFIGS","FIS_AUTH_PREFIX","getConfig","performanceController","config","expiryString","getItem","expiry","configValid","configStringified","parse","getStoredConfig","processConfig","installationsService","authTokenPromise","getAuthTokenPromise","getProjectId","getApiKey","Request","Authorization","app_instance_id","app_instance_id_token","app_id","app_version","sdk_version","COULD_NOT_GET_CONFIG_MSG","setItem","storeConfig","entries","fpr_enabled","fpr_log_source","fpr_log_endpoint_url","fpr_log_transport_key","fpr_vc_network_request_sampling_rate","fpr_vc_trace_sampling_rate","shouldLogAfterSampling","samplingRate","Math","random","initializationStatus","initializationPromise","getInitializationPromise","readyState","handler","getDocumentReadyComplete","iidPromise","iidVal","getIidPromise","changeInitializationStatus","DEFAULT_SEND_INTERVAL_MS","DEFAULT_REMAINING_TRIES","MAX_EVENT_COUNT_PER_REQUEST","remainingTries","queue","isTransportSetup","processQueue","timeOffset","staged","splice","log_event","map","evt","source_extension_json_proto3","event_time_ms","eventTime","request_time_ms","client_info","client_type","js_client_info","log_source","flTransportFullUrl","postToFlEndpoint","res","transportWait","nextRequestWaitMillis","requestOffset","isNaN","max","logResponseDetails","Array","isArray","responseAction","sendEventsToFl","dispatchQueueEvents","transportHandler","serializer","addToQueue","logger","sendLog","resource","resourceType","logTrace","trace","settingsService","isAuto","sendTraceLog","networkRequestMetric","url","http_method","httpMethod","http_response_code","response_payload_bytes","responsePayloadBytes","client_start_time_us","startTimeUs","time_to_response_initiated_us","timeToResponseInitiatedUs","time_to_response_completed_us","timeToResponseCompletedUs","perfMetric","application_info","getApplicationInfo","network_request_metric","traceMetric","is_auto","duration_us","durationUs","keys","counters","customAttributes","getAttributes","custom_attributes","trace_metric","serializeTrace","google_app_id","web_app_info","page_url","service_worker_status","serviceWorker","controller","visibility_state","effective_connection_type","navigatorConnection","connection","effectiveType","getEffectiveConnectionType","application_process_state","oobMetrics","Trace","traceMeasureName","state","api","randomId","floor","traceStartMark","traceStopMark","traceMeasure","calculateTraceMetrics","start","traceName","stop","record","startTime","duration","attributes","metrics","metricName","incrementMetric","counter","numAsInteger","putMetric","startsWith","indexOf","customMetricName","valueAsInteger","providedValue","getMetric","putAttribute","attr","isValidName","prefix","match","isValidValue","attributeName","attributeValue","getAttribute","removeAttribute","setStartTime","setDuration","perfMeasureEntries","perfMeasureEntry","createOobTrace","navigationTimings","paintTimings","firstInputDelay","route","timeOriginUs","domInteractive","domContentLoadedEventEnd","loadEventEnd","firstPaint","find","paintObject","firstContentfulPaint","createUserTimingTrace","createNetworkRequestEntry","performanceEntry","responseStart","responseEnd","networkRequest","networkRequestUrl","logEndpointUrl","flEndpointUrl","logNetworkRequest","transferSize","FID_WAIT_TIME_MS","setupOobResources","timeoutId","clearTimeout","setupOobTraces","resources","setupNetworkRequests","measures","setupUserTimingTraces","substring","PerformanceController","initialized","_init","settings","preExist","DB_CHECK_NAME","onsuccess","deleteDatabase","onupgradeneeded","onerror","isAvailable","DEFAULT_ENTRY_NAME","factory","perfInstance","PerformanceCompatImpl","_delegate","performanceFactory","firebase","INTERNAL","registerComponent"],"mappings":"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"}