Visible for testing\n */\nexport const MAX_VALUE_MILLIS = 4 * 60 * 60 * 1000; // Four hours, like iOS and Android.\n\n/**\n * The percentage of backoff time to randomize by.\n * See\n * http://go/safe-client-behavior#step-1-determine-the-appropriate-retry-interval-to-handle-spike-traffic\n * for context.\n *\n *
Visible for testing\n */\nexport const RANDOM_FACTOR = 0.5;\n\n/**\n * Based on the backoff method from\n * https://github.com/google/closure-library/blob/master/closure/goog/math/exponentialbackoff.js.\n * Extracted here so we don't need to pass metadata and a stateful ExponentialBackoff object around.\n */\nexport function calculateBackoffMillis(\n backoffCount: number,\n intervalMillis: number = DEFAULT_INTERVAL_MILLIS,\n backoffFactor: number = DEFAULT_BACKOFF_FACTOR\n): number {\n // Calculates an exponentially increasing value.\n // Deviation: calculates value from count and a constant interval, so we only need to save value\n // and count to restore state.\n const currBaseValue = intervalMillis * Math.pow(backoffFactor, backoffCount);\n\n // A random \"fuzz\" to avoid waves of retries.\n // Deviation: randomFactor is required.\n const randomWait = Math.round(\n // A fraction of the backoff value to add/subtract.\n // Deviation: changes multiplication order to improve readability.\n RANDOM_FACTOR *\n currBaseValue *\n // A random float (rounded to int by Math.round above) in the range [-1, 1]. Determines\n // if we add or subtract.\n (Math.random() - 0.5) *\n 2\n );\n\n // Limits backoff to max to avoid effectively permanent backoff.\n return Math.min(MAX_VALUE_MILLIS, currBaseValue + randomWait);\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 AppCheck,\n AppCheckOptions,\n AppCheckTokenResult,\n Unsubscribe,\n PartialObserver\n} from './public-types';\nimport { ERROR_FACTORY, AppCheckError } from './errors';\nimport {\n getStateReference,\n getDebugState,\n DEFAULT_STATE,\n setInitialState\n} from './state';\nimport { FirebaseApp, getApp, _getProvider } from '@firebase/app';\nimport { getModularInstance, ErrorFn, NextFn } from '@firebase/util';\nimport { AppCheckService } from './factory';\nimport { AppCheckProvider, ListenerType } from './types';\nimport {\n getToken as getTokenInternal,\n getLimitedUseToken as getLimitedUseTokenInternal,\n addTokenListener,\n removeTokenListener,\n isValid,\n notifyTokenListeners\n} from './internal-api';\nimport { readTokenFromStorage } from './storage';\nimport { getDebugToken, initializeDebugMode, isDebugMode } from './debug';\n\ndeclare module '@firebase/component' {\n interface NameServiceMapping {\n 'app-check': AppCheckService;\n }\n}\n\nexport {\n ReCaptchaV3Provider,\n CustomProvider,\n ReCaptchaEnterpriseProvider\n} from './providers';\n\n/**\n * Activate App Check for the given app. Can be called only once per app.\n * @param app - the {@link @firebase/app#FirebaseApp} to activate App Check for\n * @param options - App Check initialization options\n * @public\n */\nexport function initializeAppCheck(\n app: FirebaseApp = getApp(),\n options: AppCheckOptions\n): AppCheck {\n app = getModularInstance(app);\n const provider = _getProvider(app, 'app-check');\n\n // Ensure initializeDebugMode() is only called once.\n if (!getDebugState().initialized) {\n initializeDebugMode();\n }\n\n // Log a message containing the debug token when `initializeAppCheck()`\n // is called in debug mode.\n if (isDebugMode()) {\n // Do not block initialization to get the token for the message.\n void getDebugToken().then(token =>\n // Not using logger because I don't think we ever want this accidentally hidden.\n console.log(\n `App Check debug token: ${token}. You will need to add it to your app's App Check settings in the Firebase console for it to work.`\n )\n );\n }\n\n if (provider.isInitialized()) {\n const existingInstance = provider.getImmediate();\n const initialOptions = provider.getOptions() as unknown as AppCheckOptions;\n if (\n initialOptions.isTokenAutoRefreshEnabled ===\n options.isTokenAutoRefreshEnabled &&\n initialOptions.provider.isEqual(options.provider)\n ) {\n return existingInstance;\n } else {\n throw ERROR_FACTORY.create(AppCheckError.ALREADY_INITIALIZED, {\n appName: app.name\n });\n }\n }\n\n const appCheck = provider.initialize({ options });\n _activate(app, options.provider, options.isTokenAutoRefreshEnabled);\n // If isTokenAutoRefreshEnabled is false, do not send any requests to the\n // exchange endpoint without an explicit call from the user either directly\n // or through another Firebase library (storage, functions, etc.)\n if (getStateReference(app).isTokenAutoRefreshEnabled) {\n // Adding a listener will start the refresher and fetch a token if needed.\n // This gets a token ready and prevents a delay when an internal library\n // requests the token.\n // Listener function does not need to do anything, its base functionality\n // of calling getToken() already fetches token and writes it to memory/storage.\n addTokenListener(appCheck, ListenerType.INTERNAL, () => {});\n }\n\n return appCheck;\n}\n\n/**\n * Activate App Check\n * @param app - Firebase app to activate App Check for.\n * @param provider - reCAPTCHA v3 provider or\n * custom token provider.\n * @param isTokenAutoRefreshEnabled - If true, the SDK automatically\n * refreshes App Check tokens as needed. If undefined, defaults to the\n * value of `app.automaticDataCollectionEnabled`, which defaults to\n * false and can be set in the app config.\n */\nfunction _activate(\n app: FirebaseApp,\n provider: AppCheckProvider,\n isTokenAutoRefreshEnabled?: boolean\n): void {\n // Create an entry in the APP_CHECK_STATES map. Further changes should\n // directly mutate this object.\n const state = setInitialState(app, { ...DEFAULT_STATE });\n\n state.activated = true;\n state.provider = provider; // Read cached token from storage if it exists and store it in memory.\n state.cachedTokenPromise = readTokenFromStorage(app).then(cachedToken => {\n if (cachedToken && isValid(cachedToken)) {\n state.token = cachedToken;\n // notify all listeners with the cached token\n notifyTokenListeners(app, { token: cachedToken.token });\n }\n return cachedToken;\n });\n\n // Use value of global `automaticDataCollectionEnabled` (which\n // itself defaults to false if not specified in config) if\n // `isTokenAutoRefreshEnabled` param was not provided by user.\n state.isTokenAutoRefreshEnabled =\n isTokenAutoRefreshEnabled === undefined\n ? app.automaticDataCollectionEnabled\n : isTokenAutoRefreshEnabled;\n\n state.provider.initialize(app);\n}\n\n/**\n * Set whether App Check will automatically refresh tokens as needed.\n *\n * @param appCheckInstance - The App Check service instance.\n * @param isTokenAutoRefreshEnabled - If true, the SDK automatically\n * refreshes App Check tokens as needed. This overrides any value set\n * during `initializeAppCheck()`.\n * @public\n */\nexport function setTokenAutoRefreshEnabled(\n appCheckInstance: AppCheck,\n isTokenAutoRefreshEnabled: boolean\n): void {\n const app = appCheckInstance.app;\n const state = getStateReference(app);\n // This will exist if any product libraries have called\n // `addTokenListener()`\n if (state.tokenRefresher) {\n if (isTokenAutoRefreshEnabled === true) {\n state.tokenRefresher.start();\n } else {\n state.tokenRefresher.stop();\n }\n }\n state.isTokenAutoRefreshEnabled = isTokenAutoRefreshEnabled;\n}\n/**\n * Get the current App Check token. If `forceRefresh` is false, this function first\n * checks for a valid token in memory, then local persistence (IndexedDB).\n * If not found, or if `forceRefresh` is true, it makes a request to the\n * App Check endpoint for a fresh token. That request attaches\n * to the most recent in-flight request if one is present.\n *\n * @param appCheckInstance - The App Check service instance.\n * @param forceRefresh - If true, will always try to fetch a fresh token.\n * If false, will use a cached token if found in storage.\n * @public\n */\nexport async function getToken(\n appCheckInstance: AppCheck,\n forceRefresh?: boolean\n): Promise