{"version":3,"file":"EventHandler.js","sources":["../../src/event/EventHandler.ts"],"sourcesContent":["/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { ICrypto, Logger, AccountEntity, CacheManager } from \"@azure/msal-common\";\r\nimport { InteractionType } from \"../utils/BrowserConstants\";\r\nimport { EventCallbackFunction, EventError, EventMessage, EventPayload } from \"./EventMessage\";\r\nimport { EventType } from \"./EventType\";\r\n\r\nexport class EventHandler {\r\n // Callback for subscribing to events\r\n private eventCallbacks: Map;\r\n private logger: Logger;\r\n private browserCrypto: ICrypto;\r\n private listeningToStorageEvents: boolean;\r\n\r\n constructor(logger: Logger, browserCrypto: ICrypto) {\r\n this.eventCallbacks = new Map();\r\n this.logger = logger;\r\n this.browserCrypto = browserCrypto;\r\n this.listeningToStorageEvents = false;\r\n this.handleAccountCacheChange = this.handleAccountCacheChange.bind(this);\r\n }\r\n\r\n /**\r\n * Adds event callbacks to array\r\n * @param callback\r\n */\r\n addEventCallback(callback: EventCallbackFunction): string | null {\r\n if (typeof window !== \"undefined\") {\r\n const callbackId = this.browserCrypto.createNewGuid();\r\n this.eventCallbacks.set(callbackId, callback);\r\n this.logger.verbose(`Event callback registered with id: ${callbackId}`);\r\n \r\n return callbackId;\r\n }\r\n \r\n return null;\r\n }\r\n\r\n /**\r\n * Removes callback with provided id from callback array\r\n * @param callbackId\r\n */\r\n removeEventCallback(callbackId: string): void {\r\n this.eventCallbacks.delete(callbackId);\r\n this.logger.verbose(`Event callback ${callbackId} removed.`);\r\n }\r\n\r\n /**\r\n * Adds event listener that emits an event when a user account is added or removed from localstorage in a different browser tab or window\r\n */\r\n enableAccountStorageEvents(): void {\r\n if (typeof window === \"undefined\") {\r\n return;\r\n }\r\n\r\n if (!this.listeningToStorageEvents) {\r\n this.logger.verbose(\"Adding account storage listener.\");\r\n this.listeningToStorageEvents = true;\r\n window.addEventListener(\"storage\", this.handleAccountCacheChange);\r\n } else {\r\n this.logger.verbose(\"Account storage listener already registered.\");\r\n }\r\n }\r\n\r\n /**\r\n * Removes event listener that emits an event when a user account is added or removed from localstorage in a different browser tab or window\r\n */\r\n disableAccountStorageEvents(): void {\r\n if (typeof window === \"undefined\") {\r\n return;\r\n }\r\n\r\n if (this.listeningToStorageEvents) {\r\n this.logger.verbose(\"Removing account storage listener.\");\r\n window.removeEventListener(\"storage\", this.handleAccountCacheChange);\r\n this.listeningToStorageEvents = false;\r\n } else {\r\n this.logger.verbose(\"No account storage listener registered.\");\r\n }\r\n }\r\n\r\n /**\r\n * Emits events by calling callback with event message\r\n * @param eventType\r\n * @param interactionType\r\n * @param payload\r\n * @param error\r\n */\r\n emitEvent(eventType: EventType, interactionType?: InteractionType, payload?: EventPayload, error?: EventError): void {\r\n if (typeof window !== \"undefined\") {\r\n const message: EventMessage = {\r\n eventType: eventType,\r\n interactionType: interactionType || null,\r\n payload: payload || null,\r\n error: error || null,\r\n timestamp: Date.now()\r\n };\r\n\r\n this.logger.info(`Emitting event: ${eventType}`);\r\n\r\n this.eventCallbacks.forEach((callback: EventCallbackFunction, callbackId: string) => {\r\n this.logger.verbose(`Emitting event to callback ${callbackId}: ${eventType}`);\r\n callback.apply(null, [message]);\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Emit account added/removed events when cached accounts are changed in a different tab or frame\r\n */\r\n private handleAccountCacheChange(e: StorageEvent): void {\r\n try {\r\n const cacheValue = e.newValue || e.oldValue;\r\n if (!cacheValue) {\r\n return;\r\n }\r\n const parsedValue = JSON.parse(cacheValue);\r\n if (typeof parsedValue !== \"object\" || !AccountEntity.isAccountEntity(parsedValue)) {\r\n return;\r\n }\r\n const accountEntity = CacheManager.toObject(new AccountEntity(), parsedValue);\r\n const accountInfo = accountEntity.getAccountInfo();\r\n if (!e.oldValue && e.newValue) {\r\n this.logger.info(\"Account was added to cache in a different window\");\r\n this.emitEvent(EventType.ACCOUNT_ADDED, undefined, accountInfo);\r\n } else if (!e.newValue && e.oldValue) {\r\n this.logger.info(\"Account was removed from cache in a different window\");\r\n this.emitEvent(EventType.ACCOUNT_REMOVED, undefined, accountInfo);\r\n }\r\n } catch (e) {\r\n return;\r\n }\r\n }\r\n}\r\n"],"names":[],"mappings":"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"}