156 lines
5.6 KiB
JavaScript
156 lines
5.6 KiB
JavaScript
(global => {
|
|
const {
|
|
MediaStream,
|
|
MediaStreamTrack,
|
|
RTCPeerConnection,
|
|
RTCSessionDescription,
|
|
getUserMedia
|
|
} = require('react-native-webrtc');
|
|
|
|
if (typeof global.webkitMediaStream === 'undefined') {
|
|
global.webkitMediaStream = MediaStream;
|
|
}
|
|
|
|
if (typeof global.MediaStreamTrack === 'undefined') {
|
|
global.MediaStreamTrack = MediaStreamTrack;
|
|
}
|
|
|
|
if (typeof global.webkitRTCPeerConnection === 'undefined') {
|
|
// XXX At the time of this writing extending RTCPeerConnection using ES6
|
|
// 'class' and 'extends' causes a runtime error related to the attempt
|
|
// to define the onaddstream property setter. The error mentions that
|
|
// babelHelpers.set is undefined which appears to be a thing inside
|
|
// React Native's packager. As a workaround, extend using the pre-ES6
|
|
// way.
|
|
|
|
/* eslint-disable no-inner-declarations */
|
|
|
|
/**
|
|
* The RTCPeerConnection provided by react-native-webrtc fires
|
|
* onaddstream before it remembers remotedescription (and thus makes it
|
|
* available to API clients). Because that appears to be a problem for
|
|
* lib-jitsi-meet which has been successfully running
|
|
* on Chrome, Firefox, Temasys, etc. for a very long time, attempt to
|
|
* meets its expectations (by extending RTCPPeerConnection).
|
|
*
|
|
* @class
|
|
*/
|
|
function _RTCPeerConnection(...args) {
|
|
|
|
/* eslint-disable no-invalid-this */
|
|
|
|
RTCPeerConnection.apply(this, args);
|
|
|
|
this.onaddstream = (...args) => // eslint-disable-line no-shadow
|
|
(this._onaddstreamQueue
|
|
? this._queueOnaddstream
|
|
: this._invokeOnaddstream)
|
|
.apply(this, args);
|
|
|
|
// Shadow RTCPeerConnection's onaddstream but after
|
|
// _RTCPeerConnection has assigned to the property in question.
|
|
// Defining the property on _RTCPeerConnection's prototype may (or
|
|
// may not, I don't know) work but I don't want to try because the
|
|
// following approach appears to work and I understand it.
|
|
Object.defineProperty(this, 'onaddstream', {
|
|
configurable: true,
|
|
enumerable: true,
|
|
get() {
|
|
return this._onaddstream;
|
|
},
|
|
set(value) {
|
|
this._onaddstream = value;
|
|
}
|
|
});
|
|
|
|
/* eslint-enable no-invalid-this */
|
|
}
|
|
|
|
/* eslint-enable no-inner-declarations */
|
|
|
|
_RTCPeerConnection.prototype
|
|
= Object.create(RTCPeerConnection.prototype);
|
|
_RTCPeerConnection.prototype.constructor = _RTCPeerConnection;
|
|
_RTCPeerConnection.prototype._invokeOnaddstream = function(...args) {
|
|
const onaddstream = this._onaddstream;
|
|
let r;
|
|
|
|
if (onaddstream) {
|
|
r = onaddstream.apply(this, args);
|
|
}
|
|
|
|
return r;
|
|
};
|
|
_RTCPeerConnection.prototype._invokeQueuedOnaddstream = function(q) {
|
|
q && q.every(function(args) {
|
|
try {
|
|
this._invokeOnaddstream(...args);
|
|
} catch (e) {
|
|
// TODO Determine whether the combination of the standard
|
|
// setRemoteDescription and onaddstream results in a similar
|
|
// swallowing of errors.
|
|
console && console.error && console.error(e);
|
|
}
|
|
|
|
return true;
|
|
}, this);
|
|
};
|
|
_RTCPeerConnection.prototype._queueOnaddstream = function(...args) {
|
|
this._onaddstreamQueue.push(Array.from(args));
|
|
};
|
|
_RTCPeerConnection.prototype.setRemoteDescription
|
|
= function(sessionDescription, successCallback, errorCallback) {
|
|
// Ensure I'm not remembering onaddstream invocations from
|
|
// previous setRemoteDescription calls. I shouldn't be but...
|
|
// anyway.
|
|
this._onaddstreamQueue = [];
|
|
|
|
return RTCPeerConnection.prototype.setRemoteDescription.call(
|
|
this,
|
|
sessionDescription,
|
|
(...args) => {
|
|
let r;
|
|
let q;
|
|
|
|
try {
|
|
if (successCallback) {
|
|
r = successCallback(...args);
|
|
}
|
|
} finally {
|
|
q = this._onaddstreamQueue;
|
|
this._onaddstreamQueue = undefined;
|
|
}
|
|
|
|
this._invokeQueuedOnaddstream(q);
|
|
|
|
return r;
|
|
},
|
|
(...args) => {
|
|
let r;
|
|
|
|
this._onaddstreamQueue = undefined;
|
|
|
|
if (errorCallback) {
|
|
r = errorCallback(...args);
|
|
}
|
|
|
|
return r;
|
|
});
|
|
};
|
|
|
|
global.webkitRTCPeerConnection = _RTCPeerConnection;
|
|
}
|
|
if (typeof global.RTCSessionDescription === 'undefined') {
|
|
global.RTCSessionDescription = RTCSessionDescription;
|
|
}
|
|
|
|
const navigator = global.navigator;
|
|
|
|
if (navigator) {
|
|
if (typeof navigator.webkitGetUserMedia === 'undefined') {
|
|
navigator.webkitGetUserMedia = getUserMedia;
|
|
}
|
|
}
|
|
|
|
})(global || window || this); // eslint-disable-line no-invalid-this
|