mirror of https://github.com/OpenVidu/openvidu.git
OpenVidu ready beta 1.9.0 (Safari support)
parent
a23879ebf6
commit
fae55acd42
|
@ -8,7 +8,7 @@
|
|||
"sdp-translator": "0.1.24",
|
||||
"ua-parser-js": "0.7.17",
|
||||
"uuid": "3.1.0",
|
||||
"webrtc-adapter": "6.1.1",
|
||||
"webrtc-adapter": "6.1.4",
|
||||
"wolfy87-eventemitter": "5.2.4"
|
||||
},
|
||||
"description": "OpenVidu Browser",
|
||||
|
|
|
@ -94,8 +94,7 @@ function bufferizeCandidates(pc, onerror) {
|
|||
if (this.signalingState === 'stable') {
|
||||
while (candidatesQueue.length) {
|
||||
var entry = candidatesQueue.shift()
|
||||
|
||||
this.addIceCandidate(entry.candidate, entry.callback, entry.callback)
|
||||
pc.addIceCandidate(entry.candidate, entry.callback, entry.callback)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -332,7 +331,7 @@ function WebRtcPeer(mode, options, callback) {
|
|||
}
|
||||
})
|
||||
|
||||
pc.ontrack = options.onaddstream
|
||||
pc.onaddstream = options.onaddstream
|
||||
pc.onnegotiationneeded = options.onnegotiationneeded
|
||||
this.on('newListener', function (event, listener) {
|
||||
if (event === 'icecandidate' || event === 'candidategatheringdone') {
|
||||
|
@ -424,19 +423,18 @@ function WebRtcPeer(mode, options, callback) {
|
|||
|
||||
function setRemoteVideo() {
|
||||
if (remoteVideo) {
|
||||
var stream = pc.getRemoteStreams()[0]
|
||||
var url = stream ? URL.createObjectURL(stream) : ''
|
||||
|
||||
remoteVideo.pause()
|
||||
remoteVideo.src = url
|
||||
remoteVideo.load()
|
||||
|
||||
logger.debug('Remote URL:', url)
|
||||
var stream = pc.getRemoteStreams()[0]
|
||||
remoteVideo.srcObject = stream
|
||||
logger.debug('Remote stream:', stream)
|
||||
|
||||
remoteVideo.load()
|
||||
}
|
||||
}
|
||||
|
||||
this.showLocalVideo = function () {
|
||||
localVideo.src = URL.createObjectURL(videoStream)
|
||||
localVideo.srcObject = videoStream
|
||||
localVideo.muted = true
|
||||
}
|
||||
|
||||
|
@ -621,14 +619,14 @@ function WebRtcPeer(mode, options, callback) {
|
|||
this.on('_dispose', function () {
|
||||
if (localVideo) {
|
||||
localVideo.pause()
|
||||
localVideo.src = ''
|
||||
localVideo.srcObject = null
|
||||
localVideo.load()
|
||||
//Unmute local video in case the video tag is later used for remote video
|
||||
localVideo.muted = false
|
||||
}
|
||||
if (remoteVideo) {
|
||||
remoteVideo.pause()
|
||||
remoteVideo.src = ''
|
||||
remoteVideo.srcObject = null
|
||||
remoteVideo.load()
|
||||
}
|
||||
self.removeAllListeners()
|
||||
|
|
|
@ -242,7 +242,7 @@ export class OpenVidu {
|
|||
let browser = DetectRTC.browser.name;
|
||||
let version = DetectRTC.browser.version;
|
||||
|
||||
if ((browser !== 'Chrome') && (browser !== 'Firefox') && (browser !== 'Opera')) {
|
||||
if ((browser !== 'Chrome') && (browser !== 'Firefox') && (browser !== 'Opera') && (browser !== 'Safari')) {
|
||||
return 0;
|
||||
} else {
|
||||
return defaultWebRTCSupport ? 1 : 0;
|
||||
|
|
|
@ -309,6 +309,7 @@ export class Stream {
|
|||
return this.video;
|
||||
}
|
||||
|
||||
this.isReadyToPublish = true;
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,20 +2,19 @@ FROM ubuntu:16.04
|
|||
MAINTAINER openvidu@gmail.com
|
||||
|
||||
# Install Kurento Media Server (KMS)
|
||||
RUN echo "deb http://ubuntu.kurento.org xenial kms6" | tee /etc/apt/sources.list.d/kurento.list \
|
||||
&& apt-key adv --keyserver keyserver.ubuntu.com --recv 2F819BC0 \
|
||||
RUN echo "deb http://ubuntu.openvidu.io/6.7.0 xenial kms6" | tee /etc/apt/sources.list.d/kurento.list \
|
||||
&& apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 5AFA7A83 \
|
||||
&& apt-get update \
|
||||
&& apt-get -y dist-upgrade \
|
||||
&& apt-get -y install kurento-media-server-6.0 \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
&& apt-get -y install kurento-media-server
|
||||
|
||||
COPY kms.sh /kms.sh
|
||||
|
||||
# Install Java
|
||||
RUN apt-get update && apt-get install -y openjdk-8-jdk && rm -rf /var/lib/apt/lists/*
|
||||
RUN apt-get install -y openjdk-8-jdk
|
||||
|
||||
# Install supervisor
|
||||
RUN apt-get update && apt-get install -y supervisor && rm -rf /var/lib/apt/lists/*
|
||||
RUN apt-get install -y supervisor && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Configure supervisor
|
||||
RUN mkdir -p /var/log/supervisor
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"version":3,"sources":["webpack/bootstrap a86aab8ac212e4073a88"],"names":[],"mappings":";AAAA;AACA;AACA;AACA;AACA;AACA;AACA,gBAAQ,oBAAoB;AAC5B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oBAAY,2BAA2B;AACvC;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;;AAGA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAK;AACL;AACA;;AAEA;AACA;AACA;AACA,mCAA2B,0BAA0B,EAAE;AACvD,yCAAiC,eAAe;AAChD;AACA;AACA;;AAEA;AACA,8DAAsD,+DAA+D;;AAErH;AACA;;AAEA;AACA,kDAA0C,oBAAoB,WAAW","file":"inline.bundle.js","sourcesContent":[" \t// install a JSONP callback for chunk loading\n \tvar parentJsonpFunction = window[\"webpackJsonp\"];\n \twindow[\"webpackJsonp\"] = function webpackJsonpCallback(chunkIds, moreModules, executeModules) {\n \t\t// add \"moreModules\" to the modules object,\n \t\t// then flag all \"chunkIds\" as loaded and fire callback\n \t\tvar moduleId, chunkId, i = 0, resolves = [], result;\n \t\tfor(;i < chunkIds.length; i++) {\n \t\t\tchunkId = chunkIds[i];\n \t\t\tif(installedChunks[chunkId]) {\n \t\t\t\tresolves.push(installedChunks[chunkId][0]);\n \t\t\t}\n \t\t\tinstalledChunks[chunkId] = 0;\n \t\t}\n \t\tfor(moduleId in moreModules) {\n \t\t\tif(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {\n \t\t\t\tmodules[moduleId] = moreModules[moduleId];\n \t\t\t}\n \t\t}\n \t\tif(parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules, executeModules);\n \t\twhile(resolves.length) {\n \t\t\tresolves.shift()();\n \t\t}\n \t\tif(executeModules) {\n \t\t\tfor(i=0; i < executeModules.length; i++) {\n \t\t\t\tresult = __webpack_require__(__webpack_require__.s = executeModules[i]);\n \t\t\t}\n \t\t}\n \t\treturn result;\n \t};\n\n \t// The module cache\n \tvar installedModules = {};\n\n \t// objects to store loaded and loading chunks\n \tvar installedChunks = {\n \t\t\"inline\": 0\n \t};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, {\n \t\t\t\tconfigurable: false,\n \t\t\t\tenumerable: true,\n \t\t\t\tget: getter\n \t\t\t});\n \t\t}\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \t// on error function for async loading\n \t__webpack_require__.oe = function(err) { console.error(err); throw err; };\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap a86aab8ac212e4073a88"],"sourceRoot":"webpack:///"}
|
||||
{"version":3,"sources":["webpack/bootstrap 128521254b4cc7ad5819"],"names":[],"mappings":";AAAA;AACA;AACA;AACA;AACA;AACA;AACA,gBAAQ,oBAAoB;AAC5B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oBAAY,2BAA2B;AACvC;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;;AAGA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAK;AACL;AACA;;AAEA;AACA;AACA;AACA,mCAA2B,0BAA0B,EAAE;AACvD,yCAAiC,eAAe;AAChD;AACA;AACA;;AAEA;AACA,8DAAsD,+DAA+D;;AAErH;AACA;;AAEA;AACA,kDAA0C,oBAAoB,WAAW","file":"inline.bundle.js","sourcesContent":[" \t// install a JSONP callback for chunk loading\n \tvar parentJsonpFunction = window[\"webpackJsonp\"];\n \twindow[\"webpackJsonp\"] = function webpackJsonpCallback(chunkIds, moreModules, executeModules) {\n \t\t// add \"moreModules\" to the modules object,\n \t\t// then flag all \"chunkIds\" as loaded and fire callback\n \t\tvar moduleId, chunkId, i = 0, resolves = [], result;\n \t\tfor(;i < chunkIds.length; i++) {\n \t\t\tchunkId = chunkIds[i];\n \t\t\tif(installedChunks[chunkId]) {\n \t\t\t\tresolves.push(installedChunks[chunkId][0]);\n \t\t\t}\n \t\t\tinstalledChunks[chunkId] = 0;\n \t\t}\n \t\tfor(moduleId in moreModules) {\n \t\t\tif(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {\n \t\t\t\tmodules[moduleId] = moreModules[moduleId];\n \t\t\t}\n \t\t}\n \t\tif(parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules, executeModules);\n \t\twhile(resolves.length) {\n \t\t\tresolves.shift()();\n \t\t}\n \t\tif(executeModules) {\n \t\t\tfor(i=0; i < executeModules.length; i++) {\n \t\t\t\tresult = __webpack_require__(__webpack_require__.s = executeModules[i]);\n \t\t\t}\n \t\t}\n \t\treturn result;\n \t};\n\n \t// The module cache\n \tvar installedModules = {};\n\n \t// objects to store loaded and loading chunks\n \tvar installedChunks = {\n \t\t\"inline\": 0\n \t};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, {\n \t\t\t\tconfigurable: false,\n \t\t\t\tenumerable: true,\n \t\t\t\tget: getter\n \t\t\t});\n \t\t}\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \t// on error function for async loading\n \t__webpack_require__.oe = function(err) { console.error(err); throw err; };\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap 128521254b4cc7ad5819"],"sourceRoot":"webpack:///"}
|
|
@ -2322,7 +2322,7 @@ function bufferizeCandidates(pc, onerror) {
|
|||
if (this.signalingState === 'stable') {
|
||||
while (candidatesQueue.length) {
|
||||
var entry = candidatesQueue.shift();
|
||||
this.addIceCandidate(entry.candidate, entry.callback, entry.callback);
|
||||
pc.addIceCandidate(entry.candidate, entry.callback, entry.callback);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -2528,7 +2528,7 @@ function WebRtcPeer(mode, options, callback) {
|
|||
candidategatheringdone = true;
|
||||
}
|
||||
});
|
||||
pc.ontrack = options.onaddstream;
|
||||
pc.onaddstream = options.onaddstream;
|
||||
pc.onnegotiationneeded = options.onnegotiationneeded;
|
||||
this.on('newListener', function (event, listener) {
|
||||
if (event === 'icecandidate' || event === 'candidategatheringdone') {
|
||||
|
@ -2604,16 +2604,15 @@ function WebRtcPeer(mode, options, callback) {
|
|||
};
|
||||
function setRemoteVideo() {
|
||||
if (remoteVideo) {
|
||||
var stream = pc.getRemoteStreams()[0];
|
||||
var url = stream ? URL.createObjectURL(stream) : '';
|
||||
remoteVideo.pause();
|
||||
remoteVideo.src = url;
|
||||
var stream = pc.getRemoteStreams()[0];
|
||||
remoteVideo.srcObject = stream;
|
||||
logger.debug('Remote stream:', stream);
|
||||
remoteVideo.load();
|
||||
logger.debug('Remote URL:', url);
|
||||
}
|
||||
}
|
||||
this.showLocalVideo = function () {
|
||||
localVideo.src = URL.createObjectURL(videoStream);
|
||||
localVideo.srcObject = videoStream;
|
||||
localVideo.muted = true;
|
||||
};
|
||||
this.send = function (data) {
|
||||
|
@ -2770,14 +2769,14 @@ function WebRtcPeer(mode, options, callback) {
|
|||
this.on('_dispose', function () {
|
||||
if (localVideo) {
|
||||
localVideo.pause();
|
||||
localVideo.src = '';
|
||||
localVideo.srcObject = null;
|
||||
localVideo.load();
|
||||
//Unmute local video in case the video tag is later used for remote video
|
||||
localVideo.muted = false;
|
||||
}
|
||||
if (remoteVideo) {
|
||||
remoteVideo.pause();
|
||||
remoteVideo.src = '';
|
||||
remoteVideo.srcObject = null;
|
||||
remoteVideo.load();
|
||||
}
|
||||
self.removeAllListeners();
|
||||
|
@ -3160,7 +3159,7 @@ var OpenVidu = /** @class */ (function () {
|
|||
var defaultWebRTCSupport = DetectRTC.isWebRTCSupported;
|
||||
var browser = DetectRTC.browser.name;
|
||||
var version = DetectRTC.browser.version;
|
||||
if ((browser !== 'Chrome') && (browser !== 'Firefox') && (browser !== 'Opera')) {
|
||||
if ((browser !== 'Chrome') && (browser !== 'Firefox') && (browser !== 'Opera') && (browser !== 'Safari')) {
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
|
@ -12832,12 +12831,16 @@ module.exports = function(window) {
|
|||
return {
|
||||
name: {
|
||||
PermissionDeniedError: 'NotAllowedError',
|
||||
InvalidStateError: 'NotReadableError',
|
||||
PermissionDismissedError: 'NotAllowedError',
|
||||
InvalidStateError: 'NotAllowedError',
|
||||
DevicesNotFoundError: 'NotFoundError',
|
||||
ConstraintNotSatisfiedError: 'OverconstrainedError',
|
||||
TrackStartError: 'NotReadableError',
|
||||
MediaDeviceFailedDueToShutdown: 'NotReadableError',
|
||||
MediaDeviceKillSwitchOn: 'NotReadableError'
|
||||
MediaDeviceFailedDueToShutdown: 'NotAllowedError',
|
||||
MediaDeviceKillSwitchOn: 'NotAllowedError',
|
||||
TabCaptureError: 'AbortError',
|
||||
ScreenCaptureError: 'AbortError',
|
||||
DeviceCaptureError: 'AbortError'
|
||||
}[e.name] || e.name,
|
||||
message: e.message,
|
||||
constraint: e.constraintName,
|
||||
|
@ -12959,8 +12962,8 @@ module.exports = {
|
|||
shimRTCIceCandidate: function(window) {
|
||||
// foundation is arbitrarily chosen as an indicator for full support for
|
||||
// https://w3c.github.io/webrtc-pc/#rtcicecandidate-interface
|
||||
if (window.RTCIceCandidate && 'foundation' in
|
||||
window.RTCIceCandidate.prototype) {
|
||||
if (!window.RTCIceCandidate || (window.RTCIceCandidate && 'foundation' in
|
||||
window.RTCIceCandidate.prototype)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -12973,23 +12976,27 @@ module.exports = {
|
|||
args.candidate = args.candidate.substr(2);
|
||||
}
|
||||
|
||||
// Augment the native candidate with the parsed fields.
|
||||
var nativeCandidate = new NativeRTCIceCandidate(args);
|
||||
var parsedCandidate = SDPUtils.parseCandidate(args.candidate);
|
||||
var augmentedCandidate = Object.assign(nativeCandidate,
|
||||
parsedCandidate);
|
||||
if (args.candidate && args.candidate.length) {
|
||||
// Augment the native candidate with the parsed fields.
|
||||
var nativeCandidate = new NativeRTCIceCandidate(args);
|
||||
var parsedCandidate = SDPUtils.parseCandidate(args.candidate);
|
||||
var augmentedCandidate = Object.assign(nativeCandidate,
|
||||
parsedCandidate);
|
||||
|
||||
// Add a serializer that does not serialize the extra attributes.
|
||||
augmentedCandidate.toJSON = function() {
|
||||
return {
|
||||
candidate: augmentedCandidate.candidate,
|
||||
sdpMid: augmentedCandidate.sdpMid,
|
||||
sdpMLineIndex: augmentedCandidate.sdpMLineIndex,
|
||||
usernameFragment: augmentedCandidate.usernameFragment,
|
||||
// Add a serializer that does not serialize the extra attributes.
|
||||
augmentedCandidate.toJSON = function() {
|
||||
return {
|
||||
candidate: augmentedCandidate.candidate,
|
||||
sdpMid: augmentedCandidate.sdpMid,
|
||||
sdpMLineIndex: augmentedCandidate.sdpMLineIndex,
|
||||
usernameFragment: augmentedCandidate.usernameFragment,
|
||||
};
|
||||
};
|
||||
};
|
||||
return augmentedCandidate;
|
||||
return augmentedCandidate;
|
||||
}
|
||||
return new NativeRTCIceCandidate(args);
|
||||
};
|
||||
window.RTCIceCandidate.prototype = NativeRTCIceCandidate.prototype;
|
||||
|
||||
// Hook up the augmented candidate in onicecandidate and
|
||||
// addEventListener('icecandidate', ...)
|
||||
|
@ -13189,6 +13196,10 @@ module.exports = {
|
|||
},
|
||||
|
||||
shimSendThrowTypeError: function(window) {
|
||||
if (!window.RTCPeerConnection) {
|
||||
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
|
||||
|
@ -13243,16 +13254,11 @@ module.exports = {
|
|||
var browserDetails = utils.detectBrowser(window);
|
||||
|
||||
if (window.RTCIceGatherer) {
|
||||
// ORTC defines an RTCIceCandidate object but no constructor.
|
||||
// Not implemented in Edge.
|
||||
if (!window.RTCIceCandidate) {
|
||||
window.RTCIceCandidate = function(args) {
|
||||
return args;
|
||||
};
|
||||
}
|
||||
// ORTC does not have a session description object but
|
||||
// other browsers (i.e. Chrome) that will support both PC and ORTC
|
||||
// in the future might have this defined already.
|
||||
if (!window.RTCSessionDescription) {
|
||||
window.RTCSessionDescription = function(args) {
|
||||
return args;
|
||||
|
@ -13291,6 +13297,11 @@ module.exports = {
|
|||
}
|
||||
});
|
||||
}
|
||||
// Edge currently only implements the RTCDtmfSender, not the
|
||||
// RTCDTMFSender alias. See http://draft.ortc.org/#rtcdtmfsender2*
|
||||
if (window.RTCDtmfSender && !window.RTCDTMFSender) {
|
||||
window.RTCDTMFSender = window.RTCDtmfSender;
|
||||
}
|
||||
|
||||
window.RTCPeerConnection =
|
||||
shimRTCPeerConnection(window, browserDetails.version);
|
||||
|
@ -14264,7 +14275,7 @@ module.exports = {
|
|||
result.browser = 'edge';
|
||||
result.version = extractVersion(navigator.userAgent,
|
||||
/Edge\/(\d+).(\d+)$/, 2);
|
||||
} else if (navigator.mediaDevices &&
|
||||
} else if (window.RTCPeerConnection &&
|
||||
navigator.userAgent.match(/AppleWebKit\/(\d+)\./)) { // Safari.
|
||||
result.browser = 'safari';
|
||||
result.version = extractVersion(navigator.userAgent,
|
||||
|
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue