"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getLocalStorage = getLocalStorage; exports.storageKey = storageKey; exports.postMessage = postMessage; exports.addStorageEventListener = addStorageEventListener; exports.removeStorageEventListener = removeStorageEventListener; exports.create = create; exports.close = close; exports.onMessage = onMessage; exports.canBeUsed = canBeUsed; exports.averageResponseTime = averageResponseTime; exports["default"] = exports.type = exports.microSeconds = void 0; var _obliviousSet = require("oblivious-set"); var _options = require("../options"); var _util = require("../util"); /** * A localStorage-only method which uses localstorage and its 'storage'-event * This does not work inside of webworkers because they have no access to locastorage * This is basically implemented to support IE9 or your grandmothers toaster. * @link https://caniuse.com/#feat=namevalue-storage * @link https://caniuse.com/#feat=indexeddb */ var microSeconds = _util.microSeconds; exports.microSeconds = microSeconds; var KEY_PREFIX = 'pubkey.broadcastChannel-'; var type = 'localstorage'; /** * copied from crosstab * @link https://github.com/tejacques/crosstab/blob/master/src/crosstab.js#L32 */ exports.type = type; function getLocalStorage() { var localStorage; if (typeof window === 'undefined') return null; try { localStorage = window.localStorage; localStorage = window['ie8-eventlistener/storage'] || window.localStorage; } catch (e) {// New versions of Firefox throw a Security exception // if cookies are disabled. See // https://bugzilla.mozilla.org/show_bug.cgi?id=1028153 } return localStorage; } function storageKey(channelName) { return KEY_PREFIX + channelName; } /** * writes the new message to the storage * and fires the storage-event so other readers can find it */ function postMessage(channelState, messageJson) { return new Promise(function (res) { (0, _util.sleep)().then(function () { var key = storageKey(channelState.channelName); var writeObj = { token: (0, _util.randomToken)(), time: new Date().getTime(), data: messageJson, uuid: channelState.uuid }; var value = JSON.stringify(writeObj); getLocalStorage().setItem(key, value); /** * StorageEvent does not fire the 'storage' event * in the window that changes the state of the local storage. * So we fire it manually */ var ev = document.createEvent('Event'); ev.initEvent('storage', true, true); ev.key = key; ev.newValue = value; window.dispatchEvent(ev); res(); }); }); } function addStorageEventListener(channelName, fn) { var key = storageKey(channelName); var listener = function listener(ev) { if (ev.key === key) { fn(JSON.parse(ev.newValue)); } }; window.addEventListener('storage', listener); return listener; } function removeStorageEventListener(listener) { window.removeEventListener('storage', listener); } function create(channelName, options) { options = (0, _options.fillOptionsWithDefaults)(options); if (!canBeUsed()) { throw new Error('BroadcastChannel: localstorage cannot be used'); } var uuid = (0, _util.randomToken)(); /** * eMIs * contains all messages that have been emitted before * @type {ObliviousSet} */ var eMIs = new _obliviousSet.ObliviousSet(options.localstorage.removeTimeout); var state = { channelName: channelName, uuid: uuid, eMIs: eMIs // emittedMessagesIds }; state.listener = addStorageEventListener(channelName, function (msgObj) { if (!state.messagesCallback) return; // no listener if (msgObj.uuid === uuid) return; // own message if (!msgObj.token || eMIs.has(msgObj.token)) return; // already emitted if (msgObj.data.time && msgObj.data.time < state.messagesCallbackTime) return; // too old eMIs.add(msgObj.token); state.messagesCallback(msgObj.data); }); return state; } function close(channelState) { removeStorageEventListener(channelState.listener); } function onMessage(channelState, fn, time) { channelState.messagesCallbackTime = time; channelState.messagesCallback = fn; } function canBeUsed() { if (_util.isNode) return false; var ls = getLocalStorage(); if (!ls) return false; try { var key = '__broadcastchannel_check'; ls.setItem(key, 'works'); ls.removeItem(key); } catch (e) { // Safari 10 in private mode will not allow write access to local // storage and fail with a QuotaExceededError. See // https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API#Private_Browsing_Incognito_modes return false; } return true; } function averageResponseTime() { var defaultTime = 120; var userAgent = navigator.userAgent.toLowerCase(); if (userAgent.includes('safari') && !userAgent.includes('chrome')) { // safari is much slower so this time is higher return defaultTime * 2; } return defaultTime; } var _default = { create: create, close: close, onMessage: onMessage, postMessage: postMessage, canBeUsed: canBeUsed, type: type, averageResponseTime: averageResponseTime, microSeconds: microSeconds }; exports["default"] = _default;