/* * 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 }); var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; exports.shimGetUserMedia = shimGetUserMedia; var _utils = require('../utils.js'); var utils = _interopRequireWildcard(_utils); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } var logging = utils.log; function shimGetUserMedia(window) { var navigator = window && window.navigator; if (!navigator.mediaDevices) { return; } var browserDetails = utils.detectBrowser(window); var constraintsToChrome_ = function constraintsToChrome_(c) { if ((typeof c === 'undefined' ? 'undefined' : _typeof(c)) !== 'object' || c.mandatory || c.optional) { return c; } var cc = {}; Object.keys(c).forEach(function (key) { if (key === 'require' || key === 'advanced' || key === 'mediaSource') { return; } var r = _typeof(c[key]) === 'object' ? c[key] : { ideal: c[key] }; if (r.exact !== undefined && typeof r.exact === 'number') { r.min = r.max = r.exact; } var oldname_ = function oldname_(prefix, name) { if (prefix) { return prefix + name.charAt(0).toUpperCase() + name.slice(1); } return name === 'deviceId' ? 'sourceId' : name; }; if (r.ideal !== undefined) { cc.optional = cc.optional || []; var oc = {}; if (typeof r.ideal === 'number') { oc[oldname_('min', key)] = r.ideal; cc.optional.push(oc); oc = {}; oc[oldname_('max', key)] = r.ideal; cc.optional.push(oc); } else { oc[oldname_('', key)] = r.ideal; cc.optional.push(oc); } } if (r.exact !== undefined && typeof r.exact !== 'number') { cc.mandatory = cc.mandatory || {}; cc.mandatory[oldname_('', key)] = r.exact; } else { ['min', 'max'].forEach(function (mix) { if (r[mix] !== undefined) { cc.mandatory = cc.mandatory || {}; cc.mandatory[oldname_(mix, key)] = r[mix]; } }); } }); if (c.advanced) { cc.optional = (cc.optional || []).concat(c.advanced); } return cc; }; var shimConstraints_ = function shimConstraints_(constraints, func) { if (browserDetails.version >= 61) { return func(constraints); } constraints = JSON.parse(JSON.stringify(constraints)); if (constraints && _typeof(constraints.audio) === 'object') { var remap = function remap(obj, a, b) { if (a in obj && !(b in obj)) { obj[b] = obj[a]; delete obj[a]; } }; constraints = JSON.parse(JSON.stringify(constraints)); remap(constraints.audio, 'autoGainControl', 'googAutoGainControl'); remap(constraints.audio, 'noiseSuppression', 'googNoiseSuppression'); constraints.audio = constraintsToChrome_(constraints.audio); } if (constraints && _typeof(constraints.video) === 'object') { // Shim facingMode for mobile & surface pro. var face = constraints.video.facingMode; face = face && ((typeof face === 'undefined' ? 'undefined' : _typeof(face)) === 'object' ? face : { ideal: face }); var getSupportedFacingModeLies = browserDetails.version < 66; if (face && (face.exact === 'user' || face.exact === 'environment' || face.ideal === 'user' || face.ideal === 'environment') && !(navigator.mediaDevices.getSupportedConstraints && navigator.mediaDevices.getSupportedConstraints().facingMode && !getSupportedFacingModeLies)) { delete constraints.video.facingMode; var matches = void 0; if (face.exact === 'environment' || face.ideal === 'environment') { matches = ['back', 'rear']; } else if (face.exact === 'user' || face.ideal === 'user') { matches = ['front']; } if (matches) { // Look for matches in label, or use last cam for back (typical). return navigator.mediaDevices.enumerateDevices().then(function (devices) { devices = devices.filter(function (d) { return d.kind === 'videoinput'; }); var dev = devices.find(function (d) { return matches.some(function (match) { return d.label.toLowerCase().includes(match); }); }); if (!dev && devices.length && matches.includes('back')) { dev = devices[devices.length - 1]; // more likely the back cam } if (dev) { constraints.video.deviceId = face.exact ? { exact: dev.deviceId } : { ideal: dev.deviceId }; } constraints.video = constraintsToChrome_(constraints.video); logging('chrome: ' + JSON.stringify(constraints)); return func(constraints); }); } } constraints.video = constraintsToChrome_(constraints.video); } logging('chrome: ' + JSON.stringify(constraints)); return func(constraints); }; var shimError_ = function shimError_(e) { if (browserDetails.version >= 64) { return e; } return { name: { PermissionDeniedError: 'NotAllowedError', PermissionDismissedError: 'NotAllowedError', InvalidStateError: 'NotAllowedError', DevicesNotFoundError: 'NotFoundError', ConstraintNotSatisfiedError: 'OverconstrainedError', TrackStartError: 'NotReadableError', MediaDeviceFailedDueToShutdown: 'NotAllowedError', MediaDeviceKillSwitchOn: 'NotAllowedError', TabCaptureError: 'AbortError', ScreenCaptureError: 'AbortError', DeviceCaptureError: 'AbortError' }[e.name] || e.name, message: e.message, constraint: e.constraint || e.constraintName, toString: function toString() { return this.name + (this.message && ': ') + this.message; } }; }; var getUserMedia_ = function getUserMedia_(constraints, onSuccess, onError) { shimConstraints_(constraints, function (c) { navigator.webkitGetUserMedia(c, onSuccess, function (e) { if (onError) { onError(shimError_(e)); } }); }); }; navigator.getUserMedia = getUserMedia_.bind(navigator); // Even though Chrome 45 has navigator.mediaDevices and a getUserMedia // function which returns a Promise, it does not accept spec-style // constraints. if (navigator.mediaDevices.getUserMedia) { var origGetUserMedia = navigator.mediaDevices.getUserMedia.bind(navigator.mediaDevices); navigator.mediaDevices.getUserMedia = function (cs) { return shimConstraints_(cs, function (c) { return origGetUserMedia(c).then(function (stream) { if (c.audio && !stream.getAudioTracks().length || c.video && !stream.getVideoTracks().length) { stream.getTracks().forEach(function (track) { track.stop(); }); throw new DOMException('', 'NotFoundError'); } return stream; }, function (e) { return Promise.reject(shimError_(e)); }); }); }; } }