319 lines
15 KiB
JavaScript
319 lines
15 KiB
JavaScript
|
/*
|
||
|
* 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.shimAddTransceiver = shimAddTransceiver;
|
||
|
exports.shimCreateAnswer = shimCreateAnswer;
|
||
|
exports.shimCreateOffer = shimCreateOffer;
|
||
|
Object.defineProperty(exports, "shimGetDisplayMedia", {
|
||
|
enumerable: true,
|
||
|
get: function get() {
|
||
|
return _getdisplaymedia.shimGetDisplayMedia;
|
||
|
}
|
||
|
});
|
||
|
exports.shimGetParameters = shimGetParameters;
|
||
|
Object.defineProperty(exports, "shimGetUserMedia", {
|
||
|
enumerable: true,
|
||
|
get: function get() {
|
||
|
return _getusermedia.shimGetUserMedia;
|
||
|
}
|
||
|
});
|
||
|
exports.shimOnTrack = shimOnTrack;
|
||
|
exports.shimPeerConnection = shimPeerConnection;
|
||
|
exports.shimRTCDataChannel = shimRTCDataChannel;
|
||
|
exports.shimReceiverGetStats = shimReceiverGetStats;
|
||
|
exports.shimRemoveStream = shimRemoveStream;
|
||
|
exports.shimSenderGetStats = shimSenderGetStats;
|
||
|
var utils = _interopRequireWildcard(require("../utils"));
|
||
|
var _getusermedia = require("./getusermedia");
|
||
|
var _getdisplaymedia = require("./getdisplaymedia");
|
||
|
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
||
|
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
||
|
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
|
||
|
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
||
|
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
||
|
function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
|
||
|
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
|
||
|
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
|
||
|
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
||
|
function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); }
|
||
|
function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
|
||
|
function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
|
||
|
function shimOnTrack(window) {
|
||
|
if (_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) !== '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) === '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) === '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) === 'object' && window.RTCPeerConnection)) {
|
||
|
return;
|
||
|
}
|
||
|
var origAddTransceiver = window.RTCPeerConnection.prototype.addTransceiver;
|
||
|
if (origAddTransceiver) {
|
||
|
window.RTCPeerConnection.prototype.addTransceiver = function addTransceiver() {
|
||
|
this.setParametersPromises = [];
|
||
|
// WebIDL input coercion and validation
|
||
|
var sendEncodings = arguments[1] && arguments[1].sendEncodings;
|
||
|
if (sendEncodings === undefined) {
|
||
|
sendEncodings = [];
|
||
|
}
|
||
|
sendEncodings = _toConsumableArray(sendEncodings);
|
||
|
var shouldPerformCheck = sendEncodings.length > 0;
|
||
|
if (shouldPerformCheck) {
|
||
|
// If sendEncodings params are provided, validate grammar
|
||
|
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 = sendEncodings;
|
||
|
sender.sendEncodings = 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) === '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) === 'object' && window.RTCPeerConnection)) {
|
||
|
return;
|
||
|
}
|
||
|
var origCreateOffer = window.RTCPeerConnection.prototype.createOffer;
|
||
|
window.RTCPeerConnection.prototype.createOffer = function createOffer() {
|
||
|
var _arguments2 = arguments,
|
||
|
_this4 = this;
|
||
|
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) === 'object' && window.RTCPeerConnection)) {
|
||
|
return;
|
||
|
}
|
||
|
var origCreateAnswer = window.RTCPeerConnection.prototype.createAnswer;
|
||
|
window.RTCPeerConnection.prototype.createAnswer = function createAnswer() {
|
||
|
var _arguments3 = arguments,
|
||
|
_this5 = this;
|
||
|
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);
|
||
|
};
|
||
|
}
|