Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@twilio/webrtc

Package Overview
Dependencies
Maintainers
1
Versions
34
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@twilio/webrtc - npm Package Compare versions

Comparing version 2.1.4 to 2.2.0

20

CHANGELOG.md

@@ -0,1 +1,21 @@

2.2.0 (January 10, 2019)
========================
New Features
------------
- `getStats` on Firefox will now consume the spec-compliant `RTCIceCandidateStats`
available in [versions 65 and above](https://www.fxsitecompat.com/en-CA/docs/2018/rtcicecandidatestats-has-been-updated-to-the-latest-spec/). (JSDK-2235)
- Added support for Unified Plan SDPs on Safari 12.1. (JSDK-2231)
- Removed workaround for this [Safari bug](https://bugs.webkit.org/show_bug.cgi?id=174323).
- Removed workaround for this Chrome [bug](https://bugs.chromium.org/p/chromium/issues/detail?id=774303).
Now, we no longer suppress the RTCPeerConnection's native `RTCTrackEvent`.
- Worked around the [deprecation](https://blog.mozilla.org/webrtc/getstats-isremote-65/) of the
`isRemote` property in `RTCInboundRTPStreamStats` and `RTCOutboundRTPStreamStats` in Firefox.
Bug Fixes
---------
- Worked around Chrome [Bug 894231](https://bugs.chromium.org/p/chromium/issues/detail?id=894231).
2.1.4 (December 5, 2018)

@@ -2,0 +22,0 @@ =========================

328

lib/getstats.js

@@ -1,6 +0,12 @@

/* global webkitRTCPeerConnection, mozRTCPeerConnection */
/* global RTCRtpTransceiver */
'use strict';
var flatMap = require('./util').flatMap;
var guessBrowser = require('./util').guessBrowser;
var guess = guessBrowser();
var isChrome = guess === 'chrome';
var isFirefox = guess === 'firefox';
var isSafari = guess === 'safari';
/**

@@ -40,11 +46,14 @@ * Get the standardized {@link RTCPeerConnection} statistics.

var trackStatsPromises = flatMap([
[localAudioTracks, 'localAudioTrackStats'],
[localVideoTracks, 'localVideoTrackStats'],
[remoteAudioTracks, 'remoteAudioTrackStats'],
[remoteVideoTracks, 'remoteVideoTrackStats']
], function(pair) {
var tracks = pair[0];
var statsArrayName = pair[1];
[localAudioTracks, 'localAudioTrackStats', false],
[localVideoTracks, 'localVideoTrackStats', false],
[remoteAudioTracks, 'remoteAudioTrackStats', true],
[remoteVideoTracks, 'remoteVideoTrackStats', true]
], function(triple) {
var tracks = triple[0];
var statsArrayName = triple[1];
var isRemote = triple[2];
return tracks.map(function(track) {
return getTrackStats(peerConnection, track, options).then(function(stats) {
return getTrackStats(peerConnection, track, Object.assign({
isRemote: isRemote
}, options)).then(function(stats) {
stats.trackId = track.id;

@@ -74,8 +83,8 @@ statsResponse[statsArrayName].push(stats);

if (typeof options.testForChrome !== 'undefined'
|| typeof webkitRTCPeerConnection !== 'undefined') {
return peerConnection.getStats().then(standardizeChromeActiveIceCandidatePairStats);
if (typeof options.testForChrome !== 'undefined' || isChrome
|| typeof options.testForSafari !== 'undefined' || isSafari) {
return peerConnection.getStats().then(
standardizeChromeOrSafariActiveIceCandidatePairStats);
}
if (typeof options.testForFirefox !== 'undefined'
|| typeof mozRTCPeerConnection !== 'undefined') {
if (typeof options.testForFirefox !== 'undefined' || isFirefox) {
return peerConnection.getStats().then(standardizeFirefoxActiveIceCandidatePairStats);

@@ -87,7 +96,7 @@ }

/**
* Standardize the active RTCIceCandidate pair's statistics in Chrome.
* Standardize the active RTCIceCandidate pair's statistics in Chrome or Safari.
* @param {RTCStatsReport} stats
* @returns {?StandardizedActiveIceCandidatePairStatsReport}
*/
function standardizeChromeActiveIceCandidatePairStats(stats) {
function standardizeChromeOrSafariActiveIceCandidatePairStats(stats) {
var activeCandidatePairStats = Array.from(stats.values()).find(function(stat) {

@@ -188,6 +197,6 @@ return stat.type === 'candidate-pair' && stat.nominated;

{ key: 'candidateType', type: 'string' },
{ key: 'ip', ffKey: 'ipAddress', type: 'string' },
{ key: 'port', ffKey: 'portNumber', type: 'number' },
{ key: 'ip', ffKeys: ['address', 'ipAddress'], type: 'string' },
{ key: 'port', ffKeys: ['portNumber'], type: 'number' },
{ key: 'priority', type: 'number' },
{ key: 'protocol', ffKey: 'transport', type: 'string' },
{ key: 'protocol', ffKeys: ['transport'], type: 'string' },
{ key: 'url', type: 'string' }

@@ -210,3 +219,5 @@ ];

? standardizedLocalCandidateStatsKeys.reduce(function(report, keyInfo) {
var key = keyInfo.ffKey || keyInfo.key;
var key = keyInfo.ffKeys && keyInfo.ffKeys.find(function(key) {
return key in activeLocalCandidateStats;
}) || keyInfo.key;
report[keyInfo.key] = typeof activeLocalCandidateStats[key] === keyInfo.type

@@ -223,3 +234,5 @@ ? key === 'candidateType'

? standardizedCandidateStatsKeys.reduce(function(report, keyInfo) {
var key = keyInfo.ffKey || keyInfo.key;
var key = keyInfo.ffKeys && keyInfo.ffKeys.find(function(key) {
return key in activeRemoteCandidateStats;
}) || keyInfo.key;
report[keyInfo.key] = typeof activeRemoteCandidateStats[key] === keyInfo.type

@@ -300,10 +313,21 @@ ? key === 'candidateType'

if (typeof options.testForChrome !== 'undefined' ||
typeof webkitRTCPeerConnection !== 'undefined') {
return chromeGetTrackStats(peerConnection, track);
if (typeof options.testForChrome !== 'undefined' || isChrome) {
return chromeOrSafariGetTrackStats(peerConnection, track);
}
if (typeof options.testForFirefox !== 'undefined' ||
typeof mozRTCPeerConnection !== 'undefined') {
return firefoxGetTrackStats(peerConnection, track);
if (typeof options.testForFirefox !== 'undefined' || isFirefox) {
return firefoxGetTrackStats(peerConnection, track, options.isRemote);
}
if (typeof options.testForSafari !== 'undefined' || isSafari) {
if (typeof options.testForSafari !== 'undefined'
|| 'currentDirection' in RTCRtpTransceiver.prototype) {
return chromeOrSafariGetTrackStats(peerConnection, track);
}
// NOTE(syerrapragada): getStats() is not supported on
// Safari versions where plan-b is the SDP format
// due to this bug: https://bugs.webkit.org/show_bug.cgi?id=192601
return Promise.reject(new Error([
'getStats() is not supported on this version of Safari',
'due to this bug: https://bugs.webkit.org/show_bug.cgi?id=192601'
].join(' ')));
}
return Promise.reject(new Error('RTCPeerConnection#getStats() not supported'));

@@ -313,3 +337,3 @@ }

/**
* Get the standardized statistics for a particular MediaStreamTrack in Chrome.
* Get the standardized statistics for a particular MediaStreamTrack in Chrome or Safari.
* @param {RTCPeerConnection} peerConnection

@@ -319,7 +343,7 @@ * @param {MediaStreamTrack} track

*/
function chromeGetTrackStats(peerConnection, track) {
function chromeOrSafariGetTrackStats(peerConnection, track) {
return new Promise(function(resolve, reject) {
peerConnection.getStats(function(response) {
resolve(standardizeChromeStats(response, track));
}, null, reject);
peerConnection.getStats(track).then(function(response) {
resolve(standardizeChromeOrSafariStats(response));
}, reject);
});

@@ -332,8 +356,9 @@ }

* @param {MediaStreamTrack} track
* @param {boolean} isRemote
* @returns {Promise.<StandardizedTrackStatsReport>}
*/
function firefoxGetTrackStats(peerConnection, track) {
function firefoxGetTrackStats(peerConnection, track, isRemote) {
return new Promise(function(resolve, reject) {
peerConnection.getStats(track).then(function(response) {
resolve(standardizeFirefoxStats(response));
resolve(standardizeFirefoxStats(response, isRemote));
}, reject);

@@ -344,72 +369,133 @@ });

/**
* Standardize the MediaStreamTrack's statistics in Chrome.
* Standardize the MediaStreamTrack's statistics in Chrome or Safari.
* @param {RTCStatsResponse} response
* @param {MediaStreamTrack} track
* @returns {StandardizedTrackStatsReport}
*/
function standardizeChromeStats(response, track) {
var ssrcReport = response.result().find(function(report) {
return report.type === 'ssrc' && report.stat('googTrackId') === track.id;
function standardizeChromeOrSafariStats(response) {
var inbound = null;
var outbound = null;
var track = null;
var codec = null;
response.forEach(function(stat) {
switch (stat.type) {
case 'inbound-rtp':
inbound = stat;
break;
case 'outbound-rtp':
outbound = stat;
break;
case 'track':
track = stat;
break;
case 'codec':
codec = stat;
break;
}
});
var isRemote = track && track.remoteSource;
var standardizedStats = {};
if (ssrcReport) {
standardizedStats.timestamp = Math.round(Number(ssrcReport.timestamp));
standardizedStats = ssrcReport.names().reduce(function(stats, name) {
switch (name) {
case 'googCodecName':
stats.codecName = ssrcReport.stat(name);
break;
case 'googRtt':
stats.roundTripTime = Number(ssrcReport.stat(name));
break;
case 'googJitterReceived':
stats.jitter = Number(ssrcReport.stat(name));
break;
case 'googFrameWidthInput':
stats.frameWidthInput = Number(ssrcReport.stat(name));
break;
case 'googFrameHeightInput':
stats.frameHeightInput = Number(ssrcReport.stat(name));
break;
case 'googFrameWidthSent':
stats.frameWidthSent = Number(ssrcReport.stat(name));
break;
case 'googFrameHeightSent':
stats.frameHeightSent = Number(ssrcReport.stat(name));
break;
case 'googFrameWidthReceived':
stats.frameWidthReceived = Number(ssrcReport.stat(name));
break;
case 'googFrameHeightReceived':
stats.frameHeightReceived = Number(ssrcReport.stat(name));
break;
case 'googFrameRateInput':
stats.frameRateInput = Number(ssrcReport.stat(name));
break;
case 'googFrameRateSent':
stats.frameRateSent = Number(ssrcReport.stat(name));
break;
case 'googFrameRateReceived':
stats.frameRateReceived = Number(ssrcReport.stat(name));
break;
case 'ssrc':
stats[name] = ssrcReport.stat(name);
break;
case 'bytesReceived':
case 'bytesSent':
case 'packetsLost':
case 'packetsReceived':
case 'packetsSent':
case 'audioInputLevel':
case 'audioOutputLevel':
stats[name] = Number(ssrcReport.stat(name));
break;
}
var first = isRemote ? inbound : outbound;
var second = track;
var third = codec;
return stats;
}, standardizedStats);
function getStatValue(name) {
if (first && typeof first[name] !== 'undefined') {
return first[name];
}
if (second && typeof second[name] !== 'undefined') {
return second[name];
}
if (third && typeof third[name] !== 'undefined') {
return third[name];
}
return null;
}
var ssrc = getStatValue('ssrc');
if (typeof ssrc === 'number') {
standardizedStats.ssrc = String(ssrc);
}
var timestamp = getStatValue('timestamp');
standardizedStats.timestamp = Math.round(timestamp);
var mimeType = getStatValue('mimeType');
if (typeof mimeType === 'string') {
mimeType = mimeType.split('/');
standardizedStats.codecName = mimeType[mimeType.length - 1];
}
var roundTripTime = getStatValue('roundTripTime');
if (typeof roundTripTime === 'number') {
standardizedStats.roundTripTime = roundTripTime;
}
var jitter = getStatValue('jitter');
if (typeof jitter === 'number') {
standardizedStats.jitter = Math.round(jitter * 1000);
}
var frameWidth = getStatValue('frameWidth');
if (typeof frameWidth === 'number') {
if (isRemote) {
standardizedStats.frameWidthReceived = frameWidth;
} else {
standardizedStats.frameWidthSent = frameWidth;
}
}
var frameHeight = getStatValue('frameHeight');
if (typeof frameHeight === 'number') {
if (isRemote) {
standardizedStats.frameHeightReceived = frameHeight;
} else {
standardizedStats.frameHeightSent = frameHeight;
}
}
var framesPerSecond = getStatValue('framesPerSecond');
if (typeof framesPerSecond === 'number') {
standardizedStats.frameRateSent = framesPerSecond;
}
var bytesReceived = getStatValue('bytesReceived');
if (typeof bytesReceived === 'number') {
standardizedStats.bytesReceived = bytesReceived;
}
var bytesSent = getStatValue('bytesSent');
if (typeof bytesSent === 'number') {
standardizedStats.bytesSent = bytesSent;
}
var packetsLost = getStatValue('packetsLost');
if (typeof packetsLost === 'number') {
standardizedStats.packetsLost = packetsLost;
}
var packetsReceived = getStatValue('packetsReceived');
if (typeof packetsReceived === 'number') {
standardizedStats.packetsReceived = packetsReceived;
}
var packetsSent = getStatValue('packetsSent');
if (typeof packetsSent === 'number') {
standardizedStats.packetsSent = packetsSent;
}
var audioLevel = getStatValue('audioLevel');
if (typeof audioLevel === 'number') {
if (isRemote) {
standardizedStats.audioOutputLevel = audioLevel;
} else {
standardizedStats.audioInputLevel = audioLevel;
}
}
return standardizedStats;

@@ -421,5 +507,6 @@ }

* @param {RTCStatsReport} response
* @param {boolean} isRemote
* @returns {StandardizedTrackStatsReport}
*/
function standardizeFirefoxStats(response) {
function standardizeFirefoxStats(response, isRemote) {
// NOTE(mroberts): If getStats is called on a closed RTCPeerConnection,

@@ -433,32 +520,44 @@ // Firefox returns undefined instead of an RTCStatsReport. We workaround this

var inbound = Array.from(response.values()).find(function(stat) {
return stat.type === 'inbound-rtp';
});
var inbound = null;
var outbound = null;
var outbound = Array.from(response.values()).find(function(stat) {
return stat.type === 'outbound-rtp';
// NOTE(mmalavalli): Starting from Firefox 63, RTC{Inbound, Outbound}RTPStreamStats.isRemote
// will be deprecated, followed by its removal in Firefox 66. Also, trying to
// access members of the remote RTC{Inbound, Outbound}RTPStreamStats without
// using RTCStatsReport.get(remoteId) will trigger console warnings. So, we
// no longer depend on "isRemote", and we call RTCStatsReport.get(remoteId)
// to access the remote RTC{Inbound, Outbound}RTPStreamStats.
//
// Source: https://blog.mozilla.org/webrtc/getstats-isremote-65/
//
response.forEach(function(stat) {
if (stat.isRemote) {
return;
}
switch (stat.type) {
case 'inbound-rtp':
inbound = stat;
outbound = response.get(stat.remoteId);
break;
case 'outbound-rtp':
outbound = stat;
inbound = response.get(stat.remoteId);
break;
}
});
var standardizedStats = {};
var first = isRemote ? inbound : outbound;
var second = isRemote ? outbound : inbound;
function getStatValue(name) {
var first = outbound;
var second = inbound;
if (outbound && outbound.isRemote) {
first = inbound;
second = outbound;
}
if (first && typeof first[name] !== 'undefined') {
return first[name];
}
if (second && typeof second[name] !== 'undefined') {
return second[name];
}
return null;
}
var standardizedStats = {};
var timestamp = getStatValue('timestamp');

@@ -468,4 +567,4 @@ standardizedStats.timestamp = Math.round(timestamp);

var ssrc = getStatValue('ssrc');
if (typeof ssrc === 'string') {
standardizedStats.ssrc = ssrc;
if (typeof ssrc === 'number') {
standardizedStats.ssrc = String(ssrc);
}

@@ -488,3 +587,3 @@

var roundTripTime = getStatValue('mozRtt');
var roundTripTime = getStatValue('roundTripTime');
if (typeof roundTripTime === 'number') {

@@ -522,3 +621,2 @@ standardizedStats.roundTripTime = roundTripTime;

/**

@@ -525,0 +623,0 @@ * Standardized RTCIceCandidate statistics.

@@ -46,9 +46,2 @@ /* globals RTCDataChannel, RTCSessionDescription, webkitRTCPeerConnection */

// NOTE(mmalavalli): Because of a bug related to "ontrack", we prevent it
// from being delegated to ChromeRTCPeerConnection. For now, this bug
// manifests when we run Chrome with the flag: --enable-blink-features=RTCRtpSender
// Existing bug: https://bugs.chromium.org/p/chromium/issues/detail?id=774303
// Bug filed by us: https://bugs.chromium.org/p/chromium/issues/detail?id=783433
util.interceptEvent(this, 'track');
/* eslint new-cap:0 */

@@ -138,9 +131,13 @@ var peerConnection = new PeerConnection(newConfiguration, constraints);

// supported natively in Chrome.
// NOTE(mmalavalli): This shim also works around a Chrome bug in "unified-plan"
// SDPs where adding a MediaStreamTrack that was previously added and removed
// generates an SDP where the MSID does not match the MediaStreamTrack ID.
//
// Chrome bug: https://bugs.chromium.org/p/chromium/issues/detail?id=894231
//
ChromeRTCPeerConnection.prototype.addTrack = function addTrack() {
var args = [].slice.call(arguments);
if (this._peerConnection.addTrack) {
return this._peerConnection.addTrack.apply(this._peerConnection, args);
}
var track = args[0];
var sender = this._senders.get(track);
var track = args[0];
if (this._peerConnection.signalingState === 'closed') {

@@ -150,4 +147,2 @@ throw new Error('Cannot add MediaStreamTrack [' + track.id + ', '

}
var sender = this._senders.get(track);
if (sender && sender.track) {

@@ -157,2 +152,12 @@ throw new Error('Cannot add MediaStreamTrack [' + track.id + ', '

}
if (this._peerConnection.addTrack) {
if (this._sdpSemantics === 'unified-plan') {
sender = getActiveSenders(this._peerConnection).get(track)
|| this._peerConnection.addTrack.apply(this._peerConnection, args);
this._senders.set(track, sender);
return sender;
}
return this._peerConnection.addTrack.apply(this._peerConnection, args);
}
this._peerConnection.removeStream(this._localStream);

@@ -167,2 +172,18 @@ this._localStream.addTrack(track);

// NOTE(mmalavalli): This shim works around a Chrome bug in "unified-plan"
// SDPs where adding a MediaStreamTrack that was previously added and removed
// generates an SDP where the MSID does not match the MediaStreamTrack ID.
//
// Chrome bug: https://bugs.chromium.org/p/chromium/issues/detail?id=894231
//
if (PeerConnection.prototype.addTransceiver) {
ChromeRTCPeerConnection.prototype.addTransceiver = function addTransceiver() {
var transceiver = this._peerConnection.addTransceiver.apply(this._peerConnection, arguments);
var sender = transceiver.sender;
var track = sender.track;
this._senders.set(track, sender);
return transceiver;
};
}
// NOTE(mmalavalli): This shim supports our limited case of removing

@@ -172,2 +193,8 @@ // MediaStreamTracks from one MediaStream. It has been implemented this

// supported natively in Chrome.
// NOTE(mmalavalli): This shim also works around a Chrome bug in "unified-plan"
// SDPs where adding a MediaStreamTrack that was previously added and removed
// generates an SDP where the MSID does not match the MediaStreamTrack ID.
//
// Chrome bug: https://bugs.chromium.org/p/chromium/issues/detail?id=894231
//
ChromeRTCPeerConnection.prototype.removeTrack = function removeTrack(sender) {

@@ -180,3 +207,9 @@ if (this._peerConnection.signalingState === 'closed') {

try {
this._peerConnection.removeTrack(sender);
if (this._sdpSemantics === 'unified-plan') {
if (sender.track) {
this._senders.set(sender.track, new RTCRtpSenderShim(null));
}
} else {
this._peerConnection.removeTrack(sender);
}
}

@@ -206,6 +239,5 @@ catch (error) {

ChromeRTCPeerConnection.prototype.getSenders = function getSenders() {
if (this._peerConnection.getSenders) {
return this._peerConnection.getSenders();
}
return Array.from(this._senders.values());
return this._peerConnection.getSenders && this._sdpSemantics === 'plan-b'
? this._peerConnection.getSenders()
: Array.from(this._senders.values());
};

@@ -257,8 +289,3 @@

if (this._pendingRemoteOffer) {
var mediaStreamTracks = util.flatMap(this.getRemoteStreams(), function(mediaStream) {
return mediaStream.getTracks();
});
promise = this._peerConnection.setRemoteDescription(this._pendingRemoteOffer).then(function setRemoteDescriptionSucceeded() {
maybeDispatchTrackEvents(self, mediaStreamTracks);
// NOTE(mroberts): The signalingStates between the ChromeRTCPeerConnection

@@ -340,19 +367,2 @@ // and the underlying RTCPeerConnection implementation have converged. We

// Dispatch 'track' events to ChromeRTCPeerConnection if new
// MediaStreamTracks have been added. This is a temporary workaround
// for the unreliable MediaStreamTrack#addtrack event. Do this only if
// the native RTCPeerConnection has not implemented 'ontrack'.
function maybeDispatchTrackEvents(peerConnection, mediaStreamTracks) {
var currentMediaStreamTracks = util.flatMap(peerConnection.getRemoteStreams(), function(mediaStream) {
return mediaStream.getTracks();
});
var mediaStreamTracksAdded = util.difference(currentMediaStreamTracks, mediaStreamTracks);
mediaStreamTracksAdded.forEach(function(mediaStreamTrack) {
var newEvent = new Event('track');
newEvent.track = mediaStreamTrack;
peerConnection.dispatchEvent(newEvent);
});
}
// NOTE(mroberts): We workaround Chrome's lack of rollback support, per the

@@ -381,6 +391,2 @@ // workaround suggested here: https://bugs.chromium.org/p/webrtc/issues/detail?id=5738#c3

var mediaStreamTracks = util.flatMap(peerConnection.getRemoteStreams(), function(mediaStream) {
return mediaStream.getTracks();
});
var pendingLocalOffer = local ? peerConnection._pendingLocalOffer : peerConnection._pendingRemoteOffer;

@@ -435,14 +441,6 @@ var pendingRemoteOffer = local ? peerConnection._pendingRemoteOffer : peerConnection._pendingLocalOffer;

return promise || peerConnection._peerConnection[setLocalDescription](unwrap(description)).then(function() {
if (!local) {
maybeDispatchTrackEvents(peerConnection, mediaStreamTracks);
}
});
return promise || peerConnection._peerConnection[setLocalDescription](unwrap(description));
}
function setRemoteAnswer(peerConnection, answer) {
var mediaStreamTracks = util.flatMap(peerConnection.getRemoteStreams(), function(mediaStream) {
return mediaStream.getTracks();
});
// Apply the pending local offer.

@@ -454,3 +452,2 @@ var pendingLocalOffer = peerConnection._pendingLocalOffer;

}).then(function setRemoteAnswerSucceeded() {
maybeDispatchTrackEvents(peerConnection, mediaStreamTracks);
// NOTE(mroberts): The signalingStates between the ChromeRTCPeerConnection

@@ -526,2 +523,15 @@ // and the underlying RTCPeerConnection implementation have converged. We

/**
* Gets the active RTCRtpSenders of the RTCPeerConnection.
* @param peerConnection
* @returns {Map<MediaStreamTrack, RTCRtpSender>}
*/
function getActiveSenders(peerConnection) {
return new Map(peerConnection.getSenders().filter(function(sender) {
return sender.track;
}).map(function(sender) {
return [sender.track, sender];
}));
}
/**
* Get the actual `sdpSemantics`.

@@ -532,5 +542,10 @@ * @param {SdpSemantics} sdpSemantics

function getSdpSemantics(sdpSemantics) {
// NOTE(mmalavalli): Once Chrome stops supporting "plan-b" SDPs, it will
// ignore the "sdpSemantics" flag. So, in order to differentiate between
// versions of Chrome which support only "plan-b" SDPs and versions of Chrome
// which support only "unified-plan" SDPs, which check whether PeerConnection's
// addStream() method is present.
return sdpUtils.checkIfSdpSemanticsIsSupported()
? sdpSemantics
: 'plan-b';
: PeerConnection.prototype.addStream ? 'plan-b' : 'unified-plan';
}

@@ -537,0 +552,0 @@

@@ -1,2 +0,2 @@

/* globals RTCPeerConnection, RTCSessionDescription */
/* globals RTCPeerConnection, RTCRtpTransceiver, RTCSessionDescription */
'use strict';

@@ -8,5 +8,11 @@

var RTCRtpSenderShim = require('../rtcrtpsender');
var updateTracksToSSRCs = require('../util/sdp').updatePlanBTrackIdsToSSRCs;
var sdpUtils = require('../util/sdp');
var util = require('../util');
var isUnifiedPlan = 'currentDirection' in RTCRtpTransceiver.prototype;
var updateTrackIdsToSSRCs = isUnifiedPlan
? sdpUtils.updateUnifiedPlanTrackIdsToSSRCs
: sdpUtils.updatePlanBTrackIdsToSSRCs;
function SafariRTCPeerConnection(configuration) {

@@ -59,12 +65,6 @@ if (!(this instanceof SafariRTCPeerConnection)) {

},
// NOTE(mroberts): Keep this here until the following is fixed.
//
// https://bugs.webkit.org/show_bug.cgi?id=174323
//
localDescription: {
enumerable: true,
get: function() {
return this._isClosed
? null
: this._pendingLocalOffer || this._peerConnection.localDescription;
return this._pendingLocalOffer || this._peerConnection.localDescription;
}

@@ -91,5 +91,3 @@ },

get: function() {
return this._isClosed
? null
: this._pendingRemoteOffer || this._peerConnection.remoteDescription;
return this._pendingRemoteOffer || this._peerConnection.remoteDescription;
}

@@ -165,10 +163,22 @@ },

// good enough for our application.
if (options.offerToReceiveAudio && !this._audioTransceiver) {
if (options.offerToReceiveAudio && !this._audioTransceiver && !(isUnifiedPlan && hasSendersForTracksOfKind(this, 'audio'))) {
delete options.offerToReceiveAudio;
this._audioTransceiver = this.addTransceiver('audio');
try {
this._audioTransceiver = isUnifiedPlan
? this.addTransceiver('audio', { direction: 'recvonly' })
: this.addTransceiver('audio');
} catch (e) {
return Promise.reject(e);
}
}
if (options.offerToReceiveVideo && !this._videoTransceiver) {
if (options.offerToReceiveVideo && !this._videoTransceiver && !(isUnifiedPlan && hasSendersForTracksOfKind(this, 'video'))) {
delete options.offerToReceiveVideo;
this._videoTransceiver = this.addTransceiver('video');
try {
this._videoTransceiver = isUnifiedPlan
? this.addTransceiver('video', { direction: 'recvonly' })
: this.addTransceiver('video');
} catch (e) {
return Promise.reject(e);
}
}

@@ -179,3 +189,3 @@

type: offer.type,
sdp: updateTracksToSSRCs(self._tracksToSSRCs, offer.sdp)
sdp: updateTrackIdsToSSRCs(self._tracksToSSRCs, offer.sdp)
});

@@ -194,3 +204,6 @@ });

self._pendingRemoteOffer = null;
return answer;
return isUnifiedPlan ? new RTCSessionDescription({
type: answer.type,
sdp: updateTrackIdsToSSRCs(self._tracksToSSRCs, answer.sdp)
}) : answer;
}, function setRemoteDescriptionOrCreateAnswerFailed(error) {

@@ -202,3 +215,8 @@ self._pendingRemoteOffer = null;

return this._peerConnection.createAnswer(options);
return this._peerConnection.createAnswer(options).then(function(answer) {
return isUnifiedPlan ? new RTCSessionDescription({
type: answer.type,
sdp: updateTrackIdsToSSRCs(self._tracksToSSRCs, answer.sdp)
}) : answer;
});
};

@@ -259,2 +277,18 @@

// NOTE(mmalavalli): This shim works around a Safari bug in "unified-plan"
// SDPs where adding a MediaStreamTrack that was previously added and removed
// generates an SDP where the MSID does not match the MediaStreamTrack ID.
//
// Safari bug: https://bugs.webkit.org/show_bug.cgi?id=192101
//
if (RTCPeerConnection.prototype.addTransceiver) {
SafariRTCPeerConnection.prototype.addTransceiver = function addTransceiver() {
var transceiver = this._peerConnection.addTransceiver.apply(this._peerConnection, arguments);
var sender = transceiver.sender;
var track = sender.track;
this._senders.set(track, sender);
return transceiver;
};
}
// NOTE(mroberts): We can't really remove tracks right now, at least if we

@@ -265,2 +299,8 @@ // ever want to add them back...

//
// NOTE(mmalavalli): This shim also works around a Safari bug in "unified-plan"
// SDPs where adding a MediaStreamTrack that was previously added and removed
// generates an SDP where the MSID does not match the MediaStreamTrack ID.
//
// Safari bug: https://bugs.webkit.org/show_bug.cgi?id=192101
//
SafariRTCPeerConnection.prototype.removeTrack = function removeTrack(sender) {

@@ -362,2 +402,15 @@ if (this._isClosed) {

/**
* Whether a SafariRTCPeerConnection has any RTCRtpSender(s) for the given
* MediaStreamTrack kind.
* @param {SafariRTCPeerConnection} peerConnection
* @param {'audio' | 'video'} kind
* @returns {boolean}
*/
function hasSendersForTracksOfKind(peerConnection, kind) {
return !!peerConnection.getTransceivers().find(function(transceiver) {
return transceiver.sender && transceiver.sender.track && transceiver.sender.track.kind === kind;
});
}
/**
* Shim an RTCDataChannel. This function mutates the RTCDataChannel.

@@ -364,0 +417,0 @@ * @param {RTCDataChannel} dataChannel

{
"name": "@twilio/webrtc",
"version": "2.1.4",
"version": "2.2.0",
"description": "WebRTC-related APIs and shims used by twilio-video.js",

@@ -46,3 +46,3 @@ "scripts": {

"karma-mocha": "^1.3.0",
"karma-safaritechpreview-launcher": "0.0.6",
"karma-safari-launcher": "^1.0.0",
"karma-spec-reporter": "0.0.31",

@@ -55,4 +55,4 @@ "mocha": "^3.5.0",

"watchify": "^3.9.0",
"webrtc-adapter": "^6.0.1"
"webrtc-adapter": "^6.4.8"
}
}

@@ -80,5 +80,5 @@ twilio-webrtc.js

more information.
* Does not depend on the native "track" event (currently behind the flag: `--enable-blink-features=RTCRtpSender`) because
of [this bug](https://bugs.chromium.org/p/chromium/issues/detail?id=774303), which partly refers to "ontrack" not firing when expected.
We have filed [this bug](https://bugs.chromium.org/p/chromium/issues/detail?id=783433) specifically for this.
* Works around a [this bug](https://bugs.chromium.org/p/chromium/issues/detail?id=894231)
in "unified-plan" SDPs where adding a `MediaStreamTrack` that was previously added and
removed generates an SDP where the MSID does not match the `MediaStreamTrack` ID.

@@ -106,4 +106,2 @@ #### Firefox

`MediaStreamTrack`.
* Provides a workaround for [this bug](https://bugs.webkit.org/show_bug.cgi?id=174323), where
trying to access the `localDescription` or `remoteDescription` throws an exception.
* Provides a shim for the `removeTrack` method in order to work around [this bug](https://bugs.webkit.org/show_bug.cgi?id=174327).

@@ -110,0 +108,0 @@ * Provides a shim for the `addTrack` method. Since `removeTrack` is shimmed, there is a necessity to

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc