'use strict'; // Last Updated On: 2020-08-12 11:18:41 AM UTC // ________________ // DetectRTC v1.4.1 // Open-Sourced: https://github.com/muaz-khan/DetectRTC // -------------------------------------------------- // Muaz Khan - www.MuazKhan.com // MIT License - www.WebRTC-Experiment.com/licence // -------------------------------------------------- (function() { var browserFakeUserAgent = 'Fake/5.0 (FakeOS) AppleWebKit/123 (KHTML, like Gecko) Fake/12.3.4567.89 Fake/123.45'; var isNodejs = typeof process === 'object' && typeof process.versions === 'object' && process.versions.node && /*node-process*/ !process.browser; if (isNodejs) { var version = process.versions.node.toString().replace('v', ''); browserFakeUserAgent = 'Nodejs/' + version + ' (NodeOS) AppleWebKit/' + version + ' (KHTML, like Gecko) Nodejs/' + version + ' Nodejs/' + version } (function(that) { if (typeof window !== 'undefined') { return; } if (typeof window === 'undefined' && typeof global !== 'undefined') { global.navigator = { userAgent: browserFakeUserAgent, getUserMedia: function() {} }; /*global window:true */ that.window = global; } else if (typeof window === 'undefined') { // window = this; } if (typeof location === 'undefined') { /*global location:true */ that.location = { protocol: 'file:', href: '', hash: '' }; } if (typeof screen === 'undefined') { /*global screen:true */ that.screen = { width: 0, height: 0 }; } })(typeof global !== 'undefined' ? global : window); /*global navigator:true */ var navigator = window.navigator; if (typeof navigator !== 'undefined') { if (typeof navigator.webkitGetUserMedia !== 'undefined') { navigator.getUserMedia = navigator.webkitGetUserMedia; } if (typeof navigator.mozGetUserMedia !== 'undefined') { navigator.getUserMedia = navigator.mozGetUserMedia; } } else { navigator = { getUserMedia: function() {}, userAgent: browserFakeUserAgent }; } var isMobileDevice = !!(/Android|webOS|iPhone|iPad|iPod|BB10|BlackBerry|IEMobile|Opera Mini|Mobile|mobile/i.test(navigator.userAgent || '')); var isEdge = navigator.userAgent.indexOf('Edge') !== -1 && (!!navigator.msSaveOrOpenBlob || !!navigator.msSaveBlob); var isOpera = !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0; var isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1 && ('netscape' in window) && / rv:/.test(navigator.userAgent); var isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent); var isChrome = !!window.chrome && !isOpera; var isIE = typeof document !== 'undefined' && !!document.documentMode && !isEdge; // this one can also be used: // https://www.websocket.org/js/stuff.js (DetectBrowser.js) function getBrowserInfo() { var nVer = navigator.appVersion; var nAgt = navigator.userAgent; var browserName = navigator.appName; var fullVersion = '' + parseFloat(navigator.appVersion); var majorVersion = parseInt(navigator.appVersion, 10); var nameOffset, verOffset, ix; // In Opera, the true version is after 'Opera' or after 'Version' if (isOpera) { browserName = 'Opera'; try { fullVersion = navigator.userAgent.split('OPR/')[1].split(' ')[0]; majorVersion = fullVersion.split('.')[0]; } catch (e) { fullVersion = '0.0.0.0'; majorVersion = 0; } } // In MSIE version <=10, the true version is after 'MSIE' in userAgent // In IE 11, look for the string after 'rv:' else if (isIE) { verOffset = nAgt.indexOf('rv:'); if (verOffset > 0) { //IE 11 fullVersion = nAgt.substring(verOffset + 3); } else { //IE 10 or earlier verOffset = nAgt.indexOf('MSIE'); fullVersion = nAgt.substring(verOffset + 5); } browserName = 'IE'; } // In Chrome, the true version is after 'Chrome' else if (isChrome) { verOffset = nAgt.indexOf('Chrome'); browserName = 'Chrome'; fullVersion = nAgt.substring(verOffset + 7); } // In Safari, the true version is after 'Safari' or after 'Version' else if (isSafari) { // both and safri and chrome has same userAgent if (nAgt.indexOf('CriOS') !== -1) { verOffset = nAgt.indexOf('CriOS'); browserName = 'Chrome'; fullVersion = nAgt.substring(verOffset + 6); } else if (nAgt.indexOf('FxiOS') !== -1) { verOffset = nAgt.indexOf('FxiOS'); browserName = 'Firefox'; fullVersion = nAgt.substring(verOffset + 6); } else { verOffset = nAgt.indexOf('Safari'); browserName = 'Safari'; fullVersion = nAgt.substring(verOffset + 7); if ((verOffset = nAgt.indexOf('Version')) !== -1) { fullVersion = nAgt.substring(verOffset + 8); } if (navigator.userAgent.indexOf('Version/') !== -1) { fullVersion = navigator.userAgent.split('Version/')[1].split(' ')[0]; } } } // In Firefox, the true version is after 'Firefox' else if (isFirefox) { verOffset = nAgt.indexOf('Firefox'); browserName = 'Firefox'; fullVersion = nAgt.substring(verOffset + 8); } // In most other browsers, 'name/version' is at the end of userAgent else if ((nameOffset = nAgt.lastIndexOf(' ') + 1) < (verOffset = nAgt.lastIndexOf('/'))) { browserName = nAgt.substring(nameOffset, verOffset); fullVersion = nAgt.substring(verOffset + 1); if (browserName.toLowerCase() === browserName.toUpperCase()) { browserName = navigator.appName; } } if (isEdge) { browserName = 'Edge'; fullVersion = navigator.userAgent.split('Edge/')[1]; // fullVersion = parseInt(navigator.userAgent.match(/Edge\/(\d+).(\d+)$/)[2], 10).toString(); } // trim the fullVersion string at semicolon/space/bracket if present if ((ix = fullVersion.search(/[; \)]/)) !== -1) { fullVersion = fullVersion.substring(0, ix); } majorVersion = parseInt('' + fullVersion, 10); if (isNaN(majorVersion)) { fullVersion = '' + parseFloat(navigator.appVersion); majorVersion = parseInt(navigator.appVersion, 10); } return { fullVersion: fullVersion, version: majorVersion, name: browserName, isPrivateBrowsing: false }; } // via: https://gist.github.com/cou929/7973956 function retry(isDone, next) { var currentTrial = 0, maxRetry = 50, interval = 10, isTimeout = false; var id = window.setInterval( function() { if (isDone()) { window.clearInterval(id); next(isTimeout); } if (currentTrial++ > maxRetry) { window.clearInterval(id); isTimeout = true; next(isTimeout); } }, 10 ); } function isIE10OrLater(userAgent) { var ua = userAgent.toLowerCase(); if (ua.indexOf('msie') === 0 && ua.indexOf('trident') === 0) { return false; } var match = /(?:msie|rv:)\s?([\d\.]+)/.exec(ua); if (match && parseInt(match[1], 10) >= 10) { return true; } return false; } function detectPrivateMode(callback) { var isPrivate; try { if (window.webkitRequestFileSystem) { window.webkitRequestFileSystem( window.TEMPORARY, 1, function() { isPrivate = false; }, function(e) { isPrivate = true; } ); } else if (window.indexedDB && /Firefox/.test(window.navigator.userAgent)) { var db; try { db = window.indexedDB.open('test'); db.onerror = function() { return true; }; } catch (e) { isPrivate = true; } if (typeof isPrivate === 'undefined') { retry( function isDone() { return db.readyState === 'done' ? true : false; }, function next(isTimeout) { if (!isTimeout) { isPrivate = db.result ? false : true; } } ); } } else if (isIE10OrLater(window.navigator.userAgent)) { isPrivate = false; try { if (!window.indexedDB) { isPrivate = true; } } catch (e) { isPrivate = true; } } else if (window.localStorage && /Safari/.test(window.navigator.userAgent)) { try { window.localStorage.setItem('test', 1); } catch (e) { isPrivate = true; } if (typeof isPrivate === 'undefined') { isPrivate = false; window.localStorage.removeItem('test'); } } } catch (e) { isPrivate = false; } retry( function isDone() { return typeof isPrivate !== 'undefined' ? true : false; }, function next(isTimeout) { callback(isPrivate); } ); } var isMobile = { Android: function() { return navigator.userAgent.match(/Android/i); }, BlackBerry: function() { return navigator.userAgent.match(/BlackBerry|BB10/i); }, iOS: function() { return navigator.userAgent.match(/iPhone|iPad|iPod/i); }, Opera: function() { return navigator.userAgent.match(/Opera Mini/i); }, Windows: function() { return navigator.userAgent.match(/IEMobile/i); }, any: function() { return (isMobile.Android() || isMobile.BlackBerry() || isMobile.iOS() || isMobile.Opera() || isMobile.Windows()); }, getOsName: function() { var osName = 'Unknown OS'; if (isMobile.Android()) { osName = 'Android'; } if (isMobile.BlackBerry()) { osName = 'BlackBerry'; } if (isMobile.iOS()) { osName = 'iOS'; } if (isMobile.Opera()) { osName = 'Opera Mini'; } if (isMobile.Windows()) { osName = 'Windows'; } return osName; } }; // via: http://jsfiddle.net/ChristianL/AVyND/ function detectDesktopOS() { var unknown = '-'; var nVer = navigator.appVersion; var nAgt = navigator.userAgent; var os = unknown; var clientStrings = [{ s: 'Chrome OS', r: /CrOS/ }, { s: 'Windows 10', r: /(Windows 10.0|Windows NT 10.0)/ }, { s: 'Windows 8.1', r: /(Windows 8.1|Windows NT 6.3)/ }, { s: 'Windows 8', r: /(Windows 8|Windows NT 6.2)/ }, { s: 'Windows 7', r: /(Windows 7|Windows NT 6.1)/ }, { s: 'Windows Vista', r: /Windows NT 6.0/ }, { s: 'Windows Server 2003', r: /Windows NT 5.2/ }, { s: 'Windows XP', r: /(Windows NT 5.1|Windows XP)/ }, { s: 'Windows 2000', r: /(Windows NT 5.0|Windows 2000)/ }, { s: 'Windows ME', r: /(Win 9x 4.90|Windows ME)/ }, { s: 'Windows 98', r: /(Windows 98|Win98)/ }, { s: 'Windows 95', r: /(Windows 95|Win95|Windows_95)/ }, { s: 'Windows NT 4.0', r: /(Windows NT 4.0|WinNT4.0|WinNT|Windows NT)/ }, { s: 'Windows CE', r: /Windows CE/ }, { s: 'Windows 3.11', r: /Win16/ }, { s: 'Android', r: /Android/ }, { s: 'Open BSD', r: /OpenBSD/ }, { s: 'Sun OS', r: /SunOS/ }, { s: 'Linux', r: /(Linux|X11)/ }, { s: 'iOS', r: /(iPhone|iPad|iPod)/ }, { s: 'Mac OS X', r: /Mac OS X/ }, { s: 'Mac OS', r: /(MacPPC|MacIntel|Mac_PowerPC|Macintosh)/ }, { s: 'QNX', r: /QNX/ }, { s: 'UNIX', r: /UNIX/ }, { s: 'BeOS', r: /BeOS/ }, { s: 'OS/2', r: /OS\/2/ }, { s: 'Search Bot', r: /(nuhk|Googlebot|Yammybot|Openbot|Slurp|MSNBot|Ask Jeeves\/Teoma|ia_archiver)/ }]; for (var i = 0, cs; cs = clientStrings[i]; i++) { if (cs.r.test(nAgt)) { os = cs.s; break; } } var osVersion = unknown; if (/Windows/.test(os)) { if (/Windows (.*)/.test(os)) { osVersion = /Windows (.*)/.exec(os)[1]; } os = 'Windows'; } switch (os) { case 'Mac OS X': if (/Mac OS X (10[\.\_\d]+)/.test(nAgt)) { osVersion = /Mac OS X (10[\.\_\d]+)/.exec(nAgt)[1]; } break; case 'Android': if (/Android ([\.\_\d]+)/.test(nAgt)) { osVersion = /Android ([\.\_\d]+)/.exec(nAgt)[1]; } break; case 'iOS': if (/OS (\d+)_(\d+)_?(\d+)?/.test(nAgt)) { osVersion = /OS (\d+)_(\d+)_?(\d+)?/.exec(nVer); if (osVersion && osVersion.length > 3) { osVersion = osVersion[1] + '.' + osVersion[2] + '.' + (osVersion[3] | 0); } } break; } return { osName: os, osVersion: osVersion }; } var osName = 'Unknown OS'; var osVersion = 'Unknown OS Version'; function getAndroidVersion(ua) { ua = (ua || navigator.userAgent).toLowerCase(); var match = ua.match(/android\s([0-9\.]*)/); return match ? match[1] : false; } var osInfo = detectDesktopOS(); if (osInfo && osInfo.osName && osInfo.osName != '-') { osName = osInfo.osName; osVersion = osInfo.osVersion; } else if (isMobile.any()) { osName = isMobile.getOsName(); if (osName == 'Android') { osVersion = getAndroidVersion(); } } var isNodejs = typeof process === 'object' && typeof process.versions === 'object' && process.versions.node; if (osName === 'Unknown OS' && isNodejs) { osName = 'Nodejs'; osVersion = process.versions.node.toString().replace('v', ''); } var isCanvasSupportsStreamCapturing = false; var isVideoSupportsStreamCapturing = false; ['captureStream', 'mozCaptureStream', 'webkitCaptureStream'].forEach(function(item) { if (typeof document === 'undefined' || typeof document.createElement !== 'function') { return; } if (!isCanvasSupportsStreamCapturing && item in document.createElement('canvas')) { isCanvasSupportsStreamCapturing = true; } if (!isVideoSupportsStreamCapturing && item in document.createElement('video')) { isVideoSupportsStreamCapturing = true; } }); var regexIpv4Local = /^(192\.168\.|169\.254\.|10\.|172\.(1[6-9]|2\d|3[01]))/, regexIpv4 = /([0-9]{1,3}(\.[0-9]{1,3}){3})/, regexIpv6 = /[a-f0-9]{1,4}(:[a-f0-9]{1,4}){7}/; // via: https://github.com/diafygi/webrtc-ips function DetectLocalIPAddress(callback, stream) { if (!DetectRTC.isWebRTCSupported) { return; } var isPublic = true, isIpv4 = true; getIPs(function(ip) { if (!ip) { callback(); // Pass nothing to tell that ICE-gathering-ended } else if (ip.match(regexIpv4Local)) { isPublic = false; callback('Local: ' + ip, isPublic, isIpv4); } else if (ip.match(regexIpv6)) { //via https://ourcodeworld.com/articles/read/257/how-to-get-the-client-ip-address-with-javascript-only isIpv4 = false; callback('Public: ' + ip, isPublic, isIpv4); } else { callback('Public: ' + ip, isPublic, isIpv4); } }, stream); } function getIPs(callback, stream) { if (typeof document === 'undefined' || typeof document.getElementById !== 'function') { return; } var ipDuplicates = {}; var RTCPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection; if (!RTCPeerConnection) { var iframe = document.getElementById('iframe'); if (!iframe) { return; } var win = iframe.contentWindow; RTCPeerConnection = win.RTCPeerConnection || win.mozRTCPeerConnection || win.webkitRTCPeerConnection; } if (!RTCPeerConnection) { return; } var peerConfig = null; if (DetectRTC.browser === 'Chrome' && DetectRTC.browser.version < 58) { // todo: add support for older Opera peerConfig = { optional: [{ RtpDataChannels: true }] }; } var servers = { iceServers: [{ urls: 'stun:stun.l.google.com:19302' }] }; var pc = new RTCPeerConnection(servers, peerConfig); if (stream) { if (pc.addStream) { pc.addStream(stream); } else if (pc.addTrack && stream.getTracks()[0]) { pc.addTrack(stream.getTracks()[0], stream); } } function handleCandidate(candidate) { if (!candidate) { callback(); // Pass nothing to tell that ICE-gathering-ended return; } var match = regexIpv4.exec(candidate); if (!match) { return; } var ipAddress = match[1]; var isPublic = (candidate.match(regexIpv4Local)), isIpv4 = true; if (ipDuplicates[ipAddress] === undefined) { callback(ipAddress, isPublic, isIpv4); } ipDuplicates[ipAddress] = true; } // listen for candidate events pc.onicecandidate = function(event) { if (event.candidate && event.candidate.candidate) { handleCandidate(event.candidate.candidate); } else { handleCandidate(); // Pass nothing to tell that ICE-gathering-ended } }; // create data channel if (!stream) { try { pc.createDataChannel('sctp', {}); } catch (e) {} } // create an offer sdp if (DetectRTC.isPromisesSupported) { pc.createOffer().then(function(result) { pc.setLocalDescription(result).then(afterCreateOffer); }); } else { pc.createOffer(function(result) { pc.setLocalDescription(result, afterCreateOffer, function() {}); }, function() {}); } function afterCreateOffer() { var lines = pc.localDescription.sdp.split('\n'); lines.forEach(function(line) { if (line && line.indexOf('a=candidate:') === 0) { handleCandidate(line); } }); } } var MediaDevices = []; var audioInputDevices = []; var audioOutputDevices = []; var videoInputDevices = []; if (navigator.mediaDevices && navigator.mediaDevices.enumerateDevices) { // Firefox 38+ seems having support of enumerateDevices // Thanks @xdumaine/enumerateDevices navigator.enumerateDevices = function(callback) { var enumerateDevices = navigator.mediaDevices.enumerateDevices(); if (enumerateDevices && enumerateDevices.then) { navigator.mediaDevices.enumerateDevices().then(callback).catch(function() { callback([]); }); } else { callback([]); } }; } // Media Devices detection var canEnumerate = false; /*global MediaStreamTrack:true */ if (typeof MediaStreamTrack !== 'undefined' && 'getSources' in MediaStreamTrack) { canEnumerate = true; } else if (navigator.mediaDevices && !!navigator.mediaDevices.enumerateDevices) { canEnumerate = true; } var hasMicrophone = false; var hasSpeakers = false; var hasWebcam = false; var isWebsiteHasMicrophonePermissions = false; var isWebsiteHasWebcamPermissions = false; // http://dev.w3.org/2011/webrtc/editor/getusermedia.html#mediadevices function checkDeviceSupport(callback) { if (!canEnumerate) { if (callback) { callback(); } return; } if (!navigator.enumerateDevices && window.MediaStreamTrack && window.MediaStreamTrack.getSources) { navigator.enumerateDevices = window.MediaStreamTrack.getSources.bind(window.MediaStreamTrack); } if (!navigator.enumerateDevices && navigator.enumerateDevices) { navigator.enumerateDevices = navigator.enumerateDevices.bind(navigator); } if (!navigator.enumerateDevices) { if (callback) { callback(); } return; } MediaDevices = []; audioInputDevices = []; audioOutputDevices = []; videoInputDevices = []; hasMicrophone = false; hasSpeakers = false; hasWebcam = false; isWebsiteHasMicrophonePermissions = false; isWebsiteHasWebcamPermissions = false; // to prevent duplication var alreadyUsedDevices = {}; navigator.enumerateDevices(function(devices) { MediaDevices = []; audioInputDevices = []; audioOutputDevices = []; videoInputDevices = []; devices.forEach(function(_device) { var device = {}; for (var d in _device) { try { if (typeof _device[d] !== 'function') { device[d] = _device[d]; } } catch (e) {} } if (alreadyUsedDevices[device.deviceId + device.label + device.kind]) { return; } // if it is MediaStreamTrack.getSources if (device.kind === 'audio') { device.kind = 'audioinput'; } if (device.kind === 'video') { device.kind = 'videoinput'; } if (!device.deviceId) { device.deviceId = device.id; } if (!device.id) { device.id = device.deviceId; } if (!device.label) { device.isCustomLabel = true; if (device.kind === 'videoinput') { device.label = 'Camera ' + (videoInputDevices.length + 1); } else if (device.kind === 'audioinput') { device.label = 'Microphone ' + (audioInputDevices.length + 1); } else if (device.kind === 'audiooutput') { device.label = 'Speaker ' + (audioOutputDevices.length + 1); } else { device.label = 'Please invoke getUserMedia once.'; } if (typeof DetectRTC !== 'undefined' && DetectRTC.browser.isChrome && DetectRTC.browser.version >= 46 && !/^(https:|chrome-extension:)$/g.test(location.protocol || '')) { if (typeof document !== 'undefined' && typeof document.domain === 'string' && document.domain.search && document.domain.search(/localhost|127.0./g) === -1) { device.label = 'HTTPs is required to get label of this ' + device.kind + ' device.'; } } } if (device.kind === 'audioinput') { hasMicrophone = true; isWebsiteHasMicrophonePermissions = true; if (audioInputDevices.indexOf(device) === -1) { audioInputDevices.push(device); } } if (device.kind === 'audiooutput') { hasSpeakers = true; if (audioOutputDevices.indexOf(device) === -1) { audioOutputDevices.push(device); } } if (device.kind === 'videoinput') { hasWebcam = true; isWebsiteHasWebcamPermissions = true; if (videoInputDevices.indexOf(device) === -1) { videoInputDevices.push(device); } } // there is no 'videoouput' in the spec. MediaDevices.push(device); alreadyUsedDevices[device.deviceId + device.label + device.kind] = device; }); if (typeof DetectRTC !== 'undefined') { // to sync latest outputs DetectRTC.MediaDevices = MediaDevices; DetectRTC.hasMicrophone = hasMicrophone; DetectRTC.hasSpeakers = hasSpeakers; DetectRTC.hasWebcam = hasWebcam; DetectRTC.isWebsiteHasWebcamPermissions = isWebsiteHasWebcamPermissions; DetectRTC.isWebsiteHasMicrophonePermissions = isWebsiteHasMicrophonePermissions; DetectRTC.audioInputDevices = audioInputDevices; DetectRTC.audioOutputDevices = audioOutputDevices; DetectRTC.videoInputDevices = videoInputDevices; } if (callback) { callback(); } }); } var DetectRTC = window.DetectRTC || {}; // ---------- // DetectRTC.browser.name || DetectRTC.browser.version || DetectRTC.browser.fullVersion DetectRTC.browser = getBrowserInfo(); detectPrivateMode(function(isPrivateBrowsing) { DetectRTC.browser.isPrivateBrowsing = !!isPrivateBrowsing; }); // DetectRTC.isChrome || DetectRTC.isFirefox || DetectRTC.isEdge DetectRTC.browser['is' + DetectRTC.browser.name] = true; // ----------- DetectRTC.osName = osName; DetectRTC.osVersion = osVersion; var isNodeWebkit = typeof process === 'object' && typeof process.versions === 'object' && process.versions['node-webkit']; // --------- Detect if system supports WebRTC 1.0 or WebRTC 1.1. var isWebRTCSupported = false; ['RTCPeerConnection', 'webkitRTCPeerConnection', 'mozRTCPeerConnection', 'RTCIceGatherer'].forEach(function(item) { if (isWebRTCSupported) { return; } if (item in window) { isWebRTCSupported = true; } }); DetectRTC.isWebRTCSupported = isWebRTCSupported; //------- DetectRTC.isORTCSupported = typeof RTCIceGatherer !== 'undefined'; // --------- Detect if system supports screen capturing API var isScreenCapturingSupported = false; if (DetectRTC.browser.isChrome && DetectRTC.browser.version >= 35) { isScreenCapturingSupported = true; } else if (DetectRTC.browser.isFirefox && DetectRTC.browser.version >= 34) { isScreenCapturingSupported = true; } else if (DetectRTC.browser.isEdge && DetectRTC.browser.version >= 17) { isScreenCapturingSupported = true; } else if (DetectRTC.osName === 'Android' && DetectRTC.browser.isChrome) { isScreenCapturingSupported = true; } if (!!navigator.getDisplayMedia || (navigator.mediaDevices && navigator.mediaDevices.getDisplayMedia)) { isScreenCapturingSupported = true; } if (!/^(https:|chrome-extension:)$/g.test(location.protocol || '')) { var isNonLocalHost = typeof document !== 'undefined' && typeof document.domain === 'string' && document.domain.search && document.domain.search(/localhost|127.0./g) === -1; if (isNonLocalHost && (DetectRTC.browser.isChrome || DetectRTC.browser.isEdge || DetectRTC.browser.isOpera)) { isScreenCapturingSupported = false; } else if (DetectRTC.browser.isFirefox) { isScreenCapturingSupported = false; } } DetectRTC.isScreenCapturingSupported = isScreenCapturingSupported; // --------- Detect if WebAudio API are supported var webAudio = { isSupported: false, isCreateMediaStreamSourceSupported: false }; ['AudioContext', 'webkitAudioContext', 'mozAudioContext', 'msAudioContext'].forEach(function(item) { if (webAudio.isSupported) { return; } if (item in window) { webAudio.isSupported = true; if (window[item] && 'createMediaStreamSource' in window[item].prototype) { webAudio.isCreateMediaStreamSourceSupported = true; } } }); DetectRTC.isAudioContextSupported = webAudio.isSupported; DetectRTC.isCreateMediaStreamSourceSupported = webAudio.isCreateMediaStreamSourceSupported; // ---------- Detect if SCTP/RTP channels are supported. var isRtpDataChannelsSupported = false; if (DetectRTC.browser.isChrome && DetectRTC.browser.version > 31) { isRtpDataChannelsSupported = true; } DetectRTC.isRtpDataChannelsSupported = isRtpDataChannelsSupported; var isSCTPSupportd = false; if (DetectRTC.browser.isFirefox && DetectRTC.browser.version > 28) { isSCTPSupportd = true; } else if (DetectRTC.browser.isChrome && DetectRTC.browser.version > 25) { isSCTPSupportd = true; } else if (DetectRTC.browser.isOpera && DetectRTC.browser.version >= 11) { isSCTPSupportd = true; } DetectRTC.isSctpDataChannelsSupported = isSCTPSupportd; // --------- DetectRTC.isMobileDevice = isMobileDevice; // "isMobileDevice" boolean is defined in "getBrowserInfo.js" // ------ var isGetUserMediaSupported = false; if (navigator.getUserMedia) { isGetUserMediaSupported = true; } else if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) { isGetUserMediaSupported = true; } if (DetectRTC.browser.isChrome && DetectRTC.browser.version >= 46 && !/^(https:|chrome-extension:)$/g.test(location.protocol || '')) { if (typeof document !== 'undefined' && typeof document.domain === 'string' && document.domain.search && document.domain.search(/localhost|127.0./g) === -1) { isGetUserMediaSupported = 'Requires HTTPs'; } } if (DetectRTC.osName === 'Nodejs') { isGetUserMediaSupported = false; } DetectRTC.isGetUserMediaSupported = isGetUserMediaSupported; var displayResolution = ''; if (screen.width) { var width = (screen.width) ? screen.width : ''; var height = (screen.height) ? screen.height : ''; displayResolution += '' + width + ' x ' + height; } DetectRTC.displayResolution = displayResolution; function getAspectRatio(w, h) { function gcd(a, b) { return (b == 0) ? a : gcd(b, a % b); } var r = gcd(w, h); return (w / r) / (h / r); } DetectRTC.displayAspectRatio = getAspectRatio(screen.width, screen.height).toFixed(2); // ---------- DetectRTC.isCanvasSupportsStreamCapturing = isCanvasSupportsStreamCapturing; DetectRTC.isVideoSupportsStreamCapturing = isVideoSupportsStreamCapturing; if (DetectRTC.browser.name == 'Chrome' && DetectRTC.browser.version >= 53) { if (!DetectRTC.isCanvasSupportsStreamCapturing) { DetectRTC.isCanvasSupportsStreamCapturing = 'Requires chrome flag: enable-experimental-web-platform-features'; } if (!DetectRTC.isVideoSupportsStreamCapturing) { DetectRTC.isVideoSupportsStreamCapturing = 'Requires chrome flag: enable-experimental-web-platform-features'; } } // ------ DetectRTC.DetectLocalIPAddress = DetectLocalIPAddress; DetectRTC.isWebSocketsSupported = 'WebSocket' in window && 2 === window.WebSocket.CLOSING; DetectRTC.isWebSocketsBlocked = !DetectRTC.isWebSocketsSupported; if (DetectRTC.osName === 'Nodejs') { DetectRTC.isWebSocketsSupported = true; DetectRTC.isWebSocketsBlocked = false; } DetectRTC.checkWebSocketsSupport = function(callback) { callback = callback || function() {}; try { var starttime; var websocket = new WebSocket('wss://echo.websocket.org:443/'); websocket.onopen = function() { DetectRTC.isWebSocketsBlocked = false; starttime = (new Date).getTime(); websocket.send('ping'); }; websocket.onmessage = function() { DetectRTC.WebsocketLatency = (new Date).getTime() - starttime + 'ms'; callback(); websocket.close(); websocket = null; }; websocket.onerror = function() { DetectRTC.isWebSocketsBlocked = true; callback(); }; } catch (e) { DetectRTC.isWebSocketsBlocked = true; callback(); } }; // ------- DetectRTC.load = function(callback) { callback = callback || function() {}; checkDeviceSupport(callback); }; // check for microphone/camera support! if (typeof checkDeviceSupport === 'function') { // checkDeviceSupport(); } if (typeof MediaDevices !== 'undefined') { DetectRTC.MediaDevices = MediaDevices; } else { DetectRTC.MediaDevices = []; } DetectRTC.hasMicrophone = hasMicrophone; DetectRTC.hasSpeakers = hasSpeakers; DetectRTC.hasWebcam = hasWebcam; DetectRTC.isWebsiteHasWebcamPermissions = isWebsiteHasWebcamPermissions; DetectRTC.isWebsiteHasMicrophonePermissions = isWebsiteHasMicrophonePermissions; DetectRTC.audioInputDevices = audioInputDevices; DetectRTC.audioOutputDevices = audioOutputDevices; DetectRTC.videoInputDevices = videoInputDevices; // ------ var isSetSinkIdSupported = false; if (typeof document !== 'undefined' && typeof document.createElement === 'function' && 'setSinkId' in document.createElement('video')) { isSetSinkIdSupported = true; } DetectRTC.isSetSinkIdSupported = isSetSinkIdSupported; // ----- var isRTPSenderReplaceTracksSupported = false; if (DetectRTC.browser.isFirefox && typeof mozRTCPeerConnection !== 'undefined' /*&& DetectRTC.browser.version > 39*/ ) { /*global mozRTCPeerConnection:true */ if ('getSenders' in mozRTCPeerConnection.prototype) { isRTPSenderReplaceTracksSupported = true; } } else if (DetectRTC.browser.isChrome && typeof webkitRTCPeerConnection !== 'undefined') { /*global webkitRTCPeerConnection:true */ if ('getSenders' in webkitRTCPeerConnection.prototype) { isRTPSenderReplaceTracksSupported = true; } } DetectRTC.isRTPSenderReplaceTracksSupported = isRTPSenderReplaceTracksSupported; //------ var isRemoteStreamProcessingSupported = false; if (DetectRTC.browser.isFirefox && DetectRTC.browser.version > 38) { isRemoteStreamProcessingSupported = true; } DetectRTC.isRemoteStreamProcessingSupported = isRemoteStreamProcessingSupported; //------- var isApplyConstraintsSupported = false; /*global MediaStreamTrack:true */ if (typeof MediaStreamTrack !== 'undefined' && 'applyConstraints' in MediaStreamTrack.prototype) { isApplyConstraintsSupported = true; } DetectRTC.isApplyConstraintsSupported = isApplyConstraintsSupported; //------- var isMultiMonitorScreenCapturingSupported = false; if (DetectRTC.browser.isFirefox && DetectRTC.browser.version >= 43) { // version 43 merely supports platforms for multi-monitors // version 44 will support exact multi-monitor selection i.e. you can select any monitor for screen capturing. isMultiMonitorScreenCapturingSupported = true; } DetectRTC.isMultiMonitorScreenCapturingSupported = isMultiMonitorScreenCapturingSupported; DetectRTC.isPromisesSupported = !!('Promise' in window); // version is generated by "grunt" DetectRTC.version = '1.4.1'; if (typeof DetectRTC === 'undefined') { window.DetectRTC = {}; } var MediaStream = window.MediaStream; if (typeof MediaStream === 'undefined' && typeof webkitMediaStream !== 'undefined') { MediaStream = webkitMediaStream; } if (typeof MediaStream !== 'undefined' && typeof MediaStream === 'function') { DetectRTC.MediaStream = Object.keys(MediaStream.prototype); } else DetectRTC.MediaStream = false; if (typeof MediaStreamTrack !== 'undefined') { DetectRTC.MediaStreamTrack = Object.keys(MediaStreamTrack.prototype); } else DetectRTC.MediaStreamTrack = false; var RTCPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection; if (typeof RTCPeerConnection !== 'undefined') { DetectRTC.RTCPeerConnection = Object.keys(RTCPeerConnection.prototype); } else DetectRTC.RTCPeerConnection = false; window.DetectRTC = DetectRTC; if (typeof module !== 'undefined' /* && !!module.exports*/ ) { module.exports = DetectRTC; } if (typeof define === 'function' && define.amd) { define('DetectRTC', [], function() { return DetectRTC; }); } })();