From ee5e3c5fa3f247d032d48554cb41a63315522870 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 13 Oct 2022 09:14:49 +0200 Subject: Refine browser detection Try to follow the principle outlined by Mozilla when detecting browsers and engines. --- core/util/browser.js | 46 +++++++++++++++++++++++++-- tests/test.browser.js | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 130 insertions(+), 4 deletions(-) diff --git a/core/util/browser.js b/core/util/browser.js index fb0d344..7d2bfd8 100644 --- a/core/util/browser.js +++ b/core/util/browser.js @@ -77,6 +77,8 @@ export const hasScrollbarGutter = _hasScrollbarGutter; * It's better to use feature detection than platform detection. */ +/* OS */ + export function isMac() { return !!(/mac/i).exec(navigator.platform); } @@ -91,12 +93,50 @@ export function isIOS() { !!(/ipod/i).exec(navigator.platform)); } +/* Browser */ + export function isSafari() { - return (navigator.userAgent.indexOf('Safari') !== -1 && - navigator.userAgent.indexOf('Chrome') === -1); + return !!navigator.userAgent.match('Safari/...') && + !navigator.userAgent.match('Chrome/...') && + !navigator.userAgent.match('Chromium/...') && + !navigator.userAgent.match('Epiphany/...'); } export function isFirefox() { - return !!(/firefox/i).exec(navigator.userAgent); + return !!navigator.userAgent.match('Firefox/...') && + !navigator.userAgent.match('Seamonkey/...'); +} + +export function isChrome() { + return !!navigator.userAgent.match('Chrome/...') && + !navigator.userAgent.match('Chromium/...') && + !navigator.userAgent.match('Edg/...') && + !navigator.userAgent.match('OPR/...'); +} + +export function isChromium() { + return !!navigator.userAgent.match('Chromium/...'); +} + +export function isOpera() { + return !!navigator.userAgent.match('OPR/...'); } +export function isEdge() { + return !!navigator.userAgent.match('Edg/...'); +} + +/* Engine */ + +export function isGecko() { + return !!navigator.userAgent.match('Gecko/...'); +} + +export function isWebKit() { + return !!navigator.userAgent.match('AppleWebKit/...') && + !navigator.userAgent.match('Chrome/...'); +} + +export function isBlink() { + return !!navigator.userAgent.match('Chrome/...'); +} diff --git a/tests/test.browser.js b/tests/test.browser.js index ae446cc..f80b12e 100644 --- a/tests/test.browser.js +++ b/tests/test.browser.js @@ -1,7 +1,8 @@ /* eslint-disable no-console */ const expect = chai.expect; -import { isSafari, isFirefox } from '../core/util/browser.js'; +import { isSafari, isFirefox, isChrome, isChromium, isOpera, isEdge, + isGecko, isWebKit, isBlink } from '../core/util/browser.js'; describe('Browser detection', function () { let origNavigator; @@ -23,6 +24,14 @@ describe('Browser detection', function () { expect(isSafari()).to.be.false; expect(isFirefox()).to.be.false; + expect(isChrome()).to.be.true; + expect(isChromium()).to.be.false; + expect(isOpera()).to.be.false; + expect(isEdge()).to.be.false; + + expect(isGecko()).to.be.false; + expect(isWebKit()).to.be.false; + expect(isBlink()).to.be.true; }); it('should handle Chromium', function () { @@ -30,6 +39,14 @@ describe('Browser detection', function () { expect(isSafari()).to.be.false; expect(isFirefox()).to.be.false; + expect(isChrome()).to.be.false; + expect(isChromium()).to.be.true; + expect(isOpera()).to.be.false; + expect(isEdge()).to.be.false; + + expect(isGecko()).to.be.false; + expect(isWebKit()).to.be.false; + expect(isBlink()).to.be.true; }); it('should handle Firefox', function () { @@ -37,6 +54,44 @@ describe('Browser detection', function () { expect(isSafari()).to.be.false; expect(isFirefox()).to.be.true; + expect(isChrome()).to.be.false; + expect(isChromium()).to.be.false; + expect(isOpera()).to.be.false; + expect(isEdge()).to.be.false; + + expect(isGecko()).to.be.true; + expect(isWebKit()).to.be.false; + expect(isBlink()).to.be.false; + }); + + it('should handle Seamonkey', function () { + navigator.userAgent = "Mozilla/5.0 (Windows NT 6.1; rv:36.0) Gecko/20100101 Firefox/36.0 Seamonkey/2.33.1"; + + expect(isSafari()).to.be.false; + expect(isFirefox()).to.be.false; + expect(isChrome()).to.be.false; + expect(isChromium()).to.be.false; + expect(isOpera()).to.be.false; + expect(isEdge()).to.be.false; + + expect(isGecko()).to.be.true; + expect(isWebKit()).to.be.false; + expect(isBlink()).to.be.false; + }); + + it('should handle Safari', function () { + navigator.userAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 12_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.6 Safari/605.1.15"; + + expect(isSafari()).to.be.true; + expect(isFirefox()).to.be.false; + expect(isChrome()).to.be.false; + expect(isChromium()).to.be.false; + expect(isOpera()).to.be.false; + expect(isEdge()).to.be.false; + + expect(isGecko()).to.be.false; + expect(isWebKit()).to.be.true; + expect(isBlink()).to.be.false; }); it('should handle Edge', function () { @@ -44,6 +99,14 @@ describe('Browser detection', function () { expect(isSafari()).to.be.false; expect(isFirefox()).to.be.false; + expect(isChrome()).to.be.false; + expect(isChromium()).to.be.false; + expect(isOpera()).to.be.false; + expect(isEdge()).to.be.true; + + expect(isGecko()).to.be.false; + expect(isWebKit()).to.be.false; + expect(isBlink()).to.be.true; }); it('should handle Opera', function () { @@ -51,5 +114,28 @@ describe('Browser detection', function () { expect(isSafari()).to.be.false; expect(isFirefox()).to.be.false; + expect(isChrome()).to.be.false; + expect(isChromium()).to.be.false; + expect(isOpera()).to.be.true; + expect(isEdge()).to.be.false; + + expect(isGecko()).to.be.false; + expect(isWebKit()).to.be.false; + expect(isBlink()).to.be.true; + }); + + it('should handle Epiphany', function () { + navigator.userAgent = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/11.0 Safari/605.1.15 Epiphany/605.1.15"; + + expect(isSafari()).to.be.false; + expect(isFirefox()).to.be.false; + expect(isChrome()).to.be.false; + expect(isChromium()).to.be.false; + expect(isOpera()).to.be.false; + expect(isEdge()).to.be.false; + + expect(isGecko()).to.be.false; + expect(isWebKit()).to.be.true; + expect(isBlink()).to.be.false; }); }); -- cgit v1.2.1