From 61a1eb117454c669cf7ad8f3bb229df096adcb19 Mon Sep 17 00:00:00 2001 From: Jan-Ivar Bruaroey Date: Thu, 27 Feb 2025 17:25:49 -0500 Subject: [PATCH] Detect browser without relying on vendor prefixes --- src/js/utils.js | 50 ++++++++++++++------------------ test/unit/adapterfactory.test.js | 1 - test/unit/detectBrowser.test.js | 18 ++---------- 3 files changed, 24 insertions(+), 45 deletions(-) diff --git a/src/js/utils.js b/src/js/utils.js index 721c4585..c918aa26 100644 --- a/src/js/utils.js +++ b/src/js/utils.js @@ -149,16 +149,11 @@ export function deprecated(oldMethod, newMethod) { * properties. */ export function detectBrowser(window) { - // Returned result object. - const result = {browser: null, version: null}; - // Fail early if it's not a browser if (typeof window === 'undefined' || !window.navigator || !window.navigator.userAgent) { - result.browser = 'Not a browser.'; - return result; + return {browser: 'Not a browser.', version: null}; } - const {navigator} = window; // Prefer navigator.userAgentData. @@ -171,32 +166,29 @@ export function detectBrowser(window) { } } - if (navigator.mozGetUserMedia) { // Firefox. - result.browser = 'firefox'; - result.version = extractVersion(navigator.userAgent, - /Firefox\/(\d+)\./, 1); - } else if (navigator.webkitGetUserMedia || - (window.isSecureContext === false && window.webkitRTCPeerConnection)) { + const ua = navigator.userAgent; + const firefoxVer = extractVersion(ua, /Firefox\/(\d+)\./, 1); + if (firefoxVer) { + return {browser: 'firefox', version: firefoxVer}; + } + const chromeVer = extractVersion(ua, /Chrom(e|ium)\/(\d+)\./, 2); + if (chromeVer) { // Chrome, Chromium, Webview, Opera. // Version matches Chrome/WebRTC version. - // Chrome 74 removed webkitGetUserMedia on http as well so we need the - // more complicated fallback to webkitRTCPeerConnection. - result.browser = 'chrome'; - result.version = extractVersion(navigator.userAgent, - /Chrom(e|ium)\/(\d+)\./, 2); - } else if (window.RTCPeerConnection && - navigator.userAgent.match(/AppleWebKit\/(\d+)\./)) { // Safari. - result.browser = 'safari'; - result.version = extractVersion(navigator.userAgent, - /AppleWebKit\/(\d+)\./, 1); - result.supportsUnifiedPlan = window.RTCRtpTransceiver && - 'currentDirection' in window.RTCRtpTransceiver.prototype; - } else { // Default fallthrough: not supported. - result.browser = 'Not a supported browser.'; - return result; + return {browser: 'chrome', version: chromeVer}; } - - return result; + const safariVer = extractVersion(ua, /AppleWebKit\/(\d+)\./i, 1); + if (safariVer && /Safari/.test(ua)) { + // Version is the AppleWebKit one for adapter backwards compat + return { + browser: 'safari', + version: safariVer, + supportsUnifiedPlan: + window.RTCRtpTransceiver && + 'currentDirection' in window.RTCRtpTransceiver.prototype + }; + } + return {browser: 'Not a supported browser.', version: null}; } /** diff --git a/test/unit/adapterfactory.test.js b/test/unit/adapterfactory.test.js index 555a36f8..0bc1e2c8 100644 --- a/test/unit/adapterfactory.test.js +++ b/test/unit/adapterfactory.test.js @@ -35,7 +35,6 @@ describe('adapter factory', () => { it('does not throw in Firefox with peerconnection disabled', () => { window = {navigator: { - mozGetUserMedia: () => {}, mediaDevices: {getUserMedia: () => {}}, userAgent: 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:44.0) ' + 'Gecko/20100101 Firefox/44.0' diff --git a/test/unit/detectBrowser.test.js b/test/unit/detectBrowser.test.js index 8bf3c2b1..1b820e80 100644 --- a/test/unit/detectBrowser.test.js +++ b/test/unit/detectBrowser.test.js @@ -15,23 +15,18 @@ describe('detectBrowser', () => { window = {navigator}; }); - it('detects Firefox if navigator.mozGetUserMedia exists', () => { + it('detects Firefox', () => { navigator.userAgent = 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; ' + 'rv:44.0) Gecko/20100101 Firefox/44.0'; - navigator.mozGetUserMedia = function() {}; - const browserDetails = detectBrowser(window); expect(browserDetails.browser).toEqual('firefox'); expect(browserDetails.version).toEqual(44); }); - it('detects Chrome if navigator.webkitGetUserMedia exists', () => { + it('detects Chrome', () => { navigator.userAgent = 'Mozilla/5.0 (X11; Linux x86_64) ' + 'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 ' + 'Safari/537.36'; - navigator.webkitGetUserMedia = function() {}; - window.webkitRTCPeerConnection = function() {}; - const browserDetails = detectBrowser(window); expect(browserDetails.browser).toEqual('chrome'); expect(browserDetails.version).toEqual(45); @@ -41,9 +36,6 @@ describe('detectBrowser', () => { navigator.userAgent = 'Mozilla/5.0 (X11; Linux x86_64) ' + 'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.0.0 ' + 'Safari/537.36'; - navigator.webkitGetUserMedia = function() {}; - window.webkitRTCPeerConnection = function() {}; - const browserDetails = detectBrowser(window); expect(browserDetails.browser).toEqual('chrome'); expect(browserDetails.version).toEqual(95); @@ -54,18 +46,14 @@ describe('detectBrowser', () => { // Use the wrong UA string for Firefox. navigator.userAgent = 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; ' + 'rv:44.0) Gecko/20100101 Firefox/44.0'; - navigator.mozGetUserMedia = function() {}; - const browserDetails = detectBrowser(window); expect(browserDetails.browser).toEqual('chrome'); expect(browserDetails.version).toEqual(102); }); - it('detects Safari if window.RTCPeerConnection exists', () => { + it('detects Safari', () => { navigator.userAgent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) ' + 'AppleWebKit/604.1.6 (KHTML, like Gecko) Version/10.2 Safari/604.1.6'; - window.RTCPeerConnection = function() {}; - const browserDetails = detectBrowser(window); expect(browserDetails.browser).toEqual('safari'); expect(browserDetails.version).toEqual(604);