safari_shim.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. /*
  2. * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
  3. *
  4. * Use of this source code is governed by a BSD-style license
  5. * that can be found in the LICENSE file in the root of the source
  6. * tree.
  7. */
  8. 'use strict';
  9. Object.defineProperty(exports, "__esModule", {
  10. value: true
  11. });
  12. exports.shimAudioContext = shimAudioContext;
  13. exports.shimCallbacksAPI = shimCallbacksAPI;
  14. exports.shimConstraints = shimConstraints;
  15. exports.shimCreateOfferLegacy = shimCreateOfferLegacy;
  16. exports.shimGetUserMedia = shimGetUserMedia;
  17. exports.shimLocalStreamsAPI = shimLocalStreamsAPI;
  18. exports.shimRTCIceServerUrls = shimRTCIceServerUrls;
  19. exports.shimRemoteStreamsAPI = shimRemoteStreamsAPI;
  20. exports.shimTrackEventTransceiver = shimTrackEventTransceiver;
  21. var utils = _interopRequireWildcard(require("../utils"));
  22. 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); }
  23. 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; }
  24. 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); }
  25. function shimLocalStreamsAPI(window) {
  26. if (_typeof(window) !== 'object' || !window.RTCPeerConnection) {
  27. return;
  28. }
  29. if (!('getLocalStreams' in window.RTCPeerConnection.prototype)) {
  30. window.RTCPeerConnection.prototype.getLocalStreams = function getLocalStreams() {
  31. if (!this._localStreams) {
  32. this._localStreams = [];
  33. }
  34. return this._localStreams;
  35. };
  36. }
  37. if (!('addStream' in window.RTCPeerConnection.prototype)) {
  38. var _addTrack = window.RTCPeerConnection.prototype.addTrack;
  39. window.RTCPeerConnection.prototype.addStream = function addStream(stream) {
  40. var _this = this;
  41. if (!this._localStreams) {
  42. this._localStreams = [];
  43. }
  44. if (!this._localStreams.includes(stream)) {
  45. this._localStreams.push(stream);
  46. }
  47. // Try to emulate Chrome's behaviour of adding in audio-video order.
  48. // Safari orders by track id.
  49. stream.getAudioTracks().forEach(function (track) {
  50. return _addTrack.call(_this, track, stream);
  51. });
  52. stream.getVideoTracks().forEach(function (track) {
  53. return _addTrack.call(_this, track, stream);
  54. });
  55. };
  56. window.RTCPeerConnection.prototype.addTrack = function addTrack(track) {
  57. var _this2 = this;
  58. for (var _len = arguments.length, streams = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
  59. streams[_key - 1] = arguments[_key];
  60. }
  61. if (streams) {
  62. streams.forEach(function (stream) {
  63. if (!_this2._localStreams) {
  64. _this2._localStreams = [stream];
  65. } else if (!_this2._localStreams.includes(stream)) {
  66. _this2._localStreams.push(stream);
  67. }
  68. });
  69. }
  70. return _addTrack.apply(this, arguments);
  71. };
  72. }
  73. if (!('removeStream' in window.RTCPeerConnection.prototype)) {
  74. window.RTCPeerConnection.prototype.removeStream = function removeStream(stream) {
  75. var _this3 = this;
  76. if (!this._localStreams) {
  77. this._localStreams = [];
  78. }
  79. var index = this._localStreams.indexOf(stream);
  80. if (index === -1) {
  81. return;
  82. }
  83. this._localStreams.splice(index, 1);
  84. var tracks = stream.getTracks();
  85. this.getSenders().forEach(function (sender) {
  86. if (tracks.includes(sender.track)) {
  87. _this3.removeTrack(sender);
  88. }
  89. });
  90. };
  91. }
  92. }
  93. function shimRemoteStreamsAPI(window) {
  94. if (_typeof(window) !== 'object' || !window.RTCPeerConnection) {
  95. return;
  96. }
  97. if (!('getRemoteStreams' in window.RTCPeerConnection.prototype)) {
  98. window.RTCPeerConnection.prototype.getRemoteStreams = function getRemoteStreams() {
  99. return this._remoteStreams ? this._remoteStreams : [];
  100. };
  101. }
  102. if (!('onaddstream' in window.RTCPeerConnection.prototype)) {
  103. Object.defineProperty(window.RTCPeerConnection.prototype, 'onaddstream', {
  104. get: function get() {
  105. return this._onaddstream;
  106. },
  107. set: function set(f) {
  108. var _this4 = this;
  109. if (this._onaddstream) {
  110. this.removeEventListener('addstream', this._onaddstream);
  111. this.removeEventListener('track', this._onaddstreampoly);
  112. }
  113. this.addEventListener('addstream', this._onaddstream = f);
  114. this.addEventListener('track', this._onaddstreampoly = function (e) {
  115. e.streams.forEach(function (stream) {
  116. if (!_this4._remoteStreams) {
  117. _this4._remoteStreams = [];
  118. }
  119. if (_this4._remoteStreams.includes(stream)) {
  120. return;
  121. }
  122. _this4._remoteStreams.push(stream);
  123. var event = new Event('addstream');
  124. event.stream = stream;
  125. _this4.dispatchEvent(event);
  126. });
  127. });
  128. }
  129. });
  130. var origSetRemoteDescription = window.RTCPeerConnection.prototype.setRemoteDescription;
  131. window.RTCPeerConnection.prototype.setRemoteDescription = function setRemoteDescription() {
  132. var pc = this;
  133. if (!this._onaddstreampoly) {
  134. this.addEventListener('track', this._onaddstreampoly = function (e) {
  135. e.streams.forEach(function (stream) {
  136. if (!pc._remoteStreams) {
  137. pc._remoteStreams = [];
  138. }
  139. if (pc._remoteStreams.indexOf(stream) >= 0) {
  140. return;
  141. }
  142. pc._remoteStreams.push(stream);
  143. var event = new Event('addstream');
  144. event.stream = stream;
  145. pc.dispatchEvent(event);
  146. });
  147. });
  148. }
  149. return origSetRemoteDescription.apply(pc, arguments);
  150. };
  151. }
  152. }
  153. function shimCallbacksAPI(window) {
  154. if (_typeof(window) !== 'object' || !window.RTCPeerConnection) {
  155. return;
  156. }
  157. var prototype = window.RTCPeerConnection.prototype;
  158. var origCreateOffer = prototype.createOffer;
  159. var origCreateAnswer = prototype.createAnswer;
  160. var setLocalDescription = prototype.setLocalDescription;
  161. var setRemoteDescription = prototype.setRemoteDescription;
  162. var addIceCandidate = prototype.addIceCandidate;
  163. prototype.createOffer = function createOffer(successCallback, failureCallback) {
  164. var options = arguments.length >= 2 ? arguments[2] : arguments[0];
  165. var promise = origCreateOffer.apply(this, [options]);
  166. if (!failureCallback) {
  167. return promise;
  168. }
  169. promise.then(successCallback, failureCallback);
  170. return Promise.resolve();
  171. };
  172. prototype.createAnswer = function createAnswer(successCallback, failureCallback) {
  173. var options = arguments.length >= 2 ? arguments[2] : arguments[0];
  174. var promise = origCreateAnswer.apply(this, [options]);
  175. if (!failureCallback) {
  176. return promise;
  177. }
  178. promise.then(successCallback, failureCallback);
  179. return Promise.resolve();
  180. };
  181. var withCallback = function withCallback(description, successCallback, failureCallback) {
  182. var promise = setLocalDescription.apply(this, [description]);
  183. if (!failureCallback) {
  184. return promise;
  185. }
  186. promise.then(successCallback, failureCallback);
  187. return Promise.resolve();
  188. };
  189. prototype.setLocalDescription = withCallback;
  190. withCallback = function withCallback(description, successCallback, failureCallback) {
  191. var promise = setRemoteDescription.apply(this, [description]);
  192. if (!failureCallback) {
  193. return promise;
  194. }
  195. promise.then(successCallback, failureCallback);
  196. return Promise.resolve();
  197. };
  198. prototype.setRemoteDescription = withCallback;
  199. withCallback = function withCallback(candidate, successCallback, failureCallback) {
  200. var promise = addIceCandidate.apply(this, [candidate]);
  201. if (!failureCallback) {
  202. return promise;
  203. }
  204. promise.then(successCallback, failureCallback);
  205. return Promise.resolve();
  206. };
  207. prototype.addIceCandidate = withCallback;
  208. }
  209. function shimGetUserMedia(window) {
  210. var navigator = window && window.navigator;
  211. if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
  212. // shim not needed in Safari 12.1
  213. var mediaDevices = navigator.mediaDevices;
  214. var _getUserMedia = mediaDevices.getUserMedia.bind(mediaDevices);
  215. navigator.mediaDevices.getUserMedia = function (constraints) {
  216. return _getUserMedia(shimConstraints(constraints));
  217. };
  218. }
  219. if (!navigator.getUserMedia && navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
  220. navigator.getUserMedia = function getUserMedia(constraints, cb, errcb) {
  221. navigator.mediaDevices.getUserMedia(constraints).then(cb, errcb);
  222. }.bind(navigator);
  223. }
  224. }
  225. function shimConstraints(constraints) {
  226. if (constraints && constraints.video !== undefined) {
  227. return Object.assign({}, constraints, {
  228. video: utils.compactObject(constraints.video)
  229. });
  230. }
  231. return constraints;
  232. }
  233. function shimRTCIceServerUrls(window) {
  234. if (!window.RTCPeerConnection) {
  235. return;
  236. }
  237. // migrate from non-spec RTCIceServer.url to RTCIceServer.urls
  238. var OrigPeerConnection = window.RTCPeerConnection;
  239. window.RTCPeerConnection = function RTCPeerConnection(pcConfig, pcConstraints) {
  240. if (pcConfig && pcConfig.iceServers) {
  241. var newIceServers = [];
  242. for (var i = 0; i < pcConfig.iceServers.length; i++) {
  243. var server = pcConfig.iceServers[i];
  244. if (server.urls === undefined && server.url) {
  245. utils.deprecated('RTCIceServer.url', 'RTCIceServer.urls');
  246. server = JSON.parse(JSON.stringify(server));
  247. server.urls = server.url;
  248. delete server.url;
  249. newIceServers.push(server);
  250. } else {
  251. newIceServers.push(pcConfig.iceServers[i]);
  252. }
  253. }
  254. pcConfig.iceServers = newIceServers;
  255. }
  256. return new OrigPeerConnection(pcConfig, pcConstraints);
  257. };
  258. window.RTCPeerConnection.prototype = OrigPeerConnection.prototype;
  259. // wrap static methods. Currently just generateCertificate.
  260. if ('generateCertificate' in OrigPeerConnection) {
  261. Object.defineProperty(window.RTCPeerConnection, 'generateCertificate', {
  262. get: function get() {
  263. return OrigPeerConnection.generateCertificate;
  264. }
  265. });
  266. }
  267. }
  268. function shimTrackEventTransceiver(window) {
  269. // Add event.transceiver member over deprecated event.receiver
  270. if (_typeof(window) === 'object' && window.RTCTrackEvent && 'receiver' in window.RTCTrackEvent.prototype && !('transceiver' in window.RTCTrackEvent.prototype)) {
  271. Object.defineProperty(window.RTCTrackEvent.prototype, 'transceiver', {
  272. get: function get() {
  273. return {
  274. receiver: this.receiver
  275. };
  276. }
  277. });
  278. }
  279. }
  280. function shimCreateOfferLegacy(window) {
  281. var origCreateOffer = window.RTCPeerConnection.prototype.createOffer;
  282. window.RTCPeerConnection.prototype.createOffer = function createOffer(offerOptions) {
  283. if (offerOptions) {
  284. if (typeof offerOptions.offerToReceiveAudio !== 'undefined') {
  285. // support bit values
  286. offerOptions.offerToReceiveAudio = !!offerOptions.offerToReceiveAudio;
  287. }
  288. var audioTransceiver = this.getTransceivers().find(function (transceiver) {
  289. return transceiver.receiver.track.kind === 'audio';
  290. });
  291. if (offerOptions.offerToReceiveAudio === false && audioTransceiver) {
  292. if (audioTransceiver.direction === 'sendrecv') {
  293. if (audioTransceiver.setDirection) {
  294. audioTransceiver.setDirection('sendonly');
  295. } else {
  296. audioTransceiver.direction = 'sendonly';
  297. }
  298. } else if (audioTransceiver.direction === 'recvonly') {
  299. if (audioTransceiver.setDirection) {
  300. audioTransceiver.setDirection('inactive');
  301. } else {
  302. audioTransceiver.direction = 'inactive';
  303. }
  304. }
  305. } else if (offerOptions.offerToReceiveAudio === true && !audioTransceiver) {
  306. this.addTransceiver('audio', {
  307. direction: 'recvonly'
  308. });
  309. }
  310. if (typeof offerOptions.offerToReceiveVideo !== 'undefined') {
  311. // support bit values
  312. offerOptions.offerToReceiveVideo = !!offerOptions.offerToReceiveVideo;
  313. }
  314. var videoTransceiver = this.getTransceivers().find(function (transceiver) {
  315. return transceiver.receiver.track.kind === 'video';
  316. });
  317. if (offerOptions.offerToReceiveVideo === false && videoTransceiver) {
  318. if (videoTransceiver.direction === 'sendrecv') {
  319. if (videoTransceiver.setDirection) {
  320. videoTransceiver.setDirection('sendonly');
  321. } else {
  322. videoTransceiver.direction = 'sendonly';
  323. }
  324. } else if (videoTransceiver.direction === 'recvonly') {
  325. if (videoTransceiver.setDirection) {
  326. videoTransceiver.setDirection('inactive');
  327. } else {
  328. videoTransceiver.direction = 'inactive';
  329. }
  330. }
  331. } else if (offerOptions.offerToReceiveVideo === true && !videoTransceiver) {
  332. this.addTransceiver('video', {
  333. direction: 'recvonly'
  334. });
  335. }
  336. }
  337. return origCreateOffer.apply(this, arguments);
  338. };
  339. }
  340. function shimAudioContext(window) {
  341. if (_typeof(window) !== 'object' || window.AudioContext) {
  342. return;
  343. }
  344. window.AudioContext = window.webkitAudioContext;
  345. }