diff --git "a/src/app/static/assets/js/adapter-latest.js" "b/src/app/static/assets/js/adapter-latest.js" new file mode 100644--- /dev/null +++ "b/src/app/static/assets/js/adapter-latest.js" @@ -0,0 +1,5820 @@ +(function (f) { + if (typeof exports === "object" && typeof module !== "undefined") { + module.exports = f(); + } else if (typeof define === "function" && define.amd) { + define([], f); + } else { + var g; + if (typeof window !== "undefined") { + g = window; + } else if (typeof global !== "undefined") { + g = global; + } else if (typeof self !== "undefined") { + g = self; + } else { + g = this; + } + g.adapter = f(); + } +})(function () { + var define, module, exports; + return (function () { + function r(e, n, t) { + function o(i, f) { + if (!n[i]) { + if (!e[i]) { + var c = "function" == typeof require && require; + if (!f && c) return c(i, !0); + if (u) return u(i, !0); + var a = new Error("Cannot find module '" + i + "'"); + throw ((a.code = "MODULE_NOT_FOUND"), a); + } + var p = (n[i] = { exports: {} }); + e[i][0].call( + p.exports, + function (r) { + var n = e[i][1][r]; + return o(n || r); + }, + p, + p.exports, + r, + e, + n, + t + ); + } + return n[i].exports; + } + for ( + var u = "function" == typeof require && require, i = 0; + i < t.length; + i++ + ) + o(t[i]); + return o; + } + return r; + })()( + { + 1: [ + function (require, module, exports) { + /* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. + */ + /* eslint-env node */ + + "use strict"; + + var _adapter_factory = require("./adapter_factory.js"); + + var adapter = (0, _adapter_factory.adapterFactory)({ + window: + typeof window === "undefined" ? undefined : window, + }); + module.exports = adapter; // this is the difference from adapter_core. + }, + { "./adapter_factory.js": 2 }, + ], + 2: [ + function (require, module, exports) { + "use strict"; + + Object.defineProperty(exports, "__esModule", { + value: true, + }); + exports.adapterFactory = adapterFactory; + + var _utils = require("./utils"); + + var utils = _interopRequireWildcard(_utils); + + var _chrome_shim = require("./chrome/chrome_shim"); + + var chromeShim = _interopRequireWildcard(_chrome_shim); + + var _firefox_shim = require("./firefox/firefox_shim"); + + var firefoxShim = _interopRequireWildcard(_firefox_shim); + + var _safari_shim = require("./safari/safari_shim"); + + var safariShim = _interopRequireWildcard(_safari_shim); + + var _common_shim = require("./common_shim"); + + var commonShim = _interopRequireWildcard(_common_shim); + + var _sdp = require("sdp"); + + var sdp = _interopRequireWildcard(_sdp); + + function _interopRequireWildcard(obj) { + if (obj && obj.__esModule) { + return obj; + } else { + var newObj = {}; + if (obj != null) { + for (var key in obj) { + if ( + Object.prototype.hasOwnProperty.call( + obj, + key + ) + ) + newObj[key] = obj[key]; + } + } + newObj.default = obj; + return newObj; + } + } + + // Shimming starts here. + /* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. + */ + function adapterFactory() { + var _ref = + arguments.length > 0 && + arguments[0] !== undefined + ? arguments[0] + : {}, + window = _ref.window; + + var options = + arguments.length > 1 && arguments[1] !== undefined + ? arguments[1] + : { + shimChrome: true, + shimFirefox: true, + shimSafari: true, + }; + + // Utils. + var logging = utils.log; + var browserDetails = utils.detectBrowser(window); + + var adapter = { + browserDetails: browserDetails, + commonShim: commonShim, + extractVersion: utils.extractVersion, + disableLog: utils.disableLog, + disableWarnings: utils.disableWarnings, + // Expose sdp as a convenience. For production apps include directly. + sdp: sdp, + }; + + // Shim browser if found. + switch (browserDetails.browser) { + case "chrome": + if ( + !chromeShim || + !chromeShim.shimPeerConnection || + !options.shimChrome + ) { + logging( + "Chrome shim is not included in this adapter release." + ); + return adapter; + } + if (browserDetails.version === null) { + logging( + "Chrome shim can not determine version, not shimming." + ); + return adapter; + } + logging("adapter.js shimming chrome."); + // Export to the adapter global object visible in the browser. + adapter.browserShim = chromeShim; + + // Must be called before shimPeerConnection. + commonShim.shimAddIceCandidateNullOrEmpty( + window, + browserDetails + ); + + chromeShim.shimGetUserMedia( + window, + browserDetails + ); + chromeShim.shimMediaStream( + window, + browserDetails + ); + chromeShim.shimPeerConnection( + window, + browserDetails + ); + chromeShim.shimOnTrack(window, browserDetails); + chromeShim.shimAddTrackRemoveTrack( + window, + browserDetails + ); + chromeShim.shimGetSendersWithDtmf( + window, + browserDetails + ); + chromeShim.shimGetStats(window, browserDetails); + chromeShim.shimSenderReceiverGetStats( + window, + browserDetails + ); + chromeShim.fixNegotiationNeeded( + window, + browserDetails + ); + + commonShim.shimRTCIceCandidate( + window, + browserDetails + ); + commonShim.shimConnectionState( + window, + browserDetails + ); + commonShim.shimMaxMessageSize( + window, + browserDetails + ); + commonShim.shimSendThrowTypeError( + window, + browserDetails + ); + commonShim.removeExtmapAllowMixed( + window, + browserDetails + ); + break; + case "firefox": + if ( + !firefoxShim || + !firefoxShim.shimPeerConnection || + !options.shimFirefox + ) { + logging( + "Firefox shim is not included in this adapter release." + ); + return adapter; + } + logging("adapter.js shimming firefox."); + // Export to the adapter global object visible in the browser. + adapter.browserShim = firefoxShim; + + // Must be called before shimPeerConnection. + commonShim.shimAddIceCandidateNullOrEmpty( + window, + browserDetails + ); + + firefoxShim.shimGetUserMedia( + window, + browserDetails + ); + firefoxShim.shimPeerConnection( + window, + browserDetails + ); + firefoxShim.shimOnTrack(window, browserDetails); + firefoxShim.shimRemoveStream( + window, + browserDetails + ); + firefoxShim.shimSenderGetStats( + window, + browserDetails + ); + firefoxShim.shimReceiverGetStats( + window, + browserDetails + ); + firefoxShim.shimRTCDataChannel( + window, + browserDetails + ); + firefoxShim.shimAddTransceiver( + window, + browserDetails + ); + firefoxShim.shimGetParameters( + window, + browserDetails + ); + firefoxShim.shimCreateOffer( + window, + browserDetails + ); + firefoxShim.shimCreateAnswer( + window, + browserDetails + ); + + commonShim.shimRTCIceCandidate( + window, + browserDetails + ); + commonShim.shimConnectionState( + window, + browserDetails + ); + commonShim.shimMaxMessageSize( + window, + browserDetails + ); + commonShim.shimSendThrowTypeError( + window, + browserDetails + ); + break; + case "safari": + if (!safariShim || !options.shimSafari) { + logging( + "Safari shim is not included in this adapter release." + ); + return adapter; + } + logging("adapter.js shimming safari."); + // Export to the adapter global object visible in the browser. + adapter.browserShim = safariShim; + + // Must be called before shimCallbackAPI. + commonShim.shimAddIceCandidateNullOrEmpty( + window, + browserDetails + ); + + safariShim.shimRTCIceServerUrls( + window, + browserDetails + ); + safariShim.shimCreateOfferLegacy( + window, + browserDetails + ); + safariShim.shimCallbacksAPI( + window, + browserDetails + ); + safariShim.shimLocalStreamsAPI( + window, + browserDetails + ); + safariShim.shimRemoteStreamsAPI( + window, + browserDetails + ); + safariShim.shimTrackEventTransceiver( + window, + browserDetails + ); + safariShim.shimGetUserMedia( + window, + browserDetails + ); + safariShim.shimAudioContext( + window, + browserDetails + ); + + commonShim.shimRTCIceCandidate( + window, + browserDetails + ); + commonShim.shimMaxMessageSize( + window, + browserDetails + ); + commonShim.shimSendThrowTypeError( + window, + browserDetails + ); + commonShim.removeExtmapAllowMixed( + window, + browserDetails + ); + break; + default: + logging("Unsupported browser!"); + break; + } + + return adapter; + } + + // Browser shims. + }, + { + "./chrome/chrome_shim": 3, + "./common_shim": 6, + "./firefox/firefox_shim": 7, + "./safari/safari_shim": 10, + "./utils": 11, + sdp: 12, + }, + ], + 3: [ + function (require, module, exports) { + /* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. + */ + /* eslint-env node */ + "use strict"; + + Object.defineProperty(exports, "__esModule", { + value: true, + }); + exports.shimGetDisplayMedia = exports.shimGetUserMedia = + undefined; + + var _typeof = + typeof Symbol === "function" && + typeof Symbol.iterator === "symbol" + ? function (obj) { + return typeof obj; + } + : function (obj) { + return obj && + typeof Symbol === "function" && + obj.constructor === Symbol && + obj !== Symbol.prototype + ? "symbol" + : typeof obj; + }; + + var _getusermedia = require("./getusermedia"); + + Object.defineProperty(exports, "shimGetUserMedia", { + enumerable: true, + get: function get() { + return _getusermedia.shimGetUserMedia; + }, + }); + + var _getdisplaymedia = require("./getdisplaymedia"); + + Object.defineProperty(exports, "shimGetDisplayMedia", { + enumerable: true, + get: function get() { + return _getdisplaymedia.shimGetDisplayMedia; + }, + }); + exports.shimMediaStream = shimMediaStream; + exports.shimOnTrack = shimOnTrack; + exports.shimGetSendersWithDtmf = shimGetSendersWithDtmf; + exports.shimGetStats = shimGetStats; + exports.shimSenderReceiverGetStats = + shimSenderReceiverGetStats; + exports.shimAddTrackRemoveTrackWithNative = + shimAddTrackRemoveTrackWithNative; + exports.shimAddTrackRemoveTrack = shimAddTrackRemoveTrack; + exports.shimPeerConnection = shimPeerConnection; + exports.fixNegotiationNeeded = fixNegotiationNeeded; + + var _utils = require("../utils.js"); + + var utils = _interopRequireWildcard(_utils); + + function _interopRequireWildcard(obj) { + if (obj && obj.__esModule) { + return obj; + } else { + var newObj = {}; + if (obj != null) { + for (var key in obj) { + if ( + Object.prototype.hasOwnProperty.call( + obj, + key + ) + ) + newObj[key] = obj[key]; + } + } + newObj.default = obj; + return newObj; + } + } + + function _defineProperty(obj, key, value) { + if (key in obj) { + Object.defineProperty(obj, key, { + value: value, + enumerable: true, + configurable: true, + writable: true, + }); + } else { + obj[key] = value; + } + return obj; + } + + function shimMediaStream(window) { + window.MediaStream = + window.MediaStream || window.webkitMediaStream; + } + + function shimOnTrack(window) { + if ( + (typeof window === "undefined" + ? "undefined" + : _typeof(window)) === "object" && + window.RTCPeerConnection && + !("ontrack" in window.RTCPeerConnection.prototype) + ) { + Object.defineProperty( + window.RTCPeerConnection.prototype, + "ontrack", + { + get: function get() { + return this._ontrack; + }, + set: function set(f) { + if (this._ontrack) { + this.removeEventListener( + "track", + this._ontrack + ); + } + this.addEventListener( + "track", + (this._ontrack = f) + ); + }, + + enumerable: true, + configurable: true, + } + ); + var origSetRemoteDescription = + window.RTCPeerConnection.prototype + .setRemoteDescription; + window.RTCPeerConnection.prototype.setRemoteDescription = + function setRemoteDescription() { + var _this = this; + + if (!this._ontrackpoly) { + this._ontrackpoly = function (e) { + // onaddstream does not fire when a track is added to an existing + // stream. But stream.onaddtrack is implemented so we use that. + e.stream.addEventListener( + "addtrack", + function (te) { + var receiver = void 0; + if ( + window.RTCPeerConnection + .prototype + .getReceivers + ) { + receiver = _this + .getReceivers() + .find(function (r) { + return ( + r.track && + r.track + .id === + te.track + .id + ); + }); + } else { + receiver = { + track: te.track, + }; + } + + var event = new Event( + "track" + ); + event.track = te.track; + event.receiver = receiver; + event.transceiver = { + receiver: receiver, + }; + event.streams = [e.stream]; + _this.dispatchEvent(event); + } + ); + e.stream + .getTracks() + .forEach(function (track) { + var receiver = void 0; + if ( + window.RTCPeerConnection + .prototype + .getReceivers + ) { + receiver = _this + .getReceivers() + .find(function (r) { + return ( + r.track && + r.track + .id === + track.id + ); + }); + } else { + receiver = { + track: track, + }; + } + var event = new Event( + "track" + ); + event.track = track; + event.receiver = receiver; + event.transceiver = { + receiver: receiver, + }; + event.streams = [e.stream]; + _this.dispatchEvent(event); + }); + }; + this.addEventListener( + "addstream", + this._ontrackpoly + ); + } + return origSetRemoteDescription.apply( + this, + arguments + ); + }; + } else { + // even if RTCRtpTransceiver is in window, it is only used and + // emitted in unified-plan. Unfortunately this means we need + // to unconditionally wrap the event. + utils.wrapPeerConnectionEvent( + window, + "track", + function (e) { + if (!e.transceiver) { + Object.defineProperty( + e, + "transceiver", + { value: { receiver: e.receiver } } + ); + } + return e; + } + ); + } + } + + function shimGetSendersWithDtmf(window) { + // Overrides addTrack/removeTrack, depends on shimAddTrackRemoveTrack. + if ( + (typeof window === "undefined" + ? "undefined" + : _typeof(window)) === "object" && + window.RTCPeerConnection && + !( + "getSenders" in + window.RTCPeerConnection.prototype + ) && + "createDTMFSender" in + window.RTCPeerConnection.prototype + ) { + var shimSenderWithDtmf = + function shimSenderWithDtmf(pc, track) { + return { + track: track, + get dtmf() { + if (this._dtmf === undefined) { + if (track.kind === "audio") { + this._dtmf = + pc.createDTMFSender( + track + ); + } else { + this._dtmf = null; + } + } + return this._dtmf; + }, + _pc: pc, + }; + }; + + // augment addTrack when getSenders is not available. + if ( + !window.RTCPeerConnection.prototype.getSenders + ) { + window.RTCPeerConnection.prototype.getSenders = + function getSenders() { + this._senders = this._senders || []; + return this._senders.slice(); // return a copy of the internal state. + }; + var origAddTrack = + window.RTCPeerConnection.prototype.addTrack; + window.RTCPeerConnection.prototype.addTrack = + function addTrack(track, stream) { + var sender = origAddTrack.apply( + this, + arguments + ); + if (!sender) { + sender = shimSenderWithDtmf( + this, + track + ); + this._senders.push(sender); + } + return sender; + }; + + var origRemoveTrack = + window.RTCPeerConnection.prototype + .removeTrack; + window.RTCPeerConnection.prototype.removeTrack = + function removeTrack(sender) { + origRemoveTrack.apply(this, arguments); + var idx = this._senders.indexOf(sender); + if (idx !== -1) { + this._senders.splice(idx, 1); + } + }; + } + var origAddStream = + window.RTCPeerConnection.prototype.addStream; + window.RTCPeerConnection.prototype.addStream = + function addStream(stream) { + var _this2 = this; + + this._senders = this._senders || []; + origAddStream.apply(this, [stream]); + stream + .getTracks() + .forEach(function (track) { + _this2._senders.push( + shimSenderWithDtmf( + _this2, + track + ) + ); + }); + }; + + var origRemoveStream = + window.RTCPeerConnection.prototype.removeStream; + window.RTCPeerConnection.prototype.removeStream = + function removeStream(stream) { + var _this3 = this; + + this._senders = this._senders || []; + origRemoveStream.apply(this, [stream]); + + stream + .getTracks() + .forEach(function (track) { + var sender = _this3._senders.find( + function (s) { + return s.track === track; + } + ); + if (sender) { + // remove sender + _this3._senders.splice( + _this3._senders.indexOf( + sender + ), + 1 + ); + } + }); + }; + } else if ( + (typeof window === "undefined" + ? "undefined" + : _typeof(window)) === "object" && + window.RTCPeerConnection && + "getSenders" in + window.RTCPeerConnection.prototype && + "createDTMFSender" in + window.RTCPeerConnection.prototype && + window.RTCRtpSender && + !("dtmf" in window.RTCRtpSender.prototype) + ) { + var origGetSenders = + window.RTCPeerConnection.prototype.getSenders; + window.RTCPeerConnection.prototype.getSenders = + function getSenders() { + var _this4 = this; + + var senders = origGetSenders.apply( + this, + [] + ); + senders.forEach(function (sender) { + return (sender._pc = _this4); + }); + return senders; + }; + + Object.defineProperty( + window.RTCRtpSender.prototype, + "dtmf", + { + get: function get() { + if (this._dtmf === undefined) { + if (this.track.kind === "audio") { + this._dtmf = + this._pc.createDTMFSender( + this.track + ); + } else { + this._dtmf = null; + } + } + return this._dtmf; + }, + } + ); + } + } + + function shimGetStats(window) { + if (!window.RTCPeerConnection) { + return; + } + + var origGetStats = + window.RTCPeerConnection.prototype.getStats; + window.RTCPeerConnection.prototype.getStats = + function getStats() { + var _this5 = this; + + var _arguments = + Array.prototype.slice.call(arguments), + selector = _arguments[0], + onSucc = _arguments[1], + onErr = _arguments[2]; + + // If selector is a function then we are in the old style stats so just + // pass back the original getStats format to avoid breaking old users. + + if ( + arguments.length > 0 && + typeof selector === "function" + ) { + return origGetStats.apply(this, arguments); + } + + // When spec-style getStats is supported, return those when called with + // either no arguments or the selector argument is null. + if ( + origGetStats.length === 0 && + (arguments.length === 0 || + typeof selector !== "function") + ) { + return origGetStats.apply(this, []); + } + + var fixChromeStats_ = function fixChromeStats_( + response + ) { + var standardReport = {}; + var reports = response.result(); + reports.forEach(function (report) { + var standardStats = { + id: report.id, + timestamp: report.timestamp, + type: + { + localcandidate: + "local-candidate", + remotecandidate: + "remote-candidate", + }[report.type] || report.type, + }; + report.names().forEach(function (name) { + standardStats[name] = + report.stat(name); + }); + standardReport[standardStats.id] = + standardStats; + }); + + return standardReport; + }; + + // shim getStats with maplike support + var makeMapStats = function makeMapStats( + stats + ) { + return new Map( + Object.keys(stats).map(function (key) { + return [key, stats[key]]; + }) + ); + }; + + if (arguments.length >= 2) { + var successCallbackWrapper_ = + function successCallbackWrapper_( + response + ) { + onSucc( + makeMapStats( + fixChromeStats_(response) + ) + ); + }; + + return origGetStats.apply(this, [ + successCallbackWrapper_, + selector, + ]); + } + + // promise-support + return new Promise(function (resolve, reject) { + origGetStats.apply(_this5, [ + function (response) { + resolve( + makeMapStats( + fixChromeStats_(response) + ) + ); + }, + reject, + ]); + }).then(onSucc, onErr); + }; + } + + function shimSenderReceiverGetStats(window) { + if ( + !( + (typeof window === "undefined" + ? "undefined" + : _typeof(window)) === "object" && + window.RTCPeerConnection && + window.RTCRtpSender && + window.RTCRtpReceiver + ) + ) { + return; + } + + // shim sender stats. + if (!("getStats" in window.RTCRtpSender.prototype)) { + var origGetSenders = + window.RTCPeerConnection.prototype.getSenders; + if (origGetSenders) { + window.RTCPeerConnection.prototype.getSenders = + function getSenders() { + var _this6 = this; + + var senders = origGetSenders.apply( + this, + [] + ); + senders.forEach(function (sender) { + return (sender._pc = _this6); + }); + return senders; + }; + } + + var origAddTrack = + window.RTCPeerConnection.prototype.addTrack; + if (origAddTrack) { + window.RTCPeerConnection.prototype.addTrack = + function addTrack() { + var sender = origAddTrack.apply( + this, + arguments + ); + sender._pc = this; + return sender; + }; + } + window.RTCRtpSender.prototype.getStats = + function getStats() { + var sender = this; + return this._pc + .getStats() + .then(function (result) { + return ( + /* Note: this will include stats of all senders that + * send a track with the same id as sender.track as + * it is not possible to identify the RTCRtpSender. + */ + utils.filterStats( + result, + sender.track, + true + ) + ); + }); + }; + } + + // shim receiver stats. + if (!("getStats" in window.RTCRtpReceiver.prototype)) { + var origGetReceivers = + window.RTCPeerConnection.prototype.getReceivers; + if (origGetReceivers) { + window.RTCPeerConnection.prototype.getReceivers = + function getReceivers() { + var _this7 = this; + + var receivers = origGetReceivers.apply( + this, + [] + ); + receivers.forEach(function (receiver) { + return (receiver._pc = _this7); + }); + return receivers; + }; + } + utils.wrapPeerConnectionEvent( + window, + "track", + function (e) { + e.receiver._pc = e.srcElement; + return e; + } + ); + window.RTCRtpReceiver.prototype.getStats = + function getStats() { + var receiver = this; + return this._pc + .getStats() + .then(function (result) { + return utils.filterStats( + result, + receiver.track, + false + ); + }); + }; + } + + if ( + !( + "getStats" in window.RTCRtpSender.prototype && + "getStats" in window.RTCRtpReceiver.prototype + ) + ) { + return; + } + + // shim RTCPeerConnection.getStats(track). + var origGetStats = + window.RTCPeerConnection.prototype.getStats; + window.RTCPeerConnection.prototype.getStats = + function getStats() { + if ( + arguments.length > 0 && + arguments[0] instanceof + window.MediaStreamTrack + ) { + var track = arguments[0]; + var sender = void 0; + var receiver = void 0; + var err = void 0; + this.getSenders().forEach(function (s) { + if (s.track === track) { + if (sender) { + err = true; + } else { + sender = s; + } + } + }); + this.getReceivers().forEach(function (r) { + if (r.track === track) { + if (receiver) { + err = true; + } else { + receiver = r; + } + } + return r.track === track; + }); + if (err || (sender && receiver)) { + return Promise.reject( + new DOMException( + "There are more than one sender or receiver for the track.", + "InvalidAccessError" + ) + ); + } else if (sender) { + return sender.getStats(); + } else if (receiver) { + return receiver.getStats(); + } + return Promise.reject( + new DOMException( + "There is no sender or receiver for the track.", + "InvalidAccessError" + ) + ); + } + return origGetStats.apply(this, arguments); + }; + } + + function shimAddTrackRemoveTrackWithNative(window) { + // shim addTrack/removeTrack with native variants in order to make + // the interactions with legacy getLocalStreams behave as in other browsers. + // Keeps a mapping stream.id => [stream, rtpsenders...] + window.RTCPeerConnection.prototype.getLocalStreams = + function getLocalStreams() { + var _this8 = this; + + this._shimmedLocalStreams = + this._shimmedLocalStreams || {}; + return Object.keys( + this._shimmedLocalStreams + ).map(function (streamId) { + return _this8 + ._shimmedLocalStreams[streamId][0]; + }); + }; + + var origAddTrack = + window.RTCPeerConnection.prototype.addTrack; + window.RTCPeerConnection.prototype.addTrack = + function addTrack(track, stream) { + if (!stream) { + return origAddTrack.apply(this, arguments); + } + this._shimmedLocalStreams = + this._shimmedLocalStreams || {}; + + var sender = origAddTrack.apply( + this, + arguments + ); + if (!this._shimmedLocalStreams[stream.id]) { + this._shimmedLocalStreams[stream.id] = [ + stream, + sender, + ]; + } else if ( + this._shimmedLocalStreams[ + stream.id + ].indexOf(sender) === -1 + ) { + this._shimmedLocalStreams[stream.id].push( + sender + ); + } + return sender; + }; + + var origAddStream = + window.RTCPeerConnection.prototype.addStream; + window.RTCPeerConnection.prototype.addStream = + function addStream(stream) { + var _this9 = this; + + this._shimmedLocalStreams = + this._shimmedLocalStreams || {}; + + stream.getTracks().forEach(function (track) { + var alreadyExists = _this9 + .getSenders() + .find(function (s) { + return s.track === track; + }); + if (alreadyExists) { + throw new DOMException( + "Track already exists.", + "InvalidAccessError" + ); + } + }); + var existingSenders = this.getSenders(); + origAddStream.apply(this, arguments); + var newSenders = this.getSenders().filter( + function (newSender) { + return ( + existingSenders.indexOf( + newSender + ) === -1 + ); + } + ); + this._shimmedLocalStreams[stream.id] = [ + stream, + ].concat(newSenders); + }; + + var origRemoveStream = + window.RTCPeerConnection.prototype.removeStream; + window.RTCPeerConnection.prototype.removeStream = + function removeStream(stream) { + this._shimmedLocalStreams = + this._shimmedLocalStreams || {}; + delete this._shimmedLocalStreams[stream.id]; + return origRemoveStream.apply(this, arguments); + }; + + var origRemoveTrack = + window.RTCPeerConnection.prototype.removeTrack; + window.RTCPeerConnection.prototype.removeTrack = + function removeTrack(sender) { + var _this10 = this; + + this._shimmedLocalStreams = + this._shimmedLocalStreams || {}; + if (sender) { + Object.keys( + this._shimmedLocalStreams + ).forEach(function (streamId) { + var idx = + _this10._shimmedLocalStreams[ + streamId + ].indexOf(sender); + if (idx !== -1) { + _this10._shimmedLocalStreams[ + streamId + ].splice(idx, 1); + } + if ( + _this10._shimmedLocalStreams[ + streamId + ].length === 1 + ) { + delete _this10._shimmedLocalStreams[ + streamId + ]; + } + }); + } + return origRemoveTrack.apply(this, arguments); + }; + } + + function shimAddTrackRemoveTrack(window, browserDetails) { + if (!window.RTCPeerConnection) { + return; + } + // shim addTrack and removeTrack. + if ( + window.RTCPeerConnection.prototype.addTrack && + browserDetails.version >= 65 + ) { + return shimAddTrackRemoveTrackWithNative(window); + } + + // also shim pc.getLocalStreams when addTrack is shimmed + // to return the original streams. + var origGetLocalStreams = + window.RTCPeerConnection.prototype.getLocalStreams; + window.RTCPeerConnection.prototype.getLocalStreams = + function getLocalStreams() { + var _this11 = this; + + var nativeStreams = + origGetLocalStreams.apply(this); + this._reverseStreams = + this._reverseStreams || {}; + return nativeStreams.map(function (stream) { + return _this11._reverseStreams[stream.id]; + }); + }; + + var origAddStream = + window.RTCPeerConnection.prototype.addStream; + window.RTCPeerConnection.prototype.addStream = + function addStream(stream) { + var _this12 = this; + + this._streams = this._streams || {}; + this._reverseStreams = + this._reverseStreams || {}; + + stream.getTracks().forEach(function (track) { + var alreadyExists = _this12 + .getSenders() + .find(function (s) { + return s.track === track; + }); + if (alreadyExists) { + throw new DOMException( + "Track already exists.", + "InvalidAccessError" + ); + } + }); + // Add identity mapping for consistency with addTrack. + // Unless this is being used with a stream from addTrack. + if (!this._reverseStreams[stream.id]) { + var newStream = new window.MediaStream( + stream.getTracks() + ); + this._streams[stream.id] = newStream; + this._reverseStreams[newStream.id] = stream; + stream = newStream; + } + origAddStream.apply(this, [stream]); + }; + + var origRemoveStream = + window.RTCPeerConnection.prototype.removeStream; + window.RTCPeerConnection.prototype.removeStream = + function removeStream(stream) { + this._streams = this._streams || {}; + this._reverseStreams = + this._reverseStreams || {}; + + origRemoveStream.apply(this, [ + this._streams[stream.id] || stream, + ]); + delete this._reverseStreams[ + this._streams[stream.id] + ? this._streams[stream.id].id + : stream.id + ]; + delete this._streams[stream.id]; + }; + + window.RTCPeerConnection.prototype.addTrack = + function addTrack(track, stream) { + var _this13 = this; + + if (this.signalingState === "closed") { + throw new DOMException( + "The RTCPeerConnection's signalingState is 'closed'.", + "InvalidStateError" + ); + } + var streams = [].slice.call(arguments, 1); + if ( + streams.length !== 1 || + !streams[0].getTracks().find(function (t) { + return t === track; + }) + ) { + // this is not fully correct but all we can manage without + // [[associated MediaStreams]] internal slot. + throw new DOMException( + "The adapter.js addTrack polyfill only supports a single " + + " stream which is associated with the specified track.", + "NotSupportedError" + ); + } + + var alreadyExists = this.getSenders().find( + function (s) { + return s.track === track; + } + ); + if (alreadyExists) { + throw new DOMException( + "Track already exists.", + "InvalidAccessError" + ); + } + + this._streams = this._streams || {}; + this._reverseStreams = + this._reverseStreams || {}; + var oldStream = this._streams[stream.id]; + if (oldStream) { + // this is using odd Chrome behaviour, use with caution: + // https://bugs.chromium.org/p/webrtc/issues/detail?id=7815 + // Note: we rely on the high-level addTrack/dtmf shim to + // create the sender with a dtmf sender. + oldStream.addTrack(track); + + // Trigger ONN async. + Promise.resolve().then(function () { + _this13.dispatchEvent( + new Event("negotiationneeded") + ); + }); + } else { + var newStream = new window.MediaStream([ + track, + ]); + this._streams[stream.id] = newStream; + this._reverseStreams[newStream.id] = stream; + this.addStream(newStream); + } + return this.getSenders().find(function (s) { + return s.track === track; + }); + }; + + // replace the internal stream id with the external one and + // vice versa. + function replaceInternalStreamId(pc, description) { + var sdp = description.sdp; + Object.keys(pc._reverseStreams || []).forEach( + function (internalId) { + var externalStream = + pc._reverseStreams[internalId]; + var internalStream = + pc._streams[externalStream.id]; + sdp = sdp.replace( + new RegExp(internalStream.id, "g"), + externalStream.id + ); + } + ); + return new RTCSessionDescription({ + type: description.type, + sdp: sdp, + }); + } + function replaceExternalStreamId(pc, description) { + var sdp = description.sdp; + Object.keys(pc._reverseStreams || []).forEach( + function (internalId) { + var externalStream = + pc._reverseStreams[internalId]; + var internalStream = + pc._streams[externalStream.id]; + sdp = sdp.replace( + new RegExp(externalStream.id, "g"), + internalStream.id + ); + } + ); + return new RTCSessionDescription({ + type: description.type, + sdp: sdp, + }); + } + ["createOffer", "createAnswer"].forEach(function ( + method + ) { + var nativeMethod = + window.RTCPeerConnection.prototype[method]; + var methodObj = _defineProperty( + {}, + method, + function () { + var _this14 = this; + + var args = arguments; + var isLegacyCall = + arguments.length && + typeof arguments[0] === "function"; + if (isLegacyCall) { + return nativeMethod.apply(this, [ + function (description) { + var desc = + replaceInternalStreamId( + _this14, + description + ); + args[0].apply(null, [desc]); + }, + function (err) { + if (args[1]) { + args[1].apply(null, err); + } + }, + arguments[2], + ]); + } + return nativeMethod + .apply(this, arguments) + .then(function (description) { + return replaceInternalStreamId( + _this14, + description + ); + }); + } + ); + window.RTCPeerConnection.prototype[method] = + methodObj[method]; + }); + + var origSetLocalDescription = + window.RTCPeerConnection.prototype + .setLocalDescription; + window.RTCPeerConnection.prototype.setLocalDescription = + function setLocalDescription() { + if (!arguments.length || !arguments[0].type) { + return origSetLocalDescription.apply( + this, + arguments + ); + } + arguments[0] = replaceExternalStreamId( + this, + arguments[0] + ); + return origSetLocalDescription.apply( + this, + arguments + ); + }; + + // TODO: mangle getStats: https://w3c.github.io/webrtc-stats/#dom-rtcmediastreamstats-streamidentifier + + var origLocalDescription = + Object.getOwnPropertyDescriptor( + window.RTCPeerConnection.prototype, + "localDescription" + ); + Object.defineProperty( + window.RTCPeerConnection.prototype, + "localDescription", + { + get: function get() { + var description = + origLocalDescription.get.apply(this); + if (description.type === "") { + return description; + } + return replaceInternalStreamId( + this, + description + ); + }, + } + ); + + window.RTCPeerConnection.prototype.removeTrack = + function removeTrack(sender) { + var _this15 = this; + + if (this.signalingState === "closed") { + throw new DOMException( + "The RTCPeerConnection's signalingState is 'closed'.", + "InvalidStateError" + ); + } + // We can not yet check for sender instanceof RTCRtpSender + // since we shim RTPSender. So we check if sender._pc is set. + if (!sender._pc) { + throw new DOMException( + "Argument 1 of RTCPeerConnection.removeTrack " + + "does not implement interface RTCRtpSender.", + "TypeError" + ); + } + var isLocal = sender._pc === this; + if (!isLocal) { + throw new DOMException( + "Sender was not created by this connection.", + "InvalidAccessError" + ); + } + + // Search for the native stream the senders track belongs to. + this._streams = this._streams || {}; + var stream = void 0; + Object.keys(this._streams).forEach(function ( + streamid + ) { + var hasTrack = _this15._streams[streamid] + .getTracks() + .find(function (track) { + return sender.track === track; + }); + if (hasTrack) { + stream = _this15._streams[streamid]; + } + }); + + if (stream) { + if (stream.getTracks().length === 1) { + // if this is the last track of the stream, remove the stream. This + // takes care of any shimmed _senders. + this.removeStream( + this._reverseStreams[stream.id] + ); + } else { + // relying on the same odd chrome behaviour as above. + stream.removeTrack(sender.track); + } + this.dispatchEvent( + new Event("negotiationneeded") + ); + } + }; + } + + function shimPeerConnection(window, browserDetails) { + if ( + !window.RTCPeerConnection && + window.webkitRTCPeerConnection + ) { + // very basic support for old versions. + window.RTCPeerConnection = + window.webkitRTCPeerConnection; + } + if (!window.RTCPeerConnection) { + return; + } + + // shim implicit creation of RTCSessionDescription/RTCIceCandidate + if (browserDetails.version < 53) { + [ + "setLocalDescription", + "setRemoteDescription", + "addIceCandidate", + ].forEach(function (method) { + var nativeMethod = + window.RTCPeerConnection.prototype[method]; + var methodObj = _defineProperty( + {}, + method, + function () { + arguments[0] = new ( + method === "addIceCandidate" + ? window.RTCIceCandidate + : window.RTCSessionDescription + )(arguments[0]); + return nativeMethod.apply( + this, + arguments + ); + } + ); + window.RTCPeerConnection.prototype[method] = + methodObj[method]; + }); + } + } + + // Attempt to fix ONN in plan-b mode. + function fixNegotiationNeeded(window, browserDetails) { + utils.wrapPeerConnectionEvent( + window, + "negotiationneeded", + function (e) { + var pc = e.target; + if ( + browserDetails.version < 72 || + (pc.getConfiguration && + pc.getConfiguration().sdpSemantics === + "plan-b") + ) { + if (pc.signalingState !== "stable") { + return; + } + } + return e; + } + ); + } + }, + { + "../utils.js": 11, + "./getdisplaymedia": 4, + "./getusermedia": 5, + }, + ], + 4: [ + function (require, module, exports) { + /* + * Copyright (c) 2018 The adapter.js project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. + */ + /* eslint-env node */ + "use strict"; + + Object.defineProperty(exports, "__esModule", { + value: true, + }); + exports.shimGetDisplayMedia = shimGetDisplayMedia; + function shimGetDisplayMedia(window, getSourceId) { + if ( + window.navigator.mediaDevices && + "getDisplayMedia" in window.navigator.mediaDevices + ) { + return; + } + if (!window.navigator.mediaDevices) { + return; + } + // getSourceId is a function that returns a promise resolving with + // the sourceId of the screen/window/tab to be shared. + if (typeof getSourceId !== "function") { + console.error( + "shimGetDisplayMedia: getSourceId argument is not " + + "a function" + ); + return; + } + window.navigator.mediaDevices.getDisplayMedia = + function getDisplayMedia(constraints) { + return getSourceId(constraints).then(function ( + sourceId + ) { + var widthSpecified = + constraints.video && + constraints.video.width; + var heightSpecified = + constraints.video && + constraints.video.height; + var frameRateSpecified = + constraints.video && + constraints.video.frameRate; + constraints.video = { + mandatory: { + chromeMediaSource: "desktop", + chromeMediaSourceId: sourceId, + maxFrameRate: + frameRateSpecified || 3, + }, + }; + if (widthSpecified) { + constraints.video.mandatory.maxWidth = + widthSpecified; + } + if (heightSpecified) { + constraints.video.mandatory.maxHeight = + heightSpecified; + } + return window.navigator.mediaDevices.getUserMedia( + constraints + ); + }); + }; + } + }, + {}, + ], + 5: [ + function (require, module, exports) { + /* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. + */ + /* eslint-env node */ + "use strict"; + + Object.defineProperty(exports, "__esModule", { + value: true, + }); + + var _typeof = + typeof Symbol === "function" && + typeof Symbol.iterator === "symbol" + ? function (obj) { + return typeof obj; + } + : function (obj) { + return obj && + typeof Symbol === "function" && + obj.constructor === Symbol && + obj !== Symbol.prototype + ? "symbol" + : typeof obj; + }; + + exports.shimGetUserMedia = shimGetUserMedia; + + var _utils = require("../utils.js"); + + var utils = _interopRequireWildcard(_utils); + + function _interopRequireWildcard(obj) { + if (obj && obj.__esModule) { + return obj; + } else { + var newObj = {}; + if (obj != null) { + for (var key in obj) { + if ( + Object.prototype.hasOwnProperty.call( + obj, + key + ) + ) + newObj[key] = obj[key]; + } + } + newObj.default = obj; + return newObj; + } + } + + var logging = utils.log; + + function shimGetUserMedia(window, browserDetails) { + var navigator = window && window.navigator; + + if (!navigator.mediaDevices) { + return; + } + + var constraintsToChrome_ = + function constraintsToChrome_(c) { + if ( + (typeof c === "undefined" + ? "undefined" + : _typeof(c)) !== "object" || + c.mandatory || + c.optional + ) { + return c; + } + var cc = {}; + Object.keys(c).forEach(function (key) { + if ( + key === "require" || + key === "advanced" || + key === "mediaSource" + ) { + return; + } + var r = + _typeof(c[key]) === "object" + ? c[key] + : { ideal: c[key] }; + if ( + r.exact !== undefined && + typeof r.exact === "number" + ) { + r.min = r.max = r.exact; + } + var oldname_ = function oldname_( + prefix, + name + ) { + if (prefix) { + return ( + prefix + + name.charAt(0).toUpperCase() + + name.slice(1) + ); + } + return name === "deviceId" + ? "sourceId" + : name; + }; + if (r.ideal !== undefined) { + cc.optional = cc.optional || []; + var oc = {}; + if (typeof r.ideal === "number") { + oc[oldname_("min", key)] = r.ideal; + cc.optional.push(oc); + oc = {}; + oc[oldname_("max", key)] = r.ideal; + cc.optional.push(oc); + } else { + oc[oldname_("", key)] = r.ideal; + cc.optional.push(oc); + } + } + if ( + r.exact !== undefined && + typeof r.exact !== "number" + ) { + cc.mandatory = cc.mandatory || {}; + cc.mandatory[oldname_("", key)] = + r.exact; + } else { + ["min", "max"].forEach(function (mix) { + if (r[mix] !== undefined) { + cc.mandatory = + cc.mandatory || {}; + cc.mandatory[ + oldname_(mix, key) + ] = r[mix]; + } + }); + } + }); + if (c.advanced) { + cc.optional = (cc.optional || []).concat( + c.advanced + ); + } + return cc; + }; + + var shimConstraints_ = function shimConstraints_( + constraints, + func + ) { + if (browserDetails.version >= 61) { + return func(constraints); + } + constraints = JSON.parse( + JSON.stringify(constraints) + ); + if ( + constraints && + _typeof(constraints.audio) === "object" + ) { + var remap = function remap(obj, a, b) { + if (a in obj && !(b in obj)) { + obj[b] = obj[a]; + delete obj[a]; + } + }; + constraints = JSON.parse( + JSON.stringify(constraints) + ); + remap( + constraints.audio, + "autoGainControl", + "googAutoGainControl" + ); + remap( + constraints.audio, + "noiseSuppression", + "googNoiseSuppression" + ); + constraints.audio = constraintsToChrome_( + constraints.audio + ); + } + if ( + constraints && + _typeof(constraints.video) === "object" + ) { + // Shim facingMode for mobile & surface pro. + var face = constraints.video.facingMode; + face = + face && + ((typeof face === "undefined" + ? "undefined" + : _typeof(face)) === "object" + ? face + : { ideal: face }); + var getSupportedFacingModeLies = + browserDetails.version < 66; + + if ( + face && + (face.exact === "user" || + face.exact === "environment" || + face.ideal === "user" || + face.ideal === "environment") && + !( + navigator.mediaDevices + .getSupportedConstraints && + navigator.mediaDevices.getSupportedConstraints() + .facingMode && + !getSupportedFacingModeLies + ) + ) { + delete constraints.video.facingMode; + var matches = void 0; + if ( + face.exact === "environment" || + face.ideal === "environment" + ) { + matches = ["back", "rear"]; + } else if ( + face.exact === "user" || + face.ideal === "user" + ) { + matches = ["front"]; + } + if (matches) { + // Look for matches in label, or use last cam for back (typical). + return navigator.mediaDevices + .enumerateDevices() + .then(function (devices) { + devices = devices.filter( + function (d) { + return ( + d.kind === + "videoinput" + ); + } + ); + var dev = devices.find( + function (d) { + return matches.some( + function (match) { + return d.label + .toLowerCase() + .includes( + match + ); + } + ); + } + ); + if ( + !dev && + devices.length && + matches.includes("back") + ) { + dev = + devices[ + devices.length - 1 + ]; // more likely the back cam + } + if (dev) { + constraints.video.deviceId = + face.exact + ? { + exact: dev.deviceId, + } + : { + ideal: dev.deviceId, + }; + } + constraints.video = + constraintsToChrome_( + constraints.video + ); + logging( + "chrome: " + + JSON.stringify( + constraints + ) + ); + return func(constraints); + }); + } + } + constraints.video = constraintsToChrome_( + constraints.video + ); + } + logging("chrome: " + JSON.stringify(constraints)); + return func(constraints); + }; + + var shimError_ = function shimError_(e) { + if (browserDetails.version >= 64) { + return e; + } + return { + name: + { + PermissionDeniedError: + "NotAllowedError", + PermissionDismissedError: + "NotAllowedError", + InvalidStateError: "NotAllowedError", + DevicesNotFoundError: "NotFoundError", + ConstraintNotSatisfiedError: + "OverconstrainedError", + TrackStartError: "NotReadableError", + MediaDeviceFailedDueToShutdown: + "NotAllowedError", + MediaDeviceKillSwitchOn: + "NotAllowedError", + TabCaptureError: "AbortError", + ScreenCaptureError: "AbortError", + DeviceCaptureError: "AbortError", + }[e.name] || e.name, + message: e.message, + constraint: e.constraint || e.constraintName, + toString: function toString() { + return ( + this.name + + (this.message && ": ") + + this.message + ); + }, + }; + }; + + var getUserMedia_ = function getUserMedia_( + constraints, + onSuccess, + onError + ) { + shimConstraints_(constraints, function (c) { + navigator.webkitGetUserMedia( + c, + onSuccess, + function (e) { + if (onError) { + onError(shimError_(e)); + } + } + ); + }); + }; + navigator.getUserMedia = getUserMedia_.bind(navigator); + + // Even though Chrome 45 has navigator.mediaDevices and a getUserMedia + // function which returns a Promise, it does not accept spec-style + // constraints. + if (navigator.mediaDevices.getUserMedia) { + var origGetUserMedia = + navigator.mediaDevices.getUserMedia.bind( + navigator.mediaDevices + ); + navigator.mediaDevices.getUserMedia = function ( + cs + ) { + return shimConstraints_(cs, function (c) { + return origGetUserMedia(c).then( + function (stream) { + if ( + (c.audio && + !stream.getAudioTracks() + .length) || + (c.video && + !stream.getVideoTracks() + .length) + ) { + stream + .getTracks() + .forEach(function (track) { + track.stop(); + }); + throw new DOMException( + "", + "NotFoundError" + ); + } + return stream; + }, + function (e) { + return Promise.reject( + shimError_(e) + ); + } + ); + }); + }; + } + } + }, + { "../utils.js": 11 }, + ], + 6: [ + function (require, module, exports) { + /* + * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. + */ + /* eslint-env node */ + "use strict"; + + Object.defineProperty(exports, "__esModule", { + value: true, + }); + + var _typeof = + typeof Symbol === "function" && + typeof Symbol.iterator === "symbol" + ? function (obj) { + return typeof obj; + } + : function (obj) { + return obj && + typeof Symbol === "function" && + obj.constructor === Symbol && + obj !== Symbol.prototype + ? "symbol" + : typeof obj; + }; + + exports.shimRTCIceCandidate = shimRTCIceCandidate; + exports.shimMaxMessageSize = shimMaxMessageSize; + exports.shimSendThrowTypeError = shimSendThrowTypeError; + exports.shimConnectionState = shimConnectionState; + exports.removeExtmapAllowMixed = removeExtmapAllowMixed; + exports.shimAddIceCandidateNullOrEmpty = + shimAddIceCandidateNullOrEmpty; + + var _sdp = require("sdp"); + + var _sdp2 = _interopRequireDefault(_sdp); + + var _utils = require("./utils"); + + var utils = _interopRequireWildcard(_utils); + + function _interopRequireWildcard(obj) { + if (obj && obj.__esModule) { + return obj; + } else { + var newObj = {}; + if (obj != null) { + for (var key in obj) { + if ( + Object.prototype.hasOwnProperty.call( + obj, + key + ) + ) + newObj[key] = obj[key]; + } + } + newObj.default = obj; + return newObj; + } + } + + function _interopRequireDefault(obj) { + return obj && obj.__esModule ? obj : { default: obj }; + } + + function shimRTCIceCandidate(window) { + // foundation is arbitrarily chosen as an indicator for full support for + // https://w3c.github.io/webrtc-pc/#rtcicecandidate-interface + if ( + !window.RTCIceCandidate || + (window.RTCIceCandidate && + "foundation" in + window.RTCIceCandidate.prototype) + ) { + return; + } + + var NativeRTCIceCandidate = window.RTCIceCandidate; + window.RTCIceCandidate = function RTCIceCandidate( + args + ) { + // Remove the a= which shouldn't be part of the candidate string. + if ( + (typeof args === "undefined" + ? "undefined" + : _typeof(args)) === "object" && + args.candidate && + args.candidate.indexOf("a=") === 0 + ) { + args = JSON.parse(JSON.stringify(args)); + args.candidate = args.candidate.substr(2); + } + + if (args.candidate && args.candidate.length) { + // Augment the native candidate with the parsed fields. + var nativeCandidate = new NativeRTCIceCandidate( + args + ); + var parsedCandidate = + _sdp2.default.parseCandidate( + args.candidate + ); + var augmentedCandidate = Object.assign( + nativeCandidate, + parsedCandidate + ); + + // Add a serializer that does not serialize the extra attributes. + augmentedCandidate.toJSON = function toJSON() { + return { + candidate: augmentedCandidate.candidate, + sdpMid: augmentedCandidate.sdpMid, + sdpMLineIndex: + augmentedCandidate.sdpMLineIndex, + usernameFragment: + augmentedCandidate.usernameFragment, + }; + }; + return augmentedCandidate; + } + return new NativeRTCIceCandidate(args); + }; + window.RTCIceCandidate.prototype = + NativeRTCIceCandidate.prototype; + + // Hook up the augmented candidate in onicecandidate and + // addEventListener('icecandidate', ...) + utils.wrapPeerConnectionEvent( + window, + "icecandidate", + function (e) { + if (e.candidate) { + Object.defineProperty(e, "candidate", { + value: new window.RTCIceCandidate( + e.candidate + ), + writable: "false", + }); + } + return e; + } + ); + } + + function shimMaxMessageSize(window, browserDetails) { + if (!window.RTCPeerConnection) { + return; + } + + if (!("sctp" in window.RTCPeerConnection.prototype)) { + Object.defineProperty( + window.RTCPeerConnection.prototype, + "sctp", + { + get: function get() { + return typeof this._sctp === "undefined" + ? null + : this._sctp; + }, + } + ); + } + + var sctpInDescription = function sctpInDescription( + description + ) { + if (!description || !description.sdp) { + return false; + } + var sections = _sdp2.default.splitSections( + description.sdp + ); + sections.shift(); + return sections.some(function (mediaSection) { + var mLine = + _sdp2.default.parseMLine(mediaSection); + return ( + mLine && + mLine.kind === "application" && + mLine.protocol.indexOf("SCTP") !== -1 + ); + }); + }; + + var getRemoteFirefoxVersion = + function getRemoteFirefoxVersion(description) { + // TODO: Is there a better solution for detecting Firefox? + var match = description.sdp.match( + /mozilla...THIS_IS_SDPARTA-(\d+)/ + ); + if (match === null || match.length < 2) { + return -1; + } + var version = parseInt(match[1], 10); + // Test for NaN (yes, this is ugly) + return version !== version ? -1 : version; + }; + + var getCanSendMaxMessageSize = + function getCanSendMaxMessageSize(remoteIsFirefox) { + // Every implementation we know can send at least 64 KiB. + // Note: Although Chrome is technically able to send up to 256 KiB, the + // data does not reach the other peer reliably. + // See: https://bugs.chromium.org/p/webrtc/issues/detail?id=8419 + var canSendMaxMessageSize = 65536; + if (browserDetails.browser === "firefox") { + if (browserDetails.version < 57) { + if (remoteIsFirefox === -1) { + // FF < 57 will send in 16 KiB chunks using the deprecated PPID + // fragmentation. + canSendMaxMessageSize = 16384; + } else { + // However, other FF (and RAWRTC) can reassemble PPID-fragmented + // messages. Thus, supporting ~2 GiB when sending. + canSendMaxMessageSize = 2147483637; + } + } else if (browserDetails.version < 60) { + // Currently, all FF >= 57 will reset the remote maximum message size + // to the default value when a data channel is created at a later + // stage. :( + // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1426831 + canSendMaxMessageSize = + browserDetails.version === 57 + ? 65535 + : 65536; + } else { + // FF >= 60 supports sending ~2 GiB + canSendMaxMessageSize = 2147483637; + } + } + return canSendMaxMessageSize; + }; + + var getMaxMessageSize = function getMaxMessageSize( + description, + remoteIsFirefox + ) { + // Note: 65536 bytes is the default value from the SDP spec. Also, + // every implementation we know supports receiving 65536 bytes. + var maxMessageSize = 65536; + + // FF 57 has a slightly incorrect default remote max message size, so + // we need to adjust it here to avoid a failure when sending. + // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1425697 + if ( + browserDetails.browser === "firefox" && + browserDetails.version === 57 + ) { + maxMessageSize = 65535; + } + + var match = _sdp2.default.matchPrefix( + description.sdp, + "a=max-message-size:" + ); + if (match.length > 0) { + maxMessageSize = parseInt( + match[0].substr(19), + 10 + ); + } else if ( + browserDetails.browser === "firefox" && + remoteIsFirefox !== -1 + ) { + // If the maximum message size is not present in the remote SDP and + // both local and remote are Firefox, the remote peer can receive + // ~2 GiB. + maxMessageSize = 2147483637; + } + return maxMessageSize; + }; + + var origSetRemoteDescription = + window.RTCPeerConnection.prototype + .setRemoteDescription; + window.RTCPeerConnection.prototype.setRemoteDescription = + function setRemoteDescription() { + this._sctp = null; + // Chrome decided to not expose .sctp in plan-b mode. + // As usual, adapter.js has to do an 'ugly worakaround' + // to cover up the mess. + if ( + browserDetails.browser === "chrome" && + browserDetails.version >= 76 + ) { + var _getConfiguration = + this.getConfiguration(), + sdpSemantics = + _getConfiguration.sdpSemantics; + + if (sdpSemantics === "plan-b") { + Object.defineProperty(this, "sctp", { + get: function get() { + return typeof this._sctp === + "undefined" + ? null + : this._sctp; + }, + + enumerable: true, + configurable: true, + }); + } + } + + if (sctpInDescription(arguments[0])) { + // Check if the remote is FF. + var isFirefox = getRemoteFirefoxVersion( + arguments[0] + ); + + // Get the maximum message size the local peer is capable of sending + var canSendMMS = + getCanSendMaxMessageSize(isFirefox); + + // Get the maximum message size of the remote peer. + var remoteMMS = getMaxMessageSize( + arguments[0], + isFirefox + ); + + // Determine final maximum message size + var maxMessageSize = void 0; + if (canSendMMS === 0 && remoteMMS === 0) { + maxMessageSize = + Number.POSITIVE_INFINITY; + } else if ( + canSendMMS === 0 || + remoteMMS === 0 + ) { + maxMessageSize = Math.max( + canSendMMS, + remoteMMS + ); + } else { + maxMessageSize = Math.min( + canSendMMS, + remoteMMS + ); + } + + // Create a dummy RTCSctpTransport object and the 'maxMessageSize' + // attribute. + var sctp = {}; + Object.defineProperty( + sctp, + "maxMessageSize", + { + get: function get() { + return maxMessageSize; + }, + } + ); + this._sctp = sctp; + } + + return origSetRemoteDescription.apply( + this, + arguments + ); + }; + } + + function shimSendThrowTypeError(window) { + if ( + !( + window.RTCPeerConnection && + "createDataChannel" in + window.RTCPeerConnection.prototype + ) + ) { + return; + } + + // Note: Although Firefox >= 57 has a native implementation, the maximum + // message size can be reset for all data channels at a later stage. + // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1426831 + + function wrapDcSend(dc, pc) { + var origDataChannelSend = dc.send; + dc.send = function send() { + var data = arguments[0]; + var length = + data.length || data.size || data.byteLength; + if ( + dc.readyState === "open" && + pc.sctp && + length > pc.sctp.maxMessageSize + ) { + throw new TypeError( + "Message too large (can send a maximum of " + + pc.sctp.maxMessageSize + + " bytes)" + ); + } + return origDataChannelSend.apply(dc, arguments); + }; + } + var origCreateDataChannel = + window.RTCPeerConnection.prototype + .createDataChannel; + window.RTCPeerConnection.prototype.createDataChannel = + function createDataChannel() { + var dataChannel = origCreateDataChannel.apply( + this, + arguments + ); + wrapDcSend(dataChannel, this); + return dataChannel; + }; + utils.wrapPeerConnectionEvent( + window, + "datachannel", + function (e) { + wrapDcSend(e.channel, e.target); + return e; + } + ); + } + + /* shims RTCConnectionState by pretending it is the same as iceConnectionState. + * See https://bugs.chromium.org/p/webrtc/issues/detail?id=6145#c12 + * for why this is a valid hack in Chrome. In Firefox it is slightly incorrect + * since DTLS failures would be hidden. See + * https://bugzilla.mozilla.org/show_bug.cgi?id=1265827 + * for the Firefox tracking bug. + */ + function shimConnectionState(window) { + if ( + !window.RTCPeerConnection || + "connectionState" in + window.RTCPeerConnection.prototype + ) { + return; + } + var proto = window.RTCPeerConnection.prototype; + Object.defineProperty(proto, "connectionState", { + get: function get() { + return ( + { + completed: "connected", + checking: "connecting", + }[this.iceConnectionState] || + this.iceConnectionState + ); + }, + + enumerable: true, + configurable: true, + }); + Object.defineProperty( + proto, + "onconnectionstatechange", + { + get: function get() { + return ( + this._onconnectionstatechange || null + ); + }, + set: function set(cb) { + if (this._onconnectionstatechange) { + this.removeEventListener( + "connectionstatechange", + this._onconnectionstatechange + ); + delete this._onconnectionstatechange; + } + if (cb) { + this.addEventListener( + "connectionstatechange", + (this._onconnectionstatechange = cb) + ); + } + }, + + enumerable: true, + configurable: true, + } + ); + + ["setLocalDescription", "setRemoteDescription"].forEach( + function (method) { + var origMethod = proto[method]; + proto[method] = function () { + if (!this._connectionstatechangepoly) { + this._connectionstatechangepoly = + function (e) { + var pc = e.target; + if ( + pc._lastConnectionState !== + pc.connectionState + ) { + pc._lastConnectionState = + pc.connectionState; + var newEvent = new Event( + "connectionstatechange", + e + ); + pc.dispatchEvent(newEvent); + } + return e; + }; + this.addEventListener( + "iceconnectionstatechange", + this._connectionstatechangepoly + ); + } + return origMethod.apply(this, arguments); + }; + } + ); + } + + function removeExtmapAllowMixed(window, browserDetails) { + /* remove a=extmap-allow-mixed for webrtc.org < M71 */ + if (!window.RTCPeerConnection) { + return; + } + if ( + browserDetails.browser === "chrome" && + browserDetails.version >= 71 + ) { + return; + } + if ( + browserDetails.browser === "safari" && + browserDetails.version >= 605 + ) { + return; + } + var nativeSRD = + window.RTCPeerConnection.prototype + .setRemoteDescription; + window.RTCPeerConnection.prototype.setRemoteDescription = + function setRemoteDescription(desc) { + if ( + desc && + desc.sdp && + desc.sdp.indexOf( + "\na=extmap-allow-mixed" + ) !== -1 + ) { + var sdp = desc.sdp + .split("\n") + .filter(function (line) { + return ( + line.trim() !== + "a=extmap-allow-mixed" + ); + }) + .join("\n"); + // Safari enforces read-only-ness of RTCSessionDescription fields. + if ( + window.RTCSessionDescription && + desc instanceof + window.RTCSessionDescription + ) { + arguments[0] = + new window.RTCSessionDescription({ + type: desc.type, + sdp: sdp, + }); + } else { + desc.sdp = sdp; + } + } + return nativeSRD.apply(this, arguments); + }; + } + + function shimAddIceCandidateNullOrEmpty( + window, + browserDetails + ) { + // Support for addIceCandidate(null or undefined) + // as well as addIceCandidate({candidate: "", ...}) + // https://bugs.chromium.org/p/chromium/issues/detail?id=978582 + // Note: must be called before other polyfills which change the signature. + if ( + !( + window.RTCPeerConnection && + window.RTCPeerConnection.prototype + ) + ) { + return; + } + var nativeAddIceCandidate = + window.RTCPeerConnection.prototype.addIceCandidate; + if ( + !nativeAddIceCandidate || + nativeAddIceCandidate.length === 0 + ) { + return; + } + window.RTCPeerConnection.prototype.addIceCandidate = + function addIceCandidate() { + if (!arguments[0]) { + if (arguments[1]) { + arguments[1].apply(null); + } + return Promise.resolve(); + } + // Firefox 68+ emits and processes {candidate: "", ...}, ignore + // in older versions. + // Native support for ignoring exists for Chrome M77+. + // Safari ignores as well, exact version unknown but works in the same + // version that also ignores addIceCandidate(null). + if ( + ((browserDetails.browser === "chrome" && + browserDetails.version < 78) || + (browserDetails.browser === "firefox" && + browserDetails.version < 68) || + browserDetails.browser === "safari") && + arguments[0] && + arguments[0].candidate === "" + ) { + return Promise.resolve(); + } + return nativeAddIceCandidate.apply( + this, + arguments + ); + }; + } + }, + { "./utils": 11, sdp: 12 }, + ], + 7: [ + function (require, module, exports) { + /* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. + */ + /* eslint-env node */ + "use strict"; + + Object.defineProperty(exports, "__esModule", { + value: true, + }); + exports.shimGetDisplayMedia = exports.shimGetUserMedia = + undefined; + + var _typeof = + typeof Symbol === "function" && + typeof Symbol.iterator === "symbol" + ? function (obj) { + return typeof obj; + } + : function (obj) { + return obj && + typeof Symbol === "function" && + obj.constructor === Symbol && + obj !== Symbol.prototype + ? "symbol" + : typeof obj; + }; + + var _getusermedia = require("./getusermedia"); + + Object.defineProperty(exports, "shimGetUserMedia", { + enumerable: true, + get: function get() { + return _getusermedia.shimGetUserMedia; + }, + }); + + var _getdisplaymedia = require("./getdisplaymedia"); + + Object.defineProperty(exports, "shimGetDisplayMedia", { + enumerable: true, + get: function get() { + return _getdisplaymedia.shimGetDisplayMedia; + }, + }); + exports.shimOnTrack = shimOnTrack; + exports.shimPeerConnection = shimPeerConnection; + exports.shimSenderGetStats = shimSenderGetStats; + exports.shimReceiverGetStats = shimReceiverGetStats; + exports.shimRemoveStream = shimRemoveStream; + exports.shimRTCDataChannel = shimRTCDataChannel; + exports.shimAddTransceiver = shimAddTransceiver; + exports.shimGetParameters = shimGetParameters; + exports.shimCreateOffer = shimCreateOffer; + exports.shimCreateAnswer = shimCreateAnswer; + + var _utils = require("../utils"); + + var utils = _interopRequireWildcard(_utils); + + function _interopRequireWildcard(obj) { + if (obj && obj.__esModule) { + return obj; + } else { + var newObj = {}; + if (obj != null) { + for (var key in obj) { + if ( + Object.prototype.hasOwnProperty.call( + obj, + key + ) + ) + newObj[key] = obj[key]; + } + } + newObj.default = obj; + return newObj; + } + } + + function _defineProperty(obj, key, value) { + if (key in obj) { + Object.defineProperty(obj, key, { + value: value, + enumerable: true, + configurable: true, + writable: true, + }); + } else { + obj[key] = value; + } + return obj; + } + + function shimOnTrack(window) { + if ( + (typeof window === "undefined" + ? "undefined" + : _typeof(window)) === "object" && + window.RTCTrackEvent && + "receiver" in window.RTCTrackEvent.prototype && + !("transceiver" in window.RTCTrackEvent.prototype) + ) { + Object.defineProperty( + window.RTCTrackEvent.prototype, + "transceiver", + { + get: function get() { + return { receiver: this.receiver }; + }, + } + ); + } + } + + function shimPeerConnection(window, browserDetails) { + if ( + (typeof window === "undefined" + ? "undefined" + : _typeof(window)) !== "object" || + !( + window.RTCPeerConnection || + window.mozRTCPeerConnection + ) + ) { + return; // probably media.peerconnection.enabled=false in about:config + } + if ( + !window.RTCPeerConnection && + window.mozRTCPeerConnection + ) { + // very basic support for old versions. + window.RTCPeerConnection = + window.mozRTCPeerConnection; + } + + if (browserDetails.version < 53) { + // shim away need for obsolete RTCIceCandidate/RTCSessionDescription. + [ + "setLocalDescription", + "setRemoteDescription", + "addIceCandidate", + ].forEach(function (method) { + var nativeMethod = + window.RTCPeerConnection.prototype[method]; + var methodObj = _defineProperty( + {}, + method, + function () { + arguments[0] = new ( + method === "addIceCandidate" + ? window.RTCIceCandidate + : window.RTCSessionDescription + )(arguments[0]); + return nativeMethod.apply( + this, + arguments + ); + } + ); + window.RTCPeerConnection.prototype[method] = + methodObj[method]; + }); + } + + var modernStatsTypes = { + inboundrtp: "inbound-rtp", + outboundrtp: "outbound-rtp", + candidatepair: "candidate-pair", + localcandidate: "local-candidate", + remotecandidate: "remote-candidate", + }; + + var nativeGetStats = + window.RTCPeerConnection.prototype.getStats; + window.RTCPeerConnection.prototype.getStats = + function getStats() { + var _arguments = + Array.prototype.slice.call(arguments), + selector = _arguments[0], + onSucc = _arguments[1], + onErr = _arguments[2]; + + return nativeGetStats + .apply(this, [selector || null]) + .then(function (stats) { + if ( + browserDetails.version < 53 && + !onSucc + ) { + // Shim only promise getStats with spec-hyphens in type names + // Leave callback version alone; misc old uses of forEach before Map + try { + stats.forEach(function (stat) { + stat.type = + modernStatsTypes[ + stat.type + ] || stat.type; + }); + } catch (e) { + if (e.name !== "TypeError") { + throw e; + } + // Avoid TypeError: "type" is read-only, in old versions. 34-43ish + stats.forEach(function ( + stat, + i + ) { + stats.set( + i, + Object.assign( + {}, + stat, + { + type: + modernStatsTypes[ + stat + .type + ] || + stat.type, + } + ) + ); + }); + } + } + return stats; + }) + .then(onSucc, onErr); + }; + } + + function shimSenderGetStats(window) { + if ( + !( + (typeof window === "undefined" + ? "undefined" + : _typeof(window)) === "object" && + window.RTCPeerConnection && + window.RTCRtpSender + ) + ) { + return; + } + if ( + window.RTCRtpSender && + "getStats" in window.RTCRtpSender.prototype + ) { + return; + } + var origGetSenders = + window.RTCPeerConnection.prototype.getSenders; + if (origGetSenders) { + window.RTCPeerConnection.prototype.getSenders = + function getSenders() { + var _this = this; + + var senders = origGetSenders.apply( + this, + [] + ); + senders.forEach(function (sender) { + return (sender._pc = _this); + }); + return senders; + }; + } + + var origAddTrack = + window.RTCPeerConnection.prototype.addTrack; + if (origAddTrack) { + window.RTCPeerConnection.prototype.addTrack = + function addTrack() { + var sender = origAddTrack.apply( + this, + arguments + ); + sender._pc = this; + return sender; + }; + } + window.RTCRtpSender.prototype.getStats = + function getStats() { + return this.track + ? this._pc.getStats(this.track) + : Promise.resolve(new Map()); + }; + } + + function shimReceiverGetStats(window) { + if ( + !( + (typeof window === "undefined" + ? "undefined" + : _typeof(window)) === "object" && + window.RTCPeerConnection && + window.RTCRtpSender + ) + ) { + return; + } + if ( + window.RTCRtpSender && + "getStats" in window.RTCRtpReceiver.prototype + ) { + return; + } + var origGetReceivers = + window.RTCPeerConnection.prototype.getReceivers; + if (origGetReceivers) { + window.RTCPeerConnection.prototype.getReceivers = + function getReceivers() { + var _this2 = this; + + var receivers = origGetReceivers.apply( + this, + [] + ); + receivers.forEach(function (receiver) { + return (receiver._pc = _this2); + }); + return receivers; + }; + } + utils.wrapPeerConnectionEvent( + window, + "track", + function (e) { + e.receiver._pc = e.srcElement; + return e; + } + ); + window.RTCRtpReceiver.prototype.getStats = + function getStats() { + return this._pc.getStats(this.track); + }; + } + + function shimRemoveStream(window) { + if ( + !window.RTCPeerConnection || + "removeStream" in window.RTCPeerConnection.prototype + ) { + return; + } + window.RTCPeerConnection.prototype.removeStream = + function removeStream(stream) { + var _this3 = this; + + utils.deprecated("removeStream", "removeTrack"); + this.getSenders().forEach(function (sender) { + if ( + sender.track && + stream + .getTracks() + .includes(sender.track) + ) { + _this3.removeTrack(sender); + } + }); + }; + } + + function shimRTCDataChannel(window) { + // rename DataChannel to RTCDataChannel (native fix in FF60): + // https://bugzilla.mozilla.org/show_bug.cgi?id=1173851 + if (window.DataChannel && !window.RTCDataChannel) { + window.RTCDataChannel = window.DataChannel; + } + } + + function shimAddTransceiver(window) { + // https://github.com/webrtcHacks/adapter/issues/998#issuecomment-516921647 + // Firefox ignores the init sendEncodings options passed to addTransceiver + // https://bugzilla.mozilla.org/show_bug.cgi?id=1396918 + if ( + !( + (typeof window === "undefined" + ? "undefined" + : _typeof(window)) === "object" && + window.RTCPeerConnection + ) + ) { + return; + } + var origAddTransceiver = + window.RTCPeerConnection.prototype.addTransceiver; + if (origAddTransceiver) { + window.RTCPeerConnection.prototype.addTransceiver = + function addTransceiver() { + this.setParametersPromises = []; + var initParameters = arguments[1]; + var shouldPerformCheck = + initParameters && + "sendEncodings" in initParameters; + if (shouldPerformCheck) { + // If sendEncodings params are provided, validate grammar + initParameters.sendEncodings.forEach( + function (encodingParam) { + if ("rid" in encodingParam) { + var ridRegex = + /^[a-z0-9]{0,16}$/i; + if ( + !ridRegex.test( + encodingParam.rid + ) + ) { + throw new TypeError( + "Invalid RID value provided." + ); + } + } + if ( + "scaleResolutionDownBy" in + encodingParam + ) { + if ( + !( + parseFloat( + encodingParam.scaleResolutionDownBy + ) >= 1.0 + ) + ) { + throw new RangeError( + "scale_resolution_down_by must be >= 1.0" + ); + } + } + if ( + "maxFramerate" in + encodingParam + ) { + if ( + !( + parseFloat( + encodingParam.maxFramerate + ) >= 0 + ) + ) { + throw new RangeError( + "max_framerate must be >= 0.0" + ); + } + } + } + ); + } + var transceiver = origAddTransceiver.apply( + this, + arguments + ); + if (shouldPerformCheck) { + // Check if the init options were applied. If not we do this in an + // asynchronous way and save the promise reference in a global object. + // This is an ugly hack, but at the same time is way more robust than + // checking the sender parameters before and after the createOffer + // Also note that after the createoffer we are not 100% sure that + // the params were asynchronously applied so we might miss the + // opportunity to recreate offer. + var sender = transceiver.sender; + + var params = sender.getParameters(); + if ( + !("encodings" in params) || + // Avoid being fooled by patched getParameters() below. + (params.encodings.length === 1 && + Object.keys(params.encodings[0]) + .length === 0) + ) { + params.encodings = + initParameters.sendEncodings; + sender.sendEncodings = + initParameters.sendEncodings; + this.setParametersPromises.push( + sender + .setParameters(params) + .then(function () { + delete sender.sendEncodings; + }) + .catch(function () { + delete sender.sendEncodings; + }) + ); + } + } + return transceiver; + }; + } + } + + function shimGetParameters(window) { + if ( + !( + (typeof window === "undefined" + ? "undefined" + : _typeof(window)) === "object" && + window.RTCRtpSender + ) + ) { + return; + } + var origGetParameters = + window.RTCRtpSender.prototype.getParameters; + if (origGetParameters) { + window.RTCRtpSender.prototype.getParameters = + function getParameters() { + var params = origGetParameters.apply( + this, + arguments + ); + if (!("encodings" in params)) { + params.encodings = [].concat( + this.sendEncodings || [{}] + ); + } + return params; + }; + } + } + + function shimCreateOffer(window) { + // https://github.com/webrtcHacks/adapter/issues/998#issuecomment-516921647 + // Firefox ignores the init sendEncodings options passed to addTransceiver + // https://bugzilla.mozilla.org/show_bug.cgi?id=1396918 + if ( + !( + (typeof window === "undefined" + ? "undefined" + : _typeof(window)) === "object" && + window.RTCPeerConnection + ) + ) { + return; + } + var origCreateOffer = + window.RTCPeerConnection.prototype.createOffer; + window.RTCPeerConnection.prototype.createOffer = + function createOffer() { + var _this4 = this, + _arguments2 = arguments; + + if ( + this.setParametersPromises && + this.setParametersPromises.length + ) { + return Promise.all( + this.setParametersPromises + ) + .then(function () { + return origCreateOffer.apply( + _this4, + _arguments2 + ); + }) + .finally(function () { + _this4.setParametersPromises = []; + }); + } + return origCreateOffer.apply(this, arguments); + }; + } + + function shimCreateAnswer(window) { + // https://github.com/webrtcHacks/adapter/issues/998#issuecomment-516921647 + // Firefox ignores the init sendEncodings options passed to addTransceiver + // https://bugzilla.mozilla.org/show_bug.cgi?id=1396918 + if ( + !( + (typeof window === "undefined" + ? "undefined" + : _typeof(window)) === "object" && + window.RTCPeerConnection + ) + ) { + return; + } + var origCreateAnswer = + window.RTCPeerConnection.prototype.createAnswer; + window.RTCPeerConnection.prototype.createAnswer = + function createAnswer() { + var _this5 = this, + _arguments3 = arguments; + + if ( + this.setParametersPromises && + this.setParametersPromises.length + ) { + return Promise.all( + this.setParametersPromises + ) + .then(function () { + return origCreateAnswer.apply( + _this5, + _arguments3 + ); + }) + .finally(function () { + _this5.setParametersPromises = []; + }); + } + return origCreateAnswer.apply(this, arguments); + }; + } + }, + { "../utils": 11, "./getdisplaymedia": 8, "./getusermedia": 9 }, + ], + 8: [ + function (require, module, exports) { + /* + * Copyright (c) 2018 The adapter.js project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. + */ + /* eslint-env node */ + "use strict"; + + Object.defineProperty(exports, "__esModule", { + value: true, + }); + exports.shimGetDisplayMedia = shimGetDisplayMedia; + function shimGetDisplayMedia(window, preferredMediaSource) { + if ( + window.navigator.mediaDevices && + "getDisplayMedia" in window.navigator.mediaDevices + ) { + return; + } + if (!window.navigator.mediaDevices) { + return; + } + window.navigator.mediaDevices.getDisplayMedia = + function getDisplayMedia(constraints) { + if (!(constraints && constraints.video)) { + var err = new DOMException( + "getDisplayMedia without video " + + "constraints is undefined" + ); + err.name = "NotFoundError"; + // from https://heycam.github.io/webidl/#idl-DOMException-error-names + err.code = 8; + return Promise.reject(err); + } + if (constraints.video === true) { + constraints.video = { + mediaSource: preferredMediaSource, + }; + } else { + constraints.video.mediaSource = + preferredMediaSource; + } + return window.navigator.mediaDevices.getUserMedia( + constraints + ); + }; + } + }, + {}, + ], + 9: [ + function (require, module, exports) { + /* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. + */ + /* eslint-env node */ + "use strict"; + + Object.defineProperty(exports, "__esModule", { + value: true, + }); + + var _typeof = + typeof Symbol === "function" && + typeof Symbol.iterator === "symbol" + ? function (obj) { + return typeof obj; + } + : function (obj) { + return obj && + typeof Symbol === "function" && + obj.constructor === Symbol && + obj !== Symbol.prototype + ? "symbol" + : typeof obj; + }; + + exports.shimGetUserMedia = shimGetUserMedia; + + var _utils = require("../utils"); + + var utils = _interopRequireWildcard(_utils); + + function _interopRequireWildcard(obj) { + if (obj && obj.__esModule) { + return obj; + } else { + var newObj = {}; + if (obj != null) { + for (var key in obj) { + if ( + Object.prototype.hasOwnProperty.call( + obj, + key + ) + ) + newObj[key] = obj[key]; + } + } + newObj.default = obj; + return newObj; + } + } + + function shimGetUserMedia(window, browserDetails) { + var navigator = window && window.navigator; + var MediaStreamTrack = + window && window.MediaStreamTrack; + + navigator.getUserMedia = function ( + constraints, + onSuccess, + onError + ) { + // Replace Firefox 44+'s deprecation warning with unprefixed version. + utils.deprecated( + "navigator.getUserMedia", + "navigator.mediaDevices.getUserMedia" + ); + navigator.mediaDevices + .getUserMedia(constraints) + .then(onSuccess, onError); + }; + + if ( + !( + browserDetails.version > 55 && + "autoGainControl" in + navigator.mediaDevices.getSupportedConstraints() + ) + ) { + var remap = function remap(obj, a, b) { + if (a in obj && !(b in obj)) { + obj[b] = obj[a]; + delete obj[a]; + } + }; + + var nativeGetUserMedia = + navigator.mediaDevices.getUserMedia.bind( + navigator.mediaDevices + ); + navigator.mediaDevices.getUserMedia = function (c) { + if ( + (typeof c === "undefined" + ? "undefined" + : _typeof(c)) === "object" && + _typeof(c.audio) === "object" + ) { + c = JSON.parse(JSON.stringify(c)); + remap( + c.audio, + "autoGainControl", + "mozAutoGainControl" + ); + remap( + c.audio, + "noiseSuppression", + "mozNoiseSuppression" + ); + } + return nativeGetUserMedia(c); + }; + + if ( + MediaStreamTrack && + MediaStreamTrack.prototype.getSettings + ) { + var nativeGetSettings = + MediaStreamTrack.prototype.getSettings; + MediaStreamTrack.prototype.getSettings = + function () { + var obj = nativeGetSettings.apply( + this, + arguments + ); + remap( + obj, + "mozAutoGainControl", + "autoGainControl" + ); + remap( + obj, + "mozNoiseSuppression", + "noiseSuppression" + ); + return obj; + }; + } + + if ( + MediaStreamTrack && + MediaStreamTrack.prototype.applyConstraints + ) { + var nativeApplyConstraints = + MediaStreamTrack.prototype.applyConstraints; + MediaStreamTrack.prototype.applyConstraints = + function (c) { + if ( + this.kind === "audio" && + (typeof c === "undefined" + ? "undefined" + : _typeof(c)) === "object" + ) { + c = JSON.parse(JSON.stringify(c)); + remap( + c, + "autoGainControl", + "mozAutoGainControl" + ); + remap( + c, + "noiseSuppression", + "mozNoiseSuppression" + ); + } + return nativeApplyConstraints.apply( + this, + [c] + ); + }; + } + } + } + }, + { "../utils": 11 }, + ], + 10: [ + function (require, module, exports) { + /* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. + */ + "use strict"; + + Object.defineProperty(exports, "__esModule", { + value: true, + }); + + var _typeof = + typeof Symbol === "function" && + typeof Symbol.iterator === "symbol" + ? function (obj) { + return typeof obj; + } + : function (obj) { + return obj && + typeof Symbol === "function" && + obj.constructor === Symbol && + obj !== Symbol.prototype + ? "symbol" + : typeof obj; + }; + + exports.shimLocalStreamsAPI = shimLocalStreamsAPI; + exports.shimRemoteStreamsAPI = shimRemoteStreamsAPI; + exports.shimCallbacksAPI = shimCallbacksAPI; + exports.shimGetUserMedia = shimGetUserMedia; + exports.shimConstraints = shimConstraints; + exports.shimRTCIceServerUrls = shimRTCIceServerUrls; + exports.shimTrackEventTransceiver = + shimTrackEventTransceiver; + exports.shimCreateOfferLegacy = shimCreateOfferLegacy; + exports.shimAudioContext = shimAudioContext; + + var _utils = require("../utils"); + + var utils = _interopRequireWildcard(_utils); + + function _interopRequireWildcard(obj) { + if (obj && obj.__esModule) { + return obj; + } else { + var newObj = {}; + if (obj != null) { + for (var key in obj) { + if ( + Object.prototype.hasOwnProperty.call( + obj, + key + ) + ) + newObj[key] = obj[key]; + } + } + newObj.default = obj; + return newObj; + } + } + + function shimLocalStreamsAPI(window) { + if ( + (typeof window === "undefined" + ? "undefined" + : _typeof(window)) !== "object" || + !window.RTCPeerConnection + ) { + return; + } + if ( + !( + "getLocalStreams" in + window.RTCPeerConnection.prototype + ) + ) { + window.RTCPeerConnection.prototype.getLocalStreams = + function getLocalStreams() { + if (!this._localStreams) { + this._localStreams = []; + } + return this._localStreams; + }; + } + if ( + !("addStream" in window.RTCPeerConnection.prototype) + ) { + var _addTrack = + window.RTCPeerConnection.prototype.addTrack; + window.RTCPeerConnection.prototype.addStream = + function addStream(stream) { + var _this = this; + + if (!this._localStreams) { + this._localStreams = []; + } + if (!this._localStreams.includes(stream)) { + this._localStreams.push(stream); + } + // Try to emulate Chrome's behaviour of adding in audio-video order. + // Safari orders by track id. + stream + .getAudioTracks() + .forEach(function (track) { + return _addTrack.call( + _this, + track, + stream + ); + }); + stream + .getVideoTracks() + .forEach(function (track) { + return _addTrack.call( + _this, + track, + stream + ); + }); + }; + + window.RTCPeerConnection.prototype.addTrack = + function addTrack(track) { + var _this2 = this; + + for ( + var _len = arguments.length, + streams = Array( + _len > 1 ? _len - 1 : 0 + ), + _key = 1; + _key < _len; + _key++ + ) { + streams[_key - 1] = arguments[_key]; + } + + if (streams) { + streams.forEach(function (stream) { + if (!_this2._localStreams) { + _this2._localStreams = [stream]; + } else if ( + !_this2._localStreams.includes( + stream + ) + ) { + _this2._localStreams.push( + stream + ); + } + }); + } + return _addTrack.apply(this, arguments); + }; + } + if ( + !( + "removeStream" in + window.RTCPeerConnection.prototype + ) + ) { + window.RTCPeerConnection.prototype.removeStream = + function removeStream(stream) { + var _this3 = this; + + if (!this._localStreams) { + this._localStreams = []; + } + var index = + this._localStreams.indexOf(stream); + if (index === -1) { + return; + } + this._localStreams.splice(index, 1); + var tracks = stream.getTracks(); + this.getSenders().forEach(function ( + sender + ) { + if (tracks.includes(sender.track)) { + _this3.removeTrack(sender); + } + }); + }; + } + } + + function shimRemoteStreamsAPI(window) { + if ( + (typeof window === "undefined" + ? "undefined" + : _typeof(window)) !== "object" || + !window.RTCPeerConnection + ) { + return; + } + if ( + !( + "getRemoteStreams" in + window.RTCPeerConnection.prototype + ) + ) { + window.RTCPeerConnection.prototype.getRemoteStreams = + function getRemoteStreams() { + return this._remoteStreams + ? this._remoteStreams + : []; + }; + } + if ( + !( + "onaddstream" in + window.RTCPeerConnection.prototype + ) + ) { + Object.defineProperty( + window.RTCPeerConnection.prototype, + "onaddstream", + { + get: function get() { + return this._onaddstream; + }, + set: function set(f) { + var _this4 = this; + + if (this._onaddstream) { + this.removeEventListener( + "addstream", + this._onaddstream + ); + this.removeEventListener( + "track", + this._onaddstreampoly + ); + } + this.addEventListener( + "addstream", + (this._onaddstream = f) + ); + this.addEventListener( + "track", + (this._onaddstreampoly = function ( + e + ) { + e.streams.forEach(function ( + stream + ) { + if ( + !_this4._remoteStreams + ) { + _this4._remoteStreams = + []; + } + if ( + _this4._remoteStreams.includes( + stream + ) + ) { + return; + } + _this4._remoteStreams.push( + stream + ); + var event = new Event( + "addstream" + ); + event.stream = stream; + _this4.dispatchEvent(event); + }); + }) + ); + }, + } + ); + var origSetRemoteDescription = + window.RTCPeerConnection.prototype + .setRemoteDescription; + window.RTCPeerConnection.prototype.setRemoteDescription = + function setRemoteDescription() { + var pc = this; + if (!this._onaddstreampoly) { + this.addEventListener( + "track", + (this._onaddstreampoly = function ( + e + ) { + e.streams.forEach(function ( + stream + ) { + if (!pc._remoteStreams) { + pc._remoteStreams = []; + } + if ( + pc._remoteStreams.indexOf( + stream + ) >= 0 + ) { + return; + } + pc._remoteStreams.push( + stream + ); + var event = new Event( + "addstream" + ); + event.stream = stream; + pc.dispatchEvent(event); + }); + }) + ); + } + return origSetRemoteDescription.apply( + pc, + arguments + ); + }; + } + } + + function shimCallbacksAPI(window) { + if ( + (typeof window === "undefined" + ? "undefined" + : _typeof(window)) !== "object" || + !window.RTCPeerConnection + ) { + return; + } + var prototype = window.RTCPeerConnection.prototype; + var origCreateOffer = prototype.createOffer; + var origCreateAnswer = prototype.createAnswer; + var setLocalDescription = prototype.setLocalDescription; + var setRemoteDescription = + prototype.setRemoteDescription; + var addIceCandidate = prototype.addIceCandidate; + + prototype.createOffer = function createOffer( + successCallback, + failureCallback + ) { + var options = + arguments.length >= 2 + ? arguments[2] + : arguments[0]; + var promise = origCreateOffer.apply(this, [ + options, + ]); + if (!failureCallback) { + return promise; + } + promise.then(successCallback, failureCallback); + return Promise.resolve(); + }; + + prototype.createAnswer = function createAnswer( + successCallback, + failureCallback + ) { + var options = + arguments.length >= 2 + ? arguments[2] + : arguments[0]; + var promise = origCreateAnswer.apply(this, [ + options, + ]); + if (!failureCallback) { + return promise; + } + promise.then(successCallback, failureCallback); + return Promise.resolve(); + }; + + var withCallback = function withCallback( + description, + successCallback, + failureCallback + ) { + var promise = setLocalDescription.apply(this, [ + description, + ]); + if (!failureCallback) { + return promise; + } + promise.then(successCallback, failureCallback); + return Promise.resolve(); + }; + prototype.setLocalDescription = withCallback; + + withCallback = function withCallback( + description, + successCallback, + failureCallback + ) { + var promise = setRemoteDescription.apply(this, [ + description, + ]); + if (!failureCallback) { + return promise; + } + promise.then(successCallback, failureCallback); + return Promise.resolve(); + }; + prototype.setRemoteDescription = withCallback; + + withCallback = function withCallback( + candidate, + successCallback, + failureCallback + ) { + var promise = addIceCandidate.apply(this, [ + candidate, + ]); + if (!failureCallback) { + return promise; + } + promise.then(successCallback, failureCallback); + return Promise.resolve(); + }; + prototype.addIceCandidate = withCallback; + } + + function shimGetUserMedia(window) { + var navigator = window && window.navigator; + + if ( + navigator.mediaDevices && + navigator.mediaDevices.getUserMedia + ) { + // shim not needed in Safari 12.1 + var mediaDevices = navigator.mediaDevices; + var _getUserMedia = + mediaDevices.getUserMedia.bind(mediaDevices); + navigator.mediaDevices.getUserMedia = function ( + constraints + ) { + return _getUserMedia( + shimConstraints(constraints) + ); + }; + } + + if ( + !navigator.getUserMedia && + navigator.mediaDevices && + navigator.mediaDevices.getUserMedia + ) { + navigator.getUserMedia = function getUserMedia( + constraints, + cb, + errcb + ) { + navigator.mediaDevices + .getUserMedia(constraints) + .then(cb, errcb); + }.bind(navigator); + } + } + + function shimConstraints(constraints) { + if (constraints && constraints.video !== undefined) { + return Object.assign({}, constraints, { + video: utils.compactObject(constraints.video), + }); + } + + return constraints; + } + + function shimRTCIceServerUrls(window) { + if (!window.RTCPeerConnection) { + return; + } + // migrate from non-spec RTCIceServer.url to RTCIceServer.urls + var OrigPeerConnection = window.RTCPeerConnection; + window.RTCPeerConnection = function RTCPeerConnection( + pcConfig, + pcConstraints + ) { + if (pcConfig && pcConfig.iceServers) { + var newIceServers = []; + for ( + var i = 0; + i < pcConfig.iceServers.length; + i++ + ) { + var server = pcConfig.iceServers[i]; + if ( + !server.hasOwnProperty("urls") && + server.hasOwnProperty("url") + ) { + utils.deprecated( + "RTCIceServer.url", + "RTCIceServer.urls" + ); + server = JSON.parse( + JSON.stringify(server) + ); + server.urls = server.url; + delete server.url; + newIceServers.push(server); + } else { + newIceServers.push( + pcConfig.iceServers[i] + ); + } + } + pcConfig.iceServers = newIceServers; + } + return new OrigPeerConnection( + pcConfig, + pcConstraints + ); + }; + window.RTCPeerConnection.prototype = + OrigPeerConnection.prototype; + // wrap static methods. Currently just generateCertificate. + if ("generateCertificate" in OrigPeerConnection) { + Object.defineProperty( + window.RTCPeerConnection, + "generateCertificate", + { + get: function get() { + return OrigPeerConnection.generateCertificate; + }, + } + ); + } + } + + function shimTrackEventTransceiver(window) { + // Add event.transceiver member over deprecated event.receiver + if ( + (typeof window === "undefined" + ? "undefined" + : _typeof(window)) === "object" && + window.RTCTrackEvent && + "receiver" in window.RTCTrackEvent.prototype && + !("transceiver" in window.RTCTrackEvent.prototype) + ) { + Object.defineProperty( + window.RTCTrackEvent.prototype, + "transceiver", + { + get: function get() { + return { receiver: this.receiver }; + }, + } + ); + } + } + + function shimCreateOfferLegacy(window) { + var origCreateOffer = + window.RTCPeerConnection.prototype.createOffer; + window.RTCPeerConnection.prototype.createOffer = + function createOffer(offerOptions) { + if (offerOptions) { + if ( + typeof offerOptions.offerToReceiveAudio !== + "undefined" + ) { + // support bit values + offerOptions.offerToReceiveAudio = + !!offerOptions.offerToReceiveAudio; + } + var audioTransceiver = + this.getTransceivers().find(function ( + transceiver + ) { + return ( + transceiver.receiver.track + .kind === "audio" + ); + }); + if ( + offerOptions.offerToReceiveAudio === + false && + audioTransceiver + ) { + if ( + audioTransceiver.direction === + "sendrecv" + ) { + if (audioTransceiver.setDirection) { + audioTransceiver.setDirection( + "sendonly" + ); + } else { + audioTransceiver.direction = + "sendonly"; + } + } else if ( + audioTransceiver.direction === + "recvonly" + ) { + if (audioTransceiver.setDirection) { + audioTransceiver.setDirection( + "inactive" + ); + } else { + audioTransceiver.direction = + "inactive"; + } + } + } else if ( + offerOptions.offerToReceiveAudio === + true && + !audioTransceiver + ) { + this.addTransceiver("audio"); + } + + if ( + typeof offerOptions.offerToReceiveVideo !== + "undefined" + ) { + // support bit values + offerOptions.offerToReceiveVideo = + !!offerOptions.offerToReceiveVideo; + } + var videoTransceiver = + this.getTransceivers().find(function ( + transceiver + ) { + return ( + transceiver.receiver.track + .kind === "video" + ); + }); + if ( + offerOptions.offerToReceiveVideo === + false && + videoTransceiver + ) { + if ( + videoTransceiver.direction === + "sendrecv" + ) { + if (videoTransceiver.setDirection) { + videoTransceiver.setDirection( + "sendonly" + ); + } else { + videoTransceiver.direction = + "sendonly"; + } + } else if ( + videoTransceiver.direction === + "recvonly" + ) { + if (videoTransceiver.setDirection) { + videoTransceiver.setDirection( + "inactive" + ); + } else { + videoTransceiver.direction = + "inactive"; + } + } + } else if ( + offerOptions.offerToReceiveVideo === + true && + !videoTransceiver + ) { + this.addTransceiver("video"); + } + } + return origCreateOffer.apply(this, arguments); + }; + } + + function shimAudioContext(window) { + if ( + (typeof window === "undefined" + ? "undefined" + : _typeof(window)) !== "object" || + window.AudioContext + ) { + return; + } + window.AudioContext = window.webkitAudioContext; + } + }, + { "../utils": 11 }, + ], + 11: [ + function (require, module, exports) { + /* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. + */ + /* eslint-env node */ + "use strict"; + + Object.defineProperty(exports, "__esModule", { + value: true, + }); + + var _typeof = + typeof Symbol === "function" && + typeof Symbol.iterator === "symbol" + ? function (obj) { + return typeof obj; + } + : function (obj) { + return obj && + typeof Symbol === "function" && + obj.constructor === Symbol && + obj !== Symbol.prototype + ? "symbol" + : typeof obj; + }; + + exports.extractVersion = extractVersion; + exports.wrapPeerConnectionEvent = wrapPeerConnectionEvent; + exports.disableLog = disableLog; + exports.disableWarnings = disableWarnings; + exports.log = log; + exports.deprecated = deprecated; + exports.detectBrowser = detectBrowser; + exports.compactObject = compactObject; + exports.walkStats = walkStats; + exports.filterStats = filterStats; + + function _defineProperty(obj, key, value) { + if (key in obj) { + Object.defineProperty(obj, key, { + value: value, + enumerable: true, + configurable: true, + writable: true, + }); + } else { + obj[key] = value; + } + return obj; + } + + var logDisabled_ = true; + var deprecationWarnings_ = true; + + /** + * Extract browser version out of the provided user agent string. + * + * @param {!string} uastring userAgent string. + * @param {!string} expr Regular expression used as match criteria. + * @param {!number} pos position in the version string to be returned. + * @return {!number} browser version. + */ + function extractVersion(uastring, expr, pos) { + var match = uastring.match(expr); + return ( + match && + match.length >= pos && + parseInt(match[pos], 10) + ); + } + + // Wraps the peerconnection event eventNameToWrap in a function + // which returns the modified event object (or false to prevent + // the event). + function wrapPeerConnectionEvent( + window, + eventNameToWrap, + wrapper + ) { + if (!window.RTCPeerConnection) { + return; + } + var proto = window.RTCPeerConnection.prototype; + var nativeAddEventListener = proto.addEventListener; + proto.addEventListener = function ( + nativeEventName, + cb + ) { + if (nativeEventName !== eventNameToWrap) { + return nativeAddEventListener.apply( + this, + arguments + ); + } + var wrappedCallback = function wrappedCallback(e) { + var modifiedEvent = wrapper(e); + if (modifiedEvent) { + if (cb.handleEvent) { + cb.handleEvent(modifiedEvent); + } else { + cb(modifiedEvent); + } + } + }; + this._eventMap = this._eventMap || {}; + if (!this._eventMap[eventNameToWrap]) { + this._eventMap[eventNameToWrap] = new Map(); + } + this._eventMap[eventNameToWrap].set( + cb, + wrappedCallback + ); + return nativeAddEventListener.apply(this, [ + nativeEventName, + wrappedCallback, + ]); + }; + + var nativeRemoveEventListener = + proto.removeEventListener; + proto.removeEventListener = function ( + nativeEventName, + cb + ) { + if ( + nativeEventName !== eventNameToWrap || + !this._eventMap || + !this._eventMap[eventNameToWrap] + ) { + return nativeRemoveEventListener.apply( + this, + arguments + ); + } + if (!this._eventMap[eventNameToWrap].has(cb)) { + return nativeRemoveEventListener.apply( + this, + arguments + ); + } + var unwrappedCb = + this._eventMap[eventNameToWrap].get(cb); + this._eventMap[eventNameToWrap].delete(cb); + if (this._eventMap[eventNameToWrap].size === 0) { + delete this._eventMap[eventNameToWrap]; + } + if (Object.keys(this._eventMap).length === 0) { + delete this._eventMap; + } + return nativeRemoveEventListener.apply(this, [ + nativeEventName, + unwrappedCb, + ]); + }; + + Object.defineProperty(proto, "on" + eventNameToWrap, { + get: function get() { + return this["_on" + eventNameToWrap]; + }, + set: function set(cb) { + if (this["_on" + eventNameToWrap]) { + this.removeEventListener( + eventNameToWrap, + this["_on" + eventNameToWrap] + ); + delete this["_on" + eventNameToWrap]; + } + if (cb) { + this.addEventListener( + eventNameToWrap, + (this["_on" + eventNameToWrap] = cb) + ); + } + }, + + enumerable: true, + configurable: true, + }); + } + + function disableLog(bool) { + if (typeof bool !== "boolean") { + return new Error( + "Argument type: " + + (typeof bool === "undefined" + ? "undefined" + : _typeof(bool)) + + ". Please use a boolean." + ); + } + logDisabled_ = bool; + return bool + ? "adapter.js logging disabled" + : "adapter.js logging enabled"; + } + + /** + * Disable or enable deprecation warnings + * @param {!boolean} bool set to true to disable warnings. + */ + function disableWarnings(bool) { + if (typeof bool !== "boolean") { + return new Error( + "Argument type: " + + (typeof bool === "undefined" + ? "undefined" + : _typeof(bool)) + + ". Please use a boolean." + ); + } + deprecationWarnings_ = !bool; + return ( + "adapter.js deprecation warnings " + + (bool ? "disabled" : "enabled") + ); + } + + function log() { + if ( + (typeof window === "undefined" + ? "undefined" + : _typeof(window)) === "object" + ) { + if (logDisabled_) { + return; + } + if ( + typeof console !== "undefined" && + typeof console.log === "function" + ) { + console.log.apply(console, arguments); + } + } + } + + /** + * Shows a deprecation warning suggesting the modern and spec-compatible API. + */ + function deprecated(oldMethod, newMethod) { + if (!deprecationWarnings_) { + return; + } + console.warn( + oldMethod + + " is deprecated, please use " + + newMethod + + " instead." + ); + } + + /** + * Browser detector. + * + * @return {object} result containing browser and version + * properties. + */ + function detectBrowser(window) { + // Returned result object. + var result = { browser: null, version: null }; + + // Fail early if it's not a browser + if ( + typeof window === "undefined" || + !window.navigator + ) { + result.browser = "Not a browser."; + return result; + } + + var navigator = window.navigator; + + if (navigator.mozGetUserMedia) { + // Firefox. + result.browser = "firefox"; + result.version = extractVersion( + navigator.userAgent, + /Firefox\/(\d+)\./, + 1 + ); + } else if ( + navigator.webkitGetUserMedia || + (window.isSecureContext === false && + window.webkitRTCPeerConnection && + !window.RTCIceGatherer) + ) { + // Chrome, Chromium, Webview, Opera. + // Version matches Chrome/WebRTC version. + // Chrome 74 removed webkitGetUserMedia on http as well so we need the + // more complicated fallback to webkitRTCPeerConnection. + result.browser = "chrome"; + result.version = extractVersion( + navigator.userAgent, + /Chrom(e|ium)\/(\d+)\./, + 2 + ); + } else if ( + window.RTCPeerConnection && + navigator.userAgent.match(/AppleWebKit\/(\d+)\./) + ) { + // Safari. + result.browser = "safari"; + result.version = extractVersion( + navigator.userAgent, + /AppleWebKit\/(\d+)\./, + 1 + ); + result.supportsUnifiedPlan = + window.RTCRtpTransceiver && + "currentDirection" in + window.RTCRtpTransceiver.prototype; + } else { + // Default fallthrough: not supported. + result.browser = "Not a supported browser."; + return result; + } + + return result; + } + + /** + * Checks if something is an object. + * + * @param {*} val The something you want to check. + * @return true if val is an object, false otherwise. + */ + function isObject(val) { + return ( + Object.prototype.toString.call(val) === + "[object Object]" + ); + } + + /** + * Remove all empty objects and undefined values + * from a nested object -- an enhanced and vanilla version + * of Lodash's `compact`. + */ + function compactObject(data) { + if (!isObject(data)) { + return data; + } + + return Object.keys(data).reduce(function ( + accumulator, + key + ) { + var isObj = isObject(data[key]); + var value = isObj + ? compactObject(data[key]) + : data[key]; + var isEmptyObject = + isObj && !Object.keys(value).length; + if (value === undefined || isEmptyObject) { + return accumulator; + } + return Object.assign( + accumulator, + _defineProperty({}, key, value) + ); + }, + {}); + } + + /* iterates the stats graph recursively. */ + function walkStats(stats, base, resultSet) { + if (!base || resultSet.has(base.id)) { + return; + } + resultSet.set(base.id, base); + Object.keys(base).forEach(function (name) { + if (name.endsWith("Id")) { + walkStats( + stats, + stats.get(base[name]), + resultSet + ); + } else if (name.endsWith("Ids")) { + base[name].forEach(function (id) { + walkStats(stats, stats.get(id), resultSet); + }); + } + }); + } + + /* filter getStats for a sender/receiver track. */ + function filterStats(result, track, outbound) { + var streamStatsType = outbound + ? "outbound-rtp" + : "inbound-rtp"; + var filteredResult = new Map(); + if (track === null) { + return filteredResult; + } + var trackStats = []; + result.forEach(function (value) { + if ( + value.type === "track" && + value.trackIdentifier === track.id + ) { + trackStats.push(value); + } + }); + trackStats.forEach(function (trackStat) { + result.forEach(function (stats) { + if ( + stats.type === streamStatsType && + stats.trackId === trackStat.id + ) { + walkStats(result, stats, filteredResult); + } + }); + }); + return filteredResult; + } + }, + {}, + ], + 12: [ + function (require, module, exports) { + /* eslint-env node */ + "use strict"; + + // SDP helpers. + + var _typeof = + typeof Symbol === "function" && + typeof Symbol.iterator === "symbol" + ? function (obj) { + return typeof obj; + } + : function (obj) { + return obj && + typeof Symbol === "function" && + obj.constructor === Symbol && + obj !== Symbol.prototype + ? "symbol" + : typeof obj; + }; + + var SDPUtils = {}; + + // Generate an alphanumeric identifier for cname or mids. + // TODO: use UUIDs instead? https://gist.github.com/jed/982883 + SDPUtils.generateIdentifier = function () { + return Math.random().toString(36).substr(2, 10); + }; + + // The RTCP CNAME used by all peerconnections from the same JS. + SDPUtils.localCName = SDPUtils.generateIdentifier(); + + // Splits SDP into lines, dealing with both CRLF and LF. + SDPUtils.splitLines = function (blob) { + return blob + .trim() + .split("\n") + .map(function (line) { + return line.trim(); + }); + }; + // Splits SDP into sessionpart and mediasections. Ensures CRLF. + SDPUtils.splitSections = function (blob) { + var parts = blob.split("\nm="); + return parts.map(function (part, index) { + return ( + (index > 0 ? "m=" + part : part).trim() + "\r\n" + ); + }); + }; + + // returns the session description. + SDPUtils.getDescription = function (blob) { + var sections = SDPUtils.splitSections(blob); + return sections && sections[0]; + }; + + // returns the individual media sections. + SDPUtils.getMediaSections = function (blob) { + var sections = SDPUtils.splitSections(blob); + sections.shift(); + return sections; + }; + + // Returns lines that start with a certain prefix. + SDPUtils.matchPrefix = function (blob, prefix) { + return SDPUtils.splitLines(blob).filter(function ( + line + ) { + return line.indexOf(prefix) === 0; + }); + }; + + // Parses an ICE candidate line. Sample input: + // candidate:702786350 2 udp 41819902 8.8.8.8 60769 typ relay raddr 8.8.8.8 + // rport 55996" + SDPUtils.parseCandidate = function (line) { + var parts = void 0; + // Parse both variants. + if (line.indexOf("a=candidate:") === 0) { + parts = line.substring(12).split(" "); + } else { + parts = line.substring(10).split(" "); + } + + var candidate = { + foundation: parts[0], + component: { 1: "rtp", 2: "rtcp" }[parts[1]], + protocol: parts[2].toLowerCase(), + priority: parseInt(parts[3], 10), + ip: parts[4], + address: parts[4], // address is an alias for ip. + port: parseInt(parts[5], 10), + // skip parts[6] == 'typ' + type: parts[7], + }; + + for (var i = 8; i < parts.length; i += 2) { + switch (parts[i]) { + case "raddr": + candidate.relatedAddress = parts[i + 1]; + break; + case "rport": + candidate.relatedPort = parseInt( + parts[i + 1], + 10 + ); + break; + case "tcptype": + candidate.tcpType = parts[i + 1]; + break; + case "ufrag": + candidate.ufrag = parts[i + 1]; // for backward compatibility. + candidate.usernameFragment = parts[i + 1]; + break; + default: + // extension handling, in particular ufrag. Don't overwrite. + if (candidate[parts[i]] === undefined) { + candidate[parts[i]] = parts[i + 1]; + } + break; + } + } + return candidate; + }; + + // Translates a candidate object into SDP candidate attribute. + SDPUtils.writeCandidate = function (candidate) { + var sdp = []; + sdp.push(candidate.foundation); + + var component = candidate.component; + if (component === "rtp") { + sdp.push(1); + } else if (component === "rtcp") { + sdp.push(2); + } else { + sdp.push(component); + } + sdp.push(candidate.protocol.toUpperCase()); + sdp.push(candidate.priority); + sdp.push(candidate.address || candidate.ip); + sdp.push(candidate.port); + + var type = candidate.type; + sdp.push("typ"); + sdp.push(type); + if ( + type !== "host" && + candidate.relatedAddress && + candidate.relatedPort + ) { + sdp.push("raddr"); + sdp.push(candidate.relatedAddress); + sdp.push("rport"); + sdp.push(candidate.relatedPort); + } + if ( + candidate.tcpType && + candidate.protocol.toLowerCase() === "tcp" + ) { + sdp.push("tcptype"); + sdp.push(candidate.tcpType); + } + if (candidate.usernameFragment || candidate.ufrag) { + sdp.push("ufrag"); + sdp.push( + candidate.usernameFragment || candidate.ufrag + ); + } + return "candidate:" + sdp.join(" "); + }; + + // Parses an ice-options line, returns an array of option tags. + // a=ice-options:foo bar + SDPUtils.parseIceOptions = function (line) { + return line.substr(14).split(" "); + }; + + // Parses an rtpmap line, returns RTCRtpCoddecParameters. Sample input: + // a=rtpmap:111 opus/48000/2 + SDPUtils.parseRtpMap = function (line) { + var parts = line.substr(9).split(" "); + var parsed = { + payloadType: parseInt(parts.shift(), 10), // was: id + }; + + parts = parts[0].split("/"); + + parsed.name = parts[0]; + parsed.clockRate = parseInt(parts[1], 10); // was: clockrate + parsed.channels = + parts.length === 3 ? parseInt(parts[2], 10) : 1; + // legacy alias, got renamed back to channels in ORTC. + parsed.numChannels = parsed.channels; + return parsed; + }; + + // Generate an a=rtpmap line from RTCRtpCodecCapability or + // RTCRtpCodecParameters. + SDPUtils.writeRtpMap = function (codec) { + var pt = codec.payloadType; + if (codec.preferredPayloadType !== undefined) { + pt = codec.preferredPayloadType; + } + var channels = codec.channels || codec.numChannels || 1; + return ( + "a=rtpmap:" + + pt + + " " + + codec.name + + "/" + + codec.clockRate + + (channels !== 1 ? "/" + channels : "") + + "\r\n" + ); + }; + + // Parses an a=extmap line (headerextension from RFC 5285). Sample input: + // a=extmap:2 urn:ietf:params:rtp-hdrext:toffset + // a=extmap:2/sendonly urn:ietf:params:rtp-hdrext:toffset + SDPUtils.parseExtmap = function (line) { + var parts = line.substr(9).split(" "); + return { + id: parseInt(parts[0], 10), + direction: + parts[0].indexOf("/") > 0 + ? parts[0].split("/")[1] + : "sendrecv", + uri: parts[1], + }; + }; + + // Generates a=extmap line from RTCRtpHeaderExtensionParameters or + // RTCRtpHeaderExtension. + SDPUtils.writeExtmap = function (headerExtension) { + return ( + "a=extmap:" + + (headerExtension.id || + headerExtension.preferredId) + + (headerExtension.direction && + headerExtension.direction !== "sendrecv" + ? "/" + headerExtension.direction + : "") + + " " + + headerExtension.uri + + "\r\n" + ); + }; + + // Parses an ftmp line, returns dictionary. Sample input: + // a=fmtp:96 vbr=on;cng=on + // Also deals with vbr=on; cng=on + SDPUtils.parseFmtp = function (line) { + var parsed = {}; + var kv = void 0; + var parts = line + .substr(line.indexOf(" ") + 1) + .split(";"); + for (var j = 0; j < parts.length; j++) { + kv = parts[j].trim().split("="); + parsed[kv[0].trim()] = kv[1]; + } + return parsed; + }; + + // Generates an a=ftmp line from RTCRtpCodecCapability or RTCRtpCodecParameters. + SDPUtils.writeFmtp = function (codec) { + var line = ""; + var pt = codec.payloadType; + if (codec.preferredPayloadType !== undefined) { + pt = codec.preferredPayloadType; + } + if ( + codec.parameters && + Object.keys(codec.parameters).length + ) { + var params = []; + Object.keys(codec.parameters).forEach(function ( + param + ) { + if (codec.parameters[param]) { + params.push( + param + "=" + codec.parameters[param] + ); + } else { + params.push(param); + } + }); + line += + "a=fmtp:" + + pt + + " " + + params.join(";") + + "\r\n"; + } + return line; + }; + + // Parses an rtcp-fb line, returns RTCPRtcpFeedback object. Sample input: + // a=rtcp-fb:98 nack rpsi + SDPUtils.parseRtcpFb = function (line) { + var parts = line + .substr(line.indexOf(" ") + 1) + .split(" "); + return { + type: parts.shift(), + parameter: parts.join(" "), + }; + }; + // Generate a=rtcp-fb lines from RTCRtpCodecCapability or RTCRtpCodecParameters. + SDPUtils.writeRtcpFb = function (codec) { + var lines = ""; + var pt = codec.payloadType; + if (codec.preferredPayloadType !== undefined) { + pt = codec.preferredPayloadType; + } + if (codec.rtcpFeedback && codec.rtcpFeedback.length) { + // FIXME: special handling for trr-int? + codec.rtcpFeedback.forEach(function (fb) { + lines += + "a=rtcp-fb:" + + pt + + " " + + fb.type + + (fb.parameter && fb.parameter.length + ? " " + fb.parameter + : "") + + "\r\n"; + }); + } + return lines; + }; + + // Parses an RFC 5576 ssrc media attribute. Sample input: + // a=ssrc:3735928559 cname:something + SDPUtils.parseSsrcMedia = function (line) { + var sp = line.indexOf(" "); + var parts = { + ssrc: parseInt(line.substr(7, sp - 7), 10), + }; + var colon = line.indexOf(":", sp); + if (colon > -1) { + parts.attribute = line.substr( + sp + 1, + colon - sp - 1 + ); + parts.value = line.substr(colon + 1); + } else { + parts.attribute = line.substr(sp + 1); + } + return parts; + }; + + SDPUtils.parseSsrcGroup = function (line) { + var parts = line.substr(13).split(" "); + return { + semantics: parts.shift(), + ssrcs: parts.map(function (ssrc) { + return parseInt(ssrc, 10); + }), + }; + }; + + // Extracts the MID (RFC 5888) from a media section. + // returns the MID or undefined if no mid line was found. + SDPUtils.getMid = function (mediaSection) { + var mid = SDPUtils.matchPrefix( + mediaSection, + "a=mid:" + )[0]; + if (mid) { + return mid.substr(6); + } + }; + + SDPUtils.parseFingerprint = function (line) { + var parts = line.substr(14).split(" "); + return { + algorithm: parts[0].toLowerCase(), // algorithm is case-sensitive in Edge. + value: parts[1], + }; + }; + + // Extracts DTLS parameters from SDP media section or sessionpart. + // FIXME: for consistency with other functions this should only + // get the fingerprint line as input. See also getIceParameters. + SDPUtils.getDtlsParameters = function ( + mediaSection, + sessionpart + ) { + var lines = SDPUtils.matchPrefix( + mediaSection + sessionpart, + "a=fingerprint:" + ); + // Note: a=setup line is ignored since we use the 'auto' role. + // Note2: 'algorithm' is not case sensitive except in Edge. + return { + role: "auto", + fingerprints: lines.map(SDPUtils.parseFingerprint), + }; + }; + + // Serializes DTLS parameters to SDP. + SDPUtils.writeDtlsParameters = function ( + params, + setupType + ) { + var sdp = "a=setup:" + setupType + "\r\n"; + params.fingerprints.forEach(function (fp) { + sdp += + "a=fingerprint:" + + fp.algorithm + + " " + + fp.value + + "\r\n"; + }); + return sdp; + }; + + // Parses a=crypto lines into + // https://rawgit.com/aboba/edgertc/master/msortc-rs4.html#dictionary-rtcsrtpsdesparameters-members + SDPUtils.parseCryptoLine = function (line) { + var parts = line.substr(9).split(" "); + return { + tag: parseInt(parts[0], 10), + cryptoSuite: parts[1], + keyParams: parts[2], + sessionParams: parts.slice(3), + }; + }; + + SDPUtils.writeCryptoLine = function (parameters) { + return ( + "a=crypto:" + + parameters.tag + + " " + + parameters.cryptoSuite + + " " + + (_typeof(parameters.keyParams) === "object" + ? SDPUtils.writeCryptoKeyParams( + parameters.keyParams + ) + : parameters.keyParams) + + (parameters.sessionParams + ? " " + parameters.sessionParams.join(" ") + : "") + + "\r\n" + ); + }; + + // Parses the crypto key parameters into + // https://rawgit.com/aboba/edgertc/master/msortc-rs4.html#rtcsrtpkeyparam* + SDPUtils.parseCryptoKeyParams = function (keyParams) { + if (keyParams.indexOf("inline:") !== 0) { + return null; + } + var parts = keyParams.substr(7).split("|"); + return { + keyMethod: "inline", + keySalt: parts[0], + lifeTime: parts[1], + mkiValue: parts[2] + ? parts[2].split(":")[0] + : undefined, + mkiLength: parts[2] + ? parts[2].split(":")[1] + : undefined, + }; + }; + + SDPUtils.writeCryptoKeyParams = function (keyParams) { + return ( + keyParams.keyMethod + + ":" + + keyParams.keySalt + + (keyParams.lifeTime + ? "|" + keyParams.lifeTime + : "") + + (keyParams.mkiValue && keyParams.mkiLength + ? "|" + + keyParams.mkiValue + + ":" + + keyParams.mkiLength + : "") + ); + }; + + // Extracts all SDES parameters. + SDPUtils.getCryptoParameters = function ( + mediaSection, + sessionpart + ) { + var lines = SDPUtils.matchPrefix( + mediaSection + sessionpart, + "a=crypto:" + ); + return lines.map(SDPUtils.parseCryptoLine); + }; + + // Parses ICE information from SDP media section or sessionpart. + // FIXME: for consistency with other functions this should only + // get the ice-ufrag and ice-pwd lines as input. + SDPUtils.getIceParameters = function ( + mediaSection, + sessionpart + ) { + var ufrag = SDPUtils.matchPrefix( + mediaSection + sessionpart, + "a=ice-ufrag:" + )[0]; + var pwd = SDPUtils.matchPrefix( + mediaSection + sessionpart, + "a=ice-pwd:" + )[0]; + if (!(ufrag && pwd)) { + return null; + } + return { + usernameFragment: ufrag.substr(12), + password: pwd.substr(10), + }; + }; + + // Serializes ICE parameters to SDP. + SDPUtils.writeIceParameters = function (params) { + var sdp = + "a=ice-ufrag:" + + params.usernameFragment + + "\r\n" + + "a=ice-pwd:" + + params.password + + "\r\n"; + if (params.iceLite) { + sdp += "a=ice-lite\r\n"; + } + return sdp; + }; + + // Parses the SDP media section and returns RTCRtpParameters. + SDPUtils.parseRtpParameters = function (mediaSection) { + var description = { + codecs: [], + headerExtensions: [], + fecMechanisms: [], + rtcp: [], + }; + var lines = SDPUtils.splitLines(mediaSection); + var mline = lines[0].split(" "); + for (var i = 3; i < mline.length; i++) { + // find all codecs from mline[3..] + var pt = mline[i]; + var rtpmapline = SDPUtils.matchPrefix( + mediaSection, + "a=rtpmap:" + pt + " " + )[0]; + if (rtpmapline) { + var codec = SDPUtils.parseRtpMap(rtpmapline); + var fmtps = SDPUtils.matchPrefix( + mediaSection, + "a=fmtp:" + pt + " " + ); + // Only the first a=fmtp: is considered. + codec.parameters = fmtps.length + ? SDPUtils.parseFmtp(fmtps[0]) + : {}; + codec.rtcpFeedback = SDPUtils.matchPrefix( + mediaSection, + "a=rtcp-fb:" + pt + " " + ).map(SDPUtils.parseRtcpFb); + description.codecs.push(codec); + // parse FEC mechanisms from rtpmap lines. + switch (codec.name.toUpperCase()) { + case "RED": + case "ULPFEC": + description.fecMechanisms.push( + codec.name.toUpperCase() + ); + break; + default: + // only RED and ULPFEC are recognized as FEC mechanisms. + break; + } + } + } + SDPUtils.matchPrefix(mediaSection, "a=extmap:").forEach( + function (line) { + description.headerExtensions.push( + SDPUtils.parseExtmap(line) + ); + } + ); + // FIXME: parse rtcp. + return description; + }; + + // Generates parts of the SDP media section describing the capabilities / + // parameters. + SDPUtils.writeRtpDescription = function (kind, caps) { + var sdp = ""; + + // Build the mline. + sdp += "m=" + kind + " "; + sdp += caps.codecs.length > 0 ? "9" : "0"; // reject if no codecs. + sdp += " UDP/TLS/RTP/SAVPF "; + sdp += + caps.codecs + .map(function (codec) { + if ( + codec.preferredPayloadType !== undefined + ) { + return codec.preferredPayloadType; + } + return codec.payloadType; + }) + .join(" ") + "\r\n"; + + sdp += "c=IN IP4 0.0.0.0\r\n"; + sdp += "a=rtcp:9 IN IP4 0.0.0.0\r\n"; + + // Add a=rtpmap lines for each codec. Also fmtp and rtcp-fb. + caps.codecs.forEach(function (codec) { + sdp += SDPUtils.writeRtpMap(codec); + sdp += SDPUtils.writeFmtp(codec); + sdp += SDPUtils.writeRtcpFb(codec); + }); + var maxptime = 0; + caps.codecs.forEach(function (codec) { + if (codec.maxptime > maxptime) { + maxptime = codec.maxptime; + } + }); + if (maxptime > 0) { + sdp += "a=maxptime:" + maxptime + "\r\n"; + } + + if (caps.headerExtensions) { + caps.headerExtensions.forEach(function (extension) { + sdp += SDPUtils.writeExtmap(extension); + }); + } + // FIXME: write fecMechanisms. + return sdp; + }; + + // Parses the SDP media section and returns an array of + // RTCRtpEncodingParameters. + SDPUtils.parseRtpEncodingParameters = function ( + mediaSection + ) { + var encodingParameters = []; + var description = + SDPUtils.parseRtpParameters(mediaSection); + var hasRed = + description.fecMechanisms.indexOf("RED") !== -1; + var hasUlpfec = + description.fecMechanisms.indexOf("ULPFEC") !== -1; + + // filter a=ssrc:... cname:, ignore PlanB-msid + var ssrcs = SDPUtils.matchPrefix( + mediaSection, + "a=ssrc:" + ) + .map(function (line) { + return SDPUtils.parseSsrcMedia(line); + }) + .filter(function (parts) { + return parts.attribute === "cname"; + }); + var primarySsrc = ssrcs.length > 0 && ssrcs[0].ssrc; + var secondarySsrc = void 0; + + var flows = SDPUtils.matchPrefix( + mediaSection, + "a=ssrc-group:FID" + ).map(function (line) { + var parts = line.substr(17).split(" "); + return parts.map(function (part) { + return parseInt(part, 10); + }); + }); + if ( + flows.length > 0 && + flows[0].length > 1 && + flows[0][0] === primarySsrc + ) { + secondarySsrc = flows[0][1]; + } + + description.codecs.forEach(function (codec) { + if ( + codec.name.toUpperCase() === "RTX" && + codec.parameters.apt + ) { + var encParam = { + ssrc: primarySsrc, + codecPayloadType: parseInt( + codec.parameters.apt, + 10 + ), + }; + if (primarySsrc && secondarySsrc) { + encParam.rtx = { ssrc: secondarySsrc }; + } + encodingParameters.push(encParam); + if (hasRed) { + encParam = JSON.parse( + JSON.stringify(encParam) + ); + encParam.fec = { + ssrc: primarySsrc, + mechanism: hasUlpfec + ? "red+ulpfec" + : "red", + }; + encodingParameters.push(encParam); + } + } + }); + if (encodingParameters.length === 0 && primarySsrc) { + encodingParameters.push({ + ssrc: primarySsrc, + }); + } + + // we support both b=AS and b=TIAS but interpret AS as TIAS. + var bandwidth = SDPUtils.matchPrefix( + mediaSection, + "b=" + ); + if (bandwidth.length) { + if (bandwidth[0].indexOf("b=TIAS:") === 0) { + bandwidth = parseInt( + bandwidth[0].substr(7), + 10 + ); + } else if (bandwidth[0].indexOf("b=AS:") === 0) { + // use formula from JSEP to convert b=AS to TIAS value. + bandwidth = + parseInt(bandwidth[0].substr(5), 10) * + 1000 * + 0.95 - + 50 * 40 * 8; + } else { + bandwidth = undefined; + } + encodingParameters.forEach(function (params) { + params.maxBitrate = bandwidth; + }); + } + return encodingParameters; + }; + + // parses http://draft.ortc.org/#rtcrtcpparameters* + SDPUtils.parseRtcpParameters = function (mediaSection) { + var rtcpParameters = {}; + + // Gets the first SSRC. Note that with RTX there might be multiple + // SSRCs. + var remoteSsrc = SDPUtils.matchPrefix( + mediaSection, + "a=ssrc:" + ) + .map(function (line) { + return SDPUtils.parseSsrcMedia(line); + }) + .filter(function (obj) { + return obj.attribute === "cname"; + })[0]; + if (remoteSsrc) { + rtcpParameters.cname = remoteSsrc.value; + rtcpParameters.ssrc = remoteSsrc.ssrc; + } + + // Edge uses the compound attribute instead of reducedSize + // compound is !reducedSize + var rsize = SDPUtils.matchPrefix( + mediaSection, + "a=rtcp-rsize" + ); + rtcpParameters.reducedSize = rsize.length > 0; + rtcpParameters.compound = rsize.length === 0; + + // parses the rtcp-mux attrŅ–bute. + // Note that Edge does not support unmuxed RTCP. + var mux = SDPUtils.matchPrefix( + mediaSection, + "a=rtcp-mux" + ); + rtcpParameters.mux = mux.length > 0; + + return rtcpParameters; + }; + + SDPUtils.writeRtcpParameters = function (rtcpParameters) { + var sdp = ""; + if (rtcpParameters.reducedSize) { + sdp += "a=rtcp-rsize\r\n"; + } + if (rtcpParameters.mux) { + sdp += "a=rtcp-mux\r\n"; + } + if ( + rtcpParameters.ssrc !== undefined && + rtcpParameters.cname + ) { + sdp += + "a=ssrc:" + + rtcpParameters.ssrc + + " cname:" + + rtcpParameters.cname + + "\r\n"; + } + return sdp; + }; + + // parses either a=msid: or a=ssrc:... msid lines and returns + // the id of the MediaStream and MediaStreamTrack. + SDPUtils.parseMsid = function (mediaSection) { + var parts = void 0; + var spec = SDPUtils.matchPrefix( + mediaSection, + "a=msid:" + ); + if (spec.length === 1) { + parts = spec[0].substr(7).split(" "); + return { stream: parts[0], track: parts[1] }; + } + var planB = SDPUtils.matchPrefix( + mediaSection, + "a=ssrc:" + ) + .map(function (line) { + return SDPUtils.parseSsrcMedia(line); + }) + .filter(function (msidParts) { + return msidParts.attribute === "msid"; + }); + if (planB.length > 0) { + parts = planB[0].value.split(" "); + return { stream: parts[0], track: parts[1] }; + } + }; + + // SCTP + // parses draft-ietf-mmusic-sctp-sdp-26 first and falls back + // to draft-ietf-mmusic-sctp-sdp-05 + SDPUtils.parseSctpDescription = function (mediaSection) { + var mline = SDPUtils.parseMLine(mediaSection); + var maxSizeLine = SDPUtils.matchPrefix( + mediaSection, + "a=max-message-size:" + ); + var maxMessageSize = void 0; + if (maxSizeLine.length > 0) { + maxMessageSize = parseInt( + maxSizeLine[0].substr(19), + 10 + ); + } + if (isNaN(maxMessageSize)) { + maxMessageSize = 65536; + } + var sctpPort = SDPUtils.matchPrefix( + mediaSection, + "a=sctp-port:" + ); + if (sctpPort.length > 0) { + return { + port: parseInt(sctpPort[0].substr(12), 10), + protocol: mline.fmt, + maxMessageSize: maxMessageSize, + }; + } + var sctpMapLines = SDPUtils.matchPrefix( + mediaSection, + "a=sctpmap:" + ); + if (sctpMapLines.length > 0) { + var parts = sctpMapLines[0].substr(10).split(" "); + return { + port: parseInt(parts[0], 10), + protocol: parts[1], + maxMessageSize: maxMessageSize, + }; + } + }; + + // SCTP + // outputs the draft-ietf-mmusic-sctp-sdp-26 version that all browsers + // support by now receiving in this format, unless we originally parsed + // as the draft-ietf-mmusic-sctp-sdp-05 format (indicated by the m-line + // protocol of DTLS/SCTP -- without UDP/ or TCP/) + SDPUtils.writeSctpDescription = function (media, sctp) { + var output = []; + if (media.protocol !== "DTLS/SCTP") { + output = [ + "m=" + + media.kind + + " 9 " + + media.protocol + + " " + + sctp.protocol + + "\r\n", + "c=IN IP4 0.0.0.0\r\n", + "a=sctp-port:" + sctp.port + "\r\n", + ]; + } else { + output = [ + "m=" + + media.kind + + " 9 " + + media.protocol + + " " + + sctp.port + + "\r\n", + "c=IN IP4 0.0.0.0\r\n", + "a=sctpmap:" + + sctp.port + + " " + + sctp.protocol + + " 65535\r\n", + ]; + } + if (sctp.maxMessageSize !== undefined) { + output.push( + "a=max-message-size:" + + sctp.maxMessageSize + + "\r\n" + ); + } + return output.join(""); + }; + + // Generate a session ID for SDP. + // https://tools.ietf.org/html/draft-ietf-rtcweb-jsep-20#section-5.2.1 + // recommends using a cryptographically random +ve 64-bit value + // but right now this should be acceptable and within the right range + SDPUtils.generateSessionId = function () { + return Math.random().toString().substr(2, 21); + }; + + // Write boiler plate for start of SDP + // sessId argument is optional - if not supplied it will + // be generated randomly + // sessVersion is optional and defaults to 2 + // sessUser is optional and defaults to 'thisisadapterortc' + SDPUtils.writeSessionBoilerplate = function ( + sessId, + sessVer, + sessUser + ) { + var sessionId = void 0; + var version = sessVer !== undefined ? sessVer : 2; + if (sessId) { + sessionId = sessId; + } else { + sessionId = SDPUtils.generateSessionId(); + } + var user = sessUser || "thisisadapterortc"; + // FIXME: sess-id should be an NTP timestamp. + return ( + "v=0\r\n" + + "o=" + + user + + " " + + sessionId + + " " + + version + + " IN IP4 127.0.0.1\r\n" + + "s=-\r\n" + + "t=0 0\r\n" + ); + }; + + // Gets the direction from the mediaSection or the sessionpart. + SDPUtils.getDirection = function ( + mediaSection, + sessionpart + ) { + // Look for sendrecv, sendonly, recvonly, inactive, default to sendrecv. + var lines = SDPUtils.splitLines(mediaSection); + for (var i = 0; i < lines.length; i++) { + switch (lines[i]) { + case "a=sendrecv": + case "a=sendonly": + case "a=recvonly": + case "a=inactive": + return lines[i].substr(2); + default: + // FIXME: What should happen here? + } + } + if (sessionpart) { + return SDPUtils.getDirection(sessionpart); + } + return "sendrecv"; + }; + + SDPUtils.getKind = function (mediaSection) { + var lines = SDPUtils.splitLines(mediaSection); + var mline = lines[0].split(" "); + return mline[0].substr(2); + }; + + SDPUtils.isRejected = function (mediaSection) { + return mediaSection.split(" ", 2)[1] === "0"; + }; + + SDPUtils.parseMLine = function (mediaSection) { + var lines = SDPUtils.splitLines(mediaSection); + var parts = lines[0].substr(2).split(" "); + return { + kind: parts[0], + port: parseInt(parts[1], 10), + protocol: parts[2], + fmt: parts.slice(3).join(" "), + }; + }; + + SDPUtils.parseOLine = function (mediaSection) { + var line = SDPUtils.matchPrefix(mediaSection, "o=")[0]; + var parts = line.substr(2).split(" "); + return { + username: parts[0], + sessionId: parts[1], + sessionVersion: parseInt(parts[2], 10), + netType: parts[3], + addressType: parts[4], + address: parts[5], + }; + }; + + // a very naive interpretation of a valid SDP. + SDPUtils.isValidSDP = function (blob) { + if (typeof blob !== "string" || blob.length === 0) { + return false; + } + var lines = SDPUtils.splitLines(blob); + for (var i = 0; i < lines.length; i++) { + if ( + lines[i].length < 2 || + lines[i].charAt(1) !== "=" + ) { + return false; + } + // TODO: check the modifier a bit more. + } + return true; + }; + + // Expose public methods. + if ( + (typeof module === "undefined" + ? "undefined" + : _typeof(module)) === "object" + ) { + module.exports = SDPUtils; + } + }, + {}, + ], + }, + {}, + [1] + )(1); +});