diff --git a/DetectRTC.js b/DetectRTC.js index a4735de..d48a0f4 100644 --- a/DetectRTC.js +++ b/DetectRTC.js @@ -1,4 +1,4 @@ -// Last time updated at Friday, January 1st, 2016, 5:04:28 PM +// Last time updated at Saturday, January 2nd, 2016, 2:59:43 PM // Latest file can be found here: https://cdn.webrtc-experiment.com/DetectRTC.js @@ -36,6 +36,12 @@ var isMobileDevice = !!navigator.userAgent.match(/Android|iPhone|iPad|iPod|BlackBerry|IEMobile/i); var isEdge = navigator.userAgent.indexOf('Edge') !== -1 && (!!navigator.msSaveOrOpenBlob || !!navigator.msSaveBlob); + var isOpera = !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0; + var isFirefox = typeof window.InstallTrigger !== 'undefined'; + var isSafari = Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0; + var isChrome = !!window.chrome && !isOpera; + var isIE = !!document.documentMode && !isEdge; + // this one can also be used: // https://www.websocket.org/js/stuff.js (DetectBrowser.js) @@ -48,26 +54,31 @@ var nameOffset, verOffset, ix; // In Opera, the true version is after 'Opera' or after 'Version' - if ((verOffset = nAgt.indexOf('Opera')) !== -1) { + if (isOpera) { browserName = 'Opera'; - fullVersion = nAgt.substring(verOffset + 6); - - if ((verOffset = nAgt.indexOf('Version')) !== -1) { - fullVersion = nAgt.substring(verOffset + 8); + try { + fullVersion = navigator.userAgent.split('OPR/')[1].split(' ')[0]; + majorVersion = fullVersion.split('.')[0]; + } catch (e) { + fullVersion = '0.0.0.0'; + majorVersion = 0; } } // In MSIE, the true version is after 'MSIE' in userAgent - else if ((verOffset = nAgt.indexOf('MSIE')) !== -1) { + else if (isIE) { + verOffset = nAgt.indexOf('MSIE'); browserName = 'IE'; fullVersion = nAgt.substring(verOffset + 5); } // In Chrome, the true version is after 'Chrome' - else if ((verOffset = nAgt.indexOf('Chrome')) !== -1) { + 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 ((verOffset = nAgt.indexOf('Safari')) !== -1) { + else if (isSafari) { + verOffset = nAgt.indexOf('Safari'); browserName = 'Safari'; fullVersion = nAgt.substring(verOffset + 7); @@ -76,7 +87,8 @@ } } // In Firefox, the true version is after 'Firefox' - else if ((verOffset = nAgt.indexOf('Firefox')) !== -1) { + else if (isFirefox) { + verOffset = nAgt.indexOf('Firefox'); browserName = 'Firefox'; fullVersion = nAgt.substring(verOffset + 8); } @@ -116,10 +128,112 @@ return { fullVersion: fullVersion, version: majorVersion, - name: browserName + 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; + + if (window.webkitRequestFileSystem) { + window.webkitRequestFileSystem( + window.TEMPORARY, 1, + function() { + isPrivate = false; + }, + function(e) { + console.log(e); + isPrivate = true; + } + ); + } else if (window.indexedDB && /Firefox/.test(window.navigator.userAgent)) { + var db; + try { + db = window.indexedDB.open('test'); + } 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'); + } + } + + retry( + function isDone() { + return typeof isPrivate !== 'undefined' ? true : false; + }, + function next(isTimeout) { + callback(isPrivate); + } + ); + } + var isMobile = { Android: function() { return navigator.userAgent.match(/Android/i); @@ -165,28 +279,139 @@ } }; - var osName = 'Unknown OS'; + // via: http://jsfiddle.net/ChristianL/AVyND/ + function detectDesktopOS() { + var unknown = '-'; - if (isMobile.any()) { - osName = isMobile.getOsName(); - } else { - if (navigator.appVersion.indexOf('Win') !== -1) { - osName = 'Windows'; - } + var nVer = navigator.appVersion; + var nAgt = navigator.userAgent; - if (navigator.appVersion.indexOf('Mac') !== -1) { - osName = 'MacOS'; + var os = unknown; + var clientStrings = [{ + 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 id in clientStrings) { + var cs = clientStrings[id]; + if (cs.r.test(nAgt)) { + os = cs.s; + break; + } } - if (navigator.appVersion.indexOf('X11') !== -1) { - osName = 'UNIX'; + var osVersion = unknown; + + if (/Windows/.test(os)) { + osVersion = /Windows (.*)/.exec(os)[1]; + os = 'Windows'; } - if (navigator.appVersion.indexOf('Linux') !== -1) { - osName = 'Linux'; + switch (os) { + case 'Mac OS X': + osVersion = /Mac OS X (10[\.\_\d]+)/.exec(nAgt)[1]; + break; + + case 'Android': + osVersion = /Android ([\.\_\d]+)/.exec(nAgt)[1]; + break; + + case 'iOS': + osVersion = /OS (\d+)_(\d+)_?(\d+)?/.exec(nVer); + osVersion = osVersion[1] + '.' + osVersion[2] + '.' + (osVersion[3] | 0); + break; } + + return { + osName: os, + osVersion: osVersion + }; } + var osName = 'Unknown OS'; + var osVersion = 'Unknown OS Version'; + + if (isMobile.any()) { + osName = isMobile.getOsName(); + } else { + var osInfo = detectDesktopOS(); + osName = osInfo.osName; + osVersion = osInfo.osVersion; + } var isCanvasSupportsStreamCapturing = false; var isVideoSupportsStreamCapturing = false; @@ -489,6 +714,10 @@ // 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; @@ -605,7 +834,16 @@ DetectRTC.isGetUserMediaSupported = isGetUserMediaSupported; // ----------- - DetectRTC.osName = osName; // "osName" is defined in "detectOSName.js" + DetectRTC.osName = osName; + DetectRTC.osVersion = osVersion; + + var displayResolution = ''; + if (screen.width) { + var width = (screen.width) ? screen.width : ''; + var height = (screen.height) ? screen.height : ''; + displayResolution += '' + width + ' x ' + height; + } + DetectRTC.displayResolution = displayResolution; // ---------- DetectRTC.isCanvasSupportsStreamCapturing = isCanvasSupportsStreamCapturing; diff --git a/DetectRTC.min.js b/DetectRTC.min.js index ccfa4fc..00e69e3 100644 --- a/DetectRTC.min.js +++ b/DetectRTC.min.js @@ -1,3 +1,3 @@ -// Last time updated at Friday, January 1st, 2016, 5:04:28 PM +// Last time updated at Saturday, January 2nd, 2016, 2:59:44 PM -!function(){"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=parseInt(navigator.userAgent.match(/Edge\/(\d+).(\d+)$/)[2],10).toString()),-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){DetectRTC.isWebRTCSupported&&(DetectRTC.isORTCSupported||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})/,match=ipRegex.exec(candidate);if(!match)return void console.warn("Could not match IP address in",candidate);var ipAddress=match[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}if(RTCPeerConnection){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){if(canEnumerate){if(!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)return void(callback&&callback());MediaDevices=[],audioInputDevices=[],audioOutputDevices=[],videoInputDevices=[],navigator.enumerateDevices(function(devices){devices.forEach(function(_device){var device={};for(var d in _device)device[d]=_device[d];"audio"===device.kind&&(device.kind="audioinput"),"video"===device.kind&&(device.kind="videoinput");var skip;MediaDevices.forEach(function(d){d.id===device.id&&d.kind===device.kind&&(skip=!0)}),skip||(device.deviceId||(device.deviceId=device.id),device.id||(device.id=device.deviceId),device.label?("videoinput"!==device.kind||isWebsiteHasWebcamPermissions||(isWebsiteHasWebcamPermissions=!0),"audioinput"!==device.kind||isWebsiteHasMicrophonePermissions||(isWebsiteHasMicrophonePermissions=!0)):(device.label="Please invoke getUserMedia once.","https:"!==location.protocol&&(device.label="HTTPs is required to get label of this "+device.kind+" device.")),"audioinput"===device.kind&&(hasMicrophone=!0,audioInputDevices.push(device)),"audiooutput"===device.kind&&(hasSpeakers=!0,audioOutputDevices.push(device)),"videoinput"===device.kind&&(hasWebcam=!0,videoInputDevices.push(device)),MediaDevices.push(device))}),"undefined"!=typeof DetectRTC&&(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),callback&&callback()})}}var navigator=window.navigator;"undefined"!=typeof navigator?("undefined"!=typeof navigator.webkitGetUserMedia&&(navigator.getUserMedia=navigator.webkitGetUserMedia),"undefined"!=typeof navigator.mozGetUserMedia&&(navigator.getUserMedia=navigator.mozGetUserMedia)):navigator={getUserMedia:function(){},userAgent:"Fake/5.0 (FakeOS) AppleWebKit/123 (KHTML, like Gecko) Fake/12.3.4567.89 Fake/123.45"};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){!isCanvasSupportsStreamCapturing&&item in document.createElement("canvas")&&(isCanvasSupportsStreamCapturing=!0),!isVideoSupportsStreamCapturing&&item in document.createElement("video")&&(isVideoSupportsStreamCapturing=!0)});var MediaDevices=[],audioInputDevices=[],audioOutputDevices=[],videoInputDevices=[];navigator.mediaDevices&&navigator.mediaDevices.enumerateDevices&&(navigator.enumerateDevices=function(callback){navigator.mediaDevices.enumerateDevices().then(callback)});var canEnumerate=!1;"undefined"!=typeof MediaStreamTrack&&"getSources"in MediaStreamTrack?canEnumerate=!0:navigator.mediaDevices&&navigator.mediaDevices.enumerateDevices&&(canEnumerate=!0);var hasMicrophone=!1,hasSpeakers=!1,hasWebcam=!1,isWebsiteHasMicrophonePermissions=!1,isWebsiteHasWebcamPermissions=!1;checkDeviceSupport();var DetectRTC=window.DetectRTC||{};DetectRTC.browser=getBrowserInfo(),DetectRTC.browser["is"+DetectRTC.browser.name]=!0;var isWebRTCSupported=(!!(window.process&&"object"==typeof window.process&&window.process.versions&&window.process.versions["node-webkit"]),!1);["RTCPeerConnection","webkitRTCPeerConnection","mozRTCPeerConnection","RTCIceGatherer"].forEach(function(item){isWebRTCSupported||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),"https:"!==location.protocol&&(isScreenCapturingSupported=!1),DetectRTC.isScreenCapturingSupported=isScreenCapturingSupported;var webAudio={isSupported:!1,isCreateMediaStreamSourceSupported:!1};["AudioContext","webkitAudioContext","mozAudioContext","msAudioContext"].forEach(function(item){webAudio.isSupported||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.close(),websocket=null},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>=46&&"https:"!==location.protocol&&(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,DetectRTC.isWebsiteHasWebcamPermissions=isWebsiteHasWebcamPermissions,DetectRTC.isWebsiteHasMicrophonePermissions=isWebsiteHasMicrophonePermissions,DetectRTC.audioInputDevices=audioInputDevices,DetectRTC.audioOutputDevices=audioOutputDevices,DetectRTC.videoInputDevices=videoInputDevices;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;var isApplyConstraintsSupported=!1;"undefined"!=typeof MediaStreamTrack&&"applyConstraints"in MediaStreamTrack.prototype&&(isApplyConstraintsSupported=!0),DetectRTC.isApplyConstraintsSupported=isApplyConstraintsSupported;var isMultiMonitorScreenCapturingSupported=!1;DetectRTC.browser.isFirefox&&DetectRTC.browser.version>=43&&(isMultiMonitorScreenCapturingSupported=!0),DetectRTC.isMultiMonitorScreenCapturingSupported=isMultiMonitorScreenCapturingSupported,window.DetectRTC=DetectRTC}(); \ No newline at end of file +!function(){"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);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}}else isIE?(verOffset=nAgt.indexOf("MSIE"),browserName="IE",fullVersion=nAgt.substring(verOffset+5)):isChrome?(verOffset=nAgt.indexOf("Chrome"),browserName="Chrome",fullVersion=nAgt.substring(verOffset+7)):isSafari?(verOffset=nAgt.indexOf("Safari"),browserName="Safari",fullVersion=nAgt.substring(verOffset+7),-1!==(verOffset=nAgt.indexOf("Version"))&&(fullVersion=nAgt.substring(verOffset+8))):isFirefox?(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));return isEdge&&(browserName="Edge",fullVersion=parseInt(navigator.userAgent.match(/Edge\/(\d+).(\d+)$/)[2],10).toString()),-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,isPrivateBrowsing:!1}}function retry(isDone,next){var currentTrial=0,maxRetry=50,isTimeout=!1,id=window.setInterval(function(){isDone()&&(window.clearInterval(id),next(isTimeout)),currentTrial++>maxRetry&&(window.clearInterval(id),isTimeout=!0,next(isTimeout))},10)}function isIE10OrLater(userAgent){var ua=userAgent.toLowerCase();if(0===ua.indexOf("msie")&&0===ua.indexOf("trident"))return!1;var match=/(?:msie|rv:)\s?([\d\.]+)/.exec(ua);return match&&parseInt(match[1],10)>=10?!0:!1}function detectPrivateMode(callback){var isPrivate;if(window.webkitRequestFileSystem)window.webkitRequestFileSystem(window.TEMPORARY,1,function(){isPrivate=!1},function(e){console.log(e),isPrivate=!0});else if(window.indexedDB&&/Firefox/.test(window.navigator.userAgent)){var db;try{db=window.indexedDB.open("test")}catch(e){isPrivate=!0}"undefined"==typeof isPrivate&&retry(function(){return"done"===db.readyState?!0:!1},function(isTimeout){isTimeout||(isPrivate=db.result?!1:!0)})}else if(isIE10OrLater(window.navigator.userAgent)){isPrivate=!1;try{window.indexedDB||(isPrivate=!0)}catch(e){isPrivate=!0}}else if(window.localStorage&&/Safari/.test(window.navigator.userAgent)){try{window.localStorage.setItem("test",1)}catch(e){isPrivate=!0}"undefined"==typeof isPrivate&&(isPrivate=!1,window.localStorage.removeItem("test"))}retry(function(){return"undefined"!=typeof isPrivate?!0:!1},function(isTimeout){callback(isPrivate)})}function detectDesktopOS(){var unknown="-",nVer=navigator.appVersion,nAgt=navigator.userAgent,os=unknown,clientStrings=[{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 id in clientStrings){var cs=clientStrings[id];if(cs.r.test(nAgt)){os=cs.s;break}}var osVersion=unknown;switch(/Windows/.test(os)&&(osVersion=/Windows (.*)/.exec(os)[1],os="Windows"),os){case"Mac OS X":osVersion=/Mac OS X (10[\.\_\d]+)/.exec(nAgt)[1];break;case"Android":osVersion=/Android ([\.\_\d]+)/.exec(nAgt)[1];break;case"iOS":osVersion=/OS (\d+)_(\d+)_?(\d+)?/.exec(nVer),osVersion=osVersion[1]+"."+osVersion[2]+"."+(0|osVersion[3])}return{osName:os,osVersion:osVersion}}function DetectLocalIPAddress(callback){DetectRTC.isWebRTCSupported&&(DetectRTC.isORTCSupported||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})/,match=ipRegex.exec(candidate);if(!match)return void console.warn("Could not match IP address in",candidate);var ipAddress=match[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}if(RTCPeerConnection){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){if(canEnumerate){if(!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)return void(callback&&callback());MediaDevices=[],audioInputDevices=[],audioOutputDevices=[],videoInputDevices=[],navigator.enumerateDevices(function(devices){devices.forEach(function(_device){var device={};for(var d in _device)device[d]=_device[d];"audio"===device.kind&&(device.kind="audioinput"),"video"===device.kind&&(device.kind="videoinput");var skip;MediaDevices.forEach(function(d){d.id===device.id&&d.kind===device.kind&&(skip=!0)}),skip||(device.deviceId||(device.deviceId=device.id),device.id||(device.id=device.deviceId),device.label?("videoinput"!==device.kind||isWebsiteHasWebcamPermissions||(isWebsiteHasWebcamPermissions=!0),"audioinput"!==device.kind||isWebsiteHasMicrophonePermissions||(isWebsiteHasMicrophonePermissions=!0)):(device.label="Please invoke getUserMedia once.","https:"!==location.protocol&&(device.label="HTTPs is required to get label of this "+device.kind+" device.")),"audioinput"===device.kind&&(hasMicrophone=!0,audioInputDevices.push(device)),"audiooutput"===device.kind&&(hasSpeakers=!0,audioOutputDevices.push(device)),"videoinput"===device.kind&&(hasWebcam=!0,videoInputDevices.push(device)),MediaDevices.push(device))}),"undefined"!=typeof DetectRTC&&(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),callback&&callback()})}}var navigator=window.navigator;"undefined"!=typeof navigator?("undefined"!=typeof navigator.webkitGetUserMedia&&(navigator.getUserMedia=navigator.webkitGetUserMedia),"undefined"!=typeof navigator.mozGetUserMedia&&(navigator.getUserMedia=navigator.mozGetUserMedia)):navigator={getUserMedia:function(){},userAgent:"Fake/5.0 (FakeOS) AppleWebKit/123 (KHTML, like Gecko) Fake/12.3.4567.89 Fake/123.45"};var isMobileDevice=!!navigator.userAgent.match(/Android|iPhone|iPad|iPod|BlackBerry|IEMobile/i),isEdge=!(-1===navigator.userAgent.indexOf("Edge")||!navigator.msSaveOrOpenBlob&&!navigator.msSaveBlob),isOpera=!!window.opera||navigator.userAgent.indexOf(" OPR/")>=0,isFirefox="undefined"!=typeof window.InstallTrigger,isSafari=Object.prototype.toString.call(window.HTMLElement).indexOf("Constructor")>0,isChrome=!!window.chrome&&!isOpera,isIE=!!document.documentMode&&!isEdge,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",osVersion="Unknown OS Version";if(isMobile.any())osName=isMobile.getOsName();else{var osInfo=detectDesktopOS();osName=osInfo.osName,osVersion=osInfo.osVersion}var isCanvasSupportsStreamCapturing=!1,isVideoSupportsStreamCapturing=!1;["captureStream","mozCaptureStream","webkitCaptureStream"].forEach(function(item){!isCanvasSupportsStreamCapturing&&item in document.createElement("canvas")&&(isCanvasSupportsStreamCapturing=!0),!isVideoSupportsStreamCapturing&&item in document.createElement("video")&&(isVideoSupportsStreamCapturing=!0)});var MediaDevices=[],audioInputDevices=[],audioOutputDevices=[],videoInputDevices=[];navigator.mediaDevices&&navigator.mediaDevices.enumerateDevices&&(navigator.enumerateDevices=function(callback){navigator.mediaDevices.enumerateDevices().then(callback)});var canEnumerate=!1;"undefined"!=typeof MediaStreamTrack&&"getSources"in MediaStreamTrack?canEnumerate=!0:navigator.mediaDevices&&navigator.mediaDevices.enumerateDevices&&(canEnumerate=!0);var hasMicrophone=!1,hasSpeakers=!1,hasWebcam=!1,isWebsiteHasMicrophonePermissions=!1,isWebsiteHasWebcamPermissions=!1;checkDeviceSupport();var DetectRTC=window.DetectRTC||{};DetectRTC.browser=getBrowserInfo(),detectPrivateMode(function(isPrivateBrowsing){DetectRTC.browser.isPrivateBrowsing=!!isPrivateBrowsing}),DetectRTC.browser["is"+DetectRTC.browser.name]=!0;var isWebRTCSupported=(!!(window.process&&"object"==typeof window.process&&window.process.versions&&window.process.versions["node-webkit"]),!1);["RTCPeerConnection","webkitRTCPeerConnection","mozRTCPeerConnection","RTCIceGatherer"].forEach(function(item){isWebRTCSupported||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),"https:"!==location.protocol&&(isScreenCapturingSupported=!1),DetectRTC.isScreenCapturingSupported=isScreenCapturingSupported;var webAudio={isSupported:!1,isCreateMediaStreamSourceSupported:!1};["AudioContext","webkitAudioContext","mozAudioContext","msAudioContext"].forEach(function(item){webAudio.isSupported||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.close(),websocket=null},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>=46&&"https:"!==location.protocol&&(DetectRTC.isGetUserMediaSupported="Requires HTTPs"),DetectRTC.isGetUserMediaSupported=isGetUserMediaSupported,DetectRTC.osName=osName,DetectRTC.osVersion=osVersion;var displayResolution="";if(screen.width){var width=screen.width?screen.width:"",height=screen.height?screen.height:"";displayResolution+=""+width+" x "+height}DetectRTC.displayResolution=displayResolution,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,DetectRTC.isWebsiteHasWebcamPermissions=isWebsiteHasWebcamPermissions,DetectRTC.isWebsiteHasMicrophonePermissions=isWebsiteHasMicrophonePermissions,DetectRTC.audioInputDevices=audioInputDevices,DetectRTC.audioOutputDevices=audioOutputDevices,DetectRTC.videoInputDevices=videoInputDevices;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;var isApplyConstraintsSupported=!1;"undefined"!=typeof MediaStreamTrack&&"applyConstraints"in MediaStreamTrack.prototype&&(isApplyConstraintsSupported=!0),DetectRTC.isApplyConstraintsSupported=isApplyConstraintsSupported;var isMultiMonitorScreenCapturingSupported=!1;DetectRTC.browser.isFirefox&&DetectRTC.browser.version>=43&&(isMultiMonitorScreenCapturingSupported=!0),DetectRTC.isMultiMonitorScreenCapturingSupported=isMultiMonitorScreenCapturingSupported,window.DetectRTC=DetectRTC}(); \ No newline at end of file diff --git a/Gruntfile.js b/Gruntfile.js index b9f0aec..27e2aaa 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -22,7 +22,9 @@ module.exports = function(grunt) { 'dev/head.js', 'dev/common.js', 'dev/getBrowserInfo.js', + 'dev/detectPrivateBrowsing.js', 'dev/isMobile.js', + 'dev/detectDesktopOS.js', 'dev/detectOSName.js', 'dev/detectCaptureStream.js', 'dev/DetectLocalIPAddress.js', @@ -54,6 +56,7 @@ module.exports = function(grunt) { }, jsbeautifier: { files: [ + 'dev/*.js', 'DetectRTC.js', 'Gruntfile.js' ], diff --git a/README.md b/README.md index 60745ec..c4fbcb0 100644 --- a/README.md +++ b/README.md @@ -69,17 +69,17 @@ http://localhost:9001 ```javascript DetectRTC.load(function() { - // DetectRTC.hasWebcam (has webcam device!) - // DetectRTC.hasMicrophone (has microphone device!) - // DetectRTC.hasSpeakers (has speakers!) - // DetectRTC.isScreenCapturingSupported - // DetectRTC.isSctpDataChannelsSupported - // DetectRTC.isRtpDataChannelsSupported - // DetectRTC.isAudioContextSupported - // DetectRTC.isWebRTCSupported - // DetectRTC.isDesktopCapturingSupported - // DetectRTC.isMobileDevice - // DetectRTC.isWebSocketsSupported + DetectRTC.hasWebcam (has webcam device!) + DetectRTC.hasMicrophone (has microphone device!) + DetectRTC.hasSpeakers (has speakers!) + DetectRTC.isScreenCapturingSupported + DetectRTC.isSctpDataChannelsSupported + DetectRTC.isRtpDataChannelsSupported + DetectRTC.isAudioContextSupported + DetectRTC.isWebRTCSupported + DetectRTC.isDesktopCapturingSupported + DetectRTC.isMobileDevice + DetectRTC.isWebSocketsSupported DetectRTC.isWebsiteHasWebcamPermissions // getUserMedia allowed for HTTPs domain in Chrome? DetectRTC.isWebsiteHasMicrophonePermissions // getUserMedia allowed for HTTPs domain in Chrome? @@ -88,21 +88,24 @@ DetectRTC.load(function() { DetectRTC.audioOutputDevices // speakers DetectRTC.videoInputDevices // cameras - // DetectRTC.osName + DetectRTC.osName + DetectRTC.osVersion - // DetectRTC.browser.name === 'Edge' || 'Chrome' || 'Firefox' - // DetectRTC.browser.version - // DetectRTC.browser.isChrome - // DetectRTC.browser.isFirefox - // DetectRTC.browser.isOpera - // DetectRTC.browser.isIE - // DetectRTC.browser.isSafari - // DetectRTC.browser.isEdge - - // DetectRTC.isCanvasSupportsStreamCapturing - // DetectRTC.isVideoSupportsStreamCapturing - - // DetectRTC.DetectLocalIPAddress(callback) + DetectRTC.browser.name === 'Edge' || 'Chrome' || 'Firefox' + DetectRTC.browser.version + DetectRTC.browser.isChrome + DetectRTC.browser.isFirefox + DetectRTC.browser.isOpera + DetectRTC.browser.isIE + DetectRTC.browser.isSafari + DetectRTC.browser.isEdge + + DetectRTC.browser.isPrivateBrowsing // incognito or private modes + + DetectRTC.isCanvasSupportsStreamCapturing + DetectRTC.isVideoSupportsStreamCapturing + + DetectRTC.DetectLocalIPAddress(callback) }); ``` diff --git a/bower.json b/bower.json index c34c24f..315dec0 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "detectrtc", - "version": "1.2.4", + "version": "1.2.5", "authors": [ { "name": "Muaz Khan", diff --git a/dev/CheckDeviceSupport.js b/dev/CheckDeviceSupport.js index 5c826a9..c3a0cf7 100644 --- a/dev/CheckDeviceSupport.js +++ b/dev/CheckDeviceSupport.js @@ -16,11 +16,9 @@ if (navigator.mediaDevices && navigator.mediaDevices.enumerateDevices) { var canEnumerate = false; /*global MediaStreamTrack:true */ -if(typeof MediaStreamTrack !== 'undefined' && 'getSources' in MediaStreamTrack) { +if (typeof MediaStreamTrack !== 'undefined' && 'getSources' in MediaStreamTrack) { canEnumerate = true; -} - -else if(navigator.mediaDevices && !!navigator.mediaDevices.enumerateDevices) { +} else if (navigator.mediaDevices && !!navigator.mediaDevices.enumerateDevices) { canEnumerate = true; } @@ -34,7 +32,7 @@ var isWebsiteHasWebcamPermissions = false; // http://dev.w3.org/2011/webrtc/editor/getusermedia.html#mediadevices // todo: switch to enumerateDevices when landed in canary. function checkDeviceSupport(callback) { - if(!canEnumerate) { + if (!canEnumerate) { return; } @@ -98,7 +96,7 @@ function checkDeviceSupport(callback) { if (!device.label) { device.label = 'Please invoke getUserMedia once.'; - if(location.protocol !== 'https:') { + if (location.protocol !== 'https:') { device.label = 'HTTPs is required to get label of this ' + device.kind + ' device.'; } } else { @@ -131,7 +129,7 @@ function checkDeviceSupport(callback) { MediaDevices.push(device); }); - if(typeof DetectRTC !== 'undefined') { + if (typeof DetectRTC !== 'undefined') { // to sync latest outputs DetectRTC.MediaDevices = MediaDevices; DetectRTC.hasMicrophone = hasMicrophone; diff --git a/dev/DetectLocalIPAddress.js b/dev/DetectLocalIPAddress.js index 91149bc..6e2ab10 100644 --- a/dev/DetectLocalIPAddress.js +++ b/dev/DetectLocalIPAddress.js @@ -1,10 +1,10 @@ // via: https://github.com/diafygi/webrtc-ips function DetectLocalIPAddress(callback) { - if(!DetectRTC.isWebRTCSupported) { + if (!DetectRTC.isWebRTCSupported) { return; } - - if(DetectRTC.isORTCSupported) { + + if (DetectRTC.isORTCSupported) { return; } @@ -45,7 +45,7 @@ function getIPs(callback) { if (!RTCPeerConnection) { return; } - + //minimal requirements for data connection var mediaConstraints = { optional: [{ @@ -66,7 +66,7 @@ function getIPs(callback) { }] }; - if(typeof DetectRTC !== 'undefined' && DetectRTC.browser.isFirefox && DetectRTC.browser.version <= 38) { + if (typeof DetectRTC !== 'undefined' && DetectRTC.browser.isFirefox && DetectRTC.browser.version <= 38) { servers[0] = { url: servers[0].urls }; @@ -80,12 +80,12 @@ function getIPs(callback) { //match just the IP address var ipRegex = /([0-9]{1,3}(\.[0-9]{1,3}){3})/; var match = ipRegex.exec(candidate); - if (!match) { + if (!match) { console.warn('Could not match IP address in', candidate); return; } var ipAddress = match[1]; - + //remove duplicates if (ipDuplicates[ipAddress] === undefined) { callback(ipAddress); diff --git a/dev/DetectRTC.js b/dev/DetectRTC.js index 8f788ec..a0ce507 100644 --- a/dev/DetectRTC.js +++ b/dev/DetectRTC.js @@ -4,6 +4,10 @@ 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; @@ -12,13 +16,13 @@ var isNodeWebkit = !!(window.process && (typeof window.process === 'object') && // --------- 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 (isWebRTCSupported) { + return; + } - if(item in window) { - isWebRTCSupported = true; - } + if (item in window) { + isWebRTCSupported = true; + } }); DetectRTC.isWebRTCSupported = isWebRTCSupported; @@ -27,36 +31,35 @@ 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; +if (DetectRTC.browser.isChrome && DetectRTC.browser.version >= 35) { + isScreenCapturingSupported = true; +} else if (DetectRTC.browser.isFirefox && DetectRTC.browser.version >= 34) { + isScreenCapturingSupported = true; } -if(location.protocol !== 'https:') { - isScreenCapturingSupported = false; +if (location.protocol !== 'https:') { + isScreenCapturingSupported = false; } DetectRTC.isScreenCapturingSupported = isScreenCapturingSupported; // --------- Detect if WebAudio API are supported var webAudio = { - isSupported: false, - isCreateMediaStreamSourceSupported: false + isSupported: false, + isCreateMediaStreamSourceSupported: false }; ['AudioContext', 'webkitAudioContext', 'mozAudioContext', 'msAudioContext'].forEach(function(item) { - if (webAudio.isSupported) { + if (webAudio.isSupported) { return; } - if(item in window) { - webAudio.isSupported = true; + if (item in window) { + webAudio.isSupported = true; - if('createMediaStreamSource' in window[item].prototype) { - webAudio.isCreateMediaStreamSourceSupported = true; - } - } + if ('createMediaStreamSource' in window[item].prototype) { + webAudio.isCreateMediaStreamSourceSupported = true; + } + } }); DetectRTC.isAudioContextSupported = webAudio.isSupported; DetectRTC.isCreateMediaStreamSourceSupported = webAudio.isCreateMediaStreamSourceSupported; @@ -64,20 +67,18 @@ DetectRTC.isCreateMediaStreamSourceSupported = webAudio.isCreateMediaStreamSourc // ---------- Detect if SCTP/RTP channels are supported. var isRtpDataChannelsSupported = false; -if(DetectRTC.browser.isChrome && DetectRTC.browser.version > 31) { - isRtpDataChannelsSupported = true; +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; +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; @@ -90,41 +91,49 @@ DetectRTC.isMobileDevice = isMobileDevice; // "isMobileDevice" boolean is define 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.close(); - websocket = null; - }; - websocket.onerror = function() { - DetectRTC.isWebSocketsBlocked = true; - - if(DetectRTC.loadCallback) { - DetectRTC.loadCallback(); - } - }; +if (DetectRTC.isWebSocketsSupported) { + var websocket = new WebSocket('wss://echo.websocket.org:443/'); + websocket.onopen = function() { + DetectRTC.isWebSocketsBlocked = false; + + if (DetectRTC.loadCallback) { + DetectRTC.loadCallback(); + } + websocket.close(); + websocket = null; + }; + websocket.onerror = function() { + DetectRTC.isWebSocketsBlocked = true; + + if (DetectRTC.loadCallback) { + DetectRTC.loadCallback(); + } + }; } // ------ var isGetUserMediaSupported = false; -if(navigator.getUserMedia) { - isGetUserMediaSupported = true; +if (navigator.getUserMedia) { + isGetUserMediaSupported = true; +} else if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) { + isGetUserMediaSupported = true; } -else if(navigator.mediaDevices && navigator.mediaDevices.getUserMedia){ - isGetUserMediaSupported = true; -} -if(DetectRTC.browser.isChrome && DetectRTC.browser.version >= 46 && location.protocol !== 'https:') { - DetectRTC.isGetUserMediaSupported = 'Requires HTTPs'; +if (DetectRTC.browser.isChrome && DetectRTC.browser.version >= 46 && location.protocol !== 'https:') { + DetectRTC.isGetUserMediaSupported = 'Requires HTTPs'; } DetectRTC.isGetUserMediaSupported = isGetUserMediaSupported; // ----------- -DetectRTC.osName = osName; // "osName" is defined in "detectOSName.js" +DetectRTC.osName = osName; +DetectRTC.osVersion = osVersion; + +var displayResolution = ''; +if (screen.width) { + var width = (screen.width) ? screen.width : ''; + var height = (screen.height) ? screen.height : ''; + displayResolution += '' + width + ' x ' + height; +} +DetectRTC.displayResolution = displayResolution; // ---------- DetectRTC.isCanvasSupportsStreamCapturing = isCanvasSupportsStreamCapturing; @@ -154,31 +163,30 @@ DetectRTC.videoInputDevices = videoInputDevices; // ------ var isSetSinkIdSupported = false; -if('setSinkId' in document.createElement('video')) { - isSetSinkIdSupported = true; +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; - } +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; +if (DetectRTC.browser.isFirefox && DetectRTC.browser.version > 38) { + isRemoteStreamProcessingSupported = true; } DetectRTC.isRemoteStreamProcessingSupported = isRemoteStreamProcessingSupported; @@ -186,16 +194,16 @@ DetectRTC.isRemoteStreamProcessingSupported = isRemoteStreamProcessingSupported; var isApplyConstraintsSupported = false; /*global MediaStreamTrack:true */ -if(typeof MediaStreamTrack !== 'undefined' && 'applyConstraints' in MediaStreamTrack.prototype) { - isApplyConstraintsSupported = 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; +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; diff --git a/dev/common.js b/dev/common.js index 89eb46e..a37ed45 100644 --- a/dev/common.js +++ b/dev/common.js @@ -11,7 +11,7 @@ if (typeof navigator !== 'undefined') { } } else { navigator = { - getUserMedia: function() { }, + getUserMedia: function() {}, userAgent: 'Fake/5.0 (FakeOS) AppleWebKit/123 (KHTML, like Gecko) Fake/12.3.4567.89 Fake/123.45' }; } diff --git a/dev/detectCaptureStream.js b/dev/detectCaptureStream.js index 71b7ede..e727365 100644 --- a/dev/detectCaptureStream.js +++ b/dev/detectCaptureStream.js @@ -1,12 +1,11 @@ - var isCanvasSupportsStreamCapturing = false; var isVideoSupportsStreamCapturing = false; ['captureStream', 'mozCaptureStream', 'webkitCaptureStream'].forEach(function(item) { - if(!isCanvasSupportsStreamCapturing && item in document.createElement('canvas')) { + if (!isCanvasSupportsStreamCapturing && item in document.createElement('canvas')) { isCanvasSupportsStreamCapturing = true; } - if(!isVideoSupportsStreamCapturing && item in document.createElement('video')) { + if (!isVideoSupportsStreamCapturing && item in document.createElement('video')) { isVideoSupportsStreamCapturing = true; } }); diff --git a/dev/detectDesktopOS.js b/dev/detectDesktopOS.js new file mode 100644 index 0000000..84ce71d --- /dev/null +++ b/dev/detectDesktopOS.js @@ -0,0 +1,122 @@ +// via: http://jsfiddle.net/ChristianL/AVyND/ +function detectDesktopOS() { + var unknown = '-'; + + var nVer = navigator.appVersion; + var nAgt = navigator.userAgent; + + var os = unknown; + var clientStrings = [{ + 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 id in clientStrings) { + var cs = clientStrings[id]; + if (cs.r.test(nAgt)) { + os = cs.s; + break; + } + } + + var osVersion = unknown; + + if (/Windows/.test(os)) { + osVersion = /Windows (.*)/.exec(os)[1]; + os = 'Windows'; + } + + switch (os) { + case 'Mac OS X': + osVersion = /Mac OS X (10[\.\_\d]+)/.exec(nAgt)[1]; + break; + + case 'Android': + osVersion = /Android ([\.\_\d]+)/.exec(nAgt)[1]; + break; + + case 'iOS': + osVersion = /OS (\d+)_(\d+)_?(\d+)?/.exec(nVer); + osVersion = osVersion[1] + '.' + osVersion[2] + '.' + (osVersion[3] | 0); + break; + } + + return { + osName: os, + osVersion: osVersion + }; +} diff --git a/dev/detectOSName.js b/dev/detectOSName.js index 97a3a95..94ec9fd 100644 --- a/dev/detectOSName.js +++ b/dev/detectOSName.js @@ -1,21 +1,10 @@ var osName = 'Unknown OS'; - -if(isMobile.any()) { - osName = isMobile.getOsName();} -else { - if (navigator.appVersion.indexOf('Win') !== -1) { - osName = 'Windows'; - } - - if (navigator.appVersion.indexOf('Mac') !== -1) { - osName = 'MacOS'; - } - - if (navigator.appVersion.indexOf('X11') !== -1) { - osName = 'UNIX'; - } - - if (navigator.appVersion.indexOf('Linux') !== -1) { - osName = 'Linux'; - } +var osVersion = 'Unknown OS Version'; + +if (isMobile.any()) { + osName = isMobile.getOsName(); +} else { + var osInfo = detectDesktopOS(); + osName = osInfo.osName; + osVersion = osInfo.osVersion; } diff --git a/dev/detectPrivateBrowsing.js b/dev/detectPrivateBrowsing.js new file mode 100644 index 0000000..7af7dce --- /dev/null +++ b/dev/detectPrivateBrowsing.js @@ -0,0 +1,100 @@ +// 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; + + if (window.webkitRequestFileSystem) { + window.webkitRequestFileSystem( + window.TEMPORARY, 1, + function() { + isPrivate = false; + }, + function(e) { + console.log(e); + isPrivate = true; + } + ); + } else if (window.indexedDB && /Firefox/.test(window.navigator.userAgent)) { + var db; + try { + db = window.indexedDB.open('test'); + } 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'); + } + } + + retry( + function isDone() { + return typeof isPrivate !== 'undefined' ? true : false; + }, + function next(isTimeout) { + callback(isPrivate); + } + ); +} diff --git a/dev/getBrowserInfo.js b/dev/getBrowserInfo.js index c96c1dd..c95b5a5 100644 --- a/dev/getBrowserInfo.js +++ b/dev/getBrowserInfo.js @@ -1,6 +1,12 @@ var isMobileDevice = !!navigator.userAgent.match(/Android|iPhone|iPad|iPod|BlackBerry|IEMobile/i); var isEdge = navigator.userAgent.indexOf('Edge') !== -1 && (!!navigator.msSaveOrOpenBlob || !!navigator.msSaveBlob); +var isOpera = !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0; +var isFirefox = typeof window.InstallTrigger !== 'undefined'; +var isSafari = Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0; +var isChrome = !!window.chrome && !isOpera; +var isIE = !!document.documentMode && !isEdge; + // this one can also be used: // https://www.websocket.org/js/stuff.js (DetectBrowser.js) @@ -13,26 +19,31 @@ function getBrowserInfo() { var nameOffset, verOffset, ix; // In Opera, the true version is after 'Opera' or after 'Version' - if ((verOffset = nAgt.indexOf('Opera')) !== -1) { + if (isOpera) { browserName = 'Opera'; - fullVersion = nAgt.substring(verOffset + 6); - - if ((verOffset = nAgt.indexOf('Version')) !== -1) { - fullVersion = nAgt.substring(verOffset + 8); + try { + fullVersion = navigator.userAgent.split('OPR/')[1].split(' ')[0]; + majorVersion = fullVersion.split('.')[0]; + } catch (e) { + fullVersion = '0.0.0.0'; + majorVersion = 0; } } // In MSIE, the true version is after 'MSIE' in userAgent - else if ((verOffset = nAgt.indexOf('MSIE')) !== -1) { + else if (isIE) { + verOffset = nAgt.indexOf('MSIE'); browserName = 'IE'; fullVersion = nAgt.substring(verOffset + 5); } // In Chrome, the true version is after 'Chrome' - else if ((verOffset = nAgt.indexOf('Chrome')) !== -1) { + 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 ((verOffset = nAgt.indexOf('Safari')) !== -1) { + else if (isSafari) { + verOffset = nAgt.indexOf('Safari'); browserName = 'Safari'; fullVersion = nAgt.substring(verOffset + 7); @@ -41,7 +52,8 @@ function getBrowserInfo() { } } // In Firefox, the true version is after 'Firefox' - else if ((verOffset = nAgt.indexOf('Firefox')) !== -1) { + else if (isFirefox) { + verOffset = nAgt.indexOf('Firefox'); browserName = 'Firefox'; fullVersion = nAgt.substring(verOffset + 8); } @@ -81,6 +93,7 @@ function getBrowserInfo() { return { fullVersion: fullVersion, version: majorVersion, - name: browserName + name: browserName, + isPrivateBrowsing: false }; } diff --git a/dev/head.js b/dev/head.js index 3962a79..b42875e 100644 --- a/dev/head.js +++ b/dev/head.js @@ -12,4 +12,4 @@ (function() { -'use strict'; + 'use strict'; diff --git a/dev/isMobile.js b/dev/isMobile.js index 1fd05a3..d61a233 100644 --- a/dev/isMobile.js +++ b/dev/isMobile.js @@ -19,23 +19,23 @@ var isMobile = { }, getOsName: function() { var osName = 'Unknown OS'; - if(isMobile.Android()) { + if (isMobile.Android()) { osName = 'Android'; } - if(isMobile.BlackBerry()) { + if (isMobile.BlackBerry()) { osName = 'BlackBerry'; } - if(isMobile.iOS()) { + if (isMobile.iOS()) { osName = 'iOS'; } - if(isMobile.Opera()) { + if (isMobile.Opera()) { osName = 'Opera Mini'; } - if(isMobile.Windows()) { + if (isMobile.Windows()) { osName = 'Windows'; } diff --git a/index.html b/index.html index 6e0a98c..20645af 100755 --- a/index.html +++ b/index.html @@ -49,6 +49,22 @@ display: inline-block; width: 8em; } + + .info-div { + display: inline-block; + vertical-align: middle; + background-repeat: no-repeat; + background-image: url(https://i.imgur.com/tnMN9tG.png?1); + background-position: center center; + width: 32px; + height: 32px; + } + + .inline-pre { + margin: 0; + padding: 0; + border: 0; + } + + + + + + - +

@@ -99,11 +121,15 @@

+ + + +
-

Detect WebRTC!

+

DetectRTC!

@@ -115,7 +141,7 @@

Detect WebRTC!

function appendTR(firstValue, secondValue) { var tr = document.createElement('tr'); - tr.innerHTML = '' + firstValue + '' + secondValue + ''; + tr.innerHTML = '' + firstValue + '' + secondValue + ''; browserFeaturesTable.appendChild(tr); } @@ -123,26 +149,72 @@

Detect WebRTC!

return value == true ? 'Yep' : value == false ? 'Nope' : value; } + function getInfoDiv(id) { + return '
'; + } + + var output = ''; + DetectRTC.load(function() { browserFeaturesTable.innerHTML = ''; - appendTR('System has Speakers?', printVal(DetectRTC.hasSpeakers)); - appendTR('System has Microphone?', printVal(DetectRTC.hasMicrophone)); - appendTR('System has Webcam?', printVal(DetectRTC.hasWebcam)); + appendTR('Operating System', printVal(DetectRTC.osName) + '
' + printVal(DetectRTC.osVersion)); + appendTR('Browser', printVal(DetectRTC.browser.name) + '
' + printVal(DetectRTC.browser.fullVersion) + '
Private browsing? ' + printVal(DetectRTC.browser.isPrivateBrowsing)); + + appendTR('Display resolutions', printVal(DetectRTC.displayResolution)); + + output = printVal(DetectRTC.hasSpeakers); + if(DetectRTC.audioOutputDevices.length) { + output += '
Found speaker devices: ' + DetectRTC.audioOutputDevices.length; + + var labels = []; + DetectRTC.audioOutputDevices.forEach(function(device) { + labels.push(device.label); + }); + + output += '
' + labels.join('
') + '
'; + } + appendTR('System has Speakers?', output); + + output = printVal(DetectRTC.hasMicrophone); + if(DetectRTC.audioInputDevices.length) { + output += '
Found microphone devices: ' + DetectRTC.audioInputDevices.length; + + var labels = []; + DetectRTC.audioInputDevices.forEach(function(device) { + labels.push(device.label); + }); + + output += '
' + labels.join('
') + '
'; + } + appendTR('System has Microphone?', output); + + output = printVal(DetectRTC.hasWebcam); + if(DetectRTC.videoInputDevices.length) { + output += '
Found webcam devices: ' + DetectRTC.videoInputDevices.length; + + var labels = []; + DetectRTC.videoInputDevices.forEach(function(device) { + labels.push(device.label); + }); + + output += '
' + labels.join('
') + '
'; + } + appendTR('System has Webcam?', output); appendTR('Website has webcam permissions?', printVal(DetectRTC.isWebsiteHasWebcamPermissions)); appendTR('Website has mcirophone permissions?', printVal(DetectRTC.isWebsiteHasMicrophonePermissions)); appendTR('Browser allows getUserMedia on this page?', printVal(DetectRTC.isGetUserMediaSupported)); - appendTR('Can you change output audio devices?', printVal(DetectRTC.isSetSinkIdSupported)); + appendTR('Can you change output audio devices?' + getInfoDiv('infoIcon-set-sink-id'), printVal(DetectRTC.isSetSinkIdSupported)); - appendTR('Can you change camera resolutions without making new getUserMedia request?', printVal(DetectRTC.isApplyConstraintsSupported)); + appendTR('Can you change camera resolutions without making new getUserMedia request?' + getInfoDiv('infoIcon-apply-constraints'), printVal(DetectRTC.isApplyConstraintsSupported)); appendTR('Browser Supports WebRTC (Either 1.0 or 1.1)?', printVal(DetectRTC.isWebRTCSupported)); appendTR('Browser Supports ORTC (WebRTC 1.1)?', printVal(DetectRTC.isORTCSupported)); - appendTR('Can you replace tracks without renegotiating peers?', printVal(DetectRTC.isRTPSenderReplaceTracksSupported)); + appendTR('Can you replace tracks without renegotiating peers?' + getInfoDiv('infoIcon-replace-tracks'), printVal(DetectRTC.isRTPSenderReplaceTracksSupported)); appendTR('Can your browser record remote audio or process remote audio stream in WebAudio API?', printVal(DetectRTC.isRemoteStreamProcessingSupported)); @@ -159,9 +231,7 @@

Detect WebRTC!

appendTR('Is it a mobile device?', printVal(DetectRTC.isMobileDevice)); appendTR('Browser Supports WebSockets?', printVal(DetectRTC.isWebSocketsSupported)); - - document.getElementById('welcome').innerHTML = DetectRTC.osName + ': ' + DetectRTC.browser.name + ' (version: ' + DetectRTC.browser.version + ')'; - + var rightSide = ''; // you can even use "DetectRTC.audioInputDevices", "audioOutputDevices" and "videoInputDevices" @@ -184,6 +254,7 @@

Detect WebRTC!

appendTR('Is Browser Supports Video Capturing from Canvas?', printVal(DetectRTC.isVideoSupportsStreamCapturing)); appendTR('Is Browser Supports Stream Capturing from Video?', printVal(DetectRTC.isVideoSupportsStreamCapturing)); + /* DetectRTC.DetectLocalIPAddress(function(ipAddress) { if (ipAddress.indexOf('Local') !== -1) { appendTR('Your Local IP Address', ipAddress); @@ -191,6 +262,69 @@

Detect WebRTC!

appendTR('Your Public IP Address', ipAddress); } }); + */ + + document.getElementById('infoIcon-set-sink-id').onclick = function() { + var pre = this.parentNode.querySelector('pre'); + if(pre) { + pre.parentNode.removeChild(pre); + return; + } + + pre = document.createElement('pre'); + pre.className = 'sh_javascript inline-pre'; + pre.innerHTML += '\ +var secondarySpeakers = DetectRTC.audioInputDevices[1];
\ +if(secondarySpeakers) {
\ + videoElement.setSinkId(secondarySpeakers.deviceId);
\ +}'; + this.parentNode.appendChild(pre); + pre.focus(); + sh_highlightDocument(); + }; + + document.getElementById('infoIcon-apply-constraints').onclick = function() { + var pre = this.parentNode.querySelector('pre'); + if(pre) { + pre.parentNode.removeChild(pre); + return; + } + + pre = document.createElement('pre'); + pre.className = 'sh_javascript inline-pre'; + pre.innerHTML += '\ +var secondaryCamera = DetectRTC.videoInputDevices[1];
\ +if(secondaryCamera) {
\ + var videoConstraints = {
\ + deviceId: secondaryCamera.deviceId
\ + };
\ +
\ + oldMediaStream.getVideoTracks().forEach(function(track) {
\ + track.applyConstraints(videoConstraints);
\ + });
\ +}'; + this.parentNode.appendChild(pre); + pre.focus(); + sh_highlightDocument(); + }; + + document.getElementById('infoIcon-replace-tracks').onclick = function() { + var pre = this.parentNode.querySelector('pre'); + if(pre) { + pre.parentNode.removeChild(pre); + return; + } + + pre = document.createElement('pre'); + pre.className = 'sh_javascript inline-pre'; + pre.innerHTML += '\ +var newTrack = newMediaStream.getVideoTracks()[0];
\ +var rtpSenders = rtcPeerConnection.getSenders()[0];
\ +rtpSenders.replaceTrack(newTrack);'; + this.parentNode.appendChild(pre); + pre.focus(); + sh_highlightDocument(); + }; }); document.getElementById('save').onclick = function() { @@ -289,43 +423,50 @@

Feedback

How to use DetectRTC?

-
+                
 <script src="https://cdn.WebRTC-Experiment.com/DetectRTC.js"></script>
 
-
+                
 DetectRTC.load(function() {
-    // DetectRTC.hasWebcam (has webcam device!)
-    // DetectRTC.hasMicrophone (has microphone device!)
-    // DetectRTC.isWebsiteHasWebcamPermissions
-    // DetectRTC.isWebsiteHasMicrophonePermissions
-    // DetectRTC.hasSpeakers (has speakers!)
-    // DetectRTC.isScreenCapturingSupported
-    // DetectRTC.isSctpDataChannelsSupported
-    // DetectRTC.isRtpDataChannelsSupported
-    // DetectRTC.isAudioContextSupported
-    // DetectRTC.isWebRTCSupported
-    // DetectRTC.isDesktopCapturingSupported
-    // DetectRTC.isMobileDevice
-    // DetectRTC.isWebSocketsSupported
-
-    // DetectRTC.audioInputDevices       --- microphones
-    // DetectRTC.audioOutputDevices      --- speakers
-    // DetectRTC.videoInputDevices       --- cameras
-    // DetectRTC.MediaDevices            --- all devices
+    DetectRTC.hasWebcam (has webcam device!)
+    DetectRTC.hasMicrophone (has microphone device!)
+    DetectRTC.hasSpeakers (has speakers!)
+    DetectRTC.isScreenCapturingSupported
+    DetectRTC.isSctpDataChannelsSupported
+    DetectRTC.isRtpDataChannelsSupported
+    DetectRTC.isAudioContextSupported
+    DetectRTC.isWebRTCSupported
+    DetectRTC.isDesktopCapturingSupported
+    DetectRTC.isMobileDevice
+    DetectRTC.isWebSocketsSupported
+
+    DetectRTC.isWebsiteHasWebcamPermissions        // getUserMedia allowed for HTTPs domain in Chrome?
+    DetectRTC.isWebsiteHasMicrophonePermissions    // getUserMedia allowed for HTTPs domain in Chrome?
+
+    DetectRTC.audioInputDevices    // microphones
+    DetectRTC.audioOutputDevices   // speakers
+    DetectRTC.videoInputDevices    // cameras
     
-    // DetectRTC.osName
+    DetectRTC.osName
+    DetectRTC.osVersion
     
-    // DetectRTC.browser.name
-    // DetectRTC.browser.version
-    // DetectRTC.browser.isChrome
-    // DetectRTC.browser.isFirefox
-    // DetectRTC.browser.isOpera
-    // DetectRTC.browser.isIE
-    // DetectRTC.browser.isSafari
-
-    // DetectRTC.DetectLocalIPAddress(callback)
+    DetectRTC.browser.name === 'Edge' || 'Chrome' || 'Firefox'
+    DetectRTC.browser.version
+    DetectRTC.browser.isChrome
+    DetectRTC.browser.isFirefox
+    DetectRTC.browser.isOpera
+    DetectRTC.browser.isIE
+    DetectRTC.browser.isSafari
+    DetectRTC.browser.isEdge
+
+    DetectRTC.browser.isPrivateBrowsing // incognito or private modes
+
+    DetectRTC.isCanvasSupportsStreamCapturing
+    DetectRTC.isVideoSupportsStreamCapturing
+
+    DetectRTC.DetectLocalIPAddress(callback)
 });
 
diff --git a/package.json b/package.json index 21b5ed1..6a86e91 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "detectrtc", "preferGlobal": true, - "version": "1.2.4", + "version": "1.2.5", "author": { "name": "Muaz Khan", "email": "muazkh@gmail.com",