New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.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

to
4.0.0

17

CHANGELOG.md

@@ -0,1 +1,18 @@

4.0.0 (March 15, 2019)
======================
New Features
------------
- SafariRTCPeerConnection will now support Unified Plan SDPs in Safari 12.1 and above. (JSDK-2306)
Bug Fixes
---------
- Fixed a bug where getStats was throwing a TypeError in Electron 3.x. (JSDK-2267)
- Fixed a bug where createOffer(), when called in Safari 12.2 created "offerToReceive"
RTCRtpTransceivers even though the RTCPeerConnection already had "sendrecv" or
"recvonly" RTCRtpTransceivers. (JSDK-2286)
3.2.0 (January 7, 2019)

@@ -2,0 +19,0 @@ =======================

90

lib/getstats.js

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

/* global RTCRtpTransceiver */
'use strict';

@@ -6,2 +5,3 @@

var guessBrowser = require('./util').guessBrowser;
var getSdpFormat = require('./util/sdp').getSdpFormat;

@@ -12,3 +12,8 @@ var guess = guessBrowser();

var isSafari = guess === 'safari';
var sdpFormat = getSdpFormat();
var chromeMajorVersion = isChrome
? parseInt(navigator.userAgent.match(/Chrome\/([0-9]+)/)[1], 10)
: null;
/**

@@ -316,4 +321,3 @@ * Get the standardized {@link RTCPeerConnection} statistics.

if (typeof options.testForSafari !== 'undefined' || isSafari) {
if (typeof options.testForSafari !== 'undefined'
|| 'currentDirection' in RTCRtpTransceiver.prototype) {
if (typeof options.testForSafari !== 'undefined' || sdpFormat === 'unified') {
return chromeOrSafariGetTrackStats(peerConnection, track);

@@ -340,2 +344,8 @@ }

return new Promise(function(resolve, reject) {
if (chromeMajorVersion && chromeMajorVersion < 67) {
peerConnection.getStats(function(response) {
resolve(standardizeChromeLegacyStats(response, track));
}, null, reject);
return;
}
peerConnection.getStats(track).then(function(response) {

@@ -363,2 +373,76 @@ resolve(standardizeChromeOrSafariStats(response));

/**
* Standardize the MediaStreamTrack's legacy statistics in Chrome.
* @param {RTCStatsResponse} response
* @param {MediaStreamTrack} track
* @returns {StandardizedTrackStatsReport}
*/
function standardizeChromeLegacyStats(response, track) {
var ssrcReport = response.result().find(function(report) {
return report.type === 'ssrc' && report.stat('googTrackId') === track.id;
});
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;
}
return stats;
}, standardizedStats);
}
return standardizedStats;
}
/**
* Standardize the MediaStreamTrack's statistics in Chrome or Safari.

@@ -365,0 +449,0 @@ * @param {RTCStatsResponse} response

6

lib/mediastream.js

@@ -1,7 +0,5 @@

/* globals webkitMediaStream, MediaStream */
/* globals MediaStream */
'use strict';
if (typeof webkitMediaStream !== 'undefined') {
module.exports = webkitMediaStream;
} else if (typeof MediaStream !== 'undefined') {
if (typeof MediaStream !== 'undefined') {
module.exports = MediaStream;

@@ -8,0 +6,0 @@ } else {

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

/* globals RTCDataChannel, RTCSessionDescription, webkitRTCPeerConnection */
/* globals RTCDataChannel, RTCPeerConnection, RTCSessionDescription */
'use strict';

@@ -13,5 +13,3 @@

var PeerConnection = typeof RTCPeerConnection !== 'undefined'
? RTCPeerConnection
: webkitRTCPeerConnection;
var sdpFormat = sdpUtils.getSdpFormat();

@@ -36,9 +34,6 @@ // NOTE(mroberts): This class wraps Chrome's RTCPeerConnection implementation.

// NOTE(mhuynh): See
// https://webrtc.org/web-apis/chrome/unified-plan/
// for transition from 'plan-b' default to 'unified-plan' as default.
var newConfiguration = Object.assign({ sdpSemantics: 'plan-b' }, configuration);
if (newConfiguration.iceTransportPolicy) {
newConfiguration.iceTransports = newConfiguration.iceTransportPolicy;
}
configuration = configuration || {};
var newConfiguration = Object.assign(configuration.iceTransportPolicy
? { iceTransports: configuration.iceTransportPolicy }
: {}, { sdpSemantics: 'plan-b' }, configuration);

@@ -48,5 +43,3 @@ util.interceptEvent(this, 'datachannel');

/* eslint new-cap:0 */
var peerConnection = new PeerConnection(newConfiguration, constraints);
var sdpSemantics = getSdpSemantics(newConfiguration.sdpSemantics);
var peerConnection = new RTCPeerConnection(newConfiguration, constraints);

@@ -68,5 +61,2 @@ Object.defineProperties(this, {

},
_sdpSemantics: {
value: sdpSemantics
},
_senders: {

@@ -124,4 +114,6 @@ value: new Map()

peerConnection.addStream(this._localStream);
util.proxyProperties(PeerConnection.prototype, this, peerConnection);
if (typeof RTCPeerConnection.prototype.addTrack !== 'function') {
peerConnection.addStream(this._localStream);
}
util.proxyProperties(RTCPeerConnection.prototype, this, peerConnection);
}

@@ -131,3 +123,3 @@

if (typeof PeerConnection.prototype.addTrack !== 'function') {
if (typeof RTCPeerConnection.prototype.addTrack !== 'function') {
// NOTE(mmalavalli): This shim supports our limited case of adding

@@ -253,5 +245,5 @@ // all MediaStreamTracks to one MediaStream. It has been implemented this

self._pendingRemoteOffer = null;
return new RTCSessionDescription({
return new ChromeRTCSessionDescription({
type: 'answer',
sdp: updateTrackIdsToSSRCs(self._sdpSemantics, self._tracksToSSRCs, answer.sdp)
sdp: updateTrackIdsToSSRCs(sdpFormat, self._tracksToSSRCs, answer.sdp)
});

@@ -264,5 +256,5 @@ }, function setRemoteDescriptionOrCreateAnswerFailed(error) {

promise = this._peerConnection.createAnswer().then(function(answer) {
return new RTCSessionDescription({
return new ChromeRTCSessionDescription({
type: 'answer',
sdp: updateTrackIdsToSSRCs(self._sdpSemantics, self._tracksToSSRCs, answer.sdp)
sdp: updateTrackIdsToSSRCs(sdpFormat, self._tracksToSSRCs, answer.sdp)
});

@@ -285,3 +277,3 @@ });

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

@@ -321,3 +313,3 @@ });

util.delegateMethods(
PeerConnection.prototype,
RTCPeerConnection.prototype,
ChromeRTCPeerConnection.prototype,

@@ -478,28 +470,12 @@ '_peerConnection');

/**
* Get the actual `sdpSemantics`.
* @param {SdpSemantics} sdpSemantics
* @returns {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
: PeerConnection.prototype.addStream ? 'plan-b' : 'unified-plan';
}
/**
* Update the mappings from MediaStreamTrack IDs to SSRCs as indicated by both
* the Map from MediaStreamTrack IDs to SSRCs and the SDP itself. This method
* ensures that SSRCs never change once announced.
* @param {SdpSemantics} sdpSemantics
* @param {Map<string, Set<string>>} trackIdsToSSRCs
* @param {'planb'|'unified'} sdpFormat
* @param {Map<string, Set<string>>} tracksToSSRCs
* @param {string} sdp - an SDP whose format is determined by `sdpSemantics`
* @returns {string} updatedSdp - updated SDP
*/
function updateTrackIdsToSSRCs(sdpSemantics, tracksToSSRCs, sdp) {
return sdpSemantics === 'unified-plan'
function updateTrackIdsToSSRCs(sdpFormat, tracksToSSRCs, sdp) {
return sdpFormat === 'unified'
? sdpUtils.updateUnifiedPlanTrackIdsToSSRCs(tracksToSSRCs, sdp)

@@ -506,0 +482,0 @@ : sdpUtils.updatePlanBTrackIdsToSSRCs(tracksToSSRCs, sdp);

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

/* globals mozRTCPeerConnection, RTCPeerConnection */
/* globals RTCPeerConnection */
'use strict';

@@ -10,6 +10,2 @@

var PeerConnection = typeof RTCPeerConnection !== 'undefined'
? RTCPeerConnection
: mozRTCPeerConnection;
// NOTE(mroberts): This is a short-lived workaround. Checking the user agent

@@ -52,3 +48,3 @@ // string might not fix every affected Firefox instance, but it should be good

/* eslint new-cap:0 */
var peerConnection = new PeerConnection(configuration);
var peerConnection = new RTCPeerConnection(configuration);

@@ -114,3 +110,3 @@ Object.defineProperties(this, {

util.proxyProperties(PeerConnection.prototype, this, peerConnection);
util.proxyProperties(RTCPeerConnection.prototype, this, peerConnection);
}

@@ -264,3 +260,3 @@

util.delegateMethods(
PeerConnection.prototype,
RTCPeerConnection.prototype,
FirefoxRTCPeerConnection.prototype,

@@ -267,0 +263,0 @@ '_peerConnection');

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

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

@@ -10,3 +10,3 @@

var isUnifiedPlan = 'currentDirection' in RTCRtpTransceiver.prototype;
var isUnifiedPlan = sdpUtils.getSdpFormat() === 'unified';

@@ -153,3 +153,3 @@ var updateTrackIdsToSSRCs = isUnifiedPlan

// good enough for our application.
if (options.offerToReceiveAudio && !this._audioTransceiver && !(isUnifiedPlan && hasSendersForTracksOfKind(this, 'audio'))) {
if (options.offerToReceiveAudio && !this._audioTransceiver && !(isUnifiedPlan && hasReceiversForTracksOfKind(this, 'audio'))) {
delete options.offerToReceiveAudio;

@@ -165,3 +165,3 @@ try {

if (options.offerToReceiveVideo && !this._videoTransceiver && !(isUnifiedPlan && hasSendersForTracksOfKind(this, 'video'))) {
if (options.offerToReceiveVideo && !this._videoTransceiver && !(isUnifiedPlan && hasReceiversForTracksOfKind(this, 'video'))) {
delete options.offerToReceiveVideo;

@@ -318,3 +318,3 @@ try {

/**
* Whether a SafariRTCPeerConnection has any RTCRtpSender(s) for the given
* Whether a SafariRTCPeerConnection has any RTCRtpReceivers(s) for the given
* MediaStreamTrack kind.

@@ -325,5 +325,5 @@ * @param {SafariRTCPeerConnection} peerConnection

*/
function hasSendersForTracksOfKind(peerConnection, kind) {
function hasReceiversForTracksOfKind(peerConnection, kind) {
return !!peerConnection.getTransceivers().find(function(transceiver) {
return transceiver.sender && transceiver.sender.track && transceiver.sender.track.kind === kind;
return transceiver.receiver && transceiver.receiver.track && transceiver.receiver.track.kind === kind;
});

@@ -330,0 +330,0 @@ }

@@ -112,11 +112,12 @@ 'use strict';

function guessBrowser() {
if (typeof webkitRTCPeerConnection !== 'undefined') {
return 'chrome';
} else if (typeof mozRTCPeerConnection !== 'undefined') {
return 'firefox';
} else if (typeof RTCPeerConnection !== 'undefined') {
if (typeof navigator !== 'undefined' && navigator.userAgent.match(/AppleWebKit\/(\d+)\./)) {
if (typeof navigator !== 'undefined' && typeof navigator.userAgent === 'string') {
if (/Chrome/.test(navigator.userAgent)) {
return 'chrome';
}
if (/Firefox/.test(navigator.userAgent)) {
return 'firefox';
}
if (/Safari/.test(navigator.userAgent)) {
return 'safari';
}
// NOTE(mroberts): Could be Edge.
}

@@ -123,0 +124,0 @@ return null;

@@ -0,6 +1,81 @@

/* globals RTCPeerConnection, RTCRtpTransceiver */
'use strict';
var flatMap = require('./').flatMap;
var guessBrowser = require('./').guessBrowser;
// NOTE(mmalavalli): We cache Chrome's sdpSemantics support in order to prevent
// instantiation of more than one RTCPeerConnection.
var isSdpSemanticsSupported;
/**
* Check if Chrome supports specifying sdpSemantics for an RTCPeerConnection.
* @return {boolean}
*/
function checkIfSdpSemanticsIsSupported() {
if (typeof isSdpSemanticsSupported === 'boolean') {
return isSdpSemanticsSupported;
}
if (typeof RTCPeerConnection === 'undefined') {
isSdpSemanticsSupported = false;
return isSdpSemanticsSupported;
}
try {
new RTCPeerConnection({ sdpSemantics: 'foo' });
isSdpSemanticsSupported = false;
} catch (e) {
isSdpSemanticsSupported = true;
}
return isSdpSemanticsSupported;
}
// NOTE(mmalavalli): We cache Chrome's SDP format in order to prevent
// instantiation of more than one RTCPeerConnection.
var chromeSdpFormat;
/**
* Get Chrome's default SDP format.
* @returns {'planb'|'unified'}
*/
function getChromeSdpFormat() {
if (typeof chromeSdpFormat === 'string') {
return chromeSdpFormat;
}
if (checkIfSdpSemanticsIsSupported()) {
chromeSdpFormat = 'planb';
return chromeSdpFormat;
}
chromeSdpFormat = typeof RTCPeerConnection !== 'undefined'
&& 'addStream' in RTCPeerConnection.prototype
? 'planb'
: 'unified';
return chromeSdpFormat;
}
/**
* Get Safari's default SDP format.
* @returns {'planb'|'unified'}
*/
function getSafariSdpFormat() {
return typeof RTCRtpTransceiver !== 'undefined'
&& 'currentDirection' in RTCRtpTransceiver.prototype
? 'unified'
: 'planb';
}
/**
* Get the browser's default SDP format.
* @returns {'planb'|'unified'}
*/
function getSdpFormat() {
return {
chrome: getChromeSdpFormat(),
firefox: 'unified',
safari: getSafariSdpFormat()
}[guessBrowser()] || null;
}
/**
* Match a pattern across lines, returning the first capture group for any

@@ -209,29 +284,3 @@ * matches.

// NOTE(mroberts): We need to cache this result so that we don't create too many
// RTCPeerConnections.
var sdpSemanticsIsSupported;
/**
* Check whether or not `sdpSemantics` is supported.
* @returns {boolean}
*/
function checkIfSdpSemanticsIsSupported() {
if (typeof sdpSemanticsIsSupported === 'boolean') {
return sdpSemanticsIsSupported;
}
if (typeof RTCPeerConnection === 'undefined') {
sdpSemanticsIsSupported = false;
return sdpSemanticsIsSupported;
}
try {
new RTCPeerConnection({ sdpSemantics: 'bogus' });
sdpSemanticsIsSupported = false;
return sdpSemanticsIsSupported;
} catch (error) {
sdpSemanticsIsSupported = true;
return sdpSemanticsIsSupported;
}
}
exports.checkIfSdpSemanticsIsSupported = checkIfSdpSemanticsIsSupported;
exports.getSdpFormat = getSdpFormat;
exports.getMediaSections = getMediaSections;

@@ -238,0 +287,0 @@ exports.getPlanBTrackIds = getPlanBTrackIds;

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

@@ -5,0 +5,0 @@ "scripts": {