From 654285cf9c75367a3d5945959f09d8893e363671 Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Sun, 23 Jun 2024 11:59:54 +0700 Subject: [PATCH 1/3] Add new browser: Helio --- src/enums/ua-parser-enums.js | 2 +- src/main/ua-parser.js | 4 ++-- test/specs/browser-all.json | 10 ++++++++++ 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/enums/ua-parser-enums.js b/src/enums/ua-parser-enums.js index 9d93f23b..8fbee9b0 100644 --- a/src/enums/ua-parser-enums.js +++ b/src/enums/ua-parser-enums.js @@ -52,6 +52,7 @@ const Browser = Object.freeze({ FLOW: 'Flow', GO: 'GoBrowser', GOOGLE_SEARCH: 'GSA', + HELIO: 'Helio', HEYTAP: 'HeyTap', HUAWEI: 'Huawei Browser', ICAB: 'iCab', @@ -343,7 +344,6 @@ const OS = Object.freeze({ UBUNTU: 'Ubuntu', UNIX: 'Unix', VECTORLINUX: 'VectorLinux', - VIERA: 'Viera', WATCHOS: 'watchOS', WEBOS: 'WebOS', WINDOWS: 'Windows', diff --git a/src/main/ua-parser.js b/src/main/ua-parser.js index c7034f6e..1ca73630 100755 --- a/src/main/ua-parser.js +++ b/src/main/ua-parser.js @@ -327,8 +327,8 @@ /(?:ms|\()(ie) ([\w\.]+)/i, // Internet Explorer // Webkit/KHTML based // Flock/RockMelt/Midori/Epiphany/Silk/Skyfire/Bolt/Iron/Iridium/PhantomJS/Bowser/QupZilla/Falkon - /(flock|rockmelt|midori|epiphany|silk|skyfire|ovibrowser|bolt|iron|vivaldi|iridium|phantomjs|bowser|quark|qupzilla|falkon|rekonq|puffin|brave|whale(?!.+naver)|qqbrowserlite|duckduckgo|klar)\/([-\w\.]+)/i, - // Rekonq/Puffin/Brave/Whale/QQBrowserLite/QQ//Vivaldi/DuckDuckGo/Klar + /(flock|rockmelt|midori|epiphany|silk|skyfire|ovibrowser|bolt|iron|vivaldi|iridium|phantomjs|bowser|quark|qupzilla|falkon|rekonq|puffin|brave|whale(?!.+naver)|qqbrowserlite|duckduckgo|klar|helio)\/([-\w\.]+)/i, + // Rekonq/Puffin/Brave/Whale/QQBrowserLite/QQ//Vivaldi/DuckDuckGo/Klar/Helio /(heytap|ovi)browser\/([\d\.]+)/i, // HeyTap/Ovi /(weibo)__([\d\.]+)/i // Weibo ], [NAME, VERSION], [ diff --git a/test/specs/browser-all.json b/test/specs/browser-all.json index 880ba08e..71ae6f0a 100644 --- a/test/specs/browser-all.json +++ b/test/specs/browser-all.json @@ -698,6 +698,16 @@ "major" : "1" } }, + { + "desc" : "Helio", + "ua" : "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.72 Safari/537.36 Helio/0.98.20", + "expect" : + { + "name" : "Helio", + "version" : "0.98.20", + "major" : "0" + } + }, { "desc" : "HeyTap", "ua" : "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.61 Safari/537.36 HeyTapBrowser/40.8.10.1", From c391d8a73c1a030c24845bc191b021bfb6cba256 Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Sat, 27 Jul 2024 10:57:11 +0700 Subject: [PATCH 2/3] Update `isAppleSilicon()` helper method to also check for WebGL renderer info #732 --- src/helpers/ua-parser-helpers.js | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/helpers/ua-parser-helpers.js b/src/helpers/ua-parser-helpers.js index 74923e16..3c7d399d 100644 --- a/src/helpers/ua-parser-helpers.js +++ b/src/helpers/ua-parser-helpers.js @@ -9,7 +9,25 @@ const { CPU, OS, Engine } = require('../enums/ua-parser-enums'); -const isAppleSilicon = (res) => res.os.is(OS.MACOS) && res.cpu.is(CPU.ARM); +const isAppleSilicon = (res) => { + if (res.os.is(OS.MACOS)) { + if (res.cpu.is(CPU.ARM)) { + return true; + } + try { + const canvas = document.createElement('canvas'); + const webgl = canvas.getContext('webgl2') || canvas.getContext('webgl') || canvas.getContext('experimental-webgl'); + const debug = webgl.getExtension('WEBGL_debug_renderer_info'); + const renderer = webgl.getParameter(debug.UNMASKED_RENDERER_WEBGL); + if (renderer.match(/apple m\d/i)) { + return true; + } + } catch { + return false; + } + } + return false; +} const isChromeFamily = (res) => res.engine.is(Engine.BLINK); From 62fb6c29257eec5f5521ae63882f0ca2002695bb Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Sat, 27 Jul 2024 22:47:27 +0700 Subject: [PATCH 3/3] Fix #660 - Add new helper method: `getDeviceVendor()` to guess the device vendor from a model name --- src/helpers/ua-parser-helpers.d.ts | 2 ++ src/helpers/ua-parser-helpers.js | 4 ++++ test/mocha-test-helpers.js | 19 ++++++++++++++++++- 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/helpers/ua-parser-helpers.d.ts b/src/helpers/ua-parser-helpers.d.ts index 905e5eda..c58fc146 100644 --- a/src/helpers/ua-parser-helpers.d.ts +++ b/src/helpers/ua-parser-helpers.d.ts @@ -4,12 +4,14 @@ import { IResult } from "../main/ua-parser"; +declare function getDeviceVendor(model: string): string | undefined; declare function isAppleSilicon(res: IResult): boolean; declare function isChromeFamily(res: IResult): boolean; declare function isFrozenUA(ua: string): boolean; declare function isStandalonePWA(): boolean; export { + getDeviceVendor, isAppleSilicon, isChromeFamily, isFrozenUA, diff --git a/src/helpers/ua-parser-helpers.js b/src/helpers/ua-parser-helpers.js index 3c7d399d..e0729c94 100644 --- a/src/helpers/ua-parser-helpers.js +++ b/src/helpers/ua-parser-helpers.js @@ -8,6 +8,9 @@ /*jshint esversion: 6 */ const { CPU, OS, Engine } = require('../enums/ua-parser-enums'); +const { UAParser } = require('../main/ua-parser'); + +const getDeviceVendor = (model) => UAParser(`Mozilla/5.0 (Linux; Android 10; ${model}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.0.0 Safari/537.36`).device.vendor; const isAppleSilicon = (res) => { if (res.os.is(OS.MACOS)) { @@ -44,6 +47,7 @@ const isStandalonePWA = () => window && (window.matchMedia('(display-mode: stand document.referrer.startsWith('app-info://platform/microsoft-store')); module.exports = { + getDeviceVendor, isAppleSilicon, isChromeFamily, isFrozenUA, diff --git a/test/mocha-test-helpers.js b/test/mocha-test-helpers.js index 1cfffea7..da9ae2c8 100644 --- a/test/mocha-test-helpers.js +++ b/test/mocha-test-helpers.js @@ -1,6 +1,23 @@ const assert = require('assert'); const { UAParser } = require('../src/main/ua-parser'); -const { isAppleSilicon, isChromeFamily } = require('../src/helpers/ua-parser-helpers'); +const { getDeviceVendor, isAppleSilicon, isChromeFamily } = require('../src/helpers/ua-parser-helpers'); + +describe('getDeviceVendor', () => { + it('Can guess the device vendor from a model name', () => { + + const modelSM = 'SM-A605G'; + const modelRedmi = 'Redmi Note 8'; + const modelNexus = 'Nexus 6P'; + const modelQuest = 'Quest 3'; + const modelAquos = 'AQUOS-TVX19B'; + + assert.equal(getDeviceVendor(modelSM), 'Samsung'); + assert.equal(getDeviceVendor(modelRedmi), 'Xiaomi'); + assert.equal(getDeviceVendor(modelNexus), 'Huawei'); + assert.equal(getDeviceVendor(modelQuest), 'Facebook'); + assert.equal(getDeviceVendor(modelAquos), 'Sharp'); + }); +}); describe('isAppleSilicon', () => { it('Can detect Apple Silicon device', () => {