Kargi-Sitesi/node_modules/firebase/firebase-performance.js.map

1 line
No EOL
196 KiB
Text

{"version":3,"file":"firebase-performance.js","sources":["../util/src/errors.ts","../util/src/obj.ts","../util/src/compat.ts","../logger/src/logger.ts","../component/src/component.ts","../../node_modules/idb/build/wrap-idb-value.js","../../node_modules/idb/build/index.js","../installations/src/util/errors.ts","../installations/src/util/constants.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/utils/errors.ts","../performance/src/constants.ts","../performance/src/utils/console_logger.ts","../performance/src/services/api_service.ts","../performance/src/services/iid_service.ts","../performance/src/services/settings_service.ts","../util/src/environment.ts","../performance/src/utils/string_merger.ts","../performance/src/utils/attributes_utils.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"],"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/**\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<Err, string> = {\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<Err>('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<ErrorCode extends string> = {\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<string, unknown>\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 // TODO(dlarocque): Replace this with `new.target`: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html#support-for-newtarget\n // which we can now use since we no longer target ES5.\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<ErrorCode>\n ) {}\n\n create<K extends ErrorCode>(\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 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 function contains<T extends object>(obj: T, key: string): boolean {\n return Object.prototype.hasOwnProperty.call(obj, key);\n}\n\nexport function safeGet<T extends object, K extends keyof T>(\n obj: T,\n key: K\n): T[K] | undefined {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n return obj[key];\n } else {\n return undefined;\n }\n}\n\nexport function isEmpty(obj: object): obj is {} {\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n return false;\n }\n }\n return true;\n}\n\nexport function map<K extends string, V, U>(\n obj: { [key in K]: V },\n fn: (value: V, key: K, obj: { [key in K]: V }) => U,\n contextObj?: unknown\n): { [key in K]: U } {\n const res: Partial<{ [key in K]: U }> = {};\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n res[key] = fn.call(contextObj, obj[key], key, obj);\n }\n }\n return res as { [key in K]: U };\n}\n\n/**\n * Deep equal two objects. Support Arrays and Objects.\n */\nexport function deepEqual(a: object, b: object): boolean {\n if (a === b) {\n return true;\n }\n\n const aKeys = Object.keys(a);\n const bKeys = Object.keys(b);\n for (const k of aKeys) {\n if (!bKeys.includes(k)) {\n return false;\n }\n\n const aProp = (a as Record<string, unknown>)[k];\n const bProp = (b as Record<string, unknown>)[k];\n if (isObject(aProp) && isObject(bProp)) {\n if (!deepEqual(aProp, bProp)) {\n return false;\n }\n } else if (aProp !== bProp) {\n return false;\n }\n }\n\n for (const k of bKeys) {\n if (!aKeys.includes(k)) {\n return false;\n }\n }\n return true;\n}\n\nfunction isObject(thing: unknown): thing is object {\n return thing !== null && typeof thing === 'object';\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<T> {\n _delegate: T;\n}\n\nexport function getModularInstance<ExpService>(\n service: Compat<ExpService> | ExpService\n): ExpService {\n if (service && (service as Compat<ExpService>)._delegate) {\n return (service as Compat<ExpService>)._delegate;\n } else {\n return service as ExpService;\n }\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\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","/**\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<T extends Name = Name> {\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<T> | 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<T>,\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<T>): 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","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), event);\n });\n }\n if (blocked) {\n request.addEventListener('blocked', (event) => blocked(\n // Casting due to https://github.com/microsoft/TypeScript-DOM-lib-generator/pull/1405\n event.oldVersion, event.newVersion, event));\n }\n openPromise\n .then((db) => {\n if (terminated)\n db.addEventListener('close', () => terminated());\n if (blocking) {\n db.addEventListener('versionchange', (event) => blocking(event.oldVersion, event.newVersion, event));\n }\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', (event) => blocked(\n // Casting due to https://github.com/microsoft/TypeScript-DOM-lib-generator/pull/1405\n event.oldVersion, event));\n }\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 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<ErrorCode, ErrorParams>(\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 { 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 { 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<FirebaseError> {\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<Response>\n): Promise<Response> {\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<void> {\n return new Promise<void>(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<string, Set<IdChangeCallbackFn>> = 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<IDBPDatabase<InstallationsDB>> | null = null;\nfunction getDbPromise(): Promise<IDBPDatabase<InstallationsDB>> {\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<InstallationEntry | undefined> {\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<InstallationEntry>;\n}\n\n/** Assigns or overwrites the record for the given key with the given value. */\nexport async function set<ValueType extends InstallationEntry>(\n appConfig: AppConfig,\n value: ValueType\n): Promise<ValueType> {\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<void> {\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<ValueType extends InstallationEntry | undefined>(\n appConfig: AppConfig,\n updateFn: (previousValue: InstallationEntry | undefined) => ValueType\n): Promise<ValueType> {\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<void> {\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<RegisteredInstallationEntry>;\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<InstallationEntryWithRegistrationPromise> {\n let registrationPromise: Promise<RegisteredInstallationEntry> | 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<RegisteredInstallationEntry> {\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 cannot 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<RegisteredInstallationEntry> {\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<InstallationEntry> {\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<RegisteredInstallationEntry> {\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<CompletedAuthToken> {\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<CompletedAuthToken> {\n let tokenPromise: Promise<CompletedAuthToken> | 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<CompletedAuthToken> {\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<RegisteredInstallationEntry> {\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<CompletedAuthToken> {\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<string> {\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<void> {\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<keyof FirebaseOptions> = [\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<string> {\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 * The Firebase Installations Web SDK.\n * This SDK does not work in a Node.js environment.\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 esm2017, cjs2017, 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 { 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<ErrorCode, ErrorParams>(\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 { 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 { 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 /** PerformanceObserver 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 browser');\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 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<string> {\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<string> {\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 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 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 * Type placeholder for `WorkerGlobalScope` from `webworker`\n */\ndeclare class WorkerGlobalScope {}\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 * Note: This will return true for certain test frameworks that are incompletely\n * mimicking a browser, and should not lead to assuming all browser APIs are\n * available.\n */\nexport function isBrowser(): boolean {\n return typeof window !== 'undefined' || isWebWorker();\n}\n\n/**\n * Detect Web Worker context.\n */\nexport function isWebWorker(): boolean {\n return (\n typeof WorkerGlobalScope !== 'undefined' &&\n typeof self !== 'undefined' &&\n self instanceof WorkerGlobalScope\n );\n}\n\n/**\n * Detect Cloudflare Worker context.\n */\nexport function isCloudflareWorker(): boolean {\n return (\n typeof navigator !== 'undefined' &&\n navigator.userAgent === 'Cloudflare-Workers'\n );\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 &&\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<boolean> {\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 { 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 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 { 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<void> {\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<RemoteConfigResponse | undefined> {\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, otherwise 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<void> | undefined;\n\nexport function getInitializationPromise(\n performanceController: PerformanceController\n): Promise<void> {\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<void> {\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<void> {\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<void> {\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<Response> {\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\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/* eslint-enable camelcase */\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 duration 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 Delay 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 * The Firebase Performance Monitoring Web SDK.\n * This SDK does not work in a Node.js environment.\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 esm2017, cjs2017, etc during the compilation\n registerVersion(name, version, '__BUILD_TARGET__');\n}\n\nregisterPerformance();\n\nexport { FirebasePerformance, PerformanceSettings, PerformanceTrace };\n"],"names":["FirebaseError","Error","constructor","code","message","customData","super","this","name","Object","setPrototypeOf","prototype","captureStackTrace","ErrorFactory","create","service","serviceName","errors","data","fullCode","template","replaceTemplate","replace","PATTERN","_","key","value","String","fullMessage","deepEqual","a","b","aKeys","keys","bKeys","k","includes","aProp","bProp","isObject","thing","getModularInstance","_delegate","LogLevel","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","Component","instanceFactory","type","multipleInstances","serviceProps","instantiationMode","onInstanceCreated","setInstantiationMode","mode","setMultipleInstances","setServiceProps","props","setInstanceCreatedCallback","callback","idbProxyableTypes","cursorAdvanceMethods","cursorRequestMap","WeakMap","transactionDoneMap","transactionStoreNamesMap","transformCache","reverseTransformCache","idbProxyTraps","get","target","prop","receiver","IDBTransaction","objectStoreNames","undefined","objectStore","wrap","set","has","wrapFunction","func","IDBDatabase","transaction","getCursorAdvanceMethods","IDBCursor","advance","continue","continuePrimaryKey","apply","unwrap","storeNames","tx","call","sort","transformCachableValue","cacheDonePromiseForTransaction","done","Promise","resolve","reject","unlisten","removeEventListener","complete","DOMException","addEventListener","object","getIdbProxyableTypes","IDBObjectStore","IDBIndex","some","c","Proxy","IDBRequest","promisifyRequest","request","promise","success","result","then","catch","newValue","readMethods","writeMethods","cachedMethods","Map","getMethod","targetFuncName","useIndex","isWrite","async","storeName","store","index","shift","all","replaceTraps","oldTraps","assign","ERROR_FACTORY","isServerError","getInstallationsEndpoint","projectId","extractAuthTokenInfoFromResponse","response","token","requestStatus","expiresIn","responseExpiresIn","Number","creationTime","getErrorFromResponse","requestName","errorData","json","serverCode","serverMessage","serverStatus","status","getHeaders","apiKey","Headers","Accept","getHeadersWithAuth","appConfig","refreshToken","headers","append","getAuthorizationHeader","retryIfServerError","fn","sleep","ms","setTimeout","VALID_FID_PATTERN","generateFid","fidByteArray","Uint8Array","self","crypto","msCrypto","getRandomValues","fid","encode","bufferToBase64UrlSafe","array","btoa","fromCharCode","substr","test","_a","getKey","appName","appId","fidChangeCallbacks","fidChanged","callFidChangeCallbacks","broadcastFidChange","channel","getBroadcastChannel","broadcastChannel","BroadcastChannel","onmessage","e","postMessage","closeBroadcastChannel","size","close","callbacks","OBJECT_STORE_NAME","dbPromise","getDbPromise","openDB","version","blocked","upgrade","blocking","terminated","indexedDB","open","openPromise","event","oldVersion","newVersion","db","createObjectStore","oldValue","put","remove","delete","update","updateFn","getInstallationEntry","installations","registrationPromise","installationEntry","oldEntry","updateOrCreateInstallationEntry","clearTimedOutRequest","registrationStatus","entryWithPromise","triggerRegistrationIfNecessary","navigator","onLine","inProgressEntry","registrationTime","registerInstallation","registeredInstallationEntry","createInstallationRequest","heartbeatServiceProvider","endpoint","heartbeatService","getImmediate","optional","heartbeatsHeader","getHeartbeatsHeader","body","authVersion","sdkVersion","JSON","stringify","fetch","ok","responseValue","authToken","waitUntilFidRegistration","entry","updateInstallationRequest","hasInstallationRequestTimedOut","generateAuthTokenRequest","getGenerateAuthTokenEndpoint","installation","refreshAuthToken","forceRefresh","tokenPromise","isEntryRegistered","oldAuthToken","isAuthTokenValid","isAuthTokenExpired","waitUntilAuthTokenRequest","updateAuthTokenRequest","makeAuthTokenRequestInProgressEntry","inProgressAuthToken","requestTime","fetchAuthTokenFromServer","updatedInstallationEntry","hasAuthTokenRequestTimedOut","getToken","installationsImpl","completeInstallationRegistration","getMissingValueError","valueName","publicFactory","container","app","getProvider","extractAppConfig","options","configKeys","keyName","_getProvider","_delete","internalFactory","getId","registerInstallations","_registerComponent","registerVersion","consoleLogger","Logger","_logLevel","_logHandler","_userLogHandler","val","TypeError","setLogLevel","logHandler","userLogHandler","log","apiInstance","windowInstance","iid","settingsServiceInstance","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","areCookiesEnabled","isIndexedDBAvailable","setupObserver","entryType","list","getEntries","observe","entryTypes","static","getIid","mergeStrings","part1","part2","sizeDiff","length","resultArray","i","push","charAt","join","SettingsService","instrumentationEnabled","dataCollectionEnabled","loggingEnabled","tracesSamplingRate","networkRequestsSamplingRate","logEndPointUrl","flTransportEndpointUrl","transportKey","logSource","logTraceAfterSampling","logNetworkAfterSampling","configTimeToLive","getFlTransportFullUrl","concat","VisibilityState","RESERVED_ATTRIBUTE_PREFIXES","ATTRIBUTE_FORMAT_REGEX","RegExp","getServiceWorkerStatus","getInstance","serviceWorker","controller","getVisibilityState","visibilityState","VISIBLE","HIDDEN","UNKNOWN","getEffectiveConnectionType","navigatorConnection","connection","effectiveType","getAppId","firebaseApp","DEFAULT_CONFIGS","getConfig","performanceController","config","getStoredConfig","expiryString","getItem","configValid","expiry","configStringified","parse","processConfig","getRemoteConfig","getAuthTokenPromise","installationsService","authTokenPromise","authTokenVal","getProjectId","getApiKey","Request","Authorization","app_instance_id","app_instance_id_token","app_id","app_version","sdk_version","storeConfig","setItem","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","initializationPromise","initializationStatus","getInitializationPromise","initializePerf","getDocumentReadyComplete","readyState","handler","getIidPromise","iidPromise","iidVal","changeInitializationStatus","logger","remainingTries","queue","isTransportSetup","processQueue","timeOffset","dispatchQueueEvents","staged","splice","log_event","map","evt","source_extension_json_proto3","event_time_ms","eventTime","sendEventsToFl","postToFlEndpoint","flTransportFullUrl","res","transportWait","nextRequestWaitMillis","requestOffset","isNaN","max","logResponseDetails","Array","isArray","responseAction","request_time_ms","client_info","client_type","js_client_info","log_source","transportHandler","serializer","addToQueue","sendLog","resource","resourceType","logTrace","trace","settingsService","isAuto","isPerfInitialized","sendTraceLog","serializeNetworkRequest","networkRequest","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","serializeTrace","traceMetric","is_auto","duration_us","durationUs","counters","customAttributes","getAttributes","custom_attributes","trace_metric","google_app_id","web_app_info","page_url","service_worker_status","visibility_state","effective_connection_type","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","isValidMetricName","startsWith","indexOf","customMetricName","convertMetricValueToInteger","providedValue","valueAsInteger","getMetric","putAttribute","attr","isValidName","isValidCustomAttributeName","prefix","match","isValidValue","isValidCustomAttributeValue","attributeName","attributeValue","getAttribute","removeAttribute","setStartTime","setDuration","perfMeasureEntries","perfMeasureEntry","navigationTimings","paintTimings","firstInputDelay","route","timeOriginUs","domInteractive","domContentLoadedEventEnd","loadEventEnd","firstPaint","find","paintObject","firstContentfulPaint","createNetworkRequestEntry","performanceEntry","responseStart","responseEnd","logNetworkRequest","networkRequestUrl","logEndpointUrl","flEndpointUrl","transferSize","setupOobResources","setupOobTraces","timeoutId","createOobTrace","clearTimeout","setupNetworkRequests","resources","setupUserTimingTraces","measures","createUserTimingTrace","substring","PerformanceController","initialized","_init","settings","validateIndexedDBOpenable","preExist","DB_CHECK_NAME","onsuccess","deleteDatabase","onupgradeneeded","onerror","isAvailable","setupTransportService","getPerformance","getApp","initializePerformance","provider","isInitialized","existingInstance","getOptions","initialize","factory","setupApi","perfInstance","registerPerformance"],"mappings":"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","preExistingComment":"firebase-performance.js.map"}