This repository has been archived on 2026-05-25. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
Antoine Ouvrard d3277d6563 initial commit
2020-11-23 10:28:32 +01:00

1 line
159 KiB
Plaintext

{"version":3,"sources":["webpack://JitsiMeetExternalAPI/webpack/universalModuleDefinition","webpack://JitsiMeetExternalAPI/webpack/bootstrap","webpack://JitsiMeetExternalAPI/./modules/API/external/functions.js","webpack://JitsiMeetExternalAPI/./node_modules/events/events.js","webpack://JitsiMeetExternalAPI/./node_modules/jitsi-meet-logger/lib/Logger.js","webpack://JitsiMeetExternalAPI/./node_modules/@jitsi/js-utils/transport/postis.js","webpack://JitsiMeetExternalAPI/./node_modules/jitsi-meet-logger/lib/index.js","webpack://JitsiMeetExternalAPI/./modules/API/external/index.js","webpack://JitsiMeetExternalAPI/./node_modules/jitsi-meet-logger/lib/LogCollector.js","webpack://JitsiMeetExternalAPI/./node_modules/@jitsi/js-utils/jitsi-local-storage/index.js","webpack://JitsiMeetExternalAPI/./react/features/base/util/parseURLParams.js","webpack://JitsiMeetExternalAPI/./react/features/base/util/helpers.js","webpack://JitsiMeetExternalAPI/./react/features/base/util/uri.js","webpack://JitsiMeetExternalAPI/./node_modules/@jitsi/js-utils/transport/PostMessageTransportBackend.js","webpack://JitsiMeetExternalAPI/./node_modules/@jitsi/js-utils/transport/Transport.js","webpack://JitsiMeetExternalAPI/./node_modules/@jitsi/js-utils/transport/constants.js","webpack://JitsiMeetExternalAPI/./modules/API/constants.js","webpack://JitsiMeetExternalAPI/./modules/transport/index.js","webpack://JitsiMeetExternalAPI/./modules/API/external/external_api.js"],"names":["root","factory","exports","module","define","amd","window","installedModules","__webpack_require__","moduleId","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s","logger","Logger","getLogger","__filename","getAvailableDevices","transport","sendRequest","type","catch","e","error","getCurrentDevices","isDeviceChangeAvailable","deviceType","isDeviceListAvailable","isMultipleAudioInputSupported","setAudioInputDevice","label","id","_setDevice","kind","setAudioOutputDevice","device","setVideoInputDevice","ReflectOwnKeys","R","Reflect","ReflectApply","apply","target","receiver","args","Function","ownKeys","getOwnPropertySymbols","getOwnPropertyNames","concat","NumberIsNaN","Number","isNaN","EventEmitter","init","this","once","emitter","Promise","resolve","reject","eventListener","undefined","errorListener","removeListener","slice","arguments","err","_events","_eventsCount","_maxListeners","defaultMaxListeners","checkListener","listener","TypeError","_getMaxListeners","that","_addListener","prepend","events","existing","warning","newListener","emit","unshift","push","length","warned","w","Error","String","count","console","warn","onceWrapper","fired","wrapFn","_onceWrap","state","wrapped","_listeners","unwrap","evlistener","arr","ret","Array","unwrapListeners","arrayClone","listenerCount","copy","set","arg","RangeError","getPrototypeOf","setMaxListeners","getMaxListeners","doError","er","message","context","handler","len","listeners","addListener","on","prependListener","prependOnceListener","list","position","originalListener","shift","index","pop","spliceOne","off","removeAllListeners","keys","rawListeners","eventNames","levels","consoleTransport","globalTransports","addGlobalTransport","indexOf","removeGlobalTransport","transportIdx","splice","globalOptions","getCallerInfo","callerInfo","methodName","fileLocation","line","column","stack","split","match","substr","log","level","options","disableCallerInfo","transports","logPrefixes","Date","toISOString","fullLogParts","methods","setGlobalOptions","setLevel","TRACE","DEBUG","INFO","LOG","WARN","ERROR","readynessCheck","scope","targetWindow","windowForEventListening","allowedOrigin","sendBuffer","listenBuffer","ready","event","data","JSON","parse","origin","postis","listenersForMethod","method","params","addEventListener","listen","callback","listenBufferForMethod","j","send","opts","postMessage","stringify","setTimeout","destroy","clearInterval","removeEventListener","readyCheckID","Math","random","setInterval","LogCollector","idLoggers","loggers","curLevel","setLogLevelById","setLogLevel","require","default","logStorage","stringifyObjects","storeInterval","maxEntryLength","forEach","logLevel","_log","storeLogsIntervalID","queue","totalLen","outputCache","someObject","formatLogMessage","msg","timestamp","prevMessage","prevMessageText","text","_flush","start","_reschedulePublishInterval","clearTimeout","flush","force","reschedule","isReady","cachedQueue","storeLogs","stop","DummyLocalStorage","clear","_storage","getItem","keyName","setItem","keyValue","removeItem","serialize","JitsiLocalStorage","constructor","super","localStorage","_localStorageDisabled","ignore","isLocalStorageDisabled","dontEmitChangedEvent","localStorageContent","jitsiLocalStorage","parseURLParams","url","dontParse","source","paramStr","search","hash","paramParts","firstParam","startsWith","part","param","decoded","decodeURIComponent","replace","onerror","reportError","_fixURIStringScheme","uri","regex","RegExp","exec","protocol","toLowerCase","substring","lastIndex","_objectToURLParamsArray","obj","encodeURIComponent","parseStandardURIString","str","toString","_standardURIToString","pathname","authority","userinfoEndIndex","host","portBeginIndex","lastIndexOf","port","hostname","hashBeginIndex","thiz","urlObjectToString","tmp","serverURL","room","URL","scheme","endsWith","domain","contextRoot","roomName","jwt","urlPrefix","urlParamsArray","urlParamsString","join","DEFAULT_POSTIS_OPTIONS","opener","parent","PostMessageTransportBackend","postisOptions","Postis","_receiveCallback","dispose","setReceiveCallback","Transport","backend","Map","_requestID","_responseHandlers","_unprocessedMessages","Set","setBackend","_disposeBackend","_backend","_onMessageReceived","delete","result","eventName","listenersForEvent","isProcessed","size","add","sendEvent","request","API_ID","location","jitsi_meet_external_api_id","JitsiMeetJS","app","setExternalTransportBackend","externalTransportBackend","ALWAYS_ON_TOP_FILENAMES","commands","avatarUrl","displayName","e2eeKey","email","toggleLobby","hangup","muteEveryone","password","pinParticipant","resizeLargeVideo","sendEndpointTextMessage","sendTones","setLargeVideoParticipant","setVideoQuality","startRecording","stopRecording","subject","submitFeedback","toggleAudio","toggleChat","toggleFilmStrip","toggleShareScreen","toggleTileView","toggleVideo","changeParticipantNumber","APIInstance","number","_numberOfParticipants","parseSizeParam","parsedValue","JitsiMeetExternalAPI","width","height","parentNode","document","body","configOverwrite","interfaceConfigOverwrite","noSSL","onload","invitees","devices","userInfo","parseArguments","_parentNode","_url","generateURL","appData","_createIFrame","_transport","_frame","contentWindow","isArray","invite","_tmpE2EEKey","_isLargeVideoVisible","_participants","_myUserID","_onStageParticipant","_setupListeners","frameName","createElement","allow","src","_setSize","setAttribute","style","border","appendChild","_getAlwaysOnTopResources","iframeWindow","iframeDocument","baseURL","base","querySelector","href","map","filename","_getFormattedDisplayName","participantId","formattedDisplayName","_getOnStageParticipant","_getLargeVideo","iframe","getIFrame","getElementById","_getParticipantVideo","parsedHeight","parsedWidth","_height","_width","userID","executeCommand","avatarURL","user","displayname","isVisible","_videoQuality","videoQuality","addEventListeners","captureLargeVideoScreenshot","removeChild","executeCommands","commandList","getParticipantsInfo","participantIds","participantsInfo","values","participant","idx","getVideoQuality","isAudioAvailable","isAudioMuted","isSharingScreen","getAvatarURL","getDisplayName","getEmail","getNumberOfParticipants","isVideoAvailable","isVideoMuted","removeEventListeners","eventList","sendProxyConnectionEvent","deviceId","_getElectronPopupsConfig","electronPopupsConfig"],"mappings":"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","file":"external_api.min.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"JitsiMeetExternalAPI\"] = factory();\n\telse\n\t\troot[\"JitsiMeetExternalAPI\"] = factory();\n})(window, function() {\nreturn "," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"/libs/\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 6);\n","// @flow\n\nimport Logger from 'jitsi-meet-logger';\n\nconst logger = Logger.getLogger(__filename);\n\n/**\n * Returns Promise that resolves with result an list of available devices.\n *\n * @param {Transport} transport - The @code{Transport} instance responsible for\n * the external communication.\n * @returns {Promise}\n */\nexport function getAvailableDevices(transport: Object) {\n return transport.sendRequest({\n type: 'devices',\n name: 'getAvailableDevices'\n }).catch(e => {\n logger.error(e);\n\n return {};\n });\n}\n\n/**\n * Returns Promise that resolves with current selected devices.\n *\n * @param {Transport} transport - The @code{Transport} instance responsible for\n * the external communication.\n * @returns {Promise}\n */\nexport function getCurrentDevices(transport: Object) {\n return transport.sendRequest({\n type: 'devices',\n name: 'getCurrentDevices'\n }).catch(e => {\n logger.error(e);\n\n return {};\n });\n}\n\n/**\n * Returns Promise that resolves with true if the device change is available\n * and with false if not.\n *\n * @param {Transport} transport - The @code{Transport} instance responsible for\n * the external communication.\n * @param {string} [deviceType] - Values - 'output', 'input' or undefined.\n * Default - 'input'.\n * @returns {Promise}\n */\nexport function isDeviceChangeAvailable(transport: Object, deviceType: string) {\n return transport.sendRequest({\n deviceType,\n type: 'devices',\n name: 'isDeviceChangeAvailable'\n });\n}\n\n/**\n * Returns Promise that resolves with true if the device list is available\n * and with false if not.\n *\n * @param {Transport} transport - The @code{Transport} instance responsible for\n * the external communication.\n * @returns {Promise}\n */\nexport function isDeviceListAvailable(transport: Object) {\n return transport.sendRequest({\n type: 'devices',\n name: 'isDeviceListAvailable'\n });\n}\n\n/**\n * Returns Promise that resolves with true if multiple audio input is supported\n * and with false if not.\n *\n * @param {Transport} transport - The @code{Transport} instance responsible for\n * the external communication.\n * @returns {Promise}\n */\nexport function isMultipleAudioInputSupported(transport: Object) {\n return transport.sendRequest({\n type: 'devices',\n name: 'isMultipleAudioInputSupported'\n });\n}\n\n/**\n * Sets the audio input device to the one with the label or id that is passed.\n *\n * @param {Transport} transport - The @code{Transport} instance responsible for\n * the external communication.\n * @param {string} label - The label of the new device.\n * @param {string} id - The id of the new device.\n * @returns {Promise}\n */\nexport function setAudioInputDevice(transport: Object, label: string, id: string) {\n return _setDevice(transport, {\n id,\n kind: 'audioinput',\n label\n });\n}\n\n/**\n * Sets the audio output device to the one with the label or id that is passed.\n *\n * @param {Transport} transport - The @code{Transport} instance responsible for\n * the external communication.\n * @param {string} label - The label of the new device.\n * @param {string} id - The id of the new device.\n * @returns {Promise}\n */\nexport function setAudioOutputDevice(transport: Object, label: string, id: string) {\n return _setDevice(transport, {\n id,\n kind: 'audiooutput',\n label\n });\n}\n\n/**\n * Sets the currently used device to the one that is passed.\n *\n * @param {Transport} transport - The @code{Transport} instance responsible for\n * the external communication.\n * @param {Object} device - The new device to be used.\n * @returns {Promise}\n */\nfunction _setDevice(transport: Object, device) {\n return transport.sendRequest({\n type: 'devices',\n name: 'setDevice',\n device\n });\n}\n\n/**\n * Sets the video input device to the one with the label or id that is passed.\n *\n * @param {Transport} transport - The @code{Transport} instance responsible for\n * the external communication.\n * @param {string} label - The label of the new device.\n * @param {string} id - The id of the new device.\n * @returns {Promise}\n */\nexport function setVideoInputDevice(transport: Object, label: string, id: string) {\n return _setDevice(transport, {\n id,\n kind: 'videoinput',\n label\n });\n}\n","// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// copy of this software and associated documentation files (the\n// \"Software\"), to deal in the Software without restriction, including\n// without limitation the rights to use, copy, modify, merge, publish,\n// distribute, sublicense, and/or sell copies of the Software, and to permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n'use strict';\n\nvar R = typeof Reflect === 'object' ? Reflect : null\nvar ReflectApply = R && typeof R.apply === 'function'\n ? R.apply\n : function ReflectApply(target, receiver, args) {\n return Function.prototype.apply.call(target, receiver, args);\n }\n\nvar ReflectOwnKeys\nif (R && typeof R.ownKeys === 'function') {\n ReflectOwnKeys = R.ownKeys\n} else if (Object.getOwnPropertySymbols) {\n ReflectOwnKeys = function ReflectOwnKeys(target) {\n return Object.getOwnPropertyNames(target)\n .concat(Object.getOwnPropertySymbols(target));\n };\n} else {\n ReflectOwnKeys = function ReflectOwnKeys(target) {\n return Object.getOwnPropertyNames(target);\n };\n}\n\nfunction ProcessEmitWarning(warning) {\n if (console && console.warn) console.warn(warning);\n}\n\nvar NumberIsNaN = Number.isNaN || function NumberIsNaN(value) {\n return value !== value;\n}\n\nfunction EventEmitter() {\n EventEmitter.init.call(this);\n}\nmodule.exports = EventEmitter;\nmodule.exports.once = once;\n\n// Backwards-compat with node 0.10.x\nEventEmitter.EventEmitter = EventEmitter;\n\nEventEmitter.prototype._events = undefined;\nEventEmitter.prototype._eventsCount = 0;\nEventEmitter.prototype._maxListeners = undefined;\n\n// By default EventEmitters will print a warning if more than 10 listeners are\n// added to it. This is a useful default which helps finding memory leaks.\nvar defaultMaxListeners = 10;\n\nfunction checkListener(listener) {\n if (typeof listener !== 'function') {\n throw new TypeError('The \"listener\" argument must be of type Function. Received type ' + typeof listener);\n }\n}\n\nObject.defineProperty(EventEmitter, 'defaultMaxListeners', {\n enumerable: true,\n get: function() {\n return defaultMaxListeners;\n },\n set: function(arg) {\n if (typeof arg !== 'number' || arg < 0 || NumberIsNaN(arg)) {\n throw new RangeError('The value of \"defaultMaxListeners\" is out of range. It must be a non-negative number. Received ' + arg + '.');\n }\n defaultMaxListeners = arg;\n }\n});\n\nEventEmitter.init = function() {\n\n if (this._events === undefined ||\n this._events === Object.getPrototypeOf(this)._events) {\n this._events = Object.create(null);\n this._eventsCount = 0;\n }\n\n this._maxListeners = this._maxListeners || undefined;\n};\n\n// Obviously not all Emitters should be limited to 10. This function allows\n// that to be increased. Set to zero for unlimited.\nEventEmitter.prototype.setMaxListeners = function setMaxListeners(n) {\n if (typeof n !== 'number' || n < 0 || NumberIsNaN(n)) {\n throw new RangeError('The value of \"n\" is out of range. It must be a non-negative number. Received ' + n + '.');\n }\n this._maxListeners = n;\n return this;\n};\n\nfunction _getMaxListeners(that) {\n if (that._maxListeners === undefined)\n return EventEmitter.defaultMaxListeners;\n return that._maxListeners;\n}\n\nEventEmitter.prototype.getMaxListeners = function getMaxListeners() {\n return _getMaxListeners(this);\n};\n\nEventEmitter.prototype.emit = function emit(type) {\n var args = [];\n for (var i = 1; i < arguments.length; i++) args.push(arguments[i]);\n var doError = (type === 'error');\n\n var events = this._events;\n if (events !== undefined)\n doError = (doError && events.error === undefined);\n else if (!doError)\n return false;\n\n // If there is no 'error' event listener then throw.\n if (doError) {\n var er;\n if (args.length > 0)\n er = args[0];\n if (er instanceof Error) {\n // Note: The comments on the `throw` lines are intentional, they show\n // up in Node's output if this results in an unhandled exception.\n throw er; // Unhandled 'error' event\n }\n // At least give some kind of context to the user\n var err = new Error('Unhandled error.' + (er ? ' (' + er.message + ')' : ''));\n err.context = er;\n throw err; // Unhandled 'error' event\n }\n\n var handler = events[type];\n\n if (handler === undefined)\n return false;\n\n if (typeof handler === 'function') {\n ReflectApply(handler, this, args);\n } else {\n var len = handler.length;\n var listeners = arrayClone(handler, len);\n for (var i = 0; i < len; ++i)\n ReflectApply(listeners[i], this, args);\n }\n\n return true;\n};\n\nfunction _addListener(target, type, listener, prepend) {\n var m;\n var events;\n var existing;\n\n checkListener(listener);\n\n events = target._events;\n if (events === undefined) {\n events = target._events = Object.create(null);\n target._eventsCount = 0;\n } else {\n // To avoid recursion in the case that type === \"newListener\"! Before\n // adding it to the listeners, first emit \"newListener\".\n if (events.newListener !== undefined) {\n target.emit('newListener', type,\n listener.listener ? listener.listener : listener);\n\n // Re-assign `events` because a newListener handler could have caused the\n // this._events to be assigned to a new object\n events = target._events;\n }\n existing = events[type];\n }\n\n if (existing === undefined) {\n // Optimize the case of one listener. Don't need the extra array object.\n existing = events[type] = listener;\n ++target._eventsCount;\n } else {\n if (typeof existing === 'function') {\n // Adding the second element, need to change to array.\n existing = events[type] =\n prepend ? [listener, existing] : [existing, listener];\n // If we've already got an array, just append.\n } else if (prepend) {\n existing.unshift(listener);\n } else {\n existing.push(listener);\n }\n\n // Check for listener leak\n m = _getMaxListeners(target);\n if (m > 0 && existing.length > m && !existing.warned) {\n existing.warned = true;\n // No error code for this since it is a Warning\n // eslint-disable-next-line no-restricted-syntax\n var w = new Error('Possible EventEmitter memory leak detected. ' +\n existing.length + ' ' + String(type) + ' listeners ' +\n 'added. Use emitter.setMaxListeners() to ' +\n 'increase limit');\n w.name = 'MaxListenersExceededWarning';\n w.emitter = target;\n w.type = type;\n w.count = existing.length;\n ProcessEmitWarning(w);\n }\n }\n\n return target;\n}\n\nEventEmitter.prototype.addListener = function addListener(type, listener) {\n return _addListener(this, type, listener, false);\n};\n\nEventEmitter.prototype.on = EventEmitter.prototype.addListener;\n\nEventEmitter.prototype.prependListener =\n function prependListener(type, listener) {\n return _addListener(this, type, listener, true);\n };\n\nfunction onceWrapper() {\n if (!this.fired) {\n this.target.removeListener(this.type, this.wrapFn);\n this.fired = true;\n if (arguments.length === 0)\n return this.listener.call(this.target);\n return this.listener.apply(this.target, arguments);\n }\n}\n\nfunction _onceWrap(target, type, listener) {\n var state = { fired: false, wrapFn: undefined, target: target, type: type, listener: listener };\n var wrapped = onceWrapper.bind(state);\n wrapped.listener = listener;\n state.wrapFn = wrapped;\n return wrapped;\n}\n\nEventEmitter.prototype.once = function once(type, listener) {\n checkListener(listener);\n this.on(type, _onceWrap(this, type, listener));\n return this;\n};\n\nEventEmitter.prototype.prependOnceListener =\n function prependOnceListener(type, listener) {\n checkListener(listener);\n this.prependListener(type, _onceWrap(this, type, listener));\n return this;\n };\n\n// Emits a 'removeListener' event if and only if the listener was removed.\nEventEmitter.prototype.removeListener =\n function removeListener(type, listener) {\n var list, events, position, i, originalListener;\n\n checkListener(listener);\n\n events = this._events;\n if (events === undefined)\n return this;\n\n list = events[type];\n if (list === undefined)\n return this;\n\n if (list === listener || list.listener === listener) {\n if (--this._eventsCount === 0)\n this._events = Object.create(null);\n else {\n delete events[type];\n if (events.removeListener)\n this.emit('removeListener', type, list.listener || listener);\n }\n } else if (typeof list !== 'function') {\n position = -1;\n\n for (i = list.length - 1; i >= 0; i--) {\n if (list[i] === listener || list[i].listener === listener) {\n originalListener = list[i].listener;\n position = i;\n break;\n }\n }\n\n if (position < 0)\n return this;\n\n if (position === 0)\n list.shift();\n else {\n spliceOne(list, position);\n }\n\n if (list.length === 1)\n events[type] = list[0];\n\n if (events.removeListener !== undefined)\n this.emit('removeListener', type, originalListener || listener);\n }\n\n return this;\n };\n\nEventEmitter.prototype.off = EventEmitter.prototype.removeListener;\n\nEventEmitter.prototype.removeAllListeners =\n function removeAllListeners(type) {\n var listeners, events, i;\n\n events = this._events;\n if (events === undefined)\n return this;\n\n // not listening for removeListener, no need to emit\n if (events.removeListener === undefined) {\n if (arguments.length === 0) {\n this._events = Object.create(null);\n this._eventsCount = 0;\n } else if (events[type] !== undefined) {\n if (--this._eventsCount === 0)\n this._events = Object.create(null);\n else\n delete events[type];\n }\n return this;\n }\n\n // emit removeListener for all listeners on all events\n if (arguments.length === 0) {\n var keys = Object.keys(events);\n var key;\n for (i = 0; i < keys.length; ++i) {\n key = keys[i];\n if (key === 'removeListener') continue;\n this.removeAllListeners(key);\n }\n this.removeAllListeners('removeListener');\n this._events = Object.create(null);\n this._eventsCount = 0;\n return this;\n }\n\n listeners = events[type];\n\n if (typeof listeners === 'function') {\n this.removeListener(type, listeners);\n } else if (listeners !== undefined) {\n // LIFO order\n for (i = listeners.length - 1; i >= 0; i--) {\n this.removeListener(type, listeners[i]);\n }\n }\n\n return this;\n };\n\nfunction _listeners(target, type, unwrap) {\n var events = target._events;\n\n if (events === undefined)\n return [];\n\n var evlistener = events[type];\n if (evlistener === undefined)\n return [];\n\n if (typeof evlistener === 'function')\n return unwrap ? [evlistener.listener || evlistener] : [evlistener];\n\n return unwrap ?\n unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length);\n}\n\nEventEmitter.prototype.listeners = function listeners(type) {\n return _listeners(this, type, true);\n};\n\nEventEmitter.prototype.rawListeners = function rawListeners(type) {\n return _listeners(this, type, false);\n};\n\nEventEmitter.listenerCount = function(emitter, type) {\n if (typeof emitter.listenerCount === 'function') {\n return emitter.listenerCount(type);\n } else {\n return listenerCount.call(emitter, type);\n }\n};\n\nEventEmitter.prototype.listenerCount = listenerCount;\nfunction listenerCount(type) {\n var events = this._events;\n\n if (events !== undefined) {\n var evlistener = events[type];\n\n if (typeof evlistener === 'function') {\n return 1;\n } else if (evlistener !== undefined) {\n return evlistener.length;\n }\n }\n\n return 0;\n}\n\nEventEmitter.prototype.eventNames = function eventNames() {\n return this._eventsCount > 0 ? ReflectOwnKeys(this._events) : [];\n};\n\nfunction arrayClone(arr, n) {\n var copy = new Array(n);\n for (var i = 0; i < n; ++i)\n copy[i] = arr[i];\n return copy;\n}\n\nfunction spliceOne(list, index) {\n for (; index + 1 < list.length; index++)\n list[index] = list[index + 1];\n list.pop();\n}\n\nfunction unwrapListeners(arr) {\n var ret = new Array(arr.length);\n for (var i = 0; i < ret.length; ++i) {\n ret[i] = arr[i].listener || arr[i];\n }\n return ret;\n}\n\nfunction once(emitter, name) {\n return new Promise(function (resolve, reject) {\n function eventListener() {\n if (errorListener !== undefined) {\n emitter.removeListener('error', errorListener);\n }\n resolve([].slice.call(arguments));\n };\n var errorListener;\n\n // Adding an error listener is not optional because\n // if an error is thrown on an event emitter we cannot\n // guarantee that the actual event we are waiting will\n // be fired. The result could be a silent way to create\n // memory or file descriptor leaks, which is something\n // we should avoid.\n if (name !== 'error') {\n errorListener = function errorListener(err) {\n emitter.removeListener(name, eventListener);\n reject(err);\n };\n\n emitter.once('error', errorListener);\n }\n\n emitter.once(name, eventListener);\n });\n}\n","/* Copyright @ 2015-present 8x8, Inc.\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/*jslint latedef:false*/\n\n/**\n * Ordered log levels.\n */\nvar levels = {\n \"trace\": 0,\n \"debug\": 1,\n \"info\": 2,\n \"log\": 3,\n \"warn\": 4,\n \"error\": 5\n};\n\n/**\n * The default transport - console\n * @type LoggerTransport\n */\nLogger.consoleTransport = console;\n\n/**\n * The array which stores currently registered global transports.\n * @type {[LoggerTransport]}\n */\nvar globalTransports = [ Logger.consoleTransport ];\n\n/**\n * Adds given {@link LoggerTransport} instance to the list of global\n * transports which means that it'll be used by all {@link Logger}s\n * @param {LoggerTransport} transport\n */\nLogger.addGlobalTransport = function(transport) {\n if (globalTransports.indexOf(transport) === -1) {\n globalTransports.push(transport);\n }\n};\n\n/**\n * Removes given {@link LoggerTransport} instance from the list of global\n * transports\n * @param {LoggerTransport} transport\n */\nLogger.removeGlobalTransport = function(transport) {\n var transportIdx = globalTransports.indexOf(transport);\n if (transportIdx !== -1) {\n globalTransports.splice(transportIdx, 1);\n }\n};\n\n/**\n * The global configuration options.\n */\nvar globalOptions = {};\n\n/**\n * Sets global options which will be used by all loggers. Changing these works\n * even after other loggers are created.\n */\nLogger.setGlobalOptions = function(options) {\n globalOptions = options || {};\n};\n\n/**\n * Parses Error's object stack trace and extracts information about the last\n * caller before the log method was called.\n * @returns JS object with info about the caller - method name, file location,\n * line and column.\n */\nfunction getCallerInfo() {\n var callerInfo = {\n methodName: \"\",\n fileLocation: \"\",\n line: null,\n column: null\n };\n //gets the part of the stack without the logger wrappers\n var error = new Error();\n var stack = error.stack? error.stack.split(\"\\n\") : [];\n if(!stack || stack.length < 1) {\n return callerInfo;\n }\n var m = null;\n if(stack[3]) {\n m = stack[3].match(/\\s*at\\s*(.+?)\\s*\\((\\S*)\\s*:(\\d*)\\s*:(\\d*)\\)/);\n }\n if(!m || m.length <= 4) {\n //Firefox && Safari\n if(stack[2].indexOf(\"log@\") === 0){\n //Safari\n callerInfo.methodName = stack[3].substr(0, stack[3].indexOf(\"@\"));\n } else {\n //Firefox\n callerInfo.methodName = stack[2].substr(0, stack[2].indexOf(\"@\"));\n }\n return callerInfo;\n }\n\n callerInfo.methodName = m[1];\n callerInfo.fileLocation = m[2];\n callerInfo.line = m[3];\n callerInfo.column = m[4];\n return callerInfo;\n}\n\n/**\n * Logs messages using the transports and level from the logger.\n * @param logger a logger instance.\n * @param level the log level of the message. See the levels variable.\n * @param arguments array with arguments that will be logged.\n */\nfunction log() {\n var logger = arguments[0], level = arguments[1],\n args = Array.prototype.slice.call(arguments, 2);\n if(levels[level] < logger.level) {\n return;\n }\n\n var callerInfo\n = !(logger.options.disableCallerInfo || globalOptions.disableCallerInfo) &&\n getCallerInfo();\n var transports = globalTransports.concat(logger.transports);\n for(var i = 0; i < transports.length; i++) {\n var t = transports[i];\n var l = t[level];\n if(l && typeof(l) === \"function\") {\n var logPrefixes = [];\n\n logPrefixes.push(new Date().toISOString());\n\n if (logger.id) {\n logPrefixes.push(\"[\" + logger.id + \"]\");\n }\n\n if (callerInfo && callerInfo.methodName.length > 1) {\n logPrefixes.push(\"<\" + callerInfo.methodName + \">: \");\n }\n\n var fullLogParts = logPrefixes.concat(args);\n\n l.bind(t).apply(t, fullLogParts);\n }\n }\n}\n\n/**\n *\n * Constructs new logger object.\n * @param level the logging level for the new logger\n * @param id optional identifier for the logger instance.\n * @param {LoggerTransport} transports optional list of handlers(objects) for\n * the logs. The handlers must support - log, warn, error, debug, info, trace.\n * @param options optional configuration file for how the logger should behave.\n * @param {boolean} options.disableCallerInfo Whether the call site of a logger\n * method invocation should be included in the log. Defaults to false, so the\n * call site will be included.\n */\nfunction Logger(level, id, transports, options) {\n this.id = id;\n this.options = options || {};\n this.transports = transports;\n if(!this.transports) {\n this.transports = [];\n }\n this.level = levels[level];\n var methods = Object.keys(levels);\n for(var i = 0; i < methods.length; i++){\n this[methods[i]] =\n log.bind(null, this, methods[i]);\n }\n}\n\n/**\n * Sets the log level for the logger.\n * @param level the new log level.\n */\nLogger.prototype.setLevel = function (level) {\n this.level = levels[level];\n};\nmodule.exports = Logger;\n\n/**\n * Enum for the supported log levels.\n */\nLogger.levels = {\n TRACE: \"trace\",\n DEBUG: \"debug\",\n INFO: \"info\",\n LOG: \"log\",\n WARN: \"warn\",\n ERROR: \"error\"\n};\n","/* eslint-disable */\n\n// Ofiginally: https://github.com/adtile/postis\n//\n// The MIT License\n// \n// Copyright (c) 2015-2015 Adtile Technologies Inc. http://www.adtile.me\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nfunction Postis(options) {\n var scope = options.scope;\n var targetWindow = options.window;\n var windowForEventListening = options.windowForEventListening || window;\n var allowedOrigin = options.allowedOrigin;\n var listeners = {};\n var sendBuffer = [];\n var listenBuffer = {};\n var ready = false;\n var readyMethod = \"__ready__\";\n var readynessCheck;\n\n var listener = function(event) {\n var data;\n try {\n data = JSON.parse(event.data);\n } catch (e) {\n return;\n }\n\n if (allowedOrigin && event.origin !== allowedOrigin) {\n return;\n }\n\n if (data.postis && data.scope === scope) {\n var listenersForMethod = listeners[data.method];\n if (listenersForMethod) {\n for (var i = 0; i < listenersForMethod.length; i++) {\n listenersForMethod[i].call(null, data.params);\n }\n } else {\n listenBuffer[data.method] = listenBuffer[data.method] || [];\n listenBuffer[data.method].push(data.params);\n }\n }\n };\n\n windowForEventListening.addEventListener(\"message\", listener, false);\n\n var postis = {\n listen: function (method, callback) {\n listeners[method] = listeners[method] || [];\n listeners[method].push(callback);\n\n var listenBufferForMethod = listenBuffer[method];\n if (listenBufferForMethod) {\n var listenersForMethod = listeners[method];\n for (var i = 0; i < listenersForMethod.length; i++) {\n for (var j = 0; j < listenBufferForMethod.length; j++) {\n listenersForMethod[i].call(null, listenBufferForMethod[j]);\n }\n }\n }\n delete listenBuffer[method];\n },\n\n send: function (opts) {\n var method = opts.method;\n\n if ((ready || opts.method === readyMethod) && (targetWindow && typeof targetWindow.postMessage === \"function\")) {\n targetWindow.postMessage(JSON.stringify({\n postis: true,\n scope: scope,\n method: method,\n params: opts.params\n }), \"*\");\n } else {\n sendBuffer.push(opts);\n }\n },\n\n ready: function (callback) {\n if (ready) {\n callback();\n } else {\n setTimeout(function () { postis.ready(callback); }, 50);\n }\n },\n\n destroy: function (callback) {\n clearInterval(readynessCheck);\n ready = false;\n if (windowForEventListening && typeof windowForEventListening.removeEventListener === \"function\") {\n windowForEventListening.removeEventListener(\"message\", listener);\n }\n callback && callback();\n }\n };\n\n var readyCheckID = +new Date() + Math.random() + \"\";\n\n readynessCheck = setInterval(function () {\n postis.send({\n method: readyMethod,\n params: readyCheckID\n });\n }, 50);\n\n postis.listen(readyMethod, function (id) {\n if (id === readyCheckID) {\n clearInterval(readynessCheck);\n ready = true;\n\n for (var i = 0; i < sendBuffer.length; i++) {\n postis.send(sendBuffer[i]);\n }\n sendBuffer = [];\n } else {\n postis.send({\n method: readyMethod,\n params: id\n });\n }\n });\n\n return postis;\n}\n\nmodule.exports = Postis;\n","/* Copyright @ 2015-present 8x8, Inc.\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 */\nvar Logger = require(\"./Logger\");\nvar LogCollector = require(\"./LogCollector\");\n\n/**\n * Definition of the log method\n * @name log_method\n * @function\n * @param {...*} log_args the arguments to be logged\n */\n/**\n * The logger's transport type definition.\n *\n * @typedef {object} LoggerTransport\n *\n * @property {log_method} trace method called to log on {@link Logger.levels.TRACE} logging level\n * @property {log_method} debug method called to log on {@link Logger.levels.DEBUG} logging level\n * @property {log_method} info method called to log on {@link Logger.levels.INFO} logging level\n * @property {log_method} log method called to log on {@link Logger.levels.LOG} logging level\n * @property {log_method} warn method called to log on {@link Logger.levels.WARN} logging level\n * @property {log_method} error method called to log on {@link Logger.levels.ERROR} logging level\n */\n\n/**\n * Map with the created loggers with ID.\n */\nvar idLoggers = {};\n\n/**\n * Array with the loggers without id.\n */\nvar loggers = [];\n\n/**\n * Log level for the lbrary.\n */\nvar curLevel = Logger.levels.TRACE;\n\n\nmodule.exports = {\n /**\n * Adds given {@link LoggerTransport} instance to the list of global\n * transports which means that it'll be used by all {@link Logger}s\n * @param {LoggerTransport} transport\n */\n addGlobalTransport: function(transport) {\n Logger.addGlobalTransport(transport);\n },\n /**\n * Removes given {@link LoggerTransport} instance from the list of global\n * transports\n * @param {LoggerTransport} transport\n */\n removeGlobalTransport: function(transport) {\n Logger.removeGlobalTransport(transport);\n },\n /**\n * Sets global options which will be used by all loggers. Changing these\n * works even after other loggers are created.\n */\n setGlobalOptions: function(options) {\n Logger.setGlobalOptions(options);\n },\n /**\n * Creates new logger.\n * @arguments the same as Logger constructor\n */\n getLogger: function(id, transports, options) {\n var logger = new Logger(curLevel, id, transports, options);\n if(id) {\n idLoggers[id] = idLoggers[id] || [];\n idLoggers[id].push(logger);\n } else {\n loggers.push(logger);\n }\n return logger;\n },\n /**\n * Changes the log level for the existing loggers by id.\n * @param level the new log level.\n * @param id if specified the level will be changed only for loggers with the\n * same id. Otherwise the operation will affect all loggers that don't\n * have id.\n */\n setLogLevelById: function(level, id) {\n var l = id? (idLoggers[id] || []) : loggers;\n for(var i = 0; i < l.length; i++) {\n l[i].setLevel(level);\n }\n },\n /**\n * Changes the log level for all existing loggers.\n * @param level the new log level.\n */\n setLogLevel: function (level) {\n curLevel = level;\n var i = 0;\n for(; i < loggers.length; i++) {\n loggers[i].setLevel(level);\n }\n\n for(var id in idLoggers) {\n var l = idLoggers[id] || [];\n for(i = 0; i < l.length; i++) {\n l[i].setLevel(level);\n }\n }\n },\n /**\n * The supported log levels.\n */\n levels: Logger.levels,\n /**\n * Exports the <tt>LogCollector</tt>.\n */\n LogCollector: LogCollector\n};\n","// For legacy purposes, preserve the UMD of the public API of Jitsi Meet\n// external API (a.k.a. JitsiMeetExternalAPI).\nmodule.exports = require('./external_api').default;\n","/* Copyright @ 2016-present 8x8, Inc.\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 */\nvar Logger = require('./Logger.js');\n\n/**\n * Creates new <tt>LogCollector</tt>. Class implements <tt>LoggerTransport</tt>\n * and thus can be added as global transport in order to capture all the logs.\n *\n * It captures subsequent log lines created whenever <tt>Logger</tt> logs\n * a message and stores them in a queue in order to batch log entries. There are\n * time and size limit constraints which determine how often batch entries are\n * stored. Whenever one of these limits is exceeded the <tt>LogCollector</tt>\n * will use the <tt>logStorage</tt> object given as an argument to save\n * the batch log entry.\n *\n * @param {Object} logStorage an object which allows to store the logs collected\n * @param {function(string|object[])} logStorage.storeLogs a method called when\n * this <tt>LogCollector</tt> requests log entry storage. The method's argument\n * is an array which can contain <tt>string</tt>s and <tt>object</tt>s. If given\n * item is an object it means that it's an aggregated message. That is a message\n * which is the same as the previous one and it's representation has\n * the following format:\n * {\n * {string} text: 'the text of some duplicated message'\n * {number} count: 3 // how many times the message appeared in a row\n * }\n * If a message \"B\" after an aggregated message \"A\" is different, then it breaks\n * the sequence of \"A\". Which means that even if the next message \"C\" is\n * the same as \"A\" it will start a new aggregated message \"C\".\n * @param {function()} logStorage.isReady a method which should return\n * a <tt>boolean</tt> to tell the collector that it's ready to store. During the\n * time storage is not ready log batches will be cached and stored on the next\n * occasion (flush or interval timeout).\n *\n * @param {Object} options the <tt>LogCollector</tt> configuration options.\n * @param {number} options.maxEntryLength the size limit for a single log entry\n * to be stored. The <tt>LogCollector</tt> will push the entry as soon as it\n * reaches or exceeds this limit given that <tt>logStorage.isReady</tt>\n * returns <tt>true</tt>. Otherwise the log entry will be cached until the log\n * storage becomes ready. Note that the \"is ready\" condition is checked every\n * <tt>options.storeInterval</tt> milliseconds.\n * @param {number} options.storeInterval how often the logs should be stored in\n * case <tt>maxEntryLength</tt> was not exceeded.\n * @param {boolean} options.stringifyObjects indicates whether or not object\n * arguments should be \"stringified\" with <tt>JSON.stringify</tt> when a log\n * message is composed. Note that objects logged on the error log level are\n * always stringified.\n *\n * @constructor\n */\nfunction LogCollector(logStorage, options) {\n this.logStorage = logStorage;\n this.stringifyObjects = options && options.stringifyObjects ? options.stringifyObjects : false;\n this.storeInterval = options && options.storeInterval ? options.storeInterval: 30000;\n this.maxEntryLength = options && options.maxEntryLength ? options.maxEntryLength : 10000;\n // Bind the log method for each level to the corresponding method name\n // in order to implement \"global log transport\" object.\n Object.keys(Logger.levels).forEach(\n function (logLevel) {\n var methodName = Logger.levels[logLevel];\n this[methodName] = function () {\n this._log.apply(this, arguments);\n }.bind(this, logLevel);\n }.bind(this));\n /**\n * The ID of store logs interval if one is currently scheduled or\n * <tt>null</tt> otherwise.\n * @type {number|null}\n */\n this.storeLogsIntervalID = null;\n /**\n * The log messages that are to be batched into log entry when\n * {@link LogCollector._flush} method is called.\n * @type {string[]}\n */\n this.queue = [];\n /**\n * The total length of all messages currently stored in the {@link queue}.\n * @type {number}\n */\n this.totalLen = 0;\n /**\n * An array used to temporarily store log batches, before the storage gets\n * ready.\n * @type {string[]}\n */\n this.outputCache = [];\n}\n\n/**\n * Method called inside of {@link formatLogMessage} in order to covert an\n * <tt>Object</tt> argument to string. The conversion will happen when either\n * 'stringifyObjects' option is enabled or on the {@link Logger.levels.ERROR}\n * log level. The default implementation uses <tt>JSON.stringify</tt> and\n * returns \"[object with circular refs?]\" instead of an object if it fails.\n *\n * @param {object} someObject the <tt>object</tt> to be stringified.\n *\n * @return {string} the result of <tt>JSON.stringify</tt> or\n * \"[object with circular refs?]\" if any error occurs during \"stringification\".\n *\n * @protected\n */\nLogCollector.prototype.stringify = function (someObject) {\n try {\n return JSON.stringify(someObject);\n } catch (error) {\n return '[object with circular refs?]';\n }\n};\n\n/**\n * Formats log entry for the given logging level and arguments passed to the\n * <tt>Logger</tt>'s log method. The first argument is log level and the next\n * arguments have to be captured using JS built-in 'arguments' variable.\n *\n * @param {Logger.levels} logLevel provides the logging level of the message to\n * be logged.\n * @param {Date} timestamp - The {@code Date} when a message has been logged.\n *\n * @return {string|null} a non-empty string representation of the log entry\n * crafted from the log arguments. If the return value is <tt>null</tt> then\n * the message wil be discarded by this <tt>LogCollector</tt>.\n *\n * @protected\n */\nLogCollector.prototype.formatLogMessage = function (\nlogLevel /* timestamp, arg2, arg3, arg4... */) {\n var msg = '';\n for (var i = 1, len = arguments.length; i < len; i++) {\n var arg = arguments[i];\n // objects logged on error level are always converted to JSON\n if ((this.stringifyObjects || logLevel === Logger.levels.ERROR) &&\n typeof arg === 'object') {\n arg = this.stringify(arg);\n }\n msg += arg;\n if (i !== len - 1) {\n msg += ' ';\n }\n }\n return msg.length ? msg : null;\n};\n\n/**\n * The log method bound to each of the logging levels in order to implement\n * \"global log transport\" object.\n *\n * @private\n */\nLogCollector.prototype._log = function() {\n\n // var logLevel = arguments[0]; first argument is the log level\n var timestamp = arguments[1];\n var msg = this.formatLogMessage.apply(this, arguments);\n if (msg) {\n // The same as the previous message aggregation logic\n var prevMessage = this.queue[this.queue.length - 1];\n var prevMessageText = prevMessage && prevMessage.text;\n if (prevMessageText === msg) {\n prevMessage.count += 1;\n } else {\n this.queue.push({\n text: msg,\n timestamp: timestamp,\n count: 1\n });\n this.totalLen += msg.length;\n }\n }\n\n if (this.totalLen >= this.maxEntryLength) {\n this._flush(true /* force */, true /* reschedule */);\n }\n};\n\n/**\n * Starts periodical \"store logs\" task which will be triggered at the interval\n * specified in the constructor options.\n */\nLogCollector.prototype.start = function () {\n this._reschedulePublishInterval();\n};\n\n/**\n * Reschedules the periodical \"store logs\" task which will store the next batch\n * log entry in the storage.\n * @private\n */\nLogCollector.prototype._reschedulePublishInterval = function () {\n if (this.storeLogsIntervalID) {\n window.clearTimeout(this.storeLogsIntervalID);\n this.storeLogsIntervalID = null;\n }\n // It's actually a timeout, because it is rescheduled on every flush\n this.storeLogsIntervalID = window.setTimeout(\n this._flush.bind(\n this, false /* do not force */, true /* reschedule */),\n this.storeInterval);\n};\n\n/**\n * Call this method to flush the log entry buffer and store it in the log\n * storage immediately (given that the storage is ready).\n */\nLogCollector.prototype.flush = function() {\n this._flush(\n false /* do not force, as it will not be stored anyway */,\n true /* reschedule next update */ );\n};\n\n/**\n * Stores the next batch log entry in the log storage.\n * @param {boolean} force enforce current logs batch to be stored or cached if\n * there is anything to be logged, but the storage is not ready yet. One of\n * legitimate reasons to force is when the logs length exceeds size limit which\n * could result in truncation.\n * @param {boolean} reschedule <tt>true</tt> if the next periodic task should be\n * scheduled after the log entry is stored. <tt>false</tt> will end the periodic\n * task cycle.\n * @private\n */\nLogCollector.prototype._flush = function(force, reschedule) {\n // Publish only if there's anything to be logged\n if (this.totalLen > 0 && (this.logStorage.isReady() || force)) {\n //FIXME avoid truncating\n // right now we don't care if the message size is \"slightly\" exceeded\n if (this.logStorage.isReady()) {\n // Sends all cached logs\n if (this.outputCache.length) {\n this.outputCache.forEach(\n function (cachedQueue) {\n this.logStorage.storeLogs(cachedQueue);\n }.bind(this)\n );\n // Clear the cache\n this.outputCache = [];\n }\n // Send current batch\n this.logStorage.storeLogs(this.queue);\n } else {\n this.outputCache.push(this.queue);\n }\n\n this.queue = [];\n this.totalLen = 0;\n }\n\n if (reschedule) {\n this._reschedulePublishInterval();\n }\n};\n\n/**\n * Stops the periodical \"store logs\" task and immediately stores any pending\n * log entries as a batch.\n */\nLogCollector.prototype.stop = function() {\n // Flush and stop publishing logs\n this._flush(false /* do not force */, false /* do not reschedule */);\n};\n\nmodule.exports = LogCollector;\n","import EventEmitter from 'events';\n\n/**\n * Dummy implementation of Storage interface.\n */\nclass DummyLocalStorage extends EventEmitter {\n\n /**\n * The object used for storage.\n */\n _storage = {};\n\n /**\n * Empties all keys out of the storage.\n *\n * @returns {void}\n */\n clear() {\n this._storage = {};\n }\n\n /**\n * Returns the number of data items stored in the Storage object.\n *\n * @returns {number} - The number of data items stored in the Storage object.\n */\n get length() {\n return Object.keys(this._storage).length;\n }\n\n /**\n * Will return that key's value associated to the passed key name.\n *\n * @param {string} keyName - The key name.\n * @returns {*} - The key value.\n */\n getItem(keyName) {\n return this._storage[keyName];\n }\n\n /**\n * When passed a key name and value, will add that key to the storage,\n * or update that key's value if it already exists.\n *\n * @param {string} keyName - The key name.\n * @param {*} keyValue - The key value.\n * @returns {void}\n */\n setItem(keyName, keyValue) {\n this._storage[keyName] = keyValue;\n }\n\n /**\n * When passed a key name, will remove that key from the storage.\n *\n * @param {string} keyName - The key name.\n * @returns {void}\n */\n removeItem(keyName) {\n delete this._storage[keyName];\n }\n\n /**\n * When passed a number n, this method will return the name of the nth key in the storage.\n *\n * @param {number} idx - The index of the key.\n * @returns {string} - The nth key name.\n */\n key(n) {\n const keys = Object.keys(this._storage);\n\n if (keys.length <= n) {\n return undefined;\n }\n\n return keys[n];\n }\n\n /**\n * Serializes the content of the storage.\n *\n * @returns {string} - The serialized content.\n */\n serialize() {\n return JSON.stringify(this._storage);\n }\n}\n\n/**\n * Wrapper class for browser's local storage object.\n */\nclass JitsiLocalStorage extends EventEmitter {\n /**\n * @constructor\n * @param {Storage} storage browser's local storage object.\n */\n constructor() {\n super();\n\n try {\n this._storage = window.localStorage;\n this._localStorageDisabled = false;\n } catch (ignore) {\n // localStorage throws an exception.\n }\n\n if (!this._storage) { // Handles the case when window.localStorage is undefined or throws an exception.\n console.warn('Local storage is disabled.');\n this._storage = new DummyLocalStorage();\n this._localStorageDisabled = true;\n }\n }\n\n /**\n * Returns true if window.localStorage is disabled and false otherwise.\n *\n * @returns {boolean} - True if window.localStorage is disabled and false otherwise.\n */\n isLocalStorageDisabled() {\n return this._localStorageDisabled;\n }\n\n /**\n * Empties all keys out of the storage.\n *\n * @returns {void}\n */\n clear() {\n this._storage.clear();\n this.emit('changed');\n }\n\n /**\n * Returns the number of data items stored in the Storage object.\n *\n * @returns {number} - The number of data items stored in the Storage object.\n */\n get length() {\n return this._storage.length;\n }\n\n /**\n * Returns that passed key's value.\n * @param {string} keyName the name of the key you want to retrieve\n * the value of.\n * @returns {String|null} the value of the key. If the key does not exist,\n * null is returned.\n */\n getItem(keyName) {\n return this._storage.getItem(keyName);\n }\n\n /**\n * Adds a key to the storage, or update key's value if it already exists.\n * @param {string} keyName - the name of the key you want to create/update.\n * @param {string} keyValue - the value you want to give the key you are\n * creating/updating.\n * @param {boolean} dontEmitChangedEvent - If true a changed event won't be emitted.\n */\n setItem(keyName, keyValue, dontEmitChangedEvent = false) {\n this._storage.setItem(keyName, keyValue);\n\n if (!dontEmitChangedEvent) {\n this.emit('changed');\n }\n }\n\n /**\n * Remove a key from the storage.\n * @param {string} keyName the name of the key you want to remove.\n */\n removeItem(keyName) {\n this._storage.removeItem(keyName);\n this.emit('changed');\n }\n\n /**\n * Returns the name of the nth key in the list, or null if n is greater\n * than or equal to the number of key/value pairs in the object.\n *\n * @param {number} i - The index of the key in the list.\n * @returns {string}\n */\n key(i) {\n return this._storage.key(i);\n }\n\n /**\n * Serializes the content of the storage.\n *\n * @returns {string} - The serialized content.\n */\n serialize() {\n if (this.isLocalStorageDisabled) {\n return this._storage.serialize();\n }\n\n const length = this._storage.length;\n const localStorageContent = {};\n\n for (let i = 0; i < length; i++) {\n const key = this._storage.key(i);\n\n localStorageContent[key] = this._storage.getItem(key);\n }\n\n return JSON.stringify(localStorageContent);\n }\n}\n\nexport const jitsiLocalStorage = new JitsiLocalStorage();\n","/* @flow */\n\nimport { reportError } from './helpers';\n\n/**\n * Parses the query/search or fragment/hash parameters out of a specific URL and\n * returns them as a JS object.\n *\n * @param {URL} url - The URL to parse.\n * @param {boolean} dontParse - If falsy, some transformations (for parsing the\n * value as JSON) will be executed.\n * @param {string} source - If {@code 'search'}, the parameters will parsed out\n * of {@code url.search}; otherwise, out of {@code url.hash}.\n * @returns {Object}\n */\nexport function parseURLParams(\n url: URL,\n dontParse: boolean = false,\n source: string = 'hash'): Object {\n const paramStr = source === 'search' ? url.search : url.hash;\n const params = {};\n const paramParts = (paramStr && paramStr.substr(1).split('&')) || [];\n\n // Detect and ignore hash params for hash routers.\n if (source === 'hash' && paramParts.length === 1) {\n const firstParam = paramParts[0];\n\n if (firstParam.startsWith('/') && firstParam.split('&').length === 1) {\n return params;\n }\n }\n\n paramParts.forEach(part => {\n const param = part.split('=');\n const key = param[0];\n\n if (!key) {\n return;\n }\n\n let value;\n\n try {\n value = param[1];\n\n if (!dontParse) {\n const decoded = decodeURIComponent(value).replace(/\\\\&/, '&');\n\n value = decoded === 'undefined' ? undefined : JSON.parse(decoded);\n }\n } catch (e) {\n reportError(\n e, `Failed to parse URL parameter value: ${String(value)}`);\n\n return;\n }\n params[key] = value;\n });\n\n return params;\n}\n","// @flow\n\n/**\n * A helper function that behaves similar to Object.assign, but only reassigns a\n * property in target if it's defined in source.\n *\n * @param {Object} target - The target object to assign the values into.\n * @param {Object} source - The source object.\n * @returns {Object}\n */\nexport function assignIfDefined(target: Object, source: Object) {\n const to = Object(target);\n\n for (const nextKey in source) {\n if (source.hasOwnProperty(nextKey)) {\n const value = source[nextKey];\n\n if (typeof value !== 'undefined') {\n to[nextKey] = value;\n }\n }\n }\n\n return to;\n}\n\n/**\n * Tries to copy a given text to the clipboard.\n * Returns true if the action succeeds.\n *\n * @param {string} textToCopy - Text to be copied.\n * @returns {boolean}\n */\nexport function copyText(textToCopy: string) {\n const fakeTextArea = document.createElement('textarea');\n let result;\n\n // $FlowFixMe\n document.body.appendChild(fakeTextArea);\n fakeTextArea.value = textToCopy;\n fakeTextArea.select();\n\n try {\n result = document.execCommand('copy');\n } catch (err) {\n result = false;\n }\n\n // $FlowFixMe\n document.body.removeChild(fakeTextArea);\n\n return result;\n}\n\n/**\n * Creates a deferred object.\n *\n * @returns {{promise, resolve, reject}}\n */\nexport function createDeferred(): Object {\n const deferred = {};\n\n deferred.promise = new Promise((resolve, reject) => {\n deferred.resolve = resolve;\n deferred.reject = reject;\n });\n\n return deferred;\n}\n\nconst MATCH_OPERATOR_REGEXP = /[|\\\\{}()[\\]^$+*?.-]/g;\n\n/**\n * Escape RegExp special characters.\n *\n * Based on https://github.com/sindresorhus/escape-string-regexp.\n *\n * @param {string} s - The regexp string to escape.\n * @returns {string}\n */\nexport function escapeRegexp(s: string) {\n if (typeof s !== 'string') {\n throw new TypeError('Expected a string');\n }\n\n return s.replace(MATCH_OPERATOR_REGEXP, '\\\\$&');\n}\n\n/**\n * Returns the base URL of the app.\n *\n * @param {Object} w - Window object to use instead of the built in one.\n * @returns {string}\n */\nexport function getBaseUrl(w: Object = window) {\n const doc = w.document;\n const base = doc.querySelector('base');\n\n if (base && base.href) {\n return base.href;\n }\n\n const { protocol, host } = w.location;\n\n return `${protocol}//${host}`;\n}\n\n/**\n * Returns the namespace for all global variables, functions, etc that we need.\n *\n * @returns {Object} The namespace.\n *\n * NOTE: After React-ifying everything this should be the only global.\n */\nexport function getJitsiMeetGlobalNS() {\n if (!window.JitsiMeetJS) {\n window.JitsiMeetJS = {};\n }\n\n if (!window.JitsiMeetJS.app) {\n window.JitsiMeetJS.app = {};\n }\n\n return window.JitsiMeetJS.app;\n}\n\n/**\n * Prints the error and reports it to the global error handler.\n *\n * @param {Error} e - The error object.\n * @param {string} msg - A custom message to print in addition to the error.\n * @returns {void}\n */\nexport function reportError(e: Object, msg: string = '') {\n console.error(msg, e);\n window.onerror && window.onerror(msg, null, null, null, e);\n}\n","// @flow\n\nimport { parseURLParams } from './parseURLParams';\nimport { normalizeNFKC } from './strings';\n\n/**\n * The app linking scheme.\n * TODO: This should be read from the manifest files later.\n */\nexport const APP_LINK_SCHEME = 'org.jitsi.meet:';\n\n/**\n * A list of characters to be excluded/removed from the room component/segment\n * of a conference/meeting URI/URL. The list is based on RFC 3986 and the jxmpp\n * library utilized by jicofo.\n */\nconst _ROOM_EXCLUDE_PATTERN = '[\\\\:\\\\?#\\\\[\\\\]@!$&\\'()*+,;=></\"]';\n\n/**\n * The {@link RegExp} pattern of the authority of a URI.\n *\n * @private\n * @type {string}\n */\nconst _URI_AUTHORITY_PATTERN = '(//[^/?#]+)';\n\n/**\n * The {@link RegExp} pattern of the path of a URI.\n *\n * @private\n * @type {string}\n */\nconst _URI_PATH_PATTERN = '([^?#]*)';\n\n/**\n * The {@link RegExp} pattern of the protocol of a URI.\n *\n * FIXME: The URL class exposed by JavaScript will not include the colon in\n * the protocol field. Also in other places (at the time of this writing:\n * the DeepLinkingMobilePage.js) the APP_LINK_SCHEME does not include\n * the double dots, so things are inconsistent.\n *\n * @type {string}\n */\nexport const URI_PROTOCOL_PATTERN = '^([a-z][a-z0-9\\\\.\\\\+-]*:)';\n\n/**\n * Excludes/removes certain characters from a specific room (name) which are\n * incompatible with Jitsi Meet on the client and/or server sides.\n *\n * @param {?string} room - The room (name) to fix.\n * @private\n * @returns {?string}\n */\nfunction _fixRoom(room: ?string) {\n return room\n ? room.replace(new RegExp(_ROOM_EXCLUDE_PATTERN, 'g'), '')\n : room;\n}\n\n/**\n * Fixes the scheme part of a specific URI (string) so that it contains a\n * well-known scheme such as HTTP(S). For example, the mobile app implements an\n * app-specific URI scheme in addition to Universal Links. The app-specific\n * scheme may precede or replace the well-known scheme. In such a case, dealing\n * with the app-specific scheme only complicates the logic and it is simpler to\n * get rid of it (by translating the app-specific scheme into a well-known\n * scheme).\n *\n * @param {string} uri - The URI (string) to fix the scheme of.\n * @private\n * @returns {string}\n */\nfunction _fixURIStringScheme(uri: string) {\n const regex = new RegExp(`${URI_PROTOCOL_PATTERN}+`, 'gi');\n const match: Array<string> | null = regex.exec(uri);\n\n if (match) {\n // As an implementation convenience, pick up the last scheme and make\n // sure that it is a well-known one.\n let protocol = match[match.length - 1].toLowerCase();\n\n if (protocol !== 'http:' && protocol !== 'https:') {\n protocol = 'https:';\n }\n\n /* eslint-disable no-param-reassign */\n\n uri = uri.substring(regex.lastIndex);\n if (uri.startsWith('//')) {\n // The specified URL was not a room name only, it contained an\n // authority.\n uri = protocol + uri;\n }\n\n /* eslint-enable no-param-reassign */\n }\n\n return uri;\n}\n\n/**\n * Converts a path to a backend-safe format, by splitting the path '/' processing each part.\n * Properly lowercased and url encoded.\n *\n * @param {string?} path - The path to convert.\n * @returns {string?}\n */\nexport function getBackendSafePath(path: ?string): ?string {\n if (!path) {\n return path;\n }\n\n return path\n .split('/')\n .map(getBackendSafeRoomName)\n .join('/');\n}\n\n/**\n * Converts a room name to a backend-safe format. Properly lowercased and url encoded.\n *\n * @param {string?} room - The room name to convert.\n * @returns {string?}\n */\nexport function getBackendSafeRoomName(room: ?string): ?string {\n if (!room) {\n return room;\n }\n\n /* eslint-disable no-param-reassign */\n try {\n // We do not know if we get an already encoded string at this point\n // as different platforms do it differently, but we need a decoded one\n // for sure. However since decoding a non-encoded string is a noop, we're safe\n // doing it here.\n room = decodeURIComponent(room);\n } catch (e) {\n // This can happen though if we get an unencoded string and it contains\n // some characters that look like an encoded entity, but it's not.\n // But in this case we're fine goin on...\n }\n\n // Normalize the character set.\n room = normalizeNFKC(room);\n\n // Only decoded and normalized strings can be lowercased properly.\n room = room.toLowerCase();\n\n // But we still need to (re)encode it.\n room = encodeURIComponent(room);\n /* eslint-enable no-param-reassign */\n\n // Unfortunately we still need to lowercase it, because encoding a string will\n // add some uppercase characters, but some backend services\n // expect it to be full lowercase. However lowercasing an encoded string\n // doesn't change the string value.\n return room.toLowerCase();\n}\n\n/**\n * Gets the (Web application) context root defined by a specific location (URI).\n *\n * @param {Object} location - The location (URI) which defines the (Web\n * application) context root.\n * @public\n * @returns {string} - The (Web application) context root defined by the\n * specified {@code location} (URI).\n */\nexport function getLocationContextRoot({ pathname }: { pathname: string }) {\n const contextRootEndIndex = pathname.lastIndexOf('/');\n\n return (\n contextRootEndIndex === -1\n ? '/'\n : pathname.substring(0, contextRootEndIndex + 1));\n}\n\n/**\n * Constructs a new {@code Array} with URL parameter {@code String}s out of a\n * specific {@code Object}.\n *\n * @param {Object} obj - The {@code Object} to turn into URL parameter\n * {@code String}s.\n * @returns {Array<string>} The {@code Array} with URL parameter {@code String}s\n * constructed out of the specified {@code obj}.\n */\nfunction _objectToURLParamsArray(obj = {}) {\n const params = [];\n\n for (const key in obj) { // eslint-disable-line guard-for-in\n try {\n params.push(\n `${key}=${encodeURIComponent(JSON.stringify(obj[key]))}`);\n } catch (e) {\n console.warn(`Error encoding ${key}: ${e}`);\n }\n }\n\n return params;\n}\n\n/**\n * Parses a specific URI string into an object with the well-known properties of\n * the {@link Location} and/or {@link URL} interfaces implemented by Web\n * browsers. The parsing attempts to be in accord with IETF's RFC 3986.\n *\n * @param {string} str - The URI string to parse.\n * @public\n * @returns {{\n * hash: string,\n * host: (string|undefined),\n * hostname: (string|undefined),\n * pathname: string,\n * port: (string|undefined),\n * protocol: (string|undefined),\n * search: string\n * }}\n */\nexport function parseStandardURIString(str: string) {\n /* eslint-disable no-param-reassign */\n\n const obj: Object = {\n toString: _standardURIToString\n };\n\n let regex;\n let match: Array<string> | null;\n\n // XXX A URI string as defined by RFC 3986 does not contain any whitespace.\n // Usually, a browser will have already encoded any whitespace. In order to\n // avoid potential later problems related to whitespace in URI, strip any\n // whitespace. Anyway, the Jitsi Meet app is not known to utilize unencoded\n // whitespace so the stripping is deemed safe.\n str = str.replace(/\\s/g, '');\n\n // protocol\n regex = new RegExp(URI_PROTOCOL_PATTERN, 'gi');\n match = regex.exec(str);\n if (match) {\n obj.protocol = match[1].toLowerCase();\n str = str.substring(regex.lastIndex);\n }\n\n // authority\n regex = new RegExp(`^${_URI_AUTHORITY_PATTERN}`, 'gi');\n match = regex.exec(str);\n if (match) {\n let authority: string = match[1].substring(/* // */ 2);\n\n str = str.substring(regex.lastIndex);\n\n // userinfo\n const userinfoEndIndex = authority.indexOf('@');\n\n if (userinfoEndIndex !== -1) {\n authority = authority.substring(userinfoEndIndex + 1);\n }\n\n obj.host = authority;\n\n // port\n const portBeginIndex = authority.lastIndexOf(':');\n\n if (portBeginIndex !== -1) {\n obj.port = authority.substring(portBeginIndex + 1);\n authority = authority.substring(0, portBeginIndex);\n }\n\n // hostname\n obj.hostname = authority;\n }\n\n // pathname\n regex = new RegExp(`^${_URI_PATH_PATTERN}`, 'gi');\n match = regex.exec(str);\n\n let pathname: ?string;\n\n if (match) {\n pathname = match[1];\n str = str.substring(regex.lastIndex);\n }\n if (pathname) {\n pathname.startsWith('/') || (pathname = `/${pathname}`);\n } else {\n pathname = '/';\n }\n obj.pathname = pathname;\n\n // query\n if (str.startsWith('?')) {\n let hashBeginIndex = str.indexOf('#', 1);\n\n if (hashBeginIndex === -1) {\n hashBeginIndex = str.length;\n }\n obj.search = str.substring(0, hashBeginIndex);\n str = str.substring(hashBeginIndex);\n } else {\n obj.search = ''; // Google Chrome\n }\n\n // fragment\n obj.hash = str.startsWith('#') ? str : '';\n\n /* eslint-enable no-param-reassign */\n\n return obj;\n}\n\n/**\n * Parses a specific URI which (supposedly) references a Jitsi Meet resource\n * (location).\n *\n * @param {(string|undefined)} uri - The URI to parse which (supposedly)\n * references a Jitsi Meet resource (location).\n * @public\n * @returns {{\n * contextRoot: string,\n * hash: string,\n * host: string,\n * hostname: string,\n * pathname: string,\n * port: string,\n * protocol: string,\n * room: (string|undefined),\n * search: string\n * }}\n */\nexport function parseURIString(uri: ?string) {\n if (typeof uri !== 'string') {\n return undefined;\n }\n\n const obj = parseStandardURIString(_fixURIStringScheme(uri));\n\n // Add the properties that are specific to a Jitsi Meet resource (location)\n // such as contextRoot, room:\n\n // contextRoot\n obj.contextRoot = getLocationContextRoot(obj);\n\n // The room (name) is the last component/segment of pathname.\n const { pathname } = obj;\n\n // XXX While the components/segments of pathname are URI encoded, Jitsi Meet\n // on the client and/or server sides still don't support certain characters.\n const contextRootEndIndex = pathname.lastIndexOf('/');\n let room = pathname.substring(contextRootEndIndex + 1) || undefined;\n\n if (room) {\n const fixedRoom = _fixRoom(room);\n\n if (fixedRoom !== room) {\n room = fixedRoom;\n\n // XXX Drive fixedRoom into pathname (because room is derived from\n // pathname).\n obj.pathname\n = pathname.substring(0, contextRootEndIndex + 1) + (room || '');\n }\n }\n obj.room = room;\n\n return obj;\n}\n\n/**\n * Implements {@code href} and {@code toString} for the {@code Object} returned\n * by {@link #parseStandardURIString}.\n *\n * @param {Object} [thiz] - An {@code Object} returned by\n * {@code #parseStandardURIString} if any; otherwise, it is presumed that the\n * function is invoked on such an instance.\n * @returns {string}\n */\nfunction _standardURIToString(thiz: ?Object) {\n // eslint-disable-next-line no-invalid-this\n const { hash, host, pathname, protocol, search } = thiz || this;\n let str = '';\n\n protocol && (str += protocol);\n\n // TODO userinfo\n\n host && (str += `//${host}`);\n str += pathname || '/';\n search && (str += search);\n hash && (str += hash);\n\n return str;\n}\n\n/**\n * Sometimes we receive strings that we don't know if already percent-encoded, or not, due to the\n * various sources we get URLs or room names. This function encapsulates the decoding in a safe way.\n *\n * @param {string} text - The text to decode.\n * @returns {string}\n */\nexport function safeDecodeURIComponent(text: string) {\n try {\n return decodeURIComponent(text);\n } catch (e) {\n // The text wasn't encoded.\n }\n\n return text;\n}\n\n/**\n * Attempts to return a {@code String} representation of a specific\n * {@code Object} which is supposed to represent a URL. Obviously, if a\n * {@code String} is specified, it is returned. If a {@code URL} is specified,\n * its {@code URL#href} is returned. Additionally, an {@code Object} similar to\n * the one accepted by the constructor of Web's ExternalAPI is supported on both\n * mobile/React Native and Web/React.\n *\n * @param {Object|string} obj - The URL to return a {@code String}\n * representation of.\n * @returns {string} - A {@code String} representation of the specified\n * {@code obj} which is supposed to represent a URL.\n */\nexport function toURLString(obj: ?(Object | string)): ?string {\n let str;\n\n switch (typeof obj) {\n case 'object':\n if (obj) {\n if (obj instanceof URL) {\n str = obj.href;\n } else {\n str = urlObjectToString(obj);\n }\n }\n break;\n\n case 'string':\n str = String(obj);\n break;\n }\n\n return str;\n}\n\n/**\n * Attempts to return a {@code String} representation of a specific\n * {@code Object} similar to the one accepted by the constructor\n * of Web's ExternalAPI.\n *\n * @param {Object} o - The URL to return a {@code String} representation of.\n * @returns {string} - A {@code String} representation of the specified\n * {@code Object}.\n */\nexport function urlObjectToString(o: Object): ?string {\n // First normalize the given url. It come as o.url or split into o.serverURL\n // and o.room.\n let tmp;\n\n if (o.serverURL && o.room) {\n tmp = new URL(o.room, o.serverURL).toString();\n } else if (o.room) {\n tmp = o.room;\n } else {\n tmp = o.url || '';\n }\n\n const url = parseStandardURIString(_fixURIStringScheme(tmp));\n\n // protocol\n if (!url.protocol) {\n let protocol: ?string = o.protocol || o.scheme;\n\n if (protocol) {\n // Protocol is supposed to be the scheme and the final ':'. Anyway,\n // do not make a fuss if the final ':' is not there.\n protocol.endsWith(':') || (protocol += ':');\n url.protocol = protocol;\n }\n }\n\n // authority & pathname\n let { pathname } = url;\n\n if (!url.host) {\n // Web's ExternalAPI domain\n //\n // It may be host/hostname and pathname with the latter denoting the\n // tenant.\n const domain: ?string = o.domain || o.host || o.hostname;\n\n if (domain) {\n const { host, hostname, pathname: contextRoot, port }\n = parseStandardURIString(\n\n // XXX The value of domain in supposed to be host/hostname\n // and, optionally, pathname. Make sure it is not taken for\n // a pathname only.\n _fixURIStringScheme(`${APP_LINK_SCHEME}//${domain}`));\n\n // authority\n if (host) {\n url.host = host;\n url.hostname = hostname;\n url.port = port;\n }\n\n // pathname\n pathname === '/' && contextRoot !== '/' && (pathname = contextRoot);\n }\n }\n\n // pathname\n\n // Web's ExternalAPI roomName\n const room = o.roomName || o.room;\n\n if (room\n && (url.pathname.endsWith('/')\n || !url.pathname.endsWith(`/${room}`))) {\n pathname.endsWith('/') || (pathname += '/');\n pathname += room;\n }\n\n url.pathname = pathname;\n\n // query/search\n\n // Web's ExternalAPI jwt\n const { jwt } = o;\n\n if (jwt) {\n let { search } = url;\n\n if (search.indexOf('?jwt=') === -1 && search.indexOf('&jwt=') === -1) {\n search.startsWith('?') || (search = `?${search}`);\n search.length === 1 || (search += '&');\n search += `jwt=${jwt}`;\n\n url.search = search;\n }\n }\n\n // fragment/hash\n\n let { hash } = url;\n\n for (const urlPrefix of [ 'config', 'interfaceConfig', 'devices', 'userInfo', 'appData' ]) {\n const urlParamsArray\n = _objectToURLParamsArray(\n o[`${urlPrefix}Overwrite`]\n || o[urlPrefix]\n || o[`${urlPrefix}Override`]);\n\n if (urlParamsArray.length) {\n let urlParamsString\n = `${urlPrefix}.${urlParamsArray.join(`&${urlPrefix}.`)}`;\n\n if (hash.length) {\n urlParamsString = `&${urlParamsString}`;\n } else {\n hash = '#';\n }\n hash += urlParamsString;\n }\n }\n\n url.hash = hash;\n\n return url.toString() || undefined;\n}\n\n/**\n * Adds hash params to URL.\n *\n * @param {URL} url - The URL.\n * @param {Object} hashParamsToAdd - A map with the parameters to be set.\n * @returns {URL} - The new URL.\n */\nexport function addHashParamsToURL(url: URL, hashParamsToAdd: Object = {}) {\n const params = parseURLParams(url);\n const urlParamsArray = _objectToURLParamsArray({\n ...params,\n ...hashParamsToAdd\n });\n\n if (urlParamsArray.length) {\n url.hash = `#${urlParamsArray.join('&')}`;\n }\n\n return url;\n}\n\n/**\n * Returns the decoded URI.\n *\n * @param {string} uri - The URI to decode.\n * @returns {string}\n */\nexport function getDecodedURI(uri: string) {\n return decodeURI(uri.replace(/^https?:\\/\\//i, ''));\n}\n","import Postis from './postis';\n\n/**\n * The default options for postis.\n *\n * @type {Object}\n */\nconst DEFAULT_POSTIS_OPTIONS = {\n window: window.opener || window.parent\n};\n\n/**\n * The postis method used for all messages.\n *\n * @type {string}\n */\nconst POSTIS_METHOD_NAME = 'message';\n\n/**\n * Implements message transport using the postMessage API.\n */\nexport default class PostMessageTransportBackend {\n /**\n * Creates new PostMessageTransportBackend instance.\n *\n * @param {Object} options - Optional parameters for configuration of the\n * transport.\n */\n constructor({ postisOptions } = {}) {\n // eslint-disable-next-line new-cap\n this.postis = Postis({\n ...DEFAULT_POSTIS_OPTIONS,\n ...postisOptions\n });\n\n this._receiveCallback = () => {\n // Do nothing until a callback is set by the consumer of\n // PostMessageTransportBackend via setReceiveCallback.\n };\n\n this.postis.listen(\n POSTIS_METHOD_NAME,\n message => this._receiveCallback(message));\n }\n\n /**\n * Disposes the allocated resources.\n *\n * @returns {void}\n */\n dispose() {\n this.postis.destroy();\n }\n\n /**\n * Sends the passed message.\n *\n * @param {Object} message - The message to be sent.\n * @returns {void}\n */\n send(message) {\n this.postis.send({\n method: POSTIS_METHOD_NAME,\n params: message\n });\n }\n\n /**\n * Sets the callback for receiving data.\n *\n * @param {Function} callback - The new callback.\n * @returns {void}\n */\n setReceiveCallback(callback) {\n this._receiveCallback = callback;\n }\n}\n","import {\n MESSAGE_TYPE_EVENT,\n MESSAGE_TYPE_REQUEST,\n MESSAGE_TYPE_RESPONSE\n} from './constants';\n\n/**\n* Stores the currnet transport backend that have to be used. Also implements\n* request/response mechanism.\n*/\nexport default class Transport {\n /**\n * Creates new instance.\n *\n * @param {Object} options - Optional parameters for configuration of the\n * transport backend.\n */\n constructor({ backend } = {}) {\n /**\n * Maps an event name and listener that have been added to the Transport\n * instance.\n *\n * @type {Map<string, Function>}\n */\n this._listeners = new Map();\n\n /**\n * The request ID counter used for the id property of the request. This\n * property is used to match the responses with the request.\n *\n * @type {number}\n */\n this._requestID = 0;\n\n /**\n * Maps an IDs of the requests and handlers that will process the\n * responses of those requests.\n *\n * @type {Map<number, Function>}\n */\n this._responseHandlers = new Map();\n\n /**\n * A set with the events and requests that were received but not\n * processed by any listener. They are later passed on every new\n * listener until they are processed.\n *\n * @type {Set<Object>}\n */\n this._unprocessedMessages = new Set();\n\n /**\n * Alias.\n */\n this.addListener = this.on;\n\n if (backend) {\n this.setBackend(backend);\n }\n }\n\n /**\n * Disposes the current transport backend.\n *\n * @returns {void}\n */\n _disposeBackend() {\n if (this._backend) {\n this._backend.dispose();\n this._backend = null;\n }\n }\n\n /**\n * Handles incoming messages from the transport backend.\n *\n * @param {Object} message - The message.\n * @returns {void}\n */\n _onMessageReceived(message) {\n if (message.type === MESSAGE_TYPE_RESPONSE) {\n const handler = this._responseHandlers.get(message.id);\n\n if (handler) {\n handler(message);\n this._responseHandlers.delete(message.id);\n }\n } else if (message.type === MESSAGE_TYPE_REQUEST) {\n this.emit('request', message.data, (result, error) => {\n this._backend.send({\n type: MESSAGE_TYPE_RESPONSE,\n error,\n id: message.id,\n result\n });\n });\n } else {\n this.emit('event', message.data);\n }\n }\n\n /**\n * Disposes the allocated resources.\n *\n * @returns {void}\n */\n dispose() {\n this._responseHandlers.clear();\n this._unprocessedMessages.clear();\n this.removeAllListeners();\n this._disposeBackend();\n }\n\n /**\n * Calls each of the listeners registered for the event named eventName, in\n * the order they were registered, passing the supplied arguments to each.\n *\n * @param {string} eventName - The name of the event.\n * @returns {boolean} True if the event has been processed by any listener,\n * false otherwise.\n */\n emit(eventName, ...args) {\n const listenersForEvent = this._listeners.get(eventName);\n let isProcessed = false;\n\n if (listenersForEvent && listenersForEvent.size) {\n listenersForEvent.forEach(listener => {\n isProcessed = listener(...args) || isProcessed;\n });\n }\n\n if (!isProcessed) {\n this._unprocessedMessages.add(args);\n }\n\n return isProcessed;\n }\n\n /**\n * Adds the listener function to the listeners collection for the event\n * named eventName.\n *\n * @param {string} eventName - The name of the event.\n * @param {Function} listener - The listener that will be added.\n * @returns {Transport} References to the instance of Transport class, so\n * that calls can be chained.\n */\n on(eventName, listener) {\n let listenersForEvent = this._listeners.get(eventName);\n\n if (!listenersForEvent) {\n listenersForEvent = new Set();\n this._listeners.set(eventName, listenersForEvent);\n }\n\n listenersForEvent.add(listener);\n\n this._unprocessedMessages.forEach(args => {\n if (listener(...args)) {\n this._unprocessedMessages.delete(args);\n }\n });\n\n return this;\n }\n\n /**\n * Removes all listeners, or those of the specified eventName.\n *\n * @param {string} [eventName] - The name of the event. If this parameter is\n * not specified all listeners will be removed.\n * @returns {Transport} References to the instance of Transport class, so\n * that calls can be chained.\n */\n removeAllListeners(eventName) {\n if (eventName) {\n this._listeners.delete(eventName);\n } else {\n this._listeners.clear();\n }\n\n return this;\n }\n\n /**\n * Removes the listener function from the listeners collection for the event\n * named eventName.\n *\n * @param {string} eventName - The name of the event.\n * @param {Function} listener - The listener that will be removed.\n * @returns {Transport} References to the instance of Transport class, so\n * that calls can be chained.\n */\n removeListener(eventName, listener) {\n const listenersForEvent = this._listeners.get(eventName);\n\n if (listenersForEvent) {\n listenersForEvent.delete(listener);\n }\n\n return this;\n }\n\n /**\n * Sends the passed event.\n *\n * @param {Object} event - The event to be sent.\n * @returns {void}\n */\n sendEvent(event = {}) {\n if (this._backend) {\n this._backend.send({\n type: MESSAGE_TYPE_EVENT,\n data: event\n });\n }\n }\n\n /**\n * Sending request.\n *\n * @param {Object} request - The request to be sent.\n * @returns {Promise}\n */\n sendRequest(request) {\n if (!this._backend) {\n return Promise.reject(new Error('No transport backend defined!'));\n }\n\n this._requestID++;\n\n const id = this._requestID;\n\n return new Promise((resolve, reject) => {\n this._responseHandlers.set(id, ({ error, result }) => {\n if (typeof result !== 'undefined') {\n resolve(result);\n\n // eslint-disable-next-line no-negated-condition\n } else if (typeof error !== 'undefined') {\n reject(error);\n } else { // no response\n reject(new Error('Unexpected response format!'));\n }\n });\n\n this._backend.send({\n type: MESSAGE_TYPE_REQUEST,\n data: request,\n id\n });\n });\n }\n\n /**\n * Changes the current backend transport.\n *\n * @param {Object} backend - The new transport backend that will be used.\n * @returns {void}\n */\n setBackend(backend) {\n this._disposeBackend();\n\n this._backend = backend;\n this._backend.setReceiveCallback(this._onMessageReceived.bind(this));\n }\n}\n","/**\n * The message type for events.\n *\n * @type {string}\n */\nexport const MESSAGE_TYPE_EVENT = 'event';\n\n/**\n * The message type for requests.\n *\n * @type {string}\n */\nexport const MESSAGE_TYPE_REQUEST = 'request';\n\n/**\n * The message type for responses.\n *\n * @type {string}\n */\nexport const MESSAGE_TYPE_RESPONSE = 'response';\n","// XXX The function parseURLParams is exported by the feature base/util (as\n// defined in the terminology of react/). However, this file is (very likely)\n// bundled in external_api in addition to app.bundle and, consequently, it is\n// best to import as little as possible here (rather than the whole feature\n// base/util) in order to minimize the amount of source code bundled into\n// multiple bundles.\nimport { parseURLParams } from '../../react/features/base/util/parseURLParams';\n\n/**\n * JitsiMeetExternalAPI id - unique for a webpage.\n */\nexport const API_ID = parseURLParams(window.location).jitsi_meet_external_api_id;\n\n/**\n * The payload name for the datachannel/endpoint text message event\n */\nexport const ENDPOINT_TEXT_MESSAGE_NAME = 'endpoint-text-message';\n","// FIXME: change to '../API' when we update to webpack2. If we do this now all\n// files from API modules will be included in external_api.js.\nimport { PostMessageTransportBackend, Transport } from '@jitsi/js-utils/transport';\n\nimport { getJitsiMeetGlobalNS } from '../../react/features/base/util';\nimport { API_ID } from '../API/constants';\n\n\nexport {\n PostMessageTransportBackend,\n Transport\n};\n\n/**\n * Option for the default low level transport.\n *\n * @type {Object}\n */\nconst postisOptions = {};\n\nif (typeof API_ID === 'number') {\n postisOptions.scope = `jitsi_meet_external_api_${API_ID}`;\n}\n\n/**\n * The instance of Transport class that will be used by Jitsi Meet.\n *\n * @type {Transport}\n */\nlet transport;\n\n/**\n * Returns the instance of Transport class that will be used by Jitsi Meet.\n *\n * @returns {Transport}\n */\nexport function getJitsiMeetTransport() {\n if (!transport) {\n transport = new Transport({ backend: new PostMessageTransportBackend({ postisOptions }) });\n }\n\n return transport;\n}\n\n/**\n * Sets the transport to passed transport.\n *\n * @param {Object} externalTransportBackend - The new transport.\n * @returns {void}\n */\ngetJitsiMeetGlobalNS().setExternalTransportBackend = externalTransportBackend =>\n transport.setBackend(externalTransportBackend);\n","import { jitsiLocalStorage } from '@jitsi/js-utils/jitsi-local-storage';\nimport EventEmitter from 'events';\n\nimport { urlObjectToString } from '../../../react/features/base/util/uri';\nimport {\n PostMessageTransportBackend,\n Transport\n} from '../../transport';\n\nimport electronPopupsConfig from './electronPopupsConfig.json';\nimport {\n getAvailableDevices,\n getCurrentDevices,\n isDeviceChangeAvailable,\n isDeviceListAvailable,\n isMultipleAudioInputSupported,\n setAudioInputDevice,\n setAudioOutputDevice,\n setVideoInputDevice\n} from './functions';\n\nconst ALWAYS_ON_TOP_FILENAMES = [\n 'css/all.css', 'libs/alwaysontop.min.js'\n];\n\n/**\n * Maps the names of the commands expected by the API with the name of the\n * commands expected by jitsi-meet\n */\nconst commands = {\n avatarUrl: 'avatar-url',\n displayName: 'display-name',\n e2eeKey: 'e2ee-key',\n email: 'email',\n toggleLobby: 'toggle-lobby',\n hangup: 'video-hangup',\n muteEveryone: 'mute-everyone',\n password: 'password',\n pinParticipant: 'pin-participant',\n resizeLargeVideo: 'resize-large-video',\n sendEndpointTextMessage: 'send-endpoint-text-message',\n sendTones: 'send-tones',\n setLargeVideoParticipant: 'set-large-video-participant',\n setVideoQuality: 'set-video-quality',\n startRecording: 'start-recording',\n stopRecording: 'stop-recording',\n subject: 'subject',\n submitFeedback: 'submit-feedback',\n toggleAudio: 'toggle-audio',\n toggleChat: 'toggle-chat',\n toggleFilmStrip: 'toggle-film-strip',\n toggleShareScreen: 'toggle-share-screen',\n toggleTileView: 'toggle-tile-view',\n toggleVideo: 'toggle-video'\n};\n\n/**\n * Maps the names of the events expected by the API with the name of the\n * events expected by jitsi-meet\n */\nconst events = {\n 'avatar-changed': 'avatarChanged',\n 'audio-availability-changed': 'audioAvailabilityChanged',\n 'audio-mute-status-changed': 'audioMuteStatusChanged',\n 'camera-error': 'cameraError',\n 'device-list-changed': 'deviceListChanged',\n 'display-name-change': 'displayNameChange',\n 'email-change': 'emailChange',\n 'endpoint-text-message-received': 'endpointTextMessageReceived',\n 'feedback-submitted': 'feedbackSubmitted',\n 'feedback-prompt-displayed': 'feedbackPromptDisplayed',\n 'filmstrip-display-changed': 'filmstripDisplayChanged',\n 'incoming-message': 'incomingMessage',\n 'log': 'log',\n 'mic-error': 'micError',\n 'outgoing-message': 'outgoingMessage',\n 'participant-joined': 'participantJoined',\n 'participant-kicked-out': 'participantKickedOut',\n 'participant-left': 'participantLeft',\n 'participant-role-changed': 'participantRoleChanged',\n 'password-required': 'passwordRequired',\n 'proxy-connection-event': 'proxyConnectionEvent',\n 'video-ready-to-close': 'readyToClose',\n 'video-conference-joined': 'videoConferenceJoined',\n 'video-conference-left': 'videoConferenceLeft',\n 'video-availability-changed': 'videoAvailabilityChanged',\n 'video-mute-status-changed': 'videoMuteStatusChanged',\n 'video-quality-changed': 'videoQualityChanged',\n 'screen-sharing-status-changed': 'screenSharingStatusChanged',\n 'dominant-speaker-changed': 'dominantSpeakerChanged',\n 'subject-change': 'subjectChange',\n 'suspend-detected': 'suspendDetected',\n 'tile-view-changed': 'tileViewChanged'\n};\n\n/**\n * Last id of api object\n * @type {number}\n */\nlet id = 0;\n\n/**\n * Adds given number to the numberOfParticipants property of given APIInstance.\n *\n * @param {JitsiMeetExternalAPI} APIInstance - The instance of the API.\n * @param {int} number - The number of participants to be added to\n * numberOfParticipants property (this parameter can be negative number if the\n * numberOfParticipants should be decreased).\n * @returns {void}\n */\nfunction changeParticipantNumber(APIInstance, number) {\n APIInstance._numberOfParticipants += number;\n}\n\n/**\n * Generates the URL for the iframe.\n *\n * @param {string} domain - The domain name of the server that hosts the\n * conference.\n * @param {string} [options] - Another optional parameters.\n * @param {Object} [options.configOverwrite] - Object containing configuration\n * options defined in config.js to be overridden.\n * @param {Object} [options.interfaceConfigOverwrite] - Object containing\n * configuration options defined in interface_config.js to be overridden.\n * @param {string} [options.jwt] - The JWT token if needed by jitsi-meet for\n * authentication.\n * @param {boolean} [options.noSSL] - If the value is true https won't be used.\n * @param {string} [options.roomName] - The name of the room to join.\n * @returns {string} The URL.\n */\nfunction generateURL(domain, options = {}) {\n return urlObjectToString({\n ...options,\n url:\n `${options.noSSL ? 'http' : 'https'}://${\n domain}/#jitsi_meet_external_api_id=${id}`\n });\n}\n\n/**\n * Parses the arguments passed to the constructor. If the old format is used\n * the function translates the arguments to the new format.\n *\n * @param {Array} args - The arguments to be parsed.\n * @returns {Object} JS object with properties.\n */\nfunction parseArguments(args) {\n if (!args.length) {\n return {};\n }\n\n const firstArg = args[0];\n\n switch (typeof firstArg) {\n case 'string': // old arguments format\n case undefined: {\n // Not sure which format but we are trying to parse the old\n // format because if the new format is used everything will be undefined\n // anyway.\n const [\n roomName,\n width,\n height,\n parentNode,\n configOverwrite,\n interfaceConfigOverwrite,\n noSSL,\n jwt,\n onload\n ] = args;\n\n return {\n roomName,\n width,\n height,\n parentNode,\n configOverwrite,\n interfaceConfigOverwrite,\n noSSL,\n jwt,\n onload\n };\n }\n case 'object': // new arguments format\n return args[0];\n default:\n throw new Error('Can\\'t parse the arguments!');\n }\n}\n\n/**\n * Compute valid values for height and width. If a number is specified it's\n * treated as pixel units. If the value is expressed in px, em, pt or\n * percentage, it's used as is.\n *\n * @param {any} value - The value to be parsed.\n * @returns {string|undefined} The parsed value that can be used for setting\n * sizes through the style property. If invalid value is passed the method\n * retuns undefined.\n */\nfunction parseSizeParam(value) {\n let parsedValue;\n\n // This regex parses values of the form 100px, 100em, 100pt or 100%.\n // Values like 100 or 100px are handled outside of the regex, and\n // invalid values will be ignored and the minimum will be used.\n const re = /([0-9]*\\.?[0-9]+)(em|pt|px|%)$/;\n\n if (typeof value === 'string' && String(value).match(re) !== null) {\n parsedValue = value;\n } else if (typeof value === 'number') {\n parsedValue = `${value}px`;\n }\n\n return parsedValue;\n}\n\n\n/**\n * The IFrame API interface class.\n */\nexport default class JitsiMeetExternalAPI extends EventEmitter {\n /**\n * Constructs new API instance. Creates iframe and loads Jitsi Meet in it.\n *\n * @param {string} domain - The domain name of the server that hosts the\n * conference.\n * @param {Object} [options] - Optional arguments.\n * @param {string} [options.roomName] - The name of the room to join.\n * @param {number|string} [options.width] - Width of the iframe. Check\n * parseSizeParam for format details.\n * @param {number|string} [options.height] - Height of the iframe. Check\n * parseSizeParam for format details.\n * @param {DOMElement} [options.parentNode] - The node that will contain the\n * iframe.\n * @param {Object} [options.configOverwrite] - Object containing\n * configuration options defined in config.js to be overridden.\n * @param {Object} [options.interfaceConfigOverwrite] - Object containing\n * configuration options defined in interface_config.js to be overridden.\n * @param {boolean} [options.noSSL] - If the value is true https won't be\n * used.\n * @param {string} [options.jwt] - The JWT token if needed by jitsi-meet for\n * authentication.\n * @param {string} [options.onload] - The onload function that will listen\n * for iframe onload event.\n * @param {Array<Object>} [options.invitees] - Array of objects containing\n * information about new participants that will be invited in the call.\n * @param {Array<Object>} [options.devices] - Array of objects containing\n * information about the initial devices that will be used in the call.\n * @param {Object} [options.userInfo] - Object containing information about\n * the participant opening the meeting.\n * @param {string} [options.e2eeKey] - The key used for End-to-End encryption.\n * THIS IS EXPERIMENTAL.\n */\n constructor(domain, ...args) {\n super();\n const {\n roomName = '',\n width = '100%',\n height = '100%',\n parentNode = document.body,\n configOverwrite = {},\n interfaceConfigOverwrite = {},\n noSSL = false,\n jwt = undefined,\n onload = undefined,\n invitees,\n devices,\n userInfo,\n e2eeKey\n } = parseArguments(args);\n const localStorageContent = jitsiLocalStorage.getItem('jitsiLocalStorage');\n\n this._parentNode = parentNode;\n this._url = generateURL(domain, {\n configOverwrite,\n interfaceConfigOverwrite,\n jwt,\n noSSL,\n roomName,\n devices,\n userInfo,\n appData: {\n localStorageContent\n }\n });\n this._createIFrame(height, width, onload);\n this._transport = new Transport({\n backend: new PostMessageTransportBackend({\n postisOptions: {\n allowedOrigin: new URL(this._url).origin,\n scope: `jitsi_meet_external_api_${id}`,\n window: this._frame.contentWindow\n }\n })\n });\n if (Array.isArray(invitees) && invitees.length > 0) {\n this.invite(invitees);\n }\n this._tmpE2EEKey = e2eeKey;\n this._isLargeVideoVisible = true;\n this._numberOfParticipants = 0;\n this._participants = {};\n this._myUserID = undefined;\n this._onStageParticipant = undefined;\n this._setupListeners();\n id++;\n }\n\n /**\n * Creates the iframe element.\n *\n * @param {number|string} height - The height of the iframe. Check\n * parseSizeParam for format details.\n * @param {number|string} width - The with of the iframe. Check\n * parseSizeParam for format details.\n * @param {Function} onload - The function that will listen\n * for onload event.\n * @returns {void}\n *\n * @private\n */\n _createIFrame(height, width, onload) {\n const frameName = `jitsiConferenceFrame${id}`;\n\n this._frame = document.createElement('iframe');\n this._frame.allow = 'camera; microphone; display-capture';\n this._frame.src = this._url;\n this._frame.name = frameName;\n this._frame.id = frameName;\n this._setSize(height, width);\n this._frame.setAttribute('allowFullScreen', 'true');\n this._frame.style.border = 0;\n\n if (onload) {\n // waits for iframe resources to load\n // and fires event when it is done\n this._frame.onload = onload;\n }\n\n this._frame = this._parentNode.appendChild(this._frame);\n }\n\n /**\n * Returns arrays with the all resources for the always on top feature.\n *\n * @returns {Array<string>}\n */\n _getAlwaysOnTopResources() {\n const iframeWindow = this._frame.contentWindow;\n const iframeDocument = iframeWindow.document;\n let baseURL = '';\n const base = iframeDocument.querySelector('base');\n\n if (base && base.href) {\n baseURL = base.href;\n } else {\n const { protocol, host } = iframeWindow.location;\n\n baseURL = `${protocol}//${host}`;\n }\n\n return ALWAYS_ON_TOP_FILENAMES.map(\n filename => (new URL(filename, baseURL)).href\n );\n }\n\n /**\n * Returns the formatted display name of a participant.\n *\n * @param {string} participantId - The id of the participant.\n * @returns {string} The formatted display name.\n */\n _getFormattedDisplayName(participantId) {\n const { formattedDisplayName }\n = this._participants[participantId] || {};\n\n return formattedDisplayName;\n }\n\n /**\n * Returns the id of the on stage participant.\n *\n * @returns {string} - The id of the on stage participant.\n */\n _getOnStageParticipant() {\n return this._onStageParticipant;\n }\n\n\n /**\n * Getter for the large video element in Jitsi Meet.\n *\n * @returns {HTMLElement|undefined} - The large video.\n */\n _getLargeVideo() {\n const iframe = this.getIFrame();\n\n if (!this._isLargeVideoVisible\n || !iframe\n || !iframe.contentWindow\n || !iframe.contentWindow.document) {\n return;\n }\n\n return iframe.contentWindow.document.getElementById('largeVideo');\n }\n\n /**\n * Getter for participant specific video element in Jitsi Meet.\n *\n * @param {string|undefined} participantId - Id of participant to return the video for.\n *\n * @returns {HTMLElement|undefined} - The requested video. Will return the local video\n * by default if participantId is undefined.\n */\n _getParticipantVideo(participantId) {\n const iframe = this.getIFrame();\n\n if (!iframe\n || !iframe.contentWindow\n || !iframe.contentWindow.document) {\n return;\n }\n\n if (typeof participantId === 'undefined' || participantId === this._myUserID) {\n return iframe.contentWindow.document.getElementById('localVideo_container');\n }\n\n return iframe.contentWindow.document.querySelector(`#participant_${participantId} video`);\n }\n\n /**\n * Sets the size of the iframe element.\n *\n * @param {number|string} height - The height of the iframe.\n * @param {number|string} width - The with of the iframe.\n * @returns {void}\n *\n * @private\n */\n _setSize(height, width) {\n const parsedHeight = parseSizeParam(height);\n const parsedWidth = parseSizeParam(width);\n\n if (parsedHeight !== undefined) {\n this._height = height;\n this._frame.style.height = parsedHeight;\n }\n\n if (parsedWidth !== undefined) {\n this._width = width;\n this._frame.style.width = parsedWidth;\n }\n }\n\n /**\n * Setups listeners that are used internally for JitsiMeetExternalAPI.\n *\n * @returns {void}\n *\n * @private\n */\n _setupListeners() {\n this._transport.on('event', ({ name, ...data }) => {\n const userID = data.id;\n\n switch (name) {\n case 'video-conference-joined': {\n if (typeof this._tmpE2EEKey !== 'undefined') {\n this.executeCommand(commands.e2eeKey, this._tmpE2EEKey);\n this._tmpE2EEKey = undefined;\n }\n\n this._myUserID = userID;\n this._participants[userID] = {\n avatarURL: data.avatarURL\n };\n }\n\n // eslint-disable-next-line no-fallthrough\n case 'participant-joined': {\n this._participants[userID] = this._participants[userID] || {};\n this._participants[userID].displayName = data.displayName;\n this._participants[userID].formattedDisplayName\n = data.formattedDisplayName;\n changeParticipantNumber(this, 1);\n break;\n }\n case 'participant-left':\n changeParticipantNumber(this, -1);\n delete this._participants[userID];\n break;\n case 'display-name-change': {\n const user = this._participants[userID];\n\n if (user) {\n user.displayName = data.displayname;\n user.formattedDisplayName = data.formattedDisplayName;\n }\n break;\n }\n case 'email-change': {\n const user = this._participants[userID];\n\n if (user) {\n user.email = data.email;\n }\n break;\n }\n case 'avatar-changed': {\n const user = this._participants[userID];\n\n if (user) {\n user.avatarURL = data.avatarURL;\n }\n break;\n }\n case 'on-stage-participant-changed':\n this._onStageParticipant = userID;\n this.emit('largeVideoChanged');\n break;\n case 'large-video-visibility-changed':\n this._isLargeVideoVisible = data.isVisible;\n this.emit('largeVideoChanged');\n break;\n case 'video-conference-left':\n changeParticipantNumber(this, -1);\n delete this._participants[this._myUserID];\n break;\n case 'video-quality-changed':\n this._videoQuality = data.videoQuality;\n break;\n case 'local-storage-changed':\n jitsiLocalStorage.setItem('jitsiLocalStorage', data.localStorageContent);\n\n // Since this is internal event we don't need to emit it to the consumer of the API.\n return true;\n }\n\n const eventName = events[name];\n\n if (eventName) {\n this.emit(eventName, data);\n\n return true;\n }\n\n return false;\n });\n }\n\n /**\n * Adds event listener to Meet Jitsi.\n *\n * @param {string} event - The name of the event.\n * @param {Function} listener - The listener.\n * @returns {void}\n *\n * @deprecated\n * NOTE: This method is not removed for backward comatability purposes.\n */\n addEventListener(event, listener) {\n this.on(event, listener);\n }\n\n /**\n * Adds event listeners to Meet Jitsi.\n *\n * @param {Object} listeners - The object key should be the name of\n * the event and value - the listener.\n * Currently we support the following\n * events:\n * {@code log} - receives event notifications whenever information has\n * been logged and has a log level specified within {@code config.apiLogLevels}.\n * The listener will receive object with the following structure:\n * {{\n * logLevel: the message log level\n * arguments: an array of strings that compose the actual log message\n * }}\n * {@code incomingMessage} - receives event notifications about incoming\n * messages. The listener will receive object with the following structure:\n * {{\n * 'from': from,//JID of the user that sent the message\n * 'nick': nick,//the nickname of the user that sent the message\n * 'message': txt//the text of the message\n * }}\n * {@code outgoingMessage} - receives event notifications about outgoing\n * messages. The listener will receive object with the following structure:\n * {{\n * 'message': txt//the text of the message\n * }}\n * {@code displayNameChanged} - receives event notifications about display\n * name change. The listener will receive object with the following\n * structure:\n * {{\n * jid: jid,//the JID of the participant that changed his display name\n * displayname: displayName //the new display name\n * }}\n * {@code participantJoined} - receives event notifications about new\n * participant.\n * The listener will receive object with the following structure:\n * {{\n * jid: jid //the jid of the participant\n * }}\n * {@code participantLeft} - receives event notifications about the\n * participant that left the room.\n * The listener will receive object with the following structure:\n * {{\n * jid: jid //the jid of the participant\n * }}\n * {@code videoConferenceJoined} - receives event notifications about the\n * local user has successfully joined the video conference.\n * The listener will receive object with the following structure:\n * {{\n * roomName: room //the room name of the conference\n * }}\n * {@code videoConferenceLeft} - receives event notifications about the\n * local user has left the video conference.\n * The listener will receive object with the following structure:\n * {{\n * roomName: room //the room name of the conference\n * }}\n * {@code screenSharingStatusChanged} - receives event notifications about\n * turning on/off the local user screen sharing.\n * The listener will receive object with the following structure:\n * {{\n * on: on //whether screen sharing is on\n * }}\n * {@code dominantSpeakerChanged} - receives event notifications about\n * change in the dominant speaker.\n * The listener will receive object with the following structure:\n * {{\n * id: participantId //participantId of the new dominant speaker\n * }}\n * {@code suspendDetected} - receives event notifications about detecting suspend event in host computer.\n * {@code readyToClose} - all hangup operations are completed and Jitsi Meet\n * is ready to be disposed.\n * @returns {void}\n *\n * @deprecated\n * NOTE: This method is not removed for backward comatability purposes.\n */\n addEventListeners(listeners) {\n for (const event in listeners) { // eslint-disable-line guard-for-in\n this.addEventListener(event, listeners[event]);\n }\n }\n\n /**\n * Captures the screenshot of the large video.\n *\n * @returns {Promise<string>} - Resolves with a base64 encoded image data of the screenshot\n * if large video is detected, an error otherwise.\n */\n captureLargeVideoScreenshot() {\n return this._transport.sendRequest({\n name: 'capture-largevideo-screenshot'\n });\n }\n\n /**\n * Removes the listeners and removes the Jitsi Meet frame.\n *\n * @returns {void}\n */\n dispose() {\n this.emit('_willDispose');\n this._transport.dispose();\n this.removeAllListeners();\n if (this._frame && this._frame.parentNode) {\n this._frame.parentNode.removeChild(this._frame);\n }\n }\n\n /**\n * Executes command. The available commands are:\n * {@code displayName} - Sets the display name of the local participant to\n * the value passed in the arguments array.\n * {@code subject} - Sets the subject of the conference, the value passed\n * in the arguments array. Note: Available only for moderator.\n *\n * {@code toggleAudio} - Mutes / unmutes audio with no arguments.\n * {@code toggleVideo} - Mutes / unmutes video with no arguments.\n * {@code toggleFilmStrip} - Hides / shows the filmstrip with no arguments.\n *\n * If the command doesn't require any arguments the parameter should be set\n * to empty array or it may be omitted.\n *\n * @param {string} name - The name of the command.\n * @returns {void}\n */\n executeCommand(name, ...args) {\n if (!(name in commands)) {\n console.error('Not supported command name.');\n\n return;\n }\n this._transport.sendEvent({\n data: args,\n name: commands[name]\n });\n }\n\n /**\n * Executes commands. The available commands are:\n * {@code displayName} - Sets the display name of the local participant to\n * the value passed in the arguments array.\n * {@code toggleAudio} - Mutes / unmutes audio. No arguments.\n * {@code toggleVideo} - Mutes / unmutes video. No arguments.\n * {@code toggleFilmStrip} - Hides / shows the filmstrip. No arguments.\n * {@code toggleChat} - Hides / shows chat. No arguments.\n * {@code toggleShareScreen} - Starts / stops screen sharing. No arguments.\n *\n * @param {Object} commandList - The object with commands to be executed.\n * The keys of the object are the commands that will be executed and the\n * values are the arguments for the command.\n * @returns {void}\n */\n executeCommands(commandList) {\n for (const key in commandList) { // eslint-disable-line guard-for-in\n this.executeCommand(key, commandList[key]);\n }\n }\n\n /**\n * Returns Promise that resolves with a list of available devices.\n *\n * @returns {Promise}\n */\n getAvailableDevices() {\n return getAvailableDevices(this._transport);\n }\n\n /**\n * Returns Promise that resolves with current selected devices.\n *\n * @returns {Promise}\n */\n getCurrentDevices() {\n return getCurrentDevices(this._transport);\n }\n\n /**\n * Returns the conference participants information.\n *\n * @returns {Array<Object>} - Returns an array containing participants\n * information like participant id, display name, avatar URL and email.\n */\n getParticipantsInfo() {\n const participantIds = Object.keys(this._participants);\n const participantsInfo = Object.values(this._participants);\n\n participantsInfo.forEach((participant, idx) => {\n participant.participantId = participantIds[idx];\n });\n\n return participantsInfo;\n }\n\n /**\n * Returns the current video quality setting.\n *\n * @returns {number}\n */\n getVideoQuality() {\n return this._videoQuality;\n }\n\n /**\n * Check if the audio is available.\n *\n * @returns {Promise} - Resolves with true if the audio available, with\n * false if not and rejects on failure.\n */\n isAudioAvailable() {\n return this._transport.sendRequest({\n name: 'is-audio-available'\n });\n }\n\n /**\n * Returns Promise that resolves with true if the device change is available\n * and with false if not.\n *\n * @param {string} [deviceType] - Values - 'output', 'input' or undefined.\n * Default - 'input'.\n * @returns {Promise}\n */\n isDeviceChangeAvailable(deviceType) {\n return isDeviceChangeAvailable(this._transport, deviceType);\n }\n\n /**\n * Returns Promise that resolves with true if the device list is available\n * and with false if not.\n *\n * @returns {Promise}\n */\n isDeviceListAvailable() {\n return isDeviceListAvailable(this._transport);\n }\n\n /**\n * Returns Promise that resolves with true if multiple audio input is supported\n * and with false if not.\n *\n * @returns {Promise}\n */\n isMultipleAudioInputSupported() {\n return isMultipleAudioInputSupported(this._transport);\n }\n\n /**\n * Invite people to the call.\n *\n * @param {Array<Object>} invitees - The invitees.\n * @returns {Promise} - Resolves on success and rejects on failure.\n */\n invite(invitees) {\n if (!Array.isArray(invitees) || invitees.length === 0) {\n return Promise.reject(new TypeError('Invalid Argument'));\n }\n\n return this._transport.sendRequest({\n name: 'invite',\n invitees\n });\n }\n\n /**\n * Returns the audio mute status.\n *\n * @returns {Promise} - Resolves with the audio mute status and rejects on\n * failure.\n */\n isAudioMuted() {\n return this._transport.sendRequest({\n name: 'is-audio-muted'\n });\n }\n\n /**\n * Returns screen sharing status.\n *\n * @returns {Promise} - Resolves with screensharing status and rejects on failure.\n */\n isSharingScreen() {\n return this._transport.sendRequest({\n name: 'is-sharing-screen'\n });\n }\n\n /**\n * Returns the avatar URL of a participant.\n *\n * @param {string} participantId - The id of the participant.\n * @returns {string} The avatar URL.\n */\n getAvatarURL(participantId) {\n const { avatarURL } = this._participants[participantId] || {};\n\n return avatarURL;\n }\n\n /**\n * Returns the display name of a participant.\n *\n * @param {string} participantId - The id of the participant.\n * @returns {string} The display name.\n */\n getDisplayName(participantId) {\n const { displayName } = this._participants[participantId] || {};\n\n return displayName;\n }\n\n /**\n * Returns the email of a participant.\n *\n * @param {string} participantId - The id of the participant.\n * @returns {string} The email.\n */\n getEmail(participantId) {\n const { email } = this._participants[participantId] || {};\n\n return email;\n }\n\n /**\n * Returns the iframe that loads Jitsi Meet.\n *\n * @returns {HTMLElement} The iframe.\n */\n getIFrame() {\n return this._frame;\n }\n\n /**\n * Returns the number of participants in the conference. The local\n * participant is included.\n *\n * @returns {int} The number of participants in the conference.\n */\n getNumberOfParticipants() {\n return this._numberOfParticipants;\n }\n\n /**\n * Check if the video is available.\n *\n * @returns {Promise} - Resolves with true if the video available, with\n * false if not and rejects on failure.\n */\n isVideoAvailable() {\n return this._transport.sendRequest({\n name: 'is-video-available'\n });\n }\n\n /**\n * Returns the audio mute status.\n *\n * @returns {Promise} - Resolves with the audio mute status and rejects on\n * failure.\n */\n isVideoMuted() {\n return this._transport.sendRequest({\n name: 'is-video-muted'\n });\n }\n\n /**\n * Pins a participant's video on to the stage view.\n *\n * @param {string} participantId - Participant id (JID) of the participant\n * that needs to be pinned on the stage view.\n * @returns {void}\n */\n pinParticipant(participantId) {\n this.executeCommand('pinParticipant', participantId);\n }\n\n /**\n * Removes event listener.\n *\n * @param {string} event - The name of the event.\n * @returns {void}\n *\n * @deprecated\n * NOTE: This method is not removed for backward comatability purposes.\n */\n removeEventListener(event) {\n this.removeAllListeners(event);\n }\n\n /**\n * Removes event listeners.\n *\n * @param {Array<string>} eventList - Array with the names of the events.\n * @returns {void}\n *\n * @deprecated\n * NOTE: This method is not removed for backward comatability purposes.\n */\n removeEventListeners(eventList) {\n eventList.forEach(event => this.removeEventListener(event));\n }\n\n /**\n * Resizes the large video container as per the dimensions provided.\n *\n * @param {number} width - Width that needs to be applied on the large video container.\n * @param {number} height - Height that needs to be applied on the large video container.\n * @returns {void}\n */\n resizeLargeVideo(width, height) {\n if (width <= this._width && height <= this._height) {\n this.executeCommand('resizeLargeVideo', width, height);\n }\n }\n\n /**\n * Passes an event along to the local conference participant to establish\n * or update a direct peer connection. This is currently used for developing\n * wireless screensharing with room integration and it is advised against to\n * use as its api may change.\n *\n * @param {Object} event - An object with information to pass along.\n * @param {Object} event.data - The payload of the event.\n * @param {string} event.from - The jid of the sender of the event. Needed\n * when a reply is to be sent regarding the event.\n * @returns {void}\n */\n sendProxyConnectionEvent(event) {\n this._transport.sendEvent({\n data: [ event ],\n name: 'proxy-connection-event'\n });\n }\n\n /**\n * Sets the audio input device to the one with the label or id that is\n * passed.\n *\n * @param {string} label - The label of the new device.\n * @param {string} deviceId - The id of the new device.\n * @returns {Promise}\n */\n setAudioInputDevice(label, deviceId) {\n return setAudioInputDevice(this._transport, label, deviceId);\n }\n\n /**\n * Sets the audio output device to the one with the label or id that is\n * passed.\n *\n * @param {string} label - The label of the new device.\n * @param {string} deviceId - The id of the new device.\n * @returns {Promise}\n */\n setAudioOutputDevice(label, deviceId) {\n return setAudioOutputDevice(this._transport, label, deviceId);\n }\n\n /**\n * Displays the given participant on the large video. If no participant id is specified,\n * dominant and pinned speakers will be taken into consideration while selecting the\n * the large video participant.\n *\n * @param {string} participantId - Jid of the participant to be displayed on the large video.\n * @returns {void}\n */\n setLargeVideoParticipant(participantId) {\n this.executeCommand('setLargeVideoParticipant', participantId);\n }\n\n /**\n * Sets the video input device to the one with the label or id that is\n * passed.\n *\n * @param {string} label - The label of the new device.\n * @param {string} deviceId - The id of the new device.\n * @returns {Promise}\n */\n setVideoInputDevice(label, deviceId) {\n return setVideoInputDevice(this._transport, label, deviceId);\n }\n\n /**\n * Returns the configuration for electron for the windows that are open\n * from Jitsi Meet.\n *\n * @returns {Promise<Object>}\n *\n * NOTE: For internal use only.\n */\n _getElectronPopupsConfig() {\n return Promise.resolve(electronPopupsConfig);\n }\n}\n"],"sourceRoot":""}