123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514 |
- import { getLogger } from 'jitsi-meet-logger';
-
- let browserVersion; // eslint-disable-line prefer-const
-
- let currentBrowser;
-
- const logger = getLogger(__filename);
-
- const RTCBrowserType = {
-
- RTC_BROWSER_CHROME: 'rtc_browser.chrome',
-
- RTC_BROWSER_OPERA: 'rtc_browser.opera',
-
- RTC_BROWSER_FIREFOX: 'rtc_browser.firefox',
-
- RTC_BROWSER_IEXPLORER: 'rtc_browser.iexplorer',
-
- RTC_BROWSER_EDGE: 'rtc_browser.edge',
-
- RTC_BROWSER_SAFARI: 'rtc_browser.safari',
-
- RTC_BROWSER_NWJS: 'rtc_browser.nwjs',
-
- RTC_BROWSER_ELECTRON: 'rtc_browser.electron',
-
- RTC_BROWSER_REACT_NATIVE: 'rtc_browser.react-native',
-
- /**
- * Tells whether or not the <tt>MediaStream/tt> is removed from
- * the <tt>PeerConnection</tt> and disposed on video mute (in order to turn
- * off the camera device).
- * @return {boolean} <tt>true</tt> if the current browser supports this
- * strategy or <tt>false</tt> otherwise.
- */
- doesVideoMuteByStreamRemove() {
- return !(RTCBrowserType.isFirefox() || RTCBrowserType.isEdge());
- },
-
- /**
- * Gets current browser type.
- * @returns {string}
- */
- getBrowserType() {
- return currentBrowser;
- },
-
- /**
- * Gets current browser name, split from the type.
- * @returns {string}
- */
- getBrowserName() {
- const isAndroid = navigator.userAgent.indexOf('Android') !== -1;
-
- if (isAndroid) {
- return 'android';
- }
-
- return currentBrowser.split('rtc_browser.')[1];
- },
-
- /**
- * Checks if current browser is Chrome.
- * @returns {boolean}
- */
- isChrome() {
- return currentBrowser === RTCBrowserType.RTC_BROWSER_CHROME;
- },
-
- /**
- * Checks if current browser is Opera.
- * @returns {boolean}
- */
- isOpera() {
- return currentBrowser === RTCBrowserType.RTC_BROWSER_OPERA;
- },
-
- /**
- * Checks if current browser is Firefox.
- * @returns {boolean}
- */
- isFirefox() {
- return currentBrowser === RTCBrowserType.RTC_BROWSER_FIREFOX;
- },
-
- /**
- * Checks if current browser is Internet Explorer.
- * @returns {boolean}
- */
- isIExplorer() {
- return currentBrowser === RTCBrowserType.RTC_BROWSER_IEXPLORER;
- },
-
- /**
- * Checks if current browser is Microsoft Edge.
- * @returns {boolean}
- */
- isEdge() {
- return currentBrowser === RTCBrowserType.RTC_BROWSER_EDGE;
- },
-
- /**
- * Checks if current browser is Safari.
- * @returns {boolean}
- */
- isSafari() {
- return currentBrowser === RTCBrowserType.RTC_BROWSER_SAFARI;
- },
-
- /**
- * Checks if current environment is NWJS.
- * @returns {boolean}
- */
- isNWJS() {
- return currentBrowser === RTCBrowserType.RTC_BROWSER_NWJS;
- },
-
- /**
- * Checks if current environment is Electron.
- * @returns {boolean}
- */
- isElectron() {
- return currentBrowser === RTCBrowserType.RTC_BROWSER_ELECTRON;
- },
-
- /**
- * Check whether or not the current browser support peer to peer connections
- * @return {boolean} <tt>true</tt> if p2p is supported or <tt>false</tt>
- * otherwise.
- */
- isP2PSupported() {
- return !RTCBrowserType.isEdge();
- },
-
- /**
- * Checks if current environment is React Native.
- * @returns {boolean}
- */
- isReactNative() {
- return currentBrowser === RTCBrowserType.RTC_BROWSER_REACT_NATIVE;
- },
-
- /**
- * Checks if Temasys RTC plugin is used.
- * @returns {boolean}
- */
- isTemasysPluginUsed() {
- // Temasys do not support Microsoft Edge:
- // http://support.temasys.com.sg/support/solutions/articles/
- // 5000654345-can-the-temasys-webrtc-plugin-be-used-with-microsoft-edge-
- return (
- RTCBrowserType.isSafari()
- || (RTCBrowserType.isIExplorer()
- && RTCBrowserType.getIExplorerVersion() < 12)
- );
- },
-
- /**
- * Returns whether or not the current browser should be using the new
- * getUserMedia flow, which utilizes the adapter shim. This method should
- * be temporary and used while migrating all browsers to use adapter and
- * the new getUserMedia.
- *
- * @returns {boolean}
- */
- usesNewGumFlow() {
- return (RTCBrowserType.isChrome()
- && RTCBrowserType.getChromeVersion() >= 61)
- || RTCBrowserType.isFirefox();
- },
-
- /**
- * Checks if the current browser triggers 'onmute'/'onunmute' events when
- * user's connection is interrupted and the video stops playback.
- * @returns {*|boolean} 'true' if the event is supported or 'false'
- * otherwise.
- */
- isVideoMuteOnConnInterruptedSupported() {
- return RTCBrowserType.isChrome() || RTCBrowserType.isElectron();
- },
-
- /**
- * Returns Firefox version.
- * @returns {number|null}
- */
- getFirefoxVersion() {
- return RTCBrowserType.isFirefox() ? browserVersion : null;
- },
-
- /**
- * Returns Chrome version.
- * @returns {number|null}
- */
- getChromeVersion() {
- return RTCBrowserType.isChrome() ? browserVersion : null;
- },
-
- /**
- * Returns Opera version.
- * @returns {number|null}
- */
- getOperaVersion() {
- return RTCBrowserType.isOpera() ? browserVersion : null;
- },
-
- /**
- * Returns Internet Explorer version.
- *
- * @returns {number|null}
- */
- getIExplorerVersion() {
- return RTCBrowserType.isIExplorer() ? browserVersion : null;
- },
-
- /**
- * Returns Edge version.
- *
- * @returns {number|null}
- */
- getEdgeVersion() {
- return RTCBrowserType.isEdge() ? browserVersion : null;
- },
-
- usesPlanB() {
- return !RTCBrowserType.usesUnifiedPlan();
- },
-
- usesUnifiedPlan() {
- return RTCBrowserType.isFirefox();
- },
-
- /**
- * Checks if the current browser reports upload and download bandwidth
- * statistics.
- * @return {boolean}
- */
- supportsBandwidthStatistics() {
- // FIXME bandwidth stats are currently not implemented for FF on our
- // side, but not sure if not possible ?
- return !RTCBrowserType.isFirefox() && !RTCBrowserType.isEdge();
- },
-
- /**
- * Checks if the current browser supports WebRTC datachannels.
- * @return {boolean}
- */
- supportsDataChannels() {
- // NOTE: Edge does not yet implement DataChannel.
- return !RTCBrowserType.isEdge();
- },
-
- /**
- * Checks if the current browser reports round trip time statistics for
- * the ICE candidate pair.
- * @return {boolean}
- */
- supportsRTTStatistics() {
- // Firefox does not seem to report RTT for ICE candidate pair:
- // eslint-disable-next-line max-len
- // https://www.w3.org/TR/webrtc-stats/#dom-rtcicecandidatepairstats-currentroundtriptime
- // It does report mozRTT for RTP streams, but at the time of this
- // writing it's value does not make sense most of the time
- // (is reported as 1):
- // https://bugzilla.mozilla.org/show_bug.cgi?id=1241066
- // For Chrome and others we rely on 'googRtt'.
- return !RTCBrowserType.isFirefox() && !RTCBrowserType.isEdge();
- },
-
- /**
- * Whether jitsi-meet supports simulcast on the current browser.
- * @returns {boolean}
- */
- supportsSimulcast() {
- return RTCBrowserType.isChrome()
- || RTCBrowserType.isFirefox()
- || RTCBrowserType.isElectron()
- || RTCBrowserType.isNWJS();
- },
-
- supportsRtx() {
- return !RTCBrowserType.isFirefox();
- },
-
- supportsRtpSender() {
- return RTCBrowserType.isFirefox();
- }
-
- // Add version getters for other browsers when needed
- };
-
- /**
- * detectOpera() must be called before detectChrome() !!!
- * otherwise Opera wil be detected as Chrome
- */
- function detectChrome() {
- if (navigator.webkitGetUserMedia) {
- currentBrowser = RTCBrowserType.RTC_BROWSER_CHROME;
-
- // We can assume that user agent is chrome, because it's enforced when
- // 'ext' streaming method is set.
- const verMatch = navigator.userAgent.match(/chrome\/(\d+)\./i);
- const ver = verMatch ? parseInt(verMatch[1], 10) : 'undefined';
-
- logger.log(`This appears to be Chrome, ver: ${ver}`);
-
- return ver;
- }
-
- return null;
- }
-
- /**
- *
- */
- function detectOpera() {
- const userAgent = navigator.userAgent;
-
- if (userAgent.match(/Opera|OPR/)) {
- currentBrowser = RTCBrowserType.RTC_BROWSER_OPERA;
- const version = userAgent.match(/(Opera|OPR) ?\/?(\d+)\.?/)[2];
-
- logger.info(`This appears to be Opera, ver: ${version}`);
-
- return version;
- }
-
- return null;
- }
-
- /**
- *
- */
- function detectFirefox() {
- if (navigator.mozGetUserMedia) {
- currentBrowser = RTCBrowserType.RTC_BROWSER_FIREFOX;
- const version = parseInt(
- navigator.userAgent.match(/Firefox\/([0-9]+)\./)[1], 10);
-
- logger.log(`This appears to be Firefox, ver: ${version}`);
-
- return version;
- }
-
- return null;
- }
-
- /**
- *
- */
- function detectSafari() {
- if (/^((?!chrome).)*safari/i.test(navigator.userAgent)) {
- currentBrowser = RTCBrowserType.RTC_BROWSER_SAFARI;
- logger.info('This appears to be Safari');
-
- // FIXME detect Safari version when needed
- return 1;
- }
-
- return null;
- }
-
- /**
- * Detects IE.
- */
- function detectIE() {
- let version;
- const ua = window.navigator.userAgent;
-
- const msie = ua.indexOf('MSIE ');
-
- if (msie > 0) {
- // IE 10 or older => return version number
- version = parseInt(ua.substring(msie + 5, ua.indexOf('.', msie)), 10);
- }
-
- const trident = ua.indexOf('Trident/');
-
- if (!version && trident > 0) {
- // IE 11 => return version number
- const rv = ua.indexOf('rv:');
-
- version = parseInt(ua.substring(rv + 3, ua.indexOf('.', rv)), 10);
- }
-
- if (version) {
- currentBrowser = RTCBrowserType.RTC_BROWSER_IEXPLORER;
- logger.info(`This appears to be IExplorer, ver: ${version}`);
- }
-
- return version;
- }
-
- /**
- * Detects Edge.
- */
- function detectEdge() {
- let version;
- const ua = window.navigator.userAgent;
-
- const edge = ua.indexOf('Edge/');
-
- if (!version && edge > 0) {
- version = parseInt(ua.substring(edge + 5, ua.indexOf('.', edge)), 10);
- }
-
- if (version) {
- currentBrowser = RTCBrowserType.RTC_BROWSER_EDGE;
- logger.info(`This appears to be Edge, ver: ${version}`);
- }
-
- return version;
- }
-
- /**
- * Detects Electron environment.
- */
- function detectElectron() {
- const userAgent = navigator.userAgent;
-
- if (userAgent.match(/Electron/)) {
- currentBrowser = RTCBrowserType.RTC_BROWSER_ELECTRON;
- const version = userAgent.match(/Electron\/([\d.]+)/)[1];
-
- logger.info(`This appears to be Electron, ver: ${version}`);
-
- return version;
- }
-
- return null;
- }
-
- /**
- *
- */
- function detectNWJS() {
- const userAgent = navigator.userAgent;
-
- if (userAgent.match(/JitsiMeetNW/)) {
- currentBrowser = RTCBrowserType.RTC_BROWSER_NWJS;
- const version = userAgent.match(/JitsiMeetNW\/([\d.]+)/)[1];
-
- logger.info(`This appears to be JitsiMeetNW, ver: ${version}`);
-
- return version;
- }
-
- return null;
- }
-
- /**
- *
- */
- function detectReactNative() {
- const match
- = navigator.userAgent.match(/\b(react[ \t_-]*native)(?:\/(\S+))?/i);
- let version;
-
- // If we're remote debugging a React Native app, it may be treated as
- // Chrome. Check navigator.product as well and always return some version
- // even if we can't get the real one.
-
- if (match || navigator.product === 'ReactNative') {
- currentBrowser = RTCBrowserType.RTC_BROWSER_REACT_NATIVE;
- let name;
-
- if (match && match.length > 2) {
- name = match[1];
- version = match[2];
- }
- name || (name = 'react-native');
- version || (version = 'unknown');
- console.info(`This appears to be ${name}, ver: ${version}`);
- } else {
- // We're not running in a React Native environment.
- version = null;
- }
-
- return version;
- }
-
- /**
- *
- */
- function detectBrowser() {
- let version;
- const detectors = [
- detectReactNative,
- detectElectron,
- detectNWJS,
- detectOpera,
- detectChrome,
- detectFirefox,
- detectEdge,
- detectIE,
- detectSafari
- ];
-
- // Try all browser detectors
-
- for (let i = 0; i < detectors.length; i++) {
- version = detectors[i]();
- if (version) {
- return version;
- }
- }
- logger.warn('Browser type defaults to Safari ver 1');
- currentBrowser = RTCBrowserType.RTC_BROWSER_SAFARI;
-
- return 1;
- }
-
- browserVersion = detectBrowser();
-
- export default RTCBrowserType;
|