Refine browser detection

Try to follow the principle outlined by Mozilla when detecting browsers
and engines.
This commit is contained in:
Pierre Ossman 2022-10-13 09:14:49 +02:00
parent 4a34ee4b1e
commit ee5e3c5fa3
2 changed files with 130 additions and 4 deletions

View File

@ -77,6 +77,8 @@ export const hasScrollbarGutter = _hasScrollbarGutter;
* It's better to use feature detection than platform detection. * It's better to use feature detection than platform detection.
*/ */
/* OS */
export function isMac() { export function isMac() {
return !!(/mac/i).exec(navigator.platform); return !!(/mac/i).exec(navigator.platform);
} }
@ -91,12 +93,50 @@ export function isIOS() {
!!(/ipod/i).exec(navigator.platform)); !!(/ipod/i).exec(navigator.platform));
} }
/* Browser */
export function isSafari() { export function isSafari() {
return (navigator.userAgent.indexOf('Safari') !== -1 && return !!navigator.userAgent.match('Safari/...') &&
navigator.userAgent.indexOf('Chrome') === -1); !navigator.userAgent.match('Chrome/...') &&
!navigator.userAgent.match('Chromium/...') &&
!navigator.userAgent.match('Epiphany/...');
} }
export function isFirefox() { 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/...');
}

View File

@ -1,7 +1,8 @@
/* eslint-disable no-console */ /* eslint-disable no-console */
const expect = chai.expect; 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 () { describe('Browser detection', function () {
let origNavigator; let origNavigator;
@ -23,6 +24,14 @@ describe('Browser detection', function () {
expect(isSafari()).to.be.false; expect(isSafari()).to.be.false;
expect(isFirefox()).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 () { it('should handle Chromium', function () {
@ -30,6 +39,14 @@ describe('Browser detection', function () {
expect(isSafari()).to.be.false; expect(isSafari()).to.be.false;
expect(isFirefox()).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 () { it('should handle Firefox', function () {
@ -37,6 +54,44 @@ describe('Browser detection', function () {
expect(isSafari()).to.be.false; expect(isSafari()).to.be.false;
expect(isFirefox()).to.be.true; 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 () { it('should handle Edge', function () {
@ -44,6 +99,14 @@ describe('Browser detection', function () {
expect(isSafari()).to.be.false; expect(isSafari()).to.be.false;
expect(isFirefox()).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 () { it('should handle Opera', function () {
@ -51,5 +114,28 @@ describe('Browser detection', function () {
expect(isSafari()).to.be.false; expect(isSafari()).to.be.false;
expect(isFirefox()).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;
}); });
}); });