Comparing version 1.0.8 to 1.0.9
771
DetectRTC.js
@@ -1,2 +0,2 @@ | ||
// Last time updated at Sep 10, 2015, 08:32:23 | ||
// Last time updated at Sep 24, 2015, 08:32:23 | ||
@@ -14,119 +14,164 @@ // Latest file can be found here: https://cdn.webrtc-experiment.com/DetectRTC.js | ||
// DetectRTC.hasSpeakers (has speakers!) | ||
// DetectRTC.isScreenCapturingSupported | ||
// DetectRTC.isSctpDataChannelsSupported | ||
// DetectRTC.isRtpDataChannelsSupported | ||
// DetectRTC.isAudioContextSupported | ||
// DetectRTC.isWebRTCSupported | ||
// DetectRTC.isDesktopCapturingSupported | ||
// DetectRTC.isMobileDevice | ||
// DetectRTC.isWebSocketsSupported | ||
// DetectRTC.DetectLocalIPAddress(callback) | ||
'use strict'; | ||
// ----------todo: add | ||
// DetectRTC.videoResolutions | ||
// DetectRTC.screenResolutions | ||
if (navigator.mediaDevices && navigator.mediaDevices.enumerateDevices) { | ||
// Firefox 38+ seems having support of enumerateDevices | ||
// Thanks @xdumaine/enumerateDevices | ||
navigator.enumerateDevices = function(callback) { | ||
navigator.mediaDevices.enumerateDevices().then(callback); | ||
}; | ||
} | ||
(function() { | ||
'use strict'; | ||
if (typeof navigator !== 'undefined') { | ||
if (typeof navigator.webkitGetUserMedia !== 'undefined') { | ||
navigator.getUserMedia = navigator.webkitGetUserMedia; | ||
} | ||
function warn(log) { | ||
if (window.console && typeof window.console.warn !== 'undefined') { | ||
console.warn(log); | ||
} | ||
if (typeof navigator.mozGetUserMedia !== 'undefined') { | ||
navigator.getUserMedia = navigator.mozGetUserMedia; | ||
} | ||
} else { | ||
/*global navigator:true */ | ||
var navigator = { | ||
getUserMedia: {} | ||
}; | ||
} | ||
var isEdge = navigator.userAgent.indexOf('Edge') !== -1 && (!!navigator.msSaveOrOpenBlob || !!navigator.msSaveBlob); | ||
var isMobileDevice = !!navigator.userAgent.match(/Android|iPhone|iPad|iPod|BlackBerry|IEMobile/i); | ||
var isEdge = navigator.userAgent.indexOf('Edge') !== -1 && (!!navigator.msSaveOrOpenBlob || !!navigator.msSaveBlob); | ||
// detect node-webkit | ||
var browser = getBrowserInfo(); | ||
// this one can also be used: | ||
// https://www.websocket.org/js/stuff.js (DetectBrowser.js) | ||
// is this a chromium browser (opera or chrome) | ||
var isOpera = !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0; | ||
var isFirefox = typeof InstallTrigger !== 'undefined'; | ||
var isSafari = Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0; | ||
var isChrome = !!window.chrome && !isOpera && !isEdge; | ||
var isIE = !!document.documentMode && !isEdge; | ||
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; | ||
var isMobileDevice = !!navigator.userAgent.match(/Android|iPhone|iPad|iPod|BlackBerry|IEMobile/i); | ||
// In Opera, the true version is after 'Opera' or after 'Version' | ||
if ((verOffset = nAgt.indexOf('Opera')) !== -1) { | ||
browserName = 'Opera'; | ||
fullVersion = nAgt.substring(verOffset + 6); | ||
// detect node-webkit | ||
var isNodeWebkit = !!(window.process && (typeof window.process === 'object') && window.process.versions && window.process.versions['node-webkit']); | ||
if ((verOffset = nAgt.indexOf('Version')) !== -1) { | ||
fullVersion = nAgt.substring(verOffset + 8); | ||
} | ||
} | ||
// In MSIE, the true version is after 'MSIE' in userAgent | ||
else if ((verOffset = nAgt.indexOf('MSIE')) !== -1) { | ||
browserName = 'IE'; | ||
fullVersion = nAgt.substring(verOffset + 5); | ||
} | ||
// In Chrome, the true version is after 'Chrome' | ||
else if ((verOffset = nAgt.indexOf('Chrome')) !== -1) { | ||
browserName = 'Chrome'; | ||
fullVersion = nAgt.substring(verOffset + 7); | ||
} | ||
// In Safari, the true version is after 'Safari' or after 'Version' | ||
else if ((verOffset = nAgt.indexOf('Safari')) !== -1) { | ||
browserName = 'Safari'; | ||
fullVersion = nAgt.substring(verOffset + 7); | ||
var isHTTPs = location.protocol === 'https:'; | ||
if ((verOffset = nAgt.indexOf('Version')) !== -1) { | ||
fullVersion = nAgt.substring(verOffset + 8); | ||
} | ||
} | ||
// In Firefox, the true version is after 'Firefox' | ||
else if ((verOffset = nAgt.indexOf('Firefox')) !== -1) { | ||
browserName = 'Firefox'; | ||
fullVersion = nAgt.substring(verOffset + 8); | ||
} | ||
if (navigator.mediaDevices && navigator.mediaDevices.enumerateDevices) { | ||
// Firefox 38+ seems having support of enumerateDevices | ||
// Thanks @xdumaine/enumerateDevices | ||
navigator.enumerateDevices = function(callback) { | ||
navigator.mediaDevices.enumerateDevices().then(callback); | ||
}; | ||
// 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; | ||
} | ||
} | ||
window.DetectRTC = { | ||
browser: browser, | ||
hasMicrophone: navigator.enumerateDevices ? false : 'unable to detect', | ||
hasSpeakers: navigator.enumerateDevices ? false : 'unable to detect', | ||
hasWebcam: navigator.enumerateDevices ? false : 'unable to detect', | ||
if (isEdge) { | ||
browserName = 'Edge'; | ||
fullVersion = navigator.userAgent.split('Edge/')[1]; | ||
} | ||
isWebRTCSupported: !!window.webkitRTCPeerConnection || !!window.mozRTCPeerConnection, | ||
isAudioContextSupported: (!!window.AudioContext && !!window.AudioContext.prototype.createMediaStreamSource) || (!!window.webkitAudioContext && !!window.webkitAudioContext.prototype.createMediaStreamSource), | ||
// trim the fullVersion string at semicolon/space if present | ||
if ((ix = fullVersion.indexOf(';')) !== -1) { | ||
fullVersion = fullVersion.substring(0, ix); | ||
} | ||
isScreenCapturingSupported: (isFirefox && browser.version >= 33) || | ||
(isChrome && browser.version >= 26 && (isNodeWebkit ? true : location.protocol === 'https:')), | ||
if ((ix = fullVersion.indexOf(' ')) !== -1) { | ||
fullVersion = fullVersion.substring(0, ix); | ||
} | ||
isDesktopCapturingSupported: isHTTPs && ((isFirefox && browser.version >= 33) || (isChrome && browser.version >= 34) || isNodeWebkit || false), | ||
majorVersion = parseInt('' + fullVersion, 10); | ||
isSctpDataChannelsSupported: isFirefox || (isChrome && browser.version >= 25), | ||
isRtpDataChannelsSupported: isChrome && browser.version >= 31, | ||
isMobileDevice: !!navigator.userAgent.match(/Android|iPhone|iPad|iPod|BlackBerry|IEMobile/i), | ||
isWebSocketsSupported: 'WebSocket' in window && 2 === window.WebSocket.CLOSING, | ||
isCanvasSupportsStreamCapturing: false, | ||
isVideoSupportsStreamCapturing: false | ||
if (isNaN(majorVersion)) { | ||
fullVersion = '' + parseFloat(navigator.appVersion); | ||
majorVersion = parseInt(navigator.appVersion, 10); | ||
} | ||
return { | ||
fullVersion: fullVersion, | ||
version: majorVersion, | ||
name: browserName | ||
}; | ||
} | ||
(function detectCanvasCaptureStream() { | ||
// latest Firefox nighly is supporting this "awesome" feature! | ||
var canvas = document.createElement('canvas'); | ||
var isMobile = { | ||
Android: function() { | ||
return navigator.userAgent.match(/Android/i); | ||
}, | ||
BlackBerry: function() { | ||
return navigator.userAgent.match(/BlackBerry/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 (typeof canvas.captureStream === 'function') { | ||
DetectRTC.isCanvasSupportsStreamCapturing = true; | ||
} else if (typeof canvas.mozCaptureStream === 'function') { | ||
DetectRTC.isCanvasSupportsStreamCapturing = true; | ||
} else if (typeof canvas.webkitCaptureStream === 'function') { | ||
DetectRTC.isCanvasSupportsStreamCapturing = true; | ||
if (isMobile.BlackBerry()) { | ||
osName = 'BlackBerry'; | ||
} | ||
})(); | ||
(function detectVideoCaptureStream() { | ||
var video = document.createElement('video'); | ||
if (typeof video.captureStream === 'function') { | ||
DetectRTC.isVideoSupportsStreamCapturing = true; | ||
} else if (typeof video.mozCaptureStream === 'function') { | ||
DetectRTC.isVideoSupportsStreamCapturing = true; | ||
} else if (typeof video.webkitCaptureStream === 'function') { | ||
DetectRTC.isVideoSupportsStreamCapturing = true; | ||
if (isMobile.iOS()) { | ||
osName = 'iOS'; | ||
} | ||
})(); | ||
if (!isHTTPs) { | ||
window.DetectRTC.isScreenCapturingSupported = | ||
window.DetectRTC.isDesktopCapturingSupported = 'Requires HTTPs.'; | ||
if (isMobile.Opera()) { | ||
osName = 'Opera Mini'; | ||
} | ||
if (isMobile.Windows()) { | ||
osName = 'Windows'; | ||
} | ||
return osName; | ||
} | ||
}; | ||
DetectRTC.browser = { | ||
isFirefox: isFirefox, | ||
isChrome: isChrome, | ||
isMobileDevice: isMobileDevice, | ||
isNodeWebkit: isNodeWebkit, | ||
isSafari: isSafari, | ||
isIE: isIE, | ||
isOpera: isOpera, | ||
isEdge: isEdge, | ||
name: browser.name, | ||
version: browser.version | ||
}; | ||
var osName = 'Unknown OS'; | ||
var osName = 'Unknown OS'; | ||
if (isMobile.any()) { | ||
osName = isMobile.getOsName(); | ||
} else { | ||
if (navigator.appVersion.indexOf('Win') !== -1) { | ||
@@ -147,293 +192,397 @@ osName = 'Windows'; | ||
} | ||
} | ||
DetectRTC.osName = osName; | ||
DetectRTC.MediaDevices = []; | ||
var isCanvasSupportsStreamCapturing = false; | ||
var isVideoSupportsStreamCapturing = false; | ||
['captureStream', 'mozCaptureStream', 'webkitCaptureStream'].forEach(function(item) { | ||
// asdf | ||
if (item in document.createElement('canvas')) { | ||
isCanvasSupportsStreamCapturing = true; | ||
} | ||
if (!navigator.enumerateDevices) { | ||
warn('navigator.enumerateDevices API are not available.'); | ||
if (item in document.createElement('video')) { | ||
isVideoSupportsStreamCapturing = true; | ||
} | ||
}); | ||
if (!navigator.enumerateDevices && (!window.MediaStreamTrack || !window.MediaStreamTrack.getSources)) { | ||
warn('MediaStreamTrack.getSources are not available.'); | ||
// via: https://github.com/diafygi/webrtc-ips | ||
function DetectLocalIPAddress(callback) { | ||
getIPs(function(ip) { | ||
//local IPs | ||
if (ip.match(/^(192\.168\.|169\.254\.|10\.|172\.(1[6-9]|2\d|3[01]))/)) { | ||
callback('Local: ' + ip); | ||
} | ||
//assume the rest are public IPs | ||
else { | ||
callback('Public: ' + ip); | ||
} | ||
}); | ||
} | ||
//get the IP addresses associated with an account | ||
function getIPs(callback) { | ||
var ipDuplicates = {}; | ||
//compatibility for firefox and chrome | ||
var RTCPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection; | ||
var useWebKit = !!window.webkitRTCPeerConnection; | ||
// bypass naive webrtc blocking using an iframe | ||
if (!RTCPeerConnection) { | ||
var iframe = document.getElementById('iframe'); | ||
if (!iframe) { | ||
//<iframe id="iframe" sandbox="allow-same-origin" style="display: none"></iframe> | ||
throw 'NOTE: you need to have an iframe in the page right above the script tag.'; | ||
} | ||
var win = iframe.contentWindow; | ||
RTCPeerConnection = win.RTCPeerConnection || win.mozRTCPeerConnection || win.webkitRTCPeerConnection; | ||
useWebKit = !!win.webkitRTCPeerConnection; | ||
} | ||
// http://dev.w3.org/2011/webrtc/editor/getusermedia.html#mediadevices | ||
// todo: switch to enumerateDevices when landed in canary. | ||
function CheckDeviceSupport(callback) { | ||
// This method is useful only for Chrome! | ||
//minimal requirements for data connection | ||
var mediaConstraints = { | ||
optional: [{ | ||
RtpDataChannels: true | ||
}] | ||
}; | ||
if (!navigator.enumerateDevices && window.MediaStreamTrack && window.MediaStreamTrack.getSources) { | ||
navigator.enumerateDevices = window.MediaStreamTrack.getSources.bind(window.MediaStreamTrack); | ||
//firefox already has a default stun server in about:config | ||
// media.peerconnection.default_iceservers = | ||
// [{"url": "stun:stun.services.mozilla.com"}] | ||
var servers; | ||
//add same stun server for chrome | ||
if (useWebKit) { | ||
servers = { | ||
iceServers: [{ | ||
urls: 'stun:stun.services.mozilla.com' | ||
}] | ||
}; | ||
if (typeof DetectRTC !== 'undefined' && DetectRTC.browser.isFirefox && DetectRTC.browser.version <= 38) { | ||
servers[0] = { | ||
url: servers[0].urls | ||
}; | ||
} | ||
} | ||
if (!navigator.enumerateDevices && navigator.enumerateDevices) { | ||
navigator.enumerateDevices = navigator.enumerateDevices.bind(navigator); | ||
//construct a new RTCPeerConnection | ||
var pc = new RTCPeerConnection(servers, mediaConstraints); | ||
function handleCandidate(candidate) { | ||
//match just the IP address | ||
var ipRegex = /([0-9]{1,3}(\.[0-9]{1,3}){3})/; | ||
var ipAddress = ipRegex.exec(candidate)[1]; | ||
//remove duplicates | ||
if (ipDuplicates[ipAddress] === undefined) { | ||
callback(ipAddress); | ||
} | ||
if (!navigator.enumerateDevices) { | ||
warn('navigator.enumerateDevices is undefined.'); | ||
// assuming that it is older chrome or chromium implementation | ||
if (isChrome) { | ||
DetectRTC.hasMicrophone = true; | ||
DetectRTC.hasSpeakers = true; | ||
DetectRTC.hasWebcam = true; | ||
} | ||
ipDuplicates[ipAddress] = true; | ||
} | ||
if (callback) { | ||
callback(); | ||
} | ||
return; | ||
//listen for candidate events | ||
pc.onicecandidate = function(ice) { | ||
//skip non-candidate events | ||
if (ice.candidate) { | ||
handleCandidate(ice.candidate.candidate); | ||
} | ||
}; | ||
DetectRTC.MediaDevices = []; | ||
navigator.enumerateDevices(function(devices) { | ||
devices.forEach(function(_device) { | ||
var device = {}; | ||
for (var d in _device) { | ||
device[d] = _device[d]; | ||
} | ||
//create a bogus data channel | ||
pc.createDataChannel(''); | ||
var skip; | ||
DetectRTC.MediaDevices.forEach(function(d) { | ||
if (d.id === device.id) { | ||
skip = true; | ||
} | ||
}); | ||
//create an offer sdp | ||
pc.createOffer(function(result) { | ||
if (skip) { | ||
return; | ||
} | ||
//trigger the stun server request | ||
pc.setLocalDescription(result, function() {}, function() {}); | ||
// if it is MediaStreamTrack.getSources | ||
if (device.kind === 'audio') { | ||
device.kind = 'audioinput'; | ||
} | ||
}, function() {}); | ||
if (device.kind === 'video') { | ||
device.kind = 'videoinput'; | ||
} | ||
//wait for a while to let everything done | ||
setTimeout(function() { | ||
//read candidate info from local description | ||
var lines = pc.localDescription.sdp.split('\n'); | ||
if (!device.deviceId) { | ||
device.deviceId = device.id; | ||
} | ||
lines.forEach(function(line) { | ||
if (line.indexOf('a=candidate:') === 0) { | ||
handleCandidate(line); | ||
} | ||
}); | ||
}, 1000); | ||
} | ||
if (!device.id) { | ||
device.id = device.deviceId; | ||
} | ||
var MediaDevices = []; | ||
if (!device.label) { | ||
device.label = 'Please invoke getUserMedia once.'; | ||
} | ||
// ---------- Media Devices detection | ||
var canEnumerate = false; | ||
if (device.kind === 'audioinput' || device.kind === 'audio') { | ||
DetectRTC.hasMicrophone = true; | ||
} | ||
/*global MediaStreamTrack:true */ | ||
if (typeof MediaStreamTrack !== 'undefined' && 'getSources' in MediaStreamTrack) { | ||
canEnumerate = true; | ||
} else if (navigator.mediaDevices && !!navigator.mediaDevices.enumerateDevices) { | ||
canEnumerate = true; | ||
} | ||
if (device.kind === 'audiooutput') { | ||
DetectRTC.hasSpeakers = true; | ||
} | ||
var hasMicrophone = canEnumerate; | ||
var hasSpeakers = canEnumerate; | ||
var hasWebcam = canEnumerate; | ||
if (device.kind === 'videoinput' || device.kind === 'video') { | ||
DetectRTC.hasWebcam = true; | ||
} | ||
// http://dev.w3.org/2011/webrtc/editor/getusermedia.html#mediadevices | ||
// todo: switch to enumerateDevices when landed in canary. | ||
function checkDeviceSupport(callback) { | ||
// This method is useful only for Chrome! | ||
// there is no 'videoouput' in the spec. | ||
if (!navigator.enumerateDevices && window.MediaStreamTrack && window.MediaStreamTrack.getSources) { | ||
navigator.enumerateDevices = window.MediaStreamTrack.getSources.bind(window.MediaStreamTrack); | ||
} | ||
DetectRTC.MediaDevices.push(device); | ||
if (!navigator.enumerateDevices && navigator.enumerateDevices) { | ||
navigator.enumerateDevices = navigator.enumerateDevices.bind(navigator); | ||
} | ||
if (!navigator.enumerateDevices) { | ||
if (callback) { | ||
callback(); | ||
} | ||
return; | ||
} | ||
MediaDevices = []; | ||
navigator.enumerateDevices(function(devices) { | ||
devices.forEach(function(_device) { | ||
var device = {}; | ||
for (var d in _device) { | ||
device[d] = _device[d]; | ||
} | ||
var skip; | ||
MediaDevices.forEach(function(d) { | ||
if (d.id === device.id) { | ||
skip = true; | ||
} | ||
}); | ||
if (callback) { | ||
callback(); | ||
if (skip) { | ||
return; | ||
} | ||
}); | ||
} | ||
// check for microphone/camera support! | ||
new CheckDeviceSupport(); | ||
DetectRTC.load = CheckDeviceSupport; | ||
// if it is MediaStreamTrack.getSources | ||
if (device.kind === 'audio') { | ||
device.kind = 'audioinput'; | ||
} | ||
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; | ||
if (device.kind === 'video') { | ||
device.kind = 'videoinput'; | ||
} | ||
// In Opera, the true version is after 'Opera' or after 'Version' | ||
if ((verOffset = nAgt.indexOf('Opera')) !== -1) { | ||
browserName = 'Opera'; | ||
fullVersion = nAgt.substring(verOffset + 6); | ||
if (!device.deviceId) { | ||
device.deviceId = device.id; | ||
} | ||
if ((verOffset = nAgt.indexOf('Version')) !== -1) { | ||
fullVersion = nAgt.substring(verOffset + 8); | ||
if (!device.id) { | ||
device.id = device.deviceId; | ||
} | ||
} | ||
// In MSIE, the true version is after 'MSIE' in userAgent | ||
else if ((verOffset = nAgt.indexOf('MSIE')) !== -1) { | ||
browserName = 'IE'; | ||
fullVersion = nAgt.substring(verOffset + 5); | ||
} | ||
// In Chrome, the true version is after 'Chrome' | ||
else if ((verOffset = nAgt.indexOf('Chrome')) !== -1) { | ||
browserName = 'Chrome'; | ||
fullVersion = nAgt.substring(verOffset + 7); | ||
} | ||
// In Safari, the true version is after 'Safari' or after 'Version' | ||
else if ((verOffset = nAgt.indexOf('Safari')) !== -1) { | ||
browserName = 'Safari'; | ||
fullVersion = nAgt.substring(verOffset + 7); | ||
if ((verOffset = nAgt.indexOf('Version')) !== -1) { | ||
fullVersion = nAgt.substring(verOffset + 8); | ||
if (!device.label) { | ||
device.label = 'Please invoke getUserMedia once.'; | ||
if (!isHTTPs) { | ||
device.label = 'HTTPs is required to get label of this ' + device.kind + ' device.'; | ||
} | ||
} | ||
} | ||
// In Firefox, the true version is after 'Firefox' | ||
else if ((verOffset = nAgt.indexOf('Firefox')) !== -1) { | ||
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 (device.kind === 'audioinput' || device.kind === 'audio') { | ||
hasMicrophone = true; | ||
} | ||
if (browserName.toLowerCase() === browserName.toUpperCase()) { | ||
browserName = navigator.appName; | ||
if (device.kind === 'audiooutput') { | ||
hasSpeakers = true; | ||
} | ||
} | ||
if (isEdge) { | ||
browserName = 'Edge'; | ||
fullVersion = navigator.userAgent.split('Edge/')[1]; | ||
} | ||
if (device.kind === 'videoinput' || device.kind === 'video') { | ||
hasWebcam = true; | ||
} | ||
// trim the fullVersion string at semicolon/space if present | ||
if ((ix = fullVersion.indexOf(';')) !== -1) { | ||
fullVersion = fullVersion.substring(0, ix); | ||
// there is no 'videoouput' in the spec. | ||
MediaDevices.push(device); | ||
}); | ||
if (typeof DetectRTC !== 'undefined') { | ||
DetectRTC.MediaDevices = MediaDevices; | ||
DetectRTC.hasMicrophone = hasMicrophone; | ||
DetectRTC.hasSpeakers = hasSpeakers; | ||
DetectRTC.hasWebcam = hasWebcam; | ||
} | ||
if ((ix = fullVersion.indexOf(' ')) !== -1) { | ||
fullVersion = fullVersion.substring(0, ix); | ||
if (callback) { | ||
callback(); | ||
} | ||
}); | ||
} | ||
majorVersion = parseInt('' + fullVersion, 10); | ||
// check for microphone/camera support! | ||
checkDeviceSupport(); | ||
if (isNaN(majorVersion)) { | ||
fullVersion = '' + parseFloat(navigator.appVersion); | ||
majorVersion = parseInt(navigator.appVersion, 10); | ||
} | ||
var DetectRTC = {}; | ||
return { | ||
fullVersion: fullVersion, | ||
version: majorVersion, | ||
name: browserName | ||
}; | ||
// ---------- | ||
// DetectRTC.browser.name || DetectRTC.browser.version || DetectRTC.browser.fullVersion | ||
DetectRTC.browser = getBrowserInfo(); | ||
// DetectRTC.isChrome || DetectRTC.isFirefox || DetectRTC.isEdge | ||
DetectRTC.browser['is' + DetectRTC.browser.name] = true; | ||
var isHTTPs = location.protocol === 'https:'; | ||
var isNodeWebkit = !!(window.process && (typeof window.process === 'object') && window.process.versions && window.process.versions['node-webkit']); | ||
// --------- Detect if system supports WebRTC 1.0 or WebRTC 1.1. | ||
var isWebRTCSupported = false; | ||
['webkitRTCPeerConnection', 'mozRTCPeerConnection', 'RTCIceGatherer'].forEach(function(item) { | ||
if (item in window) { | ||
isWebRTCSupported = true; | ||
} | ||
}); | ||
DetectRTC.isWebRTCSupported = isWebRTCSupported; | ||
// via: https://github.com/diafygi/webrtc-ips | ||
DetectRTC.DetectLocalIPAddress = function(callback) { | ||
getIPs(function(ip) { | ||
//local IPs | ||
if (ip.match(/^(192\.168\.|169\.254\.|10\.|172\.(1[6-9]|2\d|3[01]))/)) { | ||
callback('Local: ' + ip); | ||
} | ||
//------- | ||
DetectRTC.isORTCSupported = typeof RTCIceGatherer !== 'undefined'; | ||
//assume the rest are public IPs | ||
else { | ||
callback('Public: ' + ip); | ||
} | ||
}); | ||
}; | ||
// --------- 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; | ||
} | ||
//get the IP addresses associated with an account | ||
function getIPs(callback) { | ||
var ipDuplicates = {}; | ||
if (!isHTTPs) { | ||
isScreenCapturingSupported = false; | ||
} | ||
DetectRTC.isScreenCapturingSupported = isScreenCapturingSupported; | ||
//compatibility for firefox and chrome | ||
var RTCPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection; | ||
var useWebKit = !!window.webkitRTCPeerConnection; | ||
// --------- Detect if WebAudio API are supported | ||
var webAudio = {}; | ||
['AudioContext', 'webkitAudioContext', 'mozAudioContext', 'msAudioContext'].forEach(function(item) { | ||
if (item in window) { | ||
webAudio.isSupported = true; | ||
// bypass naive webrtc blocking using an iframe | ||
if (!RTCPeerConnection) { | ||
var iframe = document.getElementById('iframe'); | ||
if (!iframe) { | ||
//<iframe id="iframe" sandbox="allow-same-origin" style="display: none"></iframe> | ||
throw 'NOTE: you need to have an iframe in the page right above the script tag.'; | ||
} | ||
var win = iframe.contentWindow; | ||
RTCPeerConnection = win.RTCPeerConnection || win.mozRTCPeerConnection || win.webkitRTCPeerConnection; | ||
useWebKit = !!win.webkitRTCPeerConnection; | ||
if ('createMediaStreamSource' in window[item].prototype) { | ||
webAudio.isCreateMediaStreamSourceSupported = true; | ||
} | ||
} | ||
}); | ||
DetectRTC.isAudioContextSupported = webAudio.isSupported; | ||
DetectRTC.isCreateMediaStreamSourceSupported = webAudio.isCreateMediaStreamSourceSupported; | ||
//minimal requirements for data connection | ||
var mediaConstraints = { | ||
optional: [{ | ||
RtpDataChannels: true | ||
}] | ||
}; | ||
// ---------- Detect if SCTP/RTP channels are supported. | ||
//firefox already has a default stun server in about:config | ||
// media.peerconnection.default_iceservers = | ||
// [{"url": "stun:stun.services.mozilla.com"}] | ||
var servers; | ||
var isRtpDataChannelsSupported = false; | ||
if (DetectRTC.browser.isChrome && DetectRTC.browser.version > 31) { | ||
isRtpDataChannelsSupported = true; | ||
} | ||
DetectRTC.isRtpDataChannelsSupported = isRtpDataChannelsSupported; | ||
//add same stun server for chrome | ||
if (useWebKit) { | ||
servers = { | ||
iceServers: [{ | ||
urls: 'stun:stun.services.mozilla.com' | ||
}] | ||
}; | ||
} | ||
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; | ||
//construct a new RTCPeerConnection | ||
var pc = new RTCPeerConnection(servers, mediaConstraints); | ||
// --------- | ||
function handleCandidate(candidate) { | ||
//match just the IP address | ||
var ipRegex = /([0-9]{1,3}(\.[0-9]{1,3}){3})/; | ||
var ipAddress = ipRegex.exec(candidate)[1]; | ||
DetectRTC.isMobileDevice = isMobileDevice; // "isMobileDevice" boolean is defined in "getBrowserInfo.js" | ||
//remove duplicates | ||
if (ipDuplicates[ipAddress] === undefined) { | ||
callback(ipAddress); | ||
} | ||
// ------ | ||
ipDuplicates[ipAddress] = true; | ||
DetectRTC.isWebSocketsSupported = 'WebSocket' in window && 2 === window.WebSocket.CLOSING; | ||
DetectRTC.isWebSocketsBlocked = 'Checking'; | ||
if (DetectRTC.isWebSocketsSupported) { | ||
var websocket = new WebSocket('wss://echo.websocket.org:443/'); | ||
websocket.onopen = function() { | ||
DetectRTC.isWebSocketsBlocked = false; | ||
if (DetectRTC.loadCallback) { | ||
DetectRTC.loadCallback(); | ||
} | ||
}; | ||
websocket.onerror = function() { | ||
DetectRTC.isWebSocketsBlocked = true; | ||
//listen for candidate events | ||
pc.onicecandidate = function(ice) { | ||
//skip non-candidate events | ||
if (ice.candidate) { | ||
handleCandidate(ice.candidate.candidate); | ||
} | ||
}; | ||
if (DetectRTC.loadCallback) { | ||
DetectRTC.loadCallback(); | ||
} | ||
}; | ||
} | ||
//create a bogus data channel | ||
pc.createDataChannel(''); | ||
// ------ | ||
var isGetUserMediaSupported = false; | ||
if (navigator.getUserMedia) { | ||
isGetUserMediaSupported = true; | ||
} else if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) { | ||
isGetUserMediaSupported = true; | ||
} | ||
if (DetectRTC.browser.isChrome && DetectRTC.browser.version >= 47 && !isHTTPs) { | ||
DetectRTC.isGetUserMediaSupported = 'Requires HTTPs'; | ||
} | ||
DetectRTC.isGetUserMediaSupported = isGetUserMediaSupported; | ||
//create an offer sdp | ||
pc.createOffer(function(result) { | ||
// ----------- | ||
DetectRTC.osName = osName; // "osName" is defined in "detectOSName.js" | ||
//trigger the stun server request | ||
pc.setLocalDescription(result, function() {}, function() {}); | ||
// ---------- | ||
DetectRTC.isCanvasSupportsStreamCapturing = isCanvasSupportsStreamCapturing; | ||
DetectRTC.isVideoSupportsStreamCapturing = isVideoSupportsStreamCapturing; | ||
}, function() {}); | ||
// ------ | ||
DetectRTC.DetectLocalIPAddress = DetectLocalIPAddress; | ||
//wait for a while to let everything done | ||
setTimeout(function() { | ||
//read candidate info from local description | ||
var lines = pc.localDescription.sdp.split('\n'); | ||
// ------- | ||
DetectRTC.load = function(callback) { | ||
this.loadCallback = callback; | ||
lines.forEach(function(line) { | ||
if (line.indexOf('a=candidate:') === 0) { | ||
handleCandidate(line); | ||
} | ||
}); | ||
}, 1000); | ||
checkDeviceSupport(callback); | ||
}; | ||
DetectRTC.MediaDevices = MediaDevices; | ||
DetectRTC.hasMicrophone = hasMicrophone; | ||
DetectRTC.hasSpeakers = hasSpeakers; | ||
DetectRTC.hasWebcam = hasWebcam; | ||
// ------ | ||
var isSetSinkIdSupported = false; | ||
if ('setSinkId' in document.createElement('video')) { | ||
isSetSinkIdSupported = true; | ||
} | ||
DetectRTC.isSetSinkIdSupported = isSetSinkIdSupported; | ||
// ----- | ||
var isRTPSenderReplaceTracksSupported = false; | ||
if (DetectRTC.browser.isFirefox /*&& DetectRTC.browser.version > 39*/ ) { | ||
/*global mozRTCPeerConnection:true */ | ||
if ('getSenders' in mozRTCPeerConnection.prototype) { | ||
isRTPSenderReplaceTracksSupported = true; | ||
} | ||
})(); | ||
} else if (DetectRTC.browser.isChrome) { | ||
/*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; |
@@ -1,1 +0,1 @@ | ||
!function(){"use strict";function warn(log){window.console&&"undefined"!=typeof window.console.warn&&console.warn(log)}function CheckDeviceSupport(callback){return!navigator.enumerateDevices&&window.MediaStreamTrack&&window.MediaStreamTrack.getSources&&(navigator.enumerateDevices=window.MediaStreamTrack.getSources.bind(window.MediaStreamTrack)),!navigator.enumerateDevices&&navigator.enumerateDevices&&(navigator.enumerateDevices=navigator.enumerateDevices.bind(navigator)),navigator.enumerateDevices?(DetectRTC.MediaDevices=[],void navigator.enumerateDevices(function(devices){devices.forEach(function(_device){var device={};for(var d in _device)device[d]=_device[d];var skip;DetectRTC.MediaDevices.forEach(function(d){d.id===device.id&&(skip=!0)}),skip||("audio"===device.kind&&(device.kind="audioinput"),"video"===device.kind&&(device.kind="videoinput"),device.deviceId||(device.deviceId=device.id),device.id||(device.id=device.deviceId),device.label||(device.label="Please invoke getUserMedia once."),("audioinput"===device.kind||"audio"===device.kind)&&(DetectRTC.hasMicrophone=!0),"audiooutput"===device.kind&&(DetectRTC.hasSpeakers=!0),("videoinput"===device.kind||"video"===device.kind)&&(DetectRTC.hasWebcam=!0),DetectRTC.MediaDevices.push(device))}),callback&&callback()})):(warn("navigator.enumerateDevices is undefined."),isChrome&&(DetectRTC.hasMicrophone=!0,DetectRTC.hasSpeakers=!0,DetectRTC.hasWebcam=!0),void(callback&&callback()))}function getBrowserInfo(){var nameOffset,verOffset,ix,nAgt=(navigator.appVersion,navigator.userAgent),browserName=navigator.appName,fullVersion=""+parseFloat(navigator.appVersion),majorVersion=parseInt(navigator.appVersion,10);return-1!==(verOffset=nAgt.indexOf("Opera"))?(browserName="Opera",fullVersion=nAgt.substring(verOffset+6),-1!==(verOffset=nAgt.indexOf("Version"))&&(fullVersion=nAgt.substring(verOffset+8))):-1!==(verOffset=nAgt.indexOf("MSIE"))?(browserName="IE",fullVersion=nAgt.substring(verOffset+5)):-1!==(verOffset=nAgt.indexOf("Chrome"))?(browserName="Chrome",fullVersion=nAgt.substring(verOffset+7)):-1!==(verOffset=nAgt.indexOf("Safari"))?(browserName="Safari",fullVersion=nAgt.substring(verOffset+7),-1!==(verOffset=nAgt.indexOf("Version"))&&(fullVersion=nAgt.substring(verOffset+8))):-1!==(verOffset=nAgt.indexOf("Firefox"))?(browserName="Firefox",fullVersion=nAgt.substring(verOffset+8)):(nameOffset=nAgt.lastIndexOf(" ")+1)<(verOffset=nAgt.lastIndexOf("/"))&&(browserName=nAgt.substring(nameOffset,verOffset),fullVersion=nAgt.substring(verOffset+1),browserName.toLowerCase()===browserName.toUpperCase()&&(browserName=navigator.appName)),isEdge&&(browserName="Edge",fullVersion=navigator.userAgent.split("Edge/")[1]),-1!==(ix=fullVersion.indexOf(";"))&&(fullVersion=fullVersion.substring(0,ix)),-1!==(ix=fullVersion.indexOf(" "))&&(fullVersion=fullVersion.substring(0,ix)),majorVersion=parseInt(""+fullVersion,10),isNaN(majorVersion)&&(fullVersion=""+parseFloat(navigator.appVersion),majorVersion=parseInt(navigator.appVersion,10)),{fullVersion:fullVersion,version:majorVersion,name:browserName}}function getIPs(callback){function handleCandidate(candidate){var ipRegex=/([0-9]{1,3}(\.[0-9]{1,3}){3})/,ipAddress=ipRegex.exec(candidate)[1];void 0===ipDuplicates[ipAddress]&&callback(ipAddress),ipDuplicates[ipAddress]=!0}var ipDuplicates={},RTCPeerConnection=window.RTCPeerConnection||window.mozRTCPeerConnection||window.webkitRTCPeerConnection,useWebKit=!!window.webkitRTCPeerConnection;if(!RTCPeerConnection){var iframe=document.getElementById("iframe");if(!iframe)throw"NOTE: you need to have an iframe in the page right above the script tag.";var win=iframe.contentWindow;RTCPeerConnection=win.RTCPeerConnection||win.mozRTCPeerConnection||win.webkitRTCPeerConnection,useWebKit=!!win.webkitRTCPeerConnection}var servers,mediaConstraints={optional:[{RtpDataChannels:!0}]};useWebKit&&(servers={iceServers:[{urls:"stun:stun.services.mozilla.com"}]});var pc=new RTCPeerConnection(servers,mediaConstraints);pc.onicecandidate=function(ice){ice.candidate&&handleCandidate(ice.candidate.candidate)},pc.createDataChannel(""),pc.createOffer(function(result){pc.setLocalDescription(result,function(){},function(){})},function(){}),setTimeout(function(){var lines=pc.localDescription.sdp.split("\n");lines.forEach(function(line){0===line.indexOf("a=candidate:")&&handleCandidate(line)})},1e3)}var isEdge=!(-1===navigator.userAgent.indexOf("Edge")||!navigator.msSaveOrOpenBlob&&!navigator.msSaveBlob),browser=getBrowserInfo(),isOpera=!!window.opera||navigator.userAgent.indexOf(" OPR/")>=0,isFirefox="undefined"!=typeof InstallTrigger,isSafari=Object.prototype.toString.call(window.HTMLElement).indexOf("Constructor")>0,isChrome=!!window.chrome&&!isOpera&&!isEdge,isIE=!!document.documentMode&&!isEdge,isMobileDevice=!!navigator.userAgent.match(/Android|iPhone|iPad|iPod|BlackBerry|IEMobile/i),isNodeWebkit=!!(window.process&&"object"==typeof window.process&&window.process.versions&&window.process.versions["node-webkit"]),isHTTPs="https:"===location.protocol;navigator.mediaDevices&&navigator.mediaDevices.enumerateDevices&&(navigator.enumerateDevices=function(callback){navigator.mediaDevices.enumerateDevices().then(callback)}),window.DetectRTC={browser:browser,hasMicrophone:navigator.enumerateDevices?!1:"unable to detect",hasSpeakers:navigator.enumerateDevices?!1:"unable to detect",hasWebcam:navigator.enumerateDevices?!1:"unable to detect",isWebRTCSupported:!!window.webkitRTCPeerConnection||!!window.mozRTCPeerConnection,isAudioContextSupported:!!window.AudioContext&&!!window.AudioContext.prototype.createMediaStreamSource||!!window.webkitAudioContext&&!!window.webkitAudioContext.prototype.createMediaStreamSource,isScreenCapturingSupported:isFirefox&&browser.version>=33||isChrome&&browser.version>=26&&(isNodeWebkit?!0:"https:"===location.protocol),isDesktopCapturingSupported:isHTTPs&&(isFirefox&&browser.version>=33||isChrome&&browser.version>=34||isNodeWebkit||!1),isSctpDataChannelsSupported:isFirefox||isChrome&&browser.version>=25,isRtpDataChannelsSupported:isChrome&&browser.version>=31,isMobileDevice:!!navigator.userAgent.match(/Android|iPhone|iPad|iPod|BlackBerry|IEMobile/i),isWebSocketsSupported:"WebSocket"in window&&2===window.WebSocket.CLOSING,isCanvasSupportsStreamCapturing:!1,isVideoSupportsStreamCapturing:!1},function(){var canvas=document.createElement("canvas");"function"==typeof canvas.captureStream?DetectRTC.isCanvasSupportsStreamCapturing=!0:"function"==typeof canvas.mozCaptureStream?DetectRTC.isCanvasSupportsStreamCapturing=!0:"function"==typeof canvas.webkitCaptureStream&&(DetectRTC.isCanvasSupportsStreamCapturing=!0)}(),function(){var video=document.createElement("video");"function"==typeof video.captureStream?DetectRTC.isVideoSupportsStreamCapturing=!0:"function"==typeof video.mozCaptureStream?DetectRTC.isVideoSupportsStreamCapturing=!0:"function"==typeof video.webkitCaptureStream&&(DetectRTC.isVideoSupportsStreamCapturing=!0)}(),isHTTPs||(window.DetectRTC.isScreenCapturingSupported=window.DetectRTC.isDesktopCapturingSupported="Requires HTTPs."),DetectRTC.browser={isFirefox:isFirefox,isChrome:isChrome,isMobileDevice:isMobileDevice,isNodeWebkit:isNodeWebkit,isSafari:isSafari,isIE:isIE,isOpera:isOpera,isEdge:isEdge,name:browser.name,version:browser.version};var osName="Unknown OS";-1!==navigator.appVersion.indexOf("Win")&&(osName="Windows"),-1!==navigator.appVersion.indexOf("Mac")&&(osName="MacOS"),-1!==navigator.appVersion.indexOf("X11")&&(osName="UNIX"),-1!==navigator.appVersion.indexOf("Linux")&&(osName="Linux"),DetectRTC.osName=osName,DetectRTC.MediaDevices=[],navigator.enumerateDevices||warn("navigator.enumerateDevices API are not available."),navigator.enumerateDevices||window.MediaStreamTrack&&window.MediaStreamTrack.getSources||warn("MediaStreamTrack.getSources are not available."),new CheckDeviceSupport,DetectRTC.load=CheckDeviceSupport,DetectRTC.DetectLocalIPAddress=function(callback){getIPs(function(ip){callback(ip.match(/^(192\.168\.|169\.254\.|10\.|172\.(1[6-9]|2\d|3[01]))/)?"Local: "+ip:"Public: "+ip)})}}(); | ||
"use strict";function getBrowserInfo(){var nameOffset,verOffset,ix,nAgt=(navigator.appVersion,navigator.userAgent),browserName=navigator.appName,fullVersion=""+parseFloat(navigator.appVersion),majorVersion=parseInt(navigator.appVersion,10);return-1!==(verOffset=nAgt.indexOf("Opera"))?(browserName="Opera",fullVersion=nAgt.substring(verOffset+6),-1!==(verOffset=nAgt.indexOf("Version"))&&(fullVersion=nAgt.substring(verOffset+8))):-1!==(verOffset=nAgt.indexOf("MSIE"))?(browserName="IE",fullVersion=nAgt.substring(verOffset+5)):-1!==(verOffset=nAgt.indexOf("Chrome"))?(browserName="Chrome",fullVersion=nAgt.substring(verOffset+7)):-1!==(verOffset=nAgt.indexOf("Safari"))?(browserName="Safari",fullVersion=nAgt.substring(verOffset+7),-1!==(verOffset=nAgt.indexOf("Version"))&&(fullVersion=nAgt.substring(verOffset+8))):-1!==(verOffset=nAgt.indexOf("Firefox"))?(browserName="Firefox",fullVersion=nAgt.substring(verOffset+8)):(nameOffset=nAgt.lastIndexOf(" ")+1)<(verOffset=nAgt.lastIndexOf("/"))&&(browserName=nAgt.substring(nameOffset,verOffset),fullVersion=nAgt.substring(verOffset+1),browserName.toLowerCase()===browserName.toUpperCase()&&(browserName=navigator.appName)),isEdge&&(browserName="Edge",fullVersion=navigator.userAgent.split("Edge/")[1]),-1!==(ix=fullVersion.indexOf(";"))&&(fullVersion=fullVersion.substring(0,ix)),-1!==(ix=fullVersion.indexOf(" "))&&(fullVersion=fullVersion.substring(0,ix)),majorVersion=parseInt(""+fullVersion,10),isNaN(majorVersion)&&(fullVersion=""+parseFloat(navigator.appVersion),majorVersion=parseInt(navigator.appVersion,10)),{fullVersion:fullVersion,version:majorVersion,name:browserName}}function DetectLocalIPAddress(callback){getIPs(function(ip){callback(ip.match(/^(192\.168\.|169\.254\.|10\.|172\.(1[6-9]|2\d|3[01]))/)?"Local: "+ip:"Public: "+ip)})}function getIPs(callback){function handleCandidate(candidate){var ipRegex=/([0-9]{1,3}(\.[0-9]{1,3}){3})/,ipAddress=ipRegex.exec(candidate)[1];void 0===ipDuplicates[ipAddress]&&callback(ipAddress),ipDuplicates[ipAddress]=!0}var ipDuplicates={},RTCPeerConnection=window.RTCPeerConnection||window.mozRTCPeerConnection||window.webkitRTCPeerConnection,useWebKit=!!window.webkitRTCPeerConnection;if(!RTCPeerConnection){var iframe=document.getElementById("iframe");if(!iframe)throw"NOTE: you need to have an iframe in the page right above the script tag.";var win=iframe.contentWindow;RTCPeerConnection=win.RTCPeerConnection||win.mozRTCPeerConnection||win.webkitRTCPeerConnection,useWebKit=!!win.webkitRTCPeerConnection}var servers,mediaConstraints={optional:[{RtpDataChannels:!0}]};useWebKit&&(servers={iceServers:[{urls:"stun:stun.services.mozilla.com"}]},"undefined"!=typeof DetectRTC&&DetectRTC.browser.isFirefox&&DetectRTC.browser.version<=38&&(servers[0]={url:servers[0].urls}));var pc=new RTCPeerConnection(servers,mediaConstraints);pc.onicecandidate=function(ice){ice.candidate&&handleCandidate(ice.candidate.candidate)},pc.createDataChannel(""),pc.createOffer(function(result){pc.setLocalDescription(result,function(){},function(){})},function(){}),setTimeout(function(){var lines=pc.localDescription.sdp.split("\n");lines.forEach(function(line){0===line.indexOf("a=candidate:")&&handleCandidate(line)})},1e3)}function checkDeviceSupport(callback){return!navigator.enumerateDevices&&window.MediaStreamTrack&&window.MediaStreamTrack.getSources&&(navigator.enumerateDevices=window.MediaStreamTrack.getSources.bind(window.MediaStreamTrack)),!navigator.enumerateDevices&&navigator.enumerateDevices&&(navigator.enumerateDevices=navigator.enumerateDevices.bind(navigator)),navigator.enumerateDevices?(MediaDevices=[],void navigator.enumerateDevices(function(devices){devices.forEach(function(_device){var device={};for(var d in _device)device[d]=_device[d];var skip;MediaDevices.forEach(function(d){d.id===device.id&&(skip=!0)}),skip||("audio"===device.kind&&(device.kind="audioinput"),"video"===device.kind&&(device.kind="videoinput"),device.deviceId||(device.deviceId=device.id),device.id||(device.id=device.deviceId),device.label||(device.label="Please invoke getUserMedia once.",isHTTPs||(device.label="HTTPs is required to get label of this "+device.kind+" device.")),("audioinput"===device.kind||"audio"===device.kind)&&(hasMicrophone=!0),"audiooutput"===device.kind&&(hasSpeakers=!0),("videoinput"===device.kind||"video"===device.kind)&&(hasWebcam=!0),MediaDevices.push(device))}),"undefined"!=typeof DetectRTC&&(DetectRTC.MediaDevices=MediaDevices,DetectRTC.hasMicrophone=hasMicrophone,DetectRTC.hasSpeakers=hasSpeakers,DetectRTC.hasWebcam=hasWebcam),callback&&callback()})):void(callback&&callback())}if(navigator.mediaDevices&&navigator.mediaDevices.enumerateDevices&&(navigator.enumerateDevices=function(callback){navigator.mediaDevices.enumerateDevices().then(callback)}),"undefined"!=typeof navigator)"undefined"!=typeof navigator.webkitGetUserMedia&&(navigator.getUserMedia=navigator.webkitGetUserMedia),"undefined"!=typeof navigator.mozGetUserMedia&&(navigator.getUserMedia=navigator.mozGetUserMedia);else var navigator={getUserMedia:{}};var isMobileDevice=!!navigator.userAgent.match(/Android|iPhone|iPad|iPod|BlackBerry|IEMobile/i),isEdge=!(-1===navigator.userAgent.indexOf("Edge")||!navigator.msSaveOrOpenBlob&&!navigator.msSaveBlob),isMobile={Android:function(){return navigator.userAgent.match(/Android/i)},BlackBerry:function(){return navigator.userAgent.match(/BlackBerry/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";return isMobile.Android()&&(osName="Android"),isMobile.BlackBerry()&&(osName="BlackBerry"),isMobile.iOS()&&(osName="iOS"),isMobile.Opera()&&(osName="Opera Mini"),isMobile.Windows()&&(osName="Windows"),osName}},osName="Unknown OS";isMobile.any()?osName=isMobile.getOsName():(-1!==navigator.appVersion.indexOf("Win")&&(osName="Windows"),-1!==navigator.appVersion.indexOf("Mac")&&(osName="MacOS"),-1!==navigator.appVersion.indexOf("X11")&&(osName="UNIX"),-1!==navigator.appVersion.indexOf("Linux")&&(osName="Linux"));var isCanvasSupportsStreamCapturing=!1,isVideoSupportsStreamCapturing=!1;["captureStream","mozCaptureStream","webkitCaptureStream"].forEach(function(item){item in document.createElement("canvas")&&(isCanvasSupportsStreamCapturing=!0),item in document.createElement("video")&&(isVideoSupportsStreamCapturing=!0)});var MediaDevices=[],canEnumerate=!1;"undefined"!=typeof MediaStreamTrack&&"getSources"in MediaStreamTrack?canEnumerate=!0:navigator.mediaDevices&&navigator.mediaDevices.enumerateDevices&&(canEnumerate=!0);var hasMicrophone=canEnumerate,hasSpeakers=canEnumerate,hasWebcam=canEnumerate;checkDeviceSupport();var DetectRTC={};DetectRTC.browser=getBrowserInfo(),DetectRTC.browser["is"+DetectRTC.browser.name]=!0;var isHTTPs="https:"===location.protocol,isNodeWebkit=!!(window.process&&"object"==typeof window.process&&window.process.versions&&window.process.versions["node-webkit"]),isWebRTCSupported=!1;["webkitRTCPeerConnection","mozRTCPeerConnection","RTCIceGatherer"].forEach(function(item){item in window&&(isWebRTCSupported=!0)}),DetectRTC.isWebRTCSupported=isWebRTCSupported,DetectRTC.isORTCSupported="undefined"!=typeof RTCIceGatherer;var isScreenCapturingSupported=!1;DetectRTC.browser.isChrome&&DetectRTC.browser.version>=35?isScreenCapturingSupported=!0:DetectRTC.browser.isFirefox&&DetectRTC.browser.version>=34&&(isScreenCapturingSupported=!0),isHTTPs||(isScreenCapturingSupported=!1),DetectRTC.isScreenCapturingSupported=isScreenCapturingSupported;var webAudio={};["AudioContext","webkitAudioContext","mozAudioContext","msAudioContext"].forEach(function(item){item in window&&(webAudio.isSupported=!0,"createMediaStreamSource"in window[item].prototype&&(webAudio.isCreateMediaStreamSourceSupported=!0))}),DetectRTC.isAudioContextSupported=webAudio.isSupported,DetectRTC.isCreateMediaStreamSourceSupported=webAudio.isCreateMediaStreamSourceSupported;var isRtpDataChannelsSupported=!1;DetectRTC.browser.isChrome&&DetectRTC.browser.version>31&&(isRtpDataChannelsSupported=!0),DetectRTC.isRtpDataChannelsSupported=isRtpDataChannelsSupported;var isSCTPSupportd=!1;if(DetectRTC.browser.isFirefox&&DetectRTC.browser.version>28?isSCTPSupportd=!0:DetectRTC.browser.isChrome&&DetectRTC.browser.version>25?isSCTPSupportd=!0:DetectRTC.browser.isOpera&&DetectRTC.browser.version>=11&&(isSCTPSupportd=!0),DetectRTC.isSctpDataChannelsSupported=isSCTPSupportd,DetectRTC.isMobileDevice=isMobileDevice,DetectRTC.isWebSocketsSupported="WebSocket"in window&&2===window.WebSocket.CLOSING,DetectRTC.isWebSocketsBlocked="Checking",DetectRTC.isWebSocketsSupported){var websocket=new WebSocket("wss://echo.websocket.org:443/");websocket.onopen=function(){DetectRTC.isWebSocketsBlocked=!1,DetectRTC.loadCallback&&DetectRTC.loadCallback()},websocket.onerror=function(){DetectRTC.isWebSocketsBlocked=!0,DetectRTC.loadCallback&&DetectRTC.loadCallback()}}var isGetUserMediaSupported=!1;navigator.getUserMedia?isGetUserMediaSupported=!0:navigator.mediaDevices&&navigator.mediaDevices.getUserMedia&&(isGetUserMediaSupported=!0),DetectRTC.browser.isChrome&&DetectRTC.browser.version>=47&&!isHTTPs&&(DetectRTC.isGetUserMediaSupported="Requires HTTPs"),DetectRTC.isGetUserMediaSupported=isGetUserMediaSupported,DetectRTC.osName=osName,DetectRTC.isCanvasSupportsStreamCapturing=isCanvasSupportsStreamCapturing,DetectRTC.isVideoSupportsStreamCapturing=isVideoSupportsStreamCapturing,DetectRTC.DetectLocalIPAddress=DetectLocalIPAddress,DetectRTC.load=function(callback){this.loadCallback=callback,checkDeviceSupport(callback)},DetectRTC.MediaDevices=MediaDevices,DetectRTC.hasMicrophone=hasMicrophone,DetectRTC.hasSpeakers=hasSpeakers,DetectRTC.hasWebcam=hasWebcam;var isSetSinkIdSupported=!1;"setSinkId"in document.createElement("video")&&(isSetSinkIdSupported=!0),DetectRTC.isSetSinkIdSupported=isSetSinkIdSupported;var isRTPSenderReplaceTracksSupported=!1;DetectRTC.browser.isFirefox?"getSenders"in mozRTCPeerConnection.prototype&&(isRTPSenderReplaceTracksSupported=!0):DetectRTC.browser.isChrome&&"getSenders"in webkitRTCPeerConnection.prototype&&(isRTPSenderReplaceTracksSupported=!0),DetectRTC.isRTPSenderReplaceTracksSupported=isRTPSenderReplaceTracksSupported;var isRemoteStreamProcessingSupported=!1;DetectRTC.browser.isFirefox&&DetectRTC.browser.version>38&&(isRemoteStreamProcessingSupported=!0),DetectRTC.isRemoteStreamProcessingSupported=isRemoteStreamProcessingSupported; |
{ | ||
"name": "detectrtc", | ||
"preferGlobal": true, | ||
"version": "1.0.8", | ||
"version": "1.0.9", | ||
"author": { | ||
@@ -6,0 +6,0 @@ "name": "Muaz Khan", |
@@ -1,3 +0,5 @@ | ||
# [DetectRTC.js](https://github.com/muaz-khan/DetectRTC) / [Demo](https://www.webrtc-experiment.com/DetectRTC/) [![npm](https://img.shields.io/npm/v/detectrtc.svg)](https://npmjs.org/package/detectrtc) [![downloads](https://img.shields.io/npm/dm/detectrtc.svg)](https://npmjs.org/package/detectrtc) [![Build Status: Linux](https://travis-ci.org/muaz-khan/DetectRTC.png?branch=master)](https://travis-ci.org/muaz-khan/DetectRTC) | ||
# [DetectRTC.js](https://github.com/muaz-khan/DetectRTC) / [Try LIVE Demo](https://www.webrtc-experiment.com/DetectRTC/) | ||
[![npm](https://img.shields.io/npm/v/detectrtc.svg)](https://npmjs.org/package/detectrtc) [![downloads](https://img.shields.io/npm/dm/detectrtc.svg)](https://npmjs.org/package/detectrtc) [![Build Status: Linux](https://travis-ci.org/muaz-khan/DetectRTC.png?branch=master)](https://travis-ci.org/muaz-khan/DetectRTC) | ||
A tiny JavaScript library that can be used to detect WebRTC features e.g. system having speakers, microphone or webcam, screen capturing is supported, number of audio/video devices etc. | ||
@@ -12,7 +14,30 @@ | ||
bower install detectrtc | ||
``` | ||
# you can test in localhost as well | ||
node server # http://127.0.0.1:9001 or http://localhost:9001 | ||
# Proposed NEW API | ||
```javascript | ||
DetectRTC.isSetSinkIdSupported // (implemented) | ||
DetectRTC.isRTPSenderReplaceTracksSupported // (implemented) | ||
DetectRTC.isORTCSupported // (implemented) | ||
DetectRTC.isRemoteStreamProcessingSupported // (implemented) | ||
# Below API are NOT implemented yet | ||
DetectRTC.browser.googSupportedFlags.googDAEEchoCancellation | ||
DetecRTC.browser.googSupportedFlags.echoCancellation | ||
DetectRTC.isMediaHintsSupportsNewSyntax | ||
``` | ||
# Test in LocalHost | ||
```javascript | ||
node server.js | ||
// and open: | ||
127.0.0.1:9001 | ||
// or | ||
http://localhost:9001 | ||
``` | ||
To use it: | ||
@@ -67,3 +92,3 @@ | ||
## Why `load` method? | ||
# Why `load` method? | ||
@@ -74,8 +99,24 @@ If you're not detecting audio/video input/outupt devices then you can skip this method. | ||
# Demo | ||
<img src="https://i.imgur.com/YXehckT.jpg?1" /> | ||
* https://www.webrtc-experiment.com/DetectRTC/ | ||
# Rules to Contribute | ||
``` | ||
git clone --depth=50 --branch=development git://github.com/muaz-khan/DetectRTC.git muaz-khan/DetectRTC | ||
# install all dependencies | ||
[sudo] npm install | ||
# install grunt for code style verifications | ||
[sudo] npm install grunt-cli | ||
[sudo] npm install grunt | ||
# verify your changes | ||
npm test # or "grunt" | ||
# Success? Make a pull request! | ||
``` | ||
# License | ||
[DetectRTC.js](https://github.com/muaz-khan/DetectRTC) is released under [MIT licence](https://www.webrtc-experiment.com/licence/) . Copyright (c) [Muaz Khan](http://www.MuazKhan.com/). |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
49882
536
120
2