diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 00000000..3ec50a0b --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,12 @@ +# These are supported funding model platforms + +github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] +patreon: # Replace with a single Patreon username +open_collective: ua-parser-js +ko_fi: # Replace with a single Ko-fi username +tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel +community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry +liberapay: # Replace with a single Liberapay username +issuehunt: # Replace with a single IssueHunt username +otechie: # Replace with a single Otechie username +custom: ['https://www.paypal.me/faisalman/'] diff --git a/.github/workflows/run-test.yml b/.github/workflows/run-test.yml new file mode 100644 index 00000000..ab126d2a --- /dev/null +++ b/.github/workflows/run-test.yml @@ -0,0 +1,17 @@ +name: ua-parser-js-run-test + +on: [push, pull_request] + +jobs: + run-test: + runs-on: ubuntu-latest + strategy: + matrix: + arch: [amd64, ppc64le] + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v2 + - name: Run the test + run: | + npm install + npm run test-ci diff --git a/.travis.yml b/.travis.yml index fbc68cd0..0f87fc37 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,6 @@ +arch: + - amd64 + - ppc64le language: node_js node_js: - stable @@ -11,3 +14,5 @@ cache: - node_modules sudo: false + +script: npm run test-ci \ No newline at end of file diff --git a/bower.json b/bower.json index d7496a9c..6539b1b8 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "ua-parser-js", - "version": "0.7.20", + "version": "0.7.28", "authors": [ "Faisal Salman " ], diff --git a/changelog.md b/changelog.md new file mode 100644 index 00000000..05fc6b90 --- /dev/null +++ b/changelog.md @@ -0,0 +1,3 @@ +# UAParser.js Changelog + +## Version 0.8.0 \ No newline at end of file diff --git a/dist/ua-parser.min.js b/dist/ua-parser.min.js index 6e8acb31..9affb6bd 100644 --- a/dist/ua-parser.min.js +++ b/dist/ua-parser.min.js @@ -1,9 +1,9 @@ -/*! - * UAParser.js v0.7.20 +/*!@license + * UAParser.js v0.7.28 * Lightweight JavaScript-based User-Agent string parser * https://github.com/faisalman/ua-parser-js * - * Copyright © 2012-2019 Faisal Salman + * Copyright © 2012-2021 Faisal Salman * Licensed under MIT License */ -(function(window,undefined){"use strict";var LIBVERSION="0.7.20",EMPTY="",UNKNOWN="?",FUNC_TYPE="function",UNDEF_TYPE="undefined",OBJ_TYPE="object",STR_TYPE="string",MAJOR="major",MODEL="model",NAME="name",TYPE="type",VENDOR="vendor",VERSION="version",ARCHITECTURE="architecture",CONSOLE="console",MOBILE="mobile",TABLET="tablet",SMARTTV="smarttv",WEARABLE="wearable",EMBEDDED="embedded";var util={extend:function(regexes,extensions){var mergedRegexes={};for(var i in regexes){if(extensions[i]&&extensions[i].length%2===0){mergedRegexes[i]=extensions[i].concat(regexes[i])}else{mergedRegexes[i]=regexes[i]}}return mergedRegexes},has:function(str1,str2){if(typeof str1==="string"){return str2.toLowerCase().indexOf(str1.toLowerCase())!==-1}else{return false}},lowerize:function(str){return str.toLowerCase()},major:function(version){return typeof version===STR_TYPE?version.replace(/[^\d\.]/g,"").split(".")[0]:undefined},trim:function(str){return str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,"")}};var mapper={rgx:function(ua,arrays){var i=0,j,k,p,q,matches,match;while(i0){if(q.length==2){if(typeof q[1]==FUNC_TYPE){this[q[0]]=q[1].call(this,match)}else{this[q[0]]=q[1]}}else if(q.length==3){if(typeof q[1]===FUNC_TYPE&&!(q[1].exec&&q[1].test)){this[q[0]]=match?q[1].call(this,match,q[2]):undefined}else{this[q[0]]=match?match.replace(q[1],q[2]):undefined}}else if(q.length==4){this[q[0]]=match?q[3].call(this,match.replace(q[1],q[2])):undefined}}else{this[q]=match?match:undefined}}}}i+=2}},str:function(str,map){for(var i in map){if(typeof map[i]===OBJ_TYPE&&map[i].length>0){for(var j=0;j0){if(q.length==2){if(typeof q[1]==FUNC_TYPE){this[q[0]]=q[1].call(this,match)}else{this[q[0]]=q[1]}}else if(q.length==3){if(typeof q[1]===FUNC_TYPE&&!(q[1].exec&&q[1].test)){this[q[0]]=match?q[1].call(this,match,q[2]):undefined}else{this[q[0]]=match?match.replace(q[1],q[2]):undefined}}else if(q.length==4){this[q[0]]=match?q[3].call(this,match.replace(q[1],q[2])):undefined}}else{this[q]=match?match:undefined}}}}i+=2}},str:function(str,map){for(var i in map){if(typeof map[i]===OBJ_TYPE&&map[i].length>0){for(var j=0;jUA_MAX_LENGTH?util.trim(ua,UA_MAX_LENGTH):ua;return this};this.setUA(_ua);return this};UAParser.VERSION=LIBVERSION;UAParser.BROWSER={NAME:NAME,MAJOR:MAJOR,VERSION:VERSION};UAParser.CPU={ARCHITECTURE:ARCHITECTURE};UAParser.DEVICE={MODEL:MODEL,VENDOR:VENDOR,TYPE:TYPE,CONSOLE:CONSOLE,MOBILE:MOBILE,SMARTTV:SMARTTV,TABLET:TABLET,WEARABLE:WEARABLE,EMBEDDED:EMBEDDED};UAParser.ENGINE={NAME:NAME,VERSION:VERSION};UAParser.OS={NAME:NAME,VERSION:VERSION};if(typeof exports!==UNDEF_TYPE){if(typeof module!==UNDEF_TYPE&&module.exports){exports=module.exports=UAParser}exports.UAParser=UAParser}else{if(typeof define==="function"&&define.amd){define(function(){return UAParser})}else if(typeof window!=="undefined"){window.UAParser=UAParser}}var $=typeof window!=="undefined"&&(window.jQuery||window.Zepto);if($&&!$.ua){var parser=new UAParser;$.ua=parser.getResult();$.ua.get=function(){return parser.getUA()};$.ua.set=function(uastring){parser.setUA(uastring);var result=parser.getResult();for(var prop in result){$.ua[prop]=result[prop]}}}})(typeof window==="object"?window:this); \ No newline at end of file diff --git a/dist/ua-parser.pack.js b/dist/ua-parser.pack.js index 1064a0cb..08dd52b5 100644 --- a/dist/ua-parser.pack.js +++ b/dist/ua-parser.pack.js @@ -1,9 +1,9 @@ -/*! - * UAParser.js v0.7.20 +/*!@license + * UAParser.js v0.7.28 * Lightweight JavaScript-based User-Agent string parser * https://github.com/faisalman/ua-parser-js * - * Copyright © 2012-2019 Faisal Salman + * Copyright © 2012-2021 Faisal Salman * Licensed under MIT License */ -!function(r,u){"use strict";var c="function",i="undefined",m="object",s="model",e="name",o="type",n="vendor",a="version",d="architecture",t="console",l="mobile",w="tablet",b="smarttv",p="wearable",f={extend:function(i,s){var e={};for(var o in i)s[o]&&s[o].length%2==0?e[o]=s[o].concat(i[o]):e[o]=i[o];return e},has:function(i,s){return"string"==typeof i&&-1!==s.toLowerCase().indexOf(i.toLowerCase())},lowerize:function(i){return i.toLowerCase()},major:function(i){return"string"==typeof i?i.replace(/[^\d\.]/g,"").split(".")[0]:u},trim:function(i){return i.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,"")}},g={rgx:function(i,s){for(var e,o,r,n,a,d,t=0;t> +Copyright (c) 2012-2021 Faisal Salman <> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/package.js b/package.js index e41d5e79..8ff9001e 100644 --- a/package.js +++ b/package.js @@ -1,6 +1,6 @@ Package.describe({ name: 'faisalman:ua-parser-js', - version: '0.7.20', + version: '0.7.28', summary: 'Lightweight JavaScript-based user-agent string parser', git: 'https://github.com/faisalman/ua-parser-js.git', documentation: 'readme.md' diff --git a/package.json b/package.json index 8b6c5545..499b2d1c 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "title": "UAParser.js", "name": "ua-parser-js", - "version": "0.7.20", + "version": "0.7.28", "author": "Faisal Salman (http://faisalman.com)", "description": "Lightweight JavaScript-based user-agent string parser", "keywords": [ @@ -15,91 +15,136 @@ "jquery-plugin", "ecosystem:jquery" ], - "homepage": "http://github.com/faisalman/ua-parser-js", + "homepage": "https://github.com/faisalman/ua-parser-js", "contributors": [ "Aamir Poonawalla ", "Admas ", "algenon ", - "Alvin Portillo ", + "Alvin Portillo ", + "Amumu ", "Andrea Vaghi ", "Anton Zhiyanov ", "Arturo Mejia ", "Arun Rama Reddy ", "Austin Pray ", + "Bendeguz ", "Benjamin Bertrand ", "Benjamin Urban ", "boneyao ", "Carl C Von Lewin ", "CESAR RAMOS ", + "Chad Killingsworth ", "Christopher De Cairos ", + "Cyrille David ", "Dario Vladovic ", + "David Annez ", "Davit Barbakadze ", "ddivernois ", + "Deliaz ", "Demis Palma ", "dhoko ", "dianhe ", + "dineshks1 ", "Dmitry Tyschenko ", "Douglas Li ", "Dumitru Uzun ", + "Dustin ", + "Elchin Valiyev ", + "Emil Hesslow ", + "Eric Redon ", "Eric Schrenker ", "Erik Hesselink ", "Fabian Becker ", - "Faisal Salman ", + "Faisal Salman ", "Frédéric Camblor ", + "Frederik Ring ", + "Gerald Host ", "Germán M. Bravo ", "Grigory Dmitrenko ", + "gulpin ", "Hendrik Helwich ", "Hermann Ebert ", + "hr6r ", + "Igor Topal ", + "Ildar Kamalov ", + "insanehong ", "jackpoll ", "Jake Mc ", + "JBYoshi <12983479+JBYoshi@users.noreply.github.com>", + "Joey Parrish ", "John Tantalo ", "John Yanarella ", "Jon Buckley ", + "Josh Goldberg ", + "Junki-Ishida ", "Kendall Buchanan ", "Lee Treveil ", "leonardo ", "Levente Balogh ", "Liam Quinn ", "Lithin ", + "ll-syber <670159357@qq.com>", "Loris Guignard ", "Lukas Drgon ", "Lukas Eipert ", "Malash ", "Martynas ", + "Masahiko Sato ", "Matt Brophy ", - "Max Maurer ", + "Matthew Origer ", "Maximilian Haupt ", + "Max Maurer ", + "Max Nordlund ", "Michael Hess ", + "MimyyK ", "naoh ", + "Nicholas Ionata ", + "Nikhil Motiani ", "Nik Rolls ", - "Nikhil Motiani ", + "nionata ", "niris ", "Nobuo Okada ", + "o.drapeza ", "otakuSiD ", + "patrick-nurt ", + "Pavel Studeny ", "Peter Dave Hello ", "philippsimon ", "Pieter Hendrickx ", "Piper Chester ", + "Queen Vinyl Darkscratch ", + "Raine Makelainen ", + "Raman Savaryn ", "Robert Tod ", + "roman.savarin ", "Ron Korland ", "Ross Noble ", + "ruicong <466403866@qq.com>", "Sandro Sonntag ", "sgautrea ", "Shane Gautreau ", "Shane Thacker ", - "shchotse ", + "Shreedhar ", "Simon Eisenmann ", "Simon Lang ", "Stiekel ", + "sUP ", "Sylvain Gizard ", "szchenghuang ", + "Tanguy Krotoff ", + "Tony Tomarchio ", + "Ulrich Schmidt ", "Vadim Kurachevsky ", - "Yun Young-jin " + "Yılmaz ", + "yuanyang ", + "Yun Young-jin ", + "Zach Bjornson " ], "main": "src/ua-parser.js", "scripts": { - "build": "uglifyjs src/ua-parser.js -o dist/ua-parser.min.js --comments '/UAParser\\.js/' && uglifyjs src/ua-parser.js -o dist/ua-parser.pack.js --comments '/UAParser\\.js/' --compress --mangle", + "build": "uglifyjs src/ua-parser.js -o dist/ua-parser.min.js --comments && uglifyjs src/ua-parser.js -o dist/ua-parser.pack.js --comments --compress --mangle", "test": "jshint src/ua-parser.js && mocha -R nyan test/test.js", + "test-ci": "jshint src/ua-parser.js && mocha -R spec test/test.js", "verup": "node ./node_modules/verup", "version": "node ./node_modules/verup 0" }, @@ -115,10 +160,11 @@ ] }, "devDependencies": { - "jshint": "~1.1.0", - "mocha": "~1.8.0", + "jshint": "~2.12.0", + "mocha": "~8.2.0", "requirejs": "^2.3.2", - "uglify-js": "~2.7.5", + "safe-regex": "^2.1.1", + "uglify-js": "~3.12.0", "verup": "^1.3.x" }, "repository": { @@ -136,5 +182,15 @@ }, "bugs": "https://github.com/faisalman/ua-parser-js/issues", "demo": "https://faisalman.github.io/ua-parser-js", - "download": "https://raw.github.com/faisalman/ua-parser-js/master/dist/ua-parser.min.js" + "download": "https://raw.github.com/faisalman/ua-parser-js/master/dist/ua-parser.min.js", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/ua-parser-js" + }, + { + "type": "paypal", + "url": "https://paypal.me/faisalman" + } + ] } diff --git a/readme.md b/readme.md index e905d47a..30871ebf 100644 --- a/readme.md +++ b/readme.md @@ -1,18 +1,26 @@ -# UAParser.js +

+ +

+ +

+ + + + + +

- A JavaScript-based User-Agent string parser. Can be used either in browser (client-side) or in node.js (server-side) environment. Also available as jQuery/Zepto plugin, Bower/Meteor package, & RequireJS/AMD module. This library aims to identify detailed type of web browser, layout engine, operating system, cpu architecture, and device type/model, entirely from user-agent string with a relatively small footprint (~17KB when minified / ~6KB gzipped). Written in vanilla JavaScript, which means it doesn't require any other library and can be used independently. However, it's not recommended to use this library as browser detection since the result may not be more accurate than using feature detection. +# UAParser.js -[![Build Status](https://travis-ci.org/faisalman/ua-parser-js.svg?branch=master)](https://travis-ci.org/faisalman/ua-parser-js) -[![NPM downloads](https://img.shields.io/npm/dw/ua-parser-js.svg)](https://www.npmjs.com/package/ua-parser-js) -[![NPM](https://img.shields.io/npm/v/ua-parser-js.svg)](https://www.npmjs.com/package/ua-parser-js) -[![Bower](https://img.shields.io/bower/v/ua-parser-js.svg)](https://bower.io/) -[![CDNJS](https://img.shields.io/cdnjs/v/UAParser.js.svg)](https://cdnjs.com/libraries/UAParser.js) +JavaScript library to detect Browser, Engine, OS, CPU, and Device type/model from User-Agent data with relatively small footprint (~17KB minified, ~6KB gzipped) that can be used either in browser (client-side) or node.js (server-side). * Author : Faisal Salman <> * Demo : http://faisalman.github.io/ua-parser-js * Source : https://github.com/faisalman/ua-parser-js -# Constructor +# Documentation + +## Constructor * `new UAParser([uastring][,extensions])` * returns new instance @@ -20,42 +28,44 @@ * `UAParser([uastring][,extensions])` * returns result object `{ ua: '', browser: {}, cpu: {}, device: {}, engine: {}, os: {} }` -# Methods +## Methods * `getBrowser()` * returns `{ name: '', version: '' }` ```sh # Possible 'browser.name': -2345Explorer, Amaya, Android Browser, Arora, Avant, BIDUBrowser, Baidu, -Basilisk, Blazer, Bolt, Bowser, Camino, Chimera, Chrome Headless, -Chrome WebView, Chrome, Chromium, Comodo Dragon, Dillo, Dolphin, Doris, Edge, -Epiphany, Facebook, Falkon, Fennec, Firebird, Firefox, Flock, GSA, GoBrowser, -ICE Browser, IE, IEMobile, IceApe, IceCat, IceDragon, Iceape, Iceweasel, -Iridium, Iron, Jasmine, K-Meleon, Kindle, Konqueror, LBBROWSER Line, Links, -Lunascape, Lynx, MIUI Browser, Maemo Browser, Maemo, Maxthon, MetaSr Midori, -Minimo, Mobile Safari, Mosaic, Mozilla, NetFront, NetSurf, Netfront, Netscape, -NokiaBrowser, Oculus Browser, OmniWeb, Opera Coast, Opera Mini, Opera Mobi, -Opera Tablet, Opera, PaleMoon, PhantomJS, Phoenix, Polaris, Puffin, QQ, -QQBrowser, QQBrowserLite, Quark, QupZilla, RockMelt, Safari, Samsung Browser, -SeaMonkey, Silk, Skyfire, Sleipnir, Slim, SlimBrowser, Swiftfox, Tizen Browser, -UCBrowser, Vivaldi, Waterfox, WeChat, Yandex, baidu, iCab, w3m, ... +2345Explorer, 360 Browser, Amaya, Android Browser, Arora, Avant, Avast, AVG, +BIDUBrowser, Baidu, Basilisk, Blazer, Bolt, Brave, Bowser, Camino, Chimera, +Chrome Headless, Chrome WebView, Chrome, Chromium, Comodo Dragon, Dillo, +Dolphin, Doris, Edge, Electron, Epiphany, Facebook, Falkon, Fennec, Firebird, +Firefox [Reality], Flock, Flow, GSA, GoBrowser, ICE Browser, IE, IEMobile, IceApe, +IceCat, IceDragon, Iceweasel, Instagram, Iridium, Iron, Jasmine, K-Meleon, +Kindle, Konqueror, LBBROWSER, Line, Links, Lunascape, Lynx, MIUI Browser, +Maemo Browser, Maemo, Maxthon, MetaSr Midori, Minimo, Mobile Safari, Mosaic, +Mozilla, NetFront, NetSurf, Netfront, Netscape, NokiaBrowser, Oculus Browser, +OmniWeb, Opera Coast, Opera [Mini/Mobi/Tablet], PaleMoon, PhantomJS, Phoenix, +Polaris, Puffin, QQ, QQBrowser, QQBrowserLite, Quark, QupZilla, RockMelt, Safari, +Sailfish Browser, Samsung Browser, SeaMonkey, Silk, Skyfire, Sleipnir, Slim, +SlimBrowser, Swiftfox, Tesla, Tizen Browser, UCBrowser, Vivaldi, Waterfox, WeChat, +Weibo, Yandex, baidu, iCab, w3m, Whale Browser... # 'browser.version' determined dynamically ``` * `getDevice()` - * returns `{ model: '', type: '', vendor: '' }` + * returns `{ model: '', type: '', vendor: '' }` ```sh # Possible 'device.type': console, mobile, tablet, smarttv, wearable, embedded # Possible 'device.vendor': -Acer, Alcatel, Amazon, Apple, Archos, Asus, BenQ, BlackBerry, Dell, Essential, -GeeksPhone, Google, HP, HTC, Huawei, Jolla, Lenovo, LG, Meizu, Microsoft, Motorola, -Nexian, Nintendo, Nokia, Nvidia, OnePlus, Ouya, Palm, Panasonic, Pebble, Polytron, -RIM, Samsung, Sharp, Siemens, Sony[Ericsson], Sprint, Xbox, Xiaomi, ZTE, ... +Acer, Alcatel, Amazon, Apple, Archos, ASUS, AT&T, BenQ, BlackBerry, Dell, +Essential, Fairphone, GeeksPhone, Google, HP, HTC, Huawei, Jolla, Lenovo, LG, +Meizu, Microsoft, Motorola, Nexian, Nintendo, Nokia, Nvidia, OnePlus, OPPO, Ouya, +Palm, Panasonic, Pebble, Polytron, Realme, RIM, Samsung, Sharp, Siemens, +Sony[Ericsson], Sprint, Tesla, Vivo, Vodafone, Xbox, Xiaomi, Zebra, ZTE, ... # 'device.model' determined dynamically ``` @@ -65,8 +75,8 @@ RIM, Samsung, Sharp, Siemens, Sony[Ericsson], Sprint, Xbox, Xiaomi, ZTE, ... ```sh # Possible 'engine.name' -Amaya, Blink, EdgeHTML, Gecko, Goanna, iCab, KHTML, Links, Lynx, NetFront, NetSurf, -Presto, Tasman, Trident, w3m, WebKit +Amaya, Blink, EdgeHTML, Flow, Gecko, Goanna, iCab, KHTML, Links, Lynx, NetFront, +NetSurf, Presto, Tasman, Trident, w3m, WebKit # 'engine.version' determined dynamically ``` @@ -76,12 +86,13 @@ Presto, Tasman, Trident, w3m, WebKit ```sh # Possible 'os.name' -AIX, Amiga OS, Android, Arch, Bada, BeOS, BlackBerry, CentOS, Chromium OS, Contiki, -Fedora, Firefox OS, FreeBSD, Debian, DragonFly, Fuchsia, Gentoo, GNU, Haiku, Hurd, iOS, -Joli, Linpus, Linux, Mac OS, Mageia, Mandriva, MeeGo, Minix, Mint, Morph OS, NetBSD, -Nintendo, OpenBSD, OpenVMS, OS/2, Palm, PC-BSD, PCLinuxOS, Plan9, Playstation, QNX, RedHat, -RIM Tablet OS, RISC OS, Sailfish, Series40, Slackware, Solaris, SUSE, Symbian, Tizen, -Ubuntu, Unix, VectorLinux, WebOS, Windows [Phone/Mobile], Zenwalk, ... +AIX, Amiga OS, Android, Arch, Bada, BeOS, BlackBerry, CentOS, Chromium OS, +Contiki, Fedora, Firefox OS, FreeBSD, Debian, DragonFly, Fuchsia, Gentoo, GNU, +Haiku, Hurd, iOS, Joli, KaiOS, Linpus, Linux, Mac OS, Mageia, Mandriva, MeeGo, +Minix, Mint, Morph OS, NetBSD, Nintendo, OpenBSD, OpenVMS, OS/2, Palm, PC-BSD, +PCLinuxOS, Plan9, PlayStation, QNX, Raspbian, RedHat, RIM Tablet OS, RISC OS, +Sailfish, Series40, Slackware, Solaris, SUSE, Symbian, Tizen, Ubuntu, Unix, +VectorLinux, WebOS, Windows [Phone/Mobile], Zenwalk, ... # 'os.version' determined dynamically ``` @@ -91,7 +102,7 @@ Ubuntu, Unix, VectorLinux, WebOS, Windows [Phone/Mobile], Zenwalk, ... ```sh # Possible 'cpu.architecture' -68k, amd64, arm[64], avr, ia[32/64], irix[64], mips[64], pa-risc, ppc, sparc[64] +68k, amd64, arm[64/hf], avr, ia[32/64], irix[64], mips[64], pa-risc, ppc, sparc[64] ``` * `getResult()` @@ -101,30 +112,30 @@ Ubuntu, Unix, VectorLinux, WebOS, Windows [Phone/Mobile], Zenwalk, ... * returns UA string of current instance * `setUA(uastring)` - * set UA string to parse + * set UA string to be parsed * returns current instance +# Usage -# Example +## Using HTML ```html - - + -``` - -## Using bower - -```sh -$ bower install ua-parser-js -``` - -## Using meteor - -```sh -$ meteor add faisalman:ua-parser-js -``` - ## Using TypeScript ```sh @@ -243,18 +220,18 @@ $ npm install --save @types/ua-parser-js ## Using jQuery/Zepto ($.ua) -Although written in vanilla js (which means it doesn't depends on jQuery), this library will automatically detect if jQuery/Zepto is present and create `$.ua` object based on browser's user-agent (although in case you need, `window.UAParser` constructor is still present). To get/set user-agent you can use: `$.ua.get()` / `$.ua.set(uastring)`. +Although written in vanilla js, this library will automatically detect if jQuery/Zepto is present and create `$.ua` object (with values based on its User-Agent) along with `window.UAParser` constructor. To get/set user-agent you can use: `$.ua.get()` / `$.ua.set(uastring)`. ```js -// In browser with default user-agent: 'Mozilla/5.0 (Linux; U; Android 2.3.4; en-us; Sprint APA7373KT Build/GRJ22) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0': +// Say we are in a browser with default user-agent: 'Mozilla/5.0 (Linux; U; Android 2.3.4; en-us; Sprint APA7373KT Build/GRJ22) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0': -// Do some tests +// Get the details console.log($.ua.device); // {vendor: "HTC", model: "Evo Shift 4G", type: "mobile"} console.log($.ua.os); // {name: "Android", version: "2.3.4"} console.log($.ua.os.name); // "Android" console.log($.ua.get()); // "Mozilla/5.0 (Linux; U; Android 2.3.4; en-us; Sprint APA7373KT Build/GRJ22) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0" -// reset to custom user-agent +// Now lets try to reset to another custom user-agent $.ua.set('Mozilla/5.0 (Linux; U; Android 3.0.1; en-us; Xoom Build/HWI69) AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13'); // Test again @@ -268,54 +245,49 @@ console.log(parseInt($.ua.browser.version.split('.')[0], 10)); // 4 $('body').addClass('ua-browser-' + $.ua.browser.name + ' ua-devicetype-' + $.ua.device.type); ``` -## Extending regex patterns +## Using Extension * `UAParser([uastring,] extensions)` -Pass your own regexes to extend the limited matching rules. - ```js // Example: -var myOwnRegex = [[/(myownbrowser)\/([\w\.]+)/i], [UAParser.BROWSER.NAME, UAParser.BROWSER.VERSION]]; -var myParser = new UAParser({ browser: myOwnRegex }); -var uaString = 'Mozilla/5.0 MyOwnBrowser/1.3'; -console.log(myParser.setUA(uaString).getBrowser()); // {name: "MyOwnBrowser", version: "1.3"} +var myOwnListOfBrowsers = [ + [/(mybrowser)\/([\w\.]+)/i], [UAParser.BROWSER.NAME, UAParser.BROWSER.VERSION] +]; +var myParser = new UAParser({ browser: myOwnListOfBrowsers }); +var myUA = 'Mozilla/5.0 MyBrowser/1.3'; +console.log(myParser.setUA(myUA).getBrowser()); // {name: "MyBrowser", version: "1.3"} ``` - # Development -## Contribute +## Sponsors -* Fork and clone this repository -* Make some changes as required -* Write a unit test to showcase your feature -* Run the test suites to make sure the changes you made didn't break anything `$ npm run test` -* Commit and push to your own repository -* Submit a pull request to this repository under `develop` branch -* Profit? $$$ - -## Build - -Build a minified & packed script + -```sh -$ npm run build -``` + +## Contributors -# Donate + + + -Do you use & like UAParser.js but you don’t find a way to show some love? If yes, please consider donating to support this project. Otherwise, no worries, regardless of whether there is support or not, I will keep maintaining this project. Still, if you buy me a cup of coffee I would be more than happy though :) +Made with [contributors-img](https://contrib.rocks). -[![Support via PayPal](https://cdn.rawgit.com/twolfson/paypal-github-button/1.0.0/dist/button.svg)](https://www.paypal.me/faisalman/) +## How To Contribute +* Fork and clone this repository +* Make some changes as required +* Write unit test to showcase its functionality +* Run the test suites to make sure it's not breaking anything `$ npm test` +* Submit a pull request under `develop` branch # License MIT License -Copyright (c) 2012-2019 Faisal Salman <> +Copyright (c) 2012-2021 Faisal Salman <> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/ua-parser.js b/src/ua-parser.js index de0579c8..ac7112dd 100755 --- a/src/ua-parser.js +++ b/src/ua-parser.js @@ -1,9 +1,9 @@ -/*! - * UAParser.js v0.7.20 +/*!@license + * UAParser.js v0.7.28 * Lightweight JavaScript-based User-Agent string parser * https://github.com/faisalman/ua-parser-js * - * Copyright © 2012-2019 Faisal Salman + * Copyright © 2012-2021 Faisal Salman * Licensed under MIT License */ @@ -16,7 +16,7 @@ ///////////// - var LIBVERSION = '0.7.20', + var LIBVERSION = '0.7.28', EMPTY = '', UNKNOWN = '?', FUNC_TYPE = 'function', @@ -35,7 +35,8 @@ TABLET = 'tablet', SMARTTV = 'smarttv', WEARABLE = 'wearable', - EMBEDDED = 'embedded'; + EMBEDDED = 'embedded', + UA_MAX_LENGTH = 255; /////////// @@ -56,11 +57,7 @@ return mergedRegexes; }, has : function (str1, str2) { - if (typeof str1 === "string") { - return str2.toLowerCase().indexOf(str1.toLowerCase()) !== -1; - } else { - return false; - } + return typeof str1 === STR_TYPE ? str2.toLowerCase().indexOf(str1.toLowerCase()) !== -1 : false; }, lowerize : function (str) { return str.toLowerCase(); @@ -68,8 +65,9 @@ major : function (version) { return typeof(version) === STR_TYPE ? version.replace(/[^\d\.]/g,'').split(".")[0] : undefined; }, - trim : function (str) { - return str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, ''); + trim : function (str, len) { + str = str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, ''); + return typeof(len) === UNDEF_TYPE ? str : str.substring(0, UA_MAX_LENGTH); } }; @@ -160,7 +158,8 @@ var maps = { browser : { - oldsafari : { + // Safari < 3.0 + oldSafari : { version : { '1.0' : '/8', '1.2' : '/1', @@ -171,22 +170,16 @@ '2.0.4' : '/419', '?' : '/' } - } - }, - - device : { - amazon : { - model : { - 'Fire Phone' : ['SD', 'KF'] - } }, - sprint : { - model : { - 'Evo Shift 4G' : '7373KT' - }, - vendor : { - 'HTC' : 'APA', - 'Sprint' : 'Sprint' + oldEdge : { + version : { + '0.1' : '12.', + '21' : '13.', + '31' : '14.', + '39' : '15.', + '41' : '16.', + '42' : '17.', + '44' : '18.' } } }, @@ -220,144 +213,110 @@ browser : [[ + /\b(?:crmo|crios)\/([\w\.]+)/i // Chrome for Android/iOS + ], [VERSION, [NAME, 'Chrome']], [ + /edg(?:e|ios|a)?\/([\w\.]+)/i // Microsoft Edge + ], [VERSION, [NAME, 'Edge']], [ + // breaking change (reserved for next major release): + ///edge\/([\w\.]+)/i // Old Edge (Trident) + //], [[VERSION, mapper.str, maps.browser.oldEdge.version], [NAME, 'Edge']], [ + // Presto based /(opera\smini)\/([\w\.-]+)/i, // Opera Mini - /(opera\s[mobiletab]+).+version\/([\w\.-]+)/i, // Opera Mobi/Tablet - /(opera).+version\/([\w\.]+)/i, // Opera > 9.80 - /(opera)[\/\s]+([\w\.]+)/i // Opera < 9.80 + /(opera\s[mobiletab]{3,6})\b.+version\/([\w\.-]+)/i, // Opera Mobi/Tablet + /(opera)(?:.+version\/|[\/\s]+)([\w\.]+)/i, // Opera ], [NAME, VERSION], [ - - /(opios)[\/\s]+([\w\.]+)/i // Opera mini on iphone >= 8.0 - ], [[NAME, 'Opera Mini'], VERSION], [ - - /\s(opr)\/([\w\.]+)/i // Opera Webkit - ], [[NAME, 'Opera'], VERSION], [ + /opios[\/\s]+([\w\.]+)/i // Opera mini on iphone >= 8.0 + ], [VERSION, [NAME, 'Opera Mini']], [ + /\sopr\/([\w\.]+)/i // Opera Webkit + ], [VERSION, [NAME, 'Opera']], [ // Mixed /(kindle)\/([\w\.]+)/i, // Kindle - /(lunascape|maxthon|netfront|jasmine|blazer)[\/\s]?([\w\.]*)/i, - // Lunascape/Maxthon/Netfront/Jasmine/Blazer - + /(lunascape|maxthon|netfront|jasmine|blazer)[\/\s]?([\w\.]*)/i, // Lunascape/Maxthon/Netfront/Jasmine/Blazer // Trident based - /(avant\s|iemobile|slim|baidu)(?:browser)?[\/\s]?([\w\.]*)/i, - // Avant/IEMobile/SlimBrowser/Baidu + /(avant\s|iemobile|slim)(?:browser)?[\/\s]?([\w\.]*)/i, // Avant/IEMobile/SlimBrowser + /(ba?idubrowser)[\/\s]?([\w\.]+)/i, // Baidu Browser /(?:ms|\()(ie)\s([\w\.]+)/i, // Internet Explorer // Webkit/KHTML based - /(rekonq)\/([\w\.]*)/i, // Rekonq - /(chromium|flock|rockmelt|midori|epiphany|silk|skyfire|ovibrowser|bolt|iron|vivaldi|iridium|phantomjs|bowser|quark|qupzilla|falkon)\/([\w\.-]+)/i - // Chromium/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)\/([\w\.-]+)/i, + // Flock/RockMelt/Midori/Epiphany/Silk/Skyfire/Bolt/Iron/Iridium/PhantomJS/Bowser/QupZilla/Falkon + /(rekonq|puffin|brave|whale|qqbrowserlite|qq)\/([\w\.]+)/i, // Rekonq/Puffin/Brave/Whale/QQBrowserLite/QQ, aka ShouQ + /(weibo)__([\d\.]+)/i // Weibo ], [NAME, VERSION], [ - - /(konqueror)\/([\w\.]+)/i // Konqueror - ], [[NAME, 'Konqueror'], VERSION], [ - - /(trident).+rv[:\s]([\w\.]+).+like\sgecko/i // IE11 - ], [[NAME, 'IE'], VERSION], [ - - /(edge|edgios|edga|edg)\/((\d+)?[\w\.]+)/i // Microsoft Edge - ], [[NAME, 'Edge'], VERSION], [ - - /(yabrowser)\/([\w\.]+)/i // Yandex - ], [[NAME, 'Yandex'], VERSION], [ - - /(puffin)\/([\w\.]+)/i // Puffin - ], [[NAME, 'Puffin'], VERSION], [ - - /(focus)\/([\w\.]+)/i // Firefox Focus - ], [[NAME, 'Firefox Focus'], VERSION], [ - - /(opt)\/([\w\.]+)/i // Opera Touch - ], [[NAME, 'Opera Touch'], VERSION], [ - - /((?:[\s\/])uc?\s?browser|(?:juc.+)ucweb)[\/\s]?([\w\.]+)/i // UCBrowser - ], [[NAME, 'UCBrowser'], VERSION], [ - + /(?:[\s\/]uc?\s?browser|(?:juc.+)ucweb)[\/\s]?([\w\.]+)/i // UCBrowser + ], [VERSION, [NAME, 'UCBrowser']], [ + /(?:windowswechat)?\sqbcore\/([\w\.]+)\b.*(?:windowswechat)?/i // WeChat Desktop for Windows Built-in Browser + ], [VERSION, [NAME, 'WeChat(Win) Desktop']], [ + /micromessenger\/([\w\.]+)/i // WeChat + ], [VERSION, [NAME, 'WeChat']], [ + /konqueror\/([\w\.]+)/i // Konqueror + ], [VERSION, [NAME, 'Konqueror']], [ + /trident.+rv[:\s]([\w\.]{1,9})\b.+like\sgecko/i // IE11 + ], [VERSION, [NAME, 'IE']], [ + /yabrowser\/([\w\.]+)/i // Yandex + ], [VERSION, [NAME, 'Yandex']], [ + /(avast|avg)\/([\w\.]+)/i // Avast/AVG Secure Browser + ], [[NAME, /(.+)/, '$1 Secure Browser'], VERSION], [ + /focus\/([\w\.]+)/i // Firefox Focus + ], [VERSION, [NAME, 'Firefox Focus']], [ + /opt\/([\w\.]+)/i // Opera Touch + ], [VERSION, [NAME, 'Opera Touch']], [ + /coc_coc_browser\/([\w\.]+)/i // Coc Coc Browser + ], [VERSION, [NAME, 'Coc Coc']], [ + /dolfin\/([\w\.]+)/i // Dolphin + ], [VERSION, [NAME, 'Dolphin']], [ + /coast\/([\w\.]+)/i // Opera Coast + ], [VERSION, [NAME, 'Opera Coast']], + [/xiaomi\/miuibrowser\/([\w\.]+)/i // MIUI Browser + ], [VERSION, [NAME, 'MIUI Browser']], [ + /fxios\/([\w\.-]+)/i // Firefox for iOS + ], [VERSION, [NAME, 'Firefox']], [ + /(qihu|qhbrowser|qihoobrowser|360browser)/i // 360 + ], [[NAME, '360 Browser']], [ + /(oculus|samsung|sailfish)browser\/([\w\.]+)/i + ], [[NAME, /(.+)/, '$1 Browser'], VERSION], [ // Oculus/Samsung/Sailfish Browser /(comodo_dragon)\/([\w\.]+)/i // Comodo Dragon ], [[NAME, /_/g, ' '], VERSION], [ - - /(windowswechat qbcore)\/([\w\.]+)/i // WeChat Desktop for Windows Built-in Browser - ], [[NAME, 'WeChat(Win) Desktop'], VERSION], [ - - /(micromessenger)\/([\w\.]+)/i // WeChat - ], [[NAME, 'WeChat'], VERSION], [ - - /(brave)\/([\w\.]+)/i // Brave browser - ], [[NAME, 'Brave'], VERSION], [ - - /(qqbrowserlite)\/([\w\.]+)/i // QQBrowserLite - ], [NAME, VERSION], [ - - /(QQ)\/([\d\.]+)/i // QQ, aka ShouQ - ], [NAME, VERSION], [ - - /m?(qqbrowser)[\/\s]?([\w\.]+)/i // QQBrowser - ], [NAME, VERSION], [ - - /(BIDUBrowser)[\/\s]?([\w\.]+)/i // Baidu Browser + /\s(electron)\/([\w\.]+)\ssafari/i, // Electron-based App + /(tesla)(?:\sqtcarbrowser|\/(20[12]\d\.[\w\.-]+))/i, // Tesla + /m?(qqbrowser|baiduboxapp|2345Explorer)[\/\s]?([\w\.]+)/i // QQBrowser/Baidu App/2345 Browser ], [NAME, VERSION], [ - - /(2345Explorer)[\/\s]?([\w\.]+)/i // 2345 Browser - ], [NAME, VERSION], [ - - /(MetaSr)[\/\s]?([\w\.]+)/i // SouGouBrowser - ], [NAME], [ - - /(LBBROWSER)/i // LieBao Browser + /(MetaSr)[\/\s]?([\w\.]+)/i, // SouGouBrowser + /(LBBROWSER)/i // LieBao Browser ], [NAME], [ - /xiaomi\/miuibrowser\/([\w\.]+)/i // MIUI Browser - ], [VERSION, [NAME, 'MIUI Browser']], [ - - /;fbav\/([\w\.]+);/i // Facebook App for iOS & Android + // WebView + /;fbav\/([\w\.]+);/i // Facebook App for iOS & Android with version ], [VERSION, [NAME, 'Facebook']], [ - + /FBAN\/FBIOS|FB_IAB\/FB4A/i // Facebook App for iOS & Android without version + ], [[NAME, 'Facebook']], [ /safari\s(line)\/([\w\.]+)/i, // Line App for iOS - /android.+(line)\/([\w\.]+)\/iab/i // Line App for Android + /\b(line)\/([\w\.]+)\/iab/i, // Line App for Android + /(chromium|instagram)[\/\s]([\w\.-]+)/i // Chromium/Instagram ], [NAME, VERSION], [ + /\bgsa\/([\w\.]+)\s.*safari\//i // Google Search Appliance on iOS + ], [VERSION, [NAME, 'GSA']], [ /headlesschrome(?:\/([\w\.]+)|\s)/i // Chrome Headless ], [VERSION, [NAME, 'Chrome Headless']], [ /\swv\).+(chrome)\/([\w\.]+)/i // Chrome WebView - ], [[NAME, /(.+)/, '$1 WebView'], VERSION], [ + ], [[NAME, 'Chrome WebView'], VERSION], [ - /((?:oculus|samsung)browser)\/([\w\.]+)/i - ], [[NAME, /(.+(?:g|us))(.+)/, '$1 $2'], VERSION], [ // Oculus / Samsung Browser - - /android.+version\/([\w\.]+)\s+(?:mobile\s?safari|safari)*/i // Android Browser + /droid.+\sversion\/([\w\.]+)\b.+(?:mobile\ssafari|safari)/i // Android Browser ], [VERSION, [NAME, 'Android Browser']], [ - /(sailfishbrowser)\/([\w\.]+)/i // Sailfish Browser - ], [[NAME, 'Sailfish Browser'], VERSION], [ - - /(chrome|omniweb|arora|[tizenoka]{5}\s?browser)\/v?([\w\.]+)/i - // Chrome/OmniWeb/Arora/Tizen/Nokia + /(chrome|omniweb|arora|[tizenoka]{5}\s?browser)\/v?([\w\.]+)/i // Chrome/OmniWeb/Arora/Tizen/Nokia ], [NAME, VERSION], [ - /(dolfin)\/([\w\.]+)/i // Dolphin - ], [[NAME, 'Dolphin'], VERSION], [ - - /((?:android.+)crmo|crios)\/([\w\.]+)/i // Chrome for Android/iOS - ], [[NAME, 'Chrome'], VERSION], [ - - /(coast)\/([\w\.]+)/i // Opera Coast - ], [[NAME, 'Opera Coast'], VERSION], [ - - /fxios\/([\w\.-]+)/i // Firefox for iOS - ], [VERSION, [NAME, 'Firefox']], [ - - /version\/([\w\.]+).+?mobile\/\w+\s(safari)/i // Mobile Safari + /version\/([\w\.]+)\s.*mobile\/\w+\s(safari)/i // Mobile Safari ], [VERSION, [NAME, 'Mobile Safari']], [ - - /version\/([\w\.]+).+?(mobile\s?safari|safari)/i // Safari & Safari Mobile + /version\/([\w\.]+)\s.*(mobile\s?safari|safari)/i // Safari & Safari Mobile ], [VERSION, NAME], [ - - /webkit.+?(gsa)\/([\w\.]+).+?(mobile\s?safari|safari)(\/[\w\.]+)/i // Google Search Appliance on iOS - ], [[NAME, 'GSA'], VERSION], [ - /webkit.+?(mobile\s?safari|safari)(\/[\w\.]+)/i // Safari < 3.0 - ], [NAME, [VERSION, mapper.str, maps.browser.oldsafari.version]], [ + ], [NAME, [VERSION, mapper.str, maps.browser.oldSafari.version]], [ /(webkit|khtml)\/([\w\.]+)/i ], [NAME, VERSION], [ @@ -365,13 +324,16 @@ // Gecko based /(navigator|netscape)\/([\w\.-]+)/i // Netscape ], [[NAME, 'Netscape'], VERSION], [ + /ile\svr;\srv:([\w\.]+)\).+firefox/i // Firefox Reality + ], [VERSION, [NAME, 'Firefox Reality']], [ + /ekiohf.+(flow)\/([\w\.]+)/i, // Flow /(swiftfox)/i, // Swiftfox /(icedragon|iceweasel|camino|chimera|fennec|maemo\sbrowser|minimo|conkeror)[\/\s]?([\w\.\+]+)/i, // IceDragon/Iceweasel/Camino/Chimera/Fennec/Maemo/Minimo/Conkeror /(firefox|seamonkey|k-meleon|icecat|iceape|firebird|phoenix|palemoon|basilisk|waterfox)\/([\w\.-]+)$/i, - // Firefox/SeaMonkey/K-Meleon/IceCat/IceApe/Firebird/Phoenix - /(mozilla)\/([\w\.]+).+rv\:.+gecko\/\d+/i, // Mozilla + /(firefox)\/([\w\.]+)\s[\w\s\-]+\/[\w\.]+$/i, // Other Firefox-based + /(mozilla)\/([\w\.]+)\s.+rv\:.+gecko\/\d+/i, // Mozilla // Other /(polaris|lynx|dillo|icab|doris|amaya|w3m|netsurf|sleipnir)[\/\s]?([\w\.]+)/i, @@ -385,15 +347,21 @@ cpu : [[ - /(?:(amd|x(?:(?:86|64)[_-])?|wow|win)64)[;\)]/i // AMD64 + /(?:(amd|x(?:(?:86|64)[_-])?|wow|win)64)[;\)]/i // AMD64 (x64) ], [[ARCHITECTURE, 'amd64']], [ /(ia32(?=;))/i // IA32 (quicktime) ], [[ARCHITECTURE, util.lowerize]], [ - /((?:i[346]|x)86)[;\)]/i // IA32 + /((?:i[346]|x)86)[;\)]/i // IA32 (x86) ], [[ARCHITECTURE, 'ia32']], [ + /\b(aarch64|armv?8e?l?)\b/i // ARM64 + ], [[ARCHITECTURE, 'arm64']], [ + + /\b(arm(?:v[67])?ht?n?[fl]p?)\b/i // ARMHF + ], [[ARCHITECTURE, 'armhf']], [ + // PocketPC mistakenly identified as PowerPC /windows\s(ce|mobile);\sppc;/i ], [[ARCHITECTURE, 'arm']], [ @@ -404,264 +372,301 @@ /(sun4\w)[;\)]/i // SPARC ], [[ARCHITECTURE, 'sparc']], [ - /((?:avr32|ia64(?=;))|68k(?=\))|arm(?:64|(?=v\d+[;l]))|(?=atmel\s)avr|(?:irix|mips|sparc)(?:64)?(?=;)|pa-risc)/i + /((?:avr32|ia64(?=;))|68k(?=\))|\barm(?:64|(?=v(?:[1-7]|[5-7]1)l?|;|eabi))|(?=atmel\s)avr|(?:irix|mips|sparc)(?:64)?\b|pa-risc)/i // IA64, 68K, ARM/64, AVR/32, IRIX/64, MIPS/64, SPARC/64, PA-RISC ], [[ARCHITECTURE, util.lowerize]] ], device : [[ - /\((ipad|playbook);[\w\s\),;-]+(rim|apple)/i // iPad/PlayBook - ], [MODEL, VENDOR, [TYPE, TABLET]], [ - - /applecoremedia\/[\w\.]+ \((ipad)/ // iPad - ], [MODEL, [VENDOR, 'Apple'], [TYPE, TABLET]], [ - - /(apple\s{0,1}tv)/i // Apple TV - ], [[MODEL, 'Apple TV'], [VENDOR, 'Apple']], [ - - /(archos)\s(gamepad2?)/i, // Archos - /(hp).+(touchpad)/i, // HP TouchPad - /(hp).+(tablet)/i, // HP Tablet - /(kindle)\/([\w\.]+)/i, // Kindle - /\s(nook)[\w\s]+build\/(\w+)/i, // Nook - /(dell)\s(strea[kpr\s\d]*[\dko])/i // Dell Streak - ], [VENDOR, MODEL, [TYPE, TABLET]], [ - - /(kf[A-z]+)\sbuild\/.+silk\//i // Kindle Fire HD - ], [MODEL, [VENDOR, 'Amazon'], [TYPE, TABLET]], [ - /(sd|kf)[0349hijorstuw]+\sbuild\/.+silk\//i // Fire Phone - ], [[MODEL, mapper.str, maps.device.amazon.model], [VENDOR, 'Amazon'], [TYPE, MOBILE]], [ - /android.+aft([bms])\sbuild/i // Fire TV - ], [MODEL, [VENDOR, 'Amazon'], [TYPE, SMARTTV]], [ - - /\((ip[honed|\s\w*]+);.+(apple)/i // iPod/iPhone - ], [MODEL, VENDOR, [TYPE, MOBILE]], [ - /\((ip[honed|\s\w*]+);/i // iPod/iPhone + ////////////////////////// + // MOBILES & TABLETS + // Ordered by popularity + ///////////////////////// + + // Samsung + /\b(sch-i[89]0\d|shw-m380s|sm-[pt]\w{2,4}|gt-[pn]\d{2,4}|sgh-t8[56]9|nexus\s10)/i + ], [MODEL, [VENDOR, 'Samsung'], [TYPE, TABLET]], [ + /\b((?:s[cgp]h|gt|sm)-\w+|galaxy\snexus)/i, + /\ssamsung[\s-]([\w-]+)/i, + /sec-(sgh\w+)/i + ], [MODEL, [VENDOR, 'Samsung'], [TYPE, MOBILE]], [ + + // Apple + /\((ip(?:hone|od)[\s\w]*);/i // iPod/iPhone ], [MODEL, [VENDOR, 'Apple'], [TYPE, MOBILE]], [ + /\((ipad);[\w\s\),;-]+apple/i, // iPad + /applecoremedia\/[\w\.]+\s\((ipad)/i, + /\b(ipad)\d\d?,\d\d?[;\]].+ios/i + ], [MODEL, [VENDOR, 'Apple'], [TYPE, TABLET]], [ - /(blackberry)[\s-]?(\w+)/i, // BlackBerry - /(blackberry|benq|palm(?=\-)|sonyericsson|acer|asus|dell|meizu|motorola|polytron)[\s_-]?([\w-]*)/i, - // BenQ/Palm/Sony-Ericsson/Acer/Asus/Dell/Meizu/Motorola/Polytron - /(hp)\s([\w\s]+\w)/i, // HP iPAQ - /(asus)-?(\w+)/i // Asus - ], [VENDOR, MODEL, [TYPE, MOBILE]], [ - /\(bb10;\s(\w+)/i // BlackBerry 10 - ], [MODEL, [VENDOR, 'BlackBerry'], [TYPE, MOBILE]], [ - // Asus Tablets - /android.+(transfo[prime\s]{4,10}\s\w+|eeepc|slider\s\w+|nexus 7|padfone|p00c)/i - ], [MODEL, [VENDOR, 'Asus'], [TYPE, TABLET]], [ - - /(sony)\s(tablet\s[ps])\sbuild\//i, // Sony - /(sony)?(?:sgp.+)\sbuild\//i - ], [[VENDOR, 'Sony'], [MODEL, 'Xperia Tablet'], [TYPE, TABLET]], [ - /android.+\s([c-g]\d{4}|so[-l]\w+)(?=\sbuild\/|\).+chrome\/(?![1-6]{0,1}\d\.))/i - ], [MODEL, [VENDOR, 'Sony'], [TYPE, MOBILE]], [ - - /\s(ouya)\s/i, // Ouya - /(nintendo)\s([wids3u]+)/i // Nintendo - ], [VENDOR, MODEL, [TYPE, CONSOLE]], [ - - /android.+;\s(shield)\sbuild/i // Nvidia - ], [MODEL, [VENDOR, 'Nvidia'], [TYPE, CONSOLE]], [ - - /(playstation\s[34portablevi]+)/i // Playstation - ], [MODEL, [VENDOR, 'Sony'], [TYPE, CONSOLE]], [ - - /(sprint\s(\w+))/i // Sprint Phones - ], [[VENDOR, mapper.str, maps.device.sprint.vendor], [MODEL, mapper.str, maps.device.sprint.model], [TYPE, MOBILE]], [ - - /(htc)[;_\s-]+([\w\s]+(?=\)|\sbuild)|\w+)/i, // HTC - /(zte)-(\w*)/i, // ZTE - /(alcatel|geeksphone|nexian|panasonic|(?=;\s)sony)[_\s-]?([\w-]*)/i - // Alcatel/GeeksPhone/Nexian/Panasonic/Sony - ], [VENDOR, [MODEL, /_/g, ' '], [TYPE, MOBILE]], [ - - /(nexus\s9)/i // HTC Nexus 9 - ], [MODEL, [VENDOR, 'HTC'], [TYPE, TABLET]], [ - + // Huawei + /\b((?:agr|ags[23]|bah2?|sht?)-a?[lw]\d{2})/i, + ], [MODEL, [VENDOR, 'Huawei'], [TYPE, TABLET]], [ /d\/huawei([\w\s-]+)[;\)]/i, - /(nexus\s6p)/i // Huawei + /\b(nexus\s6p|vog-[at]?l\d\d|ane-[at]?l[x\d]\d|eml-a?l\d\da?|lya-[at]?l\d[\dc]|clt-a?l\d\di?|ele-l\d\d)/i, + /\b(\w{2,4}-[atu][ln][01259][019])[;\)\s]/i ], [MODEL, [VENDOR, 'Huawei'], [TYPE, MOBILE]], [ - /(microsoft);\s(lumia[\s\w]+)/i // Microsoft Lumia - ], [VENDOR, MODEL, [TYPE, MOBILE]], [ - - /[\s\(;](xbox(?:\sone)?)[\s\);]/i // Microsoft Xbox - ], [MODEL, [VENDOR, 'Microsoft'], [TYPE, CONSOLE]], [ - /(kin\.[onetw]{3})/i // Microsoft Kin - ], [[MODEL, /\./g, ' '], [VENDOR, 'Microsoft'], [TYPE, MOBILE]], [ - - // Motorola - /\s(milestone|droid(?:[2-4x]|\s(?:bionic|x2|pro|razr))?:?(\s4g)?)[\w\s]+build\//i, - /mot[\s-]?(\w*)/i, - /(XT\d{3,4}) build\//i, - /(nexus\s6)/i - ], [MODEL, [VENDOR, 'Motorola'], [TYPE, MOBILE]], [ - /android.+\s(mz60\d|xoom[\s2]{0,2})\sbuild\//i - ], [MODEL, [VENDOR, 'Motorola'], [TYPE, TABLET]], [ - - /hbbtv\/\d+\.\d+\.\d+\s+\([\w\s]*;\s*(\w[^;]*);([^;]*)/i // HbbTV devices - ], [[VENDOR, util.trim], [MODEL, util.trim], [TYPE, SMARTTV]], [ - - /hbbtv.+maple;(\d+)/i - ], [[MODEL, /^/, 'SmartTV'], [VENDOR, 'Samsung'], [TYPE, SMARTTV]], [ - - /\(dtv[\);].+(aquos)/i // Sharp - ], [MODEL, [VENDOR, 'Sharp'], [TYPE, SMARTTV]], [ + // Xiaomi + /\b(poco[\s\w]+)(?:\sbuild|\))/i, // Xiaomi POCO + /\b;\s(\w+)\sbuild\/hm\1/i, // Xiaomi Hongmi 'numeric' models + /\b(hm[\s\-_]?note?[\s_]?(?:\d\w)?)\sbuild/i, // Xiaomi Hongmi + /\b(redmi[\s\-_]?(?:note|k)?[\w\s_]+)(?:\sbuild|\))/i, // Xiaomi Redmi + /\b(mi[\s\-_]?(?:a\d|one|one[\s_]plus|note lte)?[\s_]?(?:\d?\w?)[\s_]?(?:plus)?)\sbuild/i // Xiaomi Mi + ], [[MODEL, /_/g, ' '], [VENDOR, 'Xiaomi'], [TYPE, MOBILE]], [ + /\b(mi[\s\-_]?(?:pad)(?:[\w\s_]+))(?:\sbuild|\))/i // Mi Pad tablets + ],[[MODEL, /_/g, ' '], [VENDOR, 'Xiaomi'], [TYPE, TABLET]], [ - /android.+((sch-i[89]0\d|shw-m380s|gt-p\d{4}|gt-n\d+|sgh-t8[56]9|nexus 10))/i, - /((SM-T\w+))/i - ], [[VENDOR, 'Samsung'], MODEL, [TYPE, TABLET]], [ // Samsung - /smart-tv.+(samsung)/i - ], [VENDOR, [TYPE, SMARTTV], MODEL], [ - /((s[cgp]h-\w+|gt-\w+|galaxy\snexus|sm-\w[\w\d]+))/i, - /(sam[sung]*)[\s-]*(\w+-?[\w-]*)/i, - /sec-((sgh\w+))/i - ], [[VENDOR, 'Samsung'], MODEL, [TYPE, MOBILE]], [ + // OPPO + /;\s(\w+)\sbuild.+\soppo/i, + /\s(cph[12]\d{3}|p(?:af|c[al]|d\w|e[ar])[mt]\d0|x9007)\b/i + ], [MODEL, [VENDOR, 'OPPO'], [TYPE, MOBILE]], [ - /sie-(\w*)/i // Siemens - ], [MODEL, [VENDOR, 'Siemens'], [TYPE, MOBILE]], [ + // Vivo + /\svivo\s(\w+)(?:\sbuild|\))/i, + /\s(v[12]\d{3}\w?[at])(?:\sbuild|;)/i + ], [MODEL, [VENDOR, 'Vivo'], [TYPE, MOBILE]], [ - /(maemo|nokia).*(n900|lumia\s\d+)/i, // Nokia - /(nokia)[\s_-]?([\w-]*)/i - ], [[VENDOR, 'Nokia'], MODEL, [TYPE, MOBILE]], [ + // Realme + /\s(rmx[12]\d{3})(?:\sbuild|;)/i + ], [MODEL, [VENDOR, 'Realme'], [TYPE, MOBILE]], [ - /android[x\d\.\s;]+\s([ab][1-7]\-?[0178a]\d\d?)/i // Acer - ], [MODEL, [VENDOR, 'Acer'], [TYPE, TABLET]], [ + // Motorola + /\s(milestone|droid(?:[2-4x]|\s(?:bionic|x2|pro|razr))?:?(\s4g)?)\b[\w\s]+build\//i, + /\smot(?:orola)?[\s-](\w*)/i, + /((?:moto[\s\w\(\)]+|xt\d{3,4}|nexus\s6)(?=\sbuild|\)))/i + ], [MODEL, [VENDOR, 'Motorola'], [TYPE, MOBILE]], [ + /\s(mz60\d|xoom[\s2]{0,2})\sbuild\//i + ], [MODEL, [VENDOR, 'Motorola'], [TYPE, TABLET]], [ - /android.+([vl]k\-?\d{3})\s+build/i // LG Tablet + // LG + /((?=lg)?[vl]k\-?\d{3})\sbuild|\s3\.[\s\w;-]{10}lg?-([06cv9]{3,4})/i ], [MODEL, [VENDOR, 'LG'], [TYPE, TABLET]], [ - /android\s3\.[\s\w;-]{10}(lg?)-([06cv9]{3,4})/i // LG Tablet - ], [[VENDOR, 'LG'], MODEL, [TYPE, TABLET]], [ - /(lg) netcast\.tv/i // LG SmartTV - ], [VENDOR, MODEL, [TYPE, SMARTTV]], [ - /(nexus\s[45])/i, // LG - /lg[e;\s\/-]+(\w*)/i, - /android.+lg(\-?[\d\w]+)\s+build/i + /(lm-?f100[nv]?|nexus\s[45])/i, + /lg[e;\s\/-]+((?!browser|netcast)\w+)/i, + /\blg(\-?[\d\w]+)\sbuild/i ], [MODEL, [VENDOR, 'LG'], [TYPE, MOBILE]], [ - /(lenovo)\s?(s(?:5000|6000)(?:[\w-]+)|tab(?:[\s\w]+))/i // Lenovo tablets - ], [VENDOR, MODEL, [TYPE, TABLET]], [ - /android.+(ideatab[a-z0-9\-\s]+)/i // Lenovo + // Lenovo + /(ideatab[\w\-\s]+)/i, + /lenovo\s?(s(?:5000|6000)(?:[\w-]+)|tab(?:[\s\w]+)|yt[\d\w-]{6}|tb[\d\w-]{6})/i // Lenovo tablets ], [MODEL, [VENDOR, 'Lenovo'], [TYPE, TABLET]], [ - /(lenovo)[_\s-]?([\w-]+)/i - ], [VENDOR, MODEL, [TYPE, MOBILE]], [ - /linux;.+((jolla));/i // Jolla - ], [VENDOR, MODEL, [TYPE, MOBILE]], [ + // Nokia + /(?:maemo|nokia).*(n900|lumia\s\d+)/i, + /nokia[\s_-]?([\w\.-]*)/i + ], [[MODEL, /_/g, ' '], [VENDOR, 'Nokia'], [TYPE, MOBILE]], [ - /((pebble))app\/[\d\.]+\s/i // Pebble - ], [VENDOR, MODEL, [TYPE, WEARABLE]], [ + // Google + /droid.+;\s(pixel\sc)[\s)]/i // Google Pixel C + ], [MODEL, [VENDOR, 'Google'], [TYPE, TABLET]], [ + /droid.+;\s(pixel[\s\daxl]{0,6})(?:\sbuild|\))/i // Google Pixel + ], [MODEL, [VENDOR, 'Google'], [TYPE, MOBILE]], [ - /android.+;\s(oppo)\s?([\w\s]+)\sbuild/i // OPPO - ], [VENDOR, MODEL, [TYPE, MOBILE]], [ + // Sony + /droid.+\s([c-g]\d{4}|so[-l]\w+|xq-a\w[4-7][12])(?=\sbuild\/|\).+chrome\/(?![1-6]{0,1}\d\.))/i + ], [MODEL, [VENDOR, 'Sony'], [TYPE, MOBILE]], [ + /sony\stablet\s[ps]\sbuild\//i, + /(?:sony)?sgp\w+(?:\sbuild\/|\))/i + ], [[MODEL, 'Xperia Tablet'], [VENDOR, 'Sony'], [TYPE, TABLET]], [ + + // OnePlus + /\s(kb2005|in20[12]5|be20[12][59])\b/i, + /\ba000(1)\sbuild/i, // OnePlus + /\boneplus\s(a\d{4})[\s)]/i + ], [MODEL, [VENDOR, 'OnePlus'], [TYPE, MOBILE]], [ - /crkey/i // Google Chromecast - ], [[MODEL, 'Chromecast'], [VENDOR, 'Google']], [ + // Amazon + /(alexa)webm/i, + /(kf[a-z]{2}wi)(\sbuild\/|\))/i, // Kindle Fire without Silk + /(kf[a-z]+)(\sbuild\/|\)).+silk\//i // Kindle Fire HD + ], [MODEL, [VENDOR, 'Amazon'], [TYPE, TABLET]], [ + /(sd|kf)[0349hijorstuw]+(\sbuild\/|\)).+silk\//i // Fire Phone + ], [[MODEL, 'Fire Phone'], [VENDOR, 'Amazon'], [TYPE, MOBILE]], [ - /android.+;\s(glass)\s\d/i // Google Glass - ], [MODEL, [VENDOR, 'Google'], [TYPE, WEARABLE]], [ + // BlackBerry + /\((playbook);[\w\s\),;-]+(rim)/i // BlackBerry PlayBook + ], [MODEL, VENDOR, [TYPE, TABLET]], [ + /((?:bb[a-f]|st[hv])100-\d)/i, + /\(bb10;\s(\w+)/i // BlackBerry 10 + ], [MODEL, [VENDOR, 'BlackBerry'], [TYPE, MOBILE]], [ - /android.+;\s(pixel c)[\s)]/i // Google Pixel C - ], [MODEL, [VENDOR, 'Google'], [TYPE, TABLET]], [ + // Asus + /(?:\b|asus_)(transfo[prime\s]{4,10}\s\w+|eeepc|slider\s\w+|nexus\s7|padfone|p00[cj])/i + ], [MODEL, [VENDOR, 'ASUS'], [TYPE, TABLET]], [ + /\s(z[es]6[027][01][km][ls]|zenfone\s\d\w?)\b/i + ], [MODEL, [VENDOR, 'ASUS'], [TYPE, MOBILE]], [ - /android.+;\s(pixel( [23])?( xl)?)[\s)]/i // Google Pixel - ], [MODEL, [VENDOR, 'Google'], [TYPE, MOBILE]], [ + // HTC + /(nexus\s9)/i // HTC Nexus 9 + ], [MODEL, [VENDOR, 'HTC'], [TYPE, TABLET]], [ + /(htc)[;_\s-]{1,2}([\w\s]+(?=\)|\sbuild)|\w+)/i, // HTC - /android.+;\s(\w+)\s+build\/hm\1/i, // Xiaomi Hongmi 'numeric' models - /android.+(hm[\s\-_]*note?[\s_]*(?:\d\w)?)\s+build/i, // Xiaomi Hongmi - /android.+(mi[\s\-_]*(?:a\d|one|one[\s_]plus|note lte)?[\s_]*(?:\d?\w?)[\s_]*(?:plus)?)\s+build/i, - // Xiaomi Mi - /android.+(redmi[\s\-_]*(?:note)?(?:[\s_]*[\w\s]+))\s+build/i // Redmi Phones - ], [[MODEL, /_/g, ' '], [VENDOR, 'Xiaomi'], [TYPE, MOBILE]], [ - /android.+(mi[\s\-_]*(?:pad)(?:[\s_]*[\w\s]+))\s+build/i // Mi Pad tablets - ],[[MODEL, /_/g, ' '], [VENDOR, 'Xiaomi'], [TYPE, TABLET]], [ - /android.+;\s(m[1-5]\snote)\sbuild/i // Meizu + // ZTE + /(zte)-(\w*)/i, + /(alcatel|geeksphone|nexian|panasonic|(?=;\s)sony)[_\s-]?([\w-]*)/i // Alcatel/GeeksPhone/Nexian/Panasonic/Sony + ], [VENDOR, [MODEL, /_/g, ' '], [TYPE, MOBILE]], [ + + // Acer + /droid[x\d\.\s;]+\s([ab][1-7]\-?[0178a]\d\d?)/i + ], [MODEL, [VENDOR, 'Acer'], [TYPE, TABLET]], [ + + // Meizu + /droid.+;\s(m[1-5]\snote)\sbuild/i, + /\bmz-([\w-]{2,})/i ], [MODEL, [VENDOR, 'Meizu'], [TYPE, MOBILE]], [ - /(mz)-([\w-]{2,})/i - ], [[VENDOR, 'Meizu'], MODEL, [TYPE, MOBILE]], [ - /android.+a000(1)\s+build/i, // OnePlus - /android.+oneplus\s(a\d{4})\s+build/i - ], [MODEL, [VENDOR, 'OnePlus'], [TYPE, MOBILE]], [ + // MIXED + /(blackberry|benq|palm(?=\-)|sonyericsson|acer|asus|dell|meizu|motorola|polytron)[\s_-]?([\w-]*)/i, + // BlackBerry/BenQ/Palm/Sony-Ericsson/Acer/Asus/Dell/Meizu/Motorola/Polytron + /(hp)\s([\w\s]+\w)/i, // HP iPAQ + /(asus)-?(\w+)/i, // Asus + /(microsoft);\s(lumia[\s\w]+)/i, // Microsoft Lumia + /(lenovo)[_\s-]?([\w-]+)/i, // Lenovo + /linux;.+(jolla);/i, // Jolla + /droid.+;\s(oppo)\s?([\w\s]+)\sbuild/i // OPPO + ], [VENDOR, MODEL, [TYPE, MOBILE]], [ - /android.+[;\/]\s*(RCT[\d\w]+)\s+build/i // RCA Tablets - ], [MODEL, [VENDOR, 'RCA'], [TYPE, TABLET]], [ + /(archos)\s(gamepad2?)/i, // Archos + /(hp).+(touchpad(?!.+tablet)|tablet)/i, // HP TouchPad + /(kindle)\/([\w\.]+)/i, // Kindle + /\s(nook)[\w\s]+build\/(\w+)/i, // Nook + /(dell)\s(strea[kpr\s\d]*[\dko])/i, // Dell Streak + /[;\/]\s?(le[\s\-]+pan)[\s\-]+(\w{1,9})\sbuild/i, // Le Pan Tablets + /[;\/]\s?(trinity)[\-\s]*(t\d{3})\sbuild/i, // Trinity Tablets + /\b(gigaset)[\s\-]+(q\w{1,9})\sbuild/i, // Gigaset Tablets + /\b(vodafone)\s([\w\s]+)(?:\)|\sbuild)/i // Vodafone + ], [VENDOR, MODEL, [TYPE, TABLET]], [ - /android.+[;\/\s]+(Venue[\d\s]{2,7})\s+build/i // Dell Venue Tablets + /\s(surface\sduo)\s/i // Surface Duo + ], [MODEL, [VENDOR, 'Microsoft'], [TYPE, TABLET]], [ + /droid\s[\d\.]+;\s(fp\du?)\sbuild/i + ], [MODEL, [VENDOR, 'Fairphone'], [TYPE, MOBILE]], [ + /\s(u304aa)\sbuild/i // AT&T + ], [MODEL, [VENDOR, 'AT&T'], [TYPE, MOBILE]], [ + /sie-(\w*)/i // Siemens + ], [MODEL, [VENDOR, 'Siemens'], [TYPE, MOBILE]], [ + /[;\/]\s?(rct\w+)\sbuild/i // RCA Tablets + ], [MODEL, [VENDOR, 'RCA'], [TYPE, TABLET]], [ + /[;\/\s](venue[\d\s]{2,7})\sbuild/i // Dell Venue Tablets ], [MODEL, [VENDOR, 'Dell'], [TYPE, TABLET]], [ - - /android.+[;\/]\s*(Q[T|M][\d\w]+)\s+build/i // Verizon Tablet + /[;\/]\s?(q(?:mv|ta)\w+)\sbuild/i // Verizon Tablet ], [MODEL, [VENDOR, 'Verizon'], [TYPE, TABLET]], [ - - /android.+[;\/]\s+(Barnes[&\s]+Noble\s+|BN[RT])(V?.*)\s+build/i // Barnes & Noble Tablet - ], [[VENDOR, 'Barnes & Noble'], MODEL, [TYPE, TABLET]], [ - - /android.+[;\/]\s+(TM\d{3}.*\b)\s+build/i // Barnes & Noble Tablet + /[;\/]\s(?:barnes[&\s]+noble\s|bn[rt])([\w\s\+]*)\sbuild/i // Barnes & Noble Tablet + ], [MODEL, [VENDOR, 'Barnes & Noble'], [TYPE, TABLET]], [ + /[;\/]\s(tm\d{3}\w+)\sbuild/i ], [MODEL, [VENDOR, 'NuVision'], [TYPE, TABLET]], [ - - /android.+;\s(k88)\sbuild/i // ZTE K Series Tablet + /;\s(k88)\sbuild/i // ZTE K Series Tablet ], [MODEL, [VENDOR, 'ZTE'], [TYPE, TABLET]], [ - - /android.+[;\/]\s*(gen\d{3})\s+build.*49h/i // Swiss GEN Mobile + /;\s(nx\d{3}j)\sbuild/i // ZTE Nubia + ], [MODEL, [VENDOR, 'ZTE'], [TYPE, MOBILE]], [ + /[;\/]\s?(gen\d{3})\sbuild.*49h/i // Swiss GEN Mobile ], [MODEL, [VENDOR, 'Swiss'], [TYPE, MOBILE]], [ - - /android.+[;\/]\s*(zur\d{3})\s+build/i // Swiss ZUR Tablet + /[;\/]\s?(zur\d{3})\sbuild/i // Swiss ZUR Tablet ], [MODEL, [VENDOR, 'Swiss'], [TYPE, TABLET]], [ - - /android.+[;\/]\s*((Zeki)?TB.*\b)\s+build/i // Zeki Tablets + /[;\/]\s?((zeki)?tb.*\b)\sbuild/i // Zeki Tablets ], [MODEL, [VENDOR, 'Zeki'], [TYPE, TABLET]], [ - - /(android).+[;\/]\s+([YR]\d{2})\s+build/i, - /android.+[;\/]\s+(Dragon[\-\s]+Touch\s+|DT)(\w{5})\sbuild/i // Dragon Touch Tablet + /[;\/]\s([yr]\d{2})\sbuild/i, + /[;\/]\s(dragon[\-\s]+touch\s|dt)(\w{5})\sbuild/i // Dragon Touch Tablet ], [[VENDOR, 'Dragon Touch'], MODEL, [TYPE, TABLET]], [ - - /android.+[;\/]\s*(NS-?\w{0,9})\sbuild/i // Insignia Tablets + /[;\/]\s?(ns-?\w{0,9})\sbuild/i // Insignia Tablets ], [MODEL, [VENDOR, 'Insignia'], [TYPE, TABLET]], [ - - /android.+[;\/]\s*((NX|Next)-?\w{0,9})\s+build/i // NextBook Tablets + /[;\/]\s?((nxa|Next)-?\w{0,9})\sbuild/i // NextBook Tablets ], [MODEL, [VENDOR, 'NextBook'], [TYPE, TABLET]], [ - - /android.+[;\/]\s*(Xtreme\_)?(V(1[045]|2[015]|30|40|60|7[05]|90))\s+build/i + /[;\/]\s?(xtreme\_)?(v(1[045]|2[015]|[3469]0|7[05]))\sbuild/i ], [[VENDOR, 'Voice'], MODEL, [TYPE, MOBILE]], [ // Voice Xtreme Phones - - /android.+[;\/]\s*(LVTEL\-)?(V1[12])\s+build/i // LvTel Phones + /[;\/]\s?(lvtel\-)?(v1[12])\sbuild/i // LvTel Phones ], [[VENDOR, 'LvTel'], MODEL, [TYPE, MOBILE]], [ - - /android.+;\s(PH-1)\s/i + /;\s(ph-1)\s/i ], [MODEL, [VENDOR, 'Essential'], [TYPE, MOBILE]], [ // Essential PH-1 - - /android.+[;\/]\s*(V(100MD|700NA|7011|917G).*\b)\s+build/i // Envizen Tablets + /[;\/]\s?(v(100md|700na|7011|917g).*\b)\sbuild/i // Envizen Tablets ], [MODEL, [VENDOR, 'Envizen'], [TYPE, TABLET]], [ + /[;\/]\s?(trio[\s\w\-\.]+)\sbuild/i // MachSpeed Tablets + ], [MODEL, [VENDOR, 'MachSpeed'], [TYPE, TABLET]], [ + /[;\/]\s?tu_(1491)\sbuild/i // Rotor Tablets + ], [MODEL, [VENDOR, 'Rotor'], [TYPE, TABLET]], [ + /(shield[\w\s]+)\sbuild/i // Nvidia Shield Tablets + ], [MODEL, [VENDOR, 'Nvidia'], [TYPE, TABLET]], [ + /(sprint)\s(\w+)/i // Sprint Phones + ], [VENDOR, MODEL, [TYPE, MOBILE]], [ + /(kin\.[onetw]{3})/i // Microsoft Kin + ], [[MODEL, /\./g, ' '], [VENDOR, 'Microsoft'], [TYPE, MOBILE]], [ + /droid\s[\d\.]+;\s(cc6666?|et5[16]|mc[239][23]x?|vc8[03]x?)\)/i // Zebra + ], [MODEL, [VENDOR, 'Zebra'], [TYPE, TABLET]], [ + /droid\s[\d\.]+;\s(ec30|ps20|tc[2-8]\d[kx])\)/i + ], [MODEL, [VENDOR, 'Zebra'], [TYPE, MOBILE]], [ - /android.+[;\/]\s*(Le[\s\-]+Pan)[\s\-]+(\w{1,9})\s+build/i // Le Pan Tablets - ], [VENDOR, MODEL, [TYPE, TABLET]], [ + /////////////////// + // CONSOLES + /////////////////// - /android.+[;\/]\s*(Trio[\s\-]*.*)\s+build/i // MachSpeed Tablets - ], [MODEL, [VENDOR, 'MachSpeed'], [TYPE, TABLET]], [ + /\s(ouya)\s/i, // Ouya + /(nintendo)\s([wids3utch]+)/i // Nintendo + ], [VENDOR, MODEL, [TYPE, CONSOLE]], [ + /droid.+;\s(shield)\sbuild/i // Nvidia + ], [MODEL, [VENDOR, 'Nvidia'], [TYPE, CONSOLE]], [ + /(playstation\s[345portablevi]+)/i // Playstation + ], [MODEL, [VENDOR, 'Sony'], [TYPE, CONSOLE]], [ + /[\s\(;](xbox(?:\sone)?(?!;\sxbox))[\s\);]/i // Microsoft Xbox + ], [MODEL, [VENDOR, 'Microsoft'], [TYPE, CONSOLE]], [ - /android.+[;\/]\s*(Trinity)[\-\s]*(T\d{3})\s+build/i // Trinity Tablets - ], [VENDOR, MODEL, [TYPE, TABLET]], [ + /////////////////// + // SMARTTVS + /////////////////// - /android.+[;\/]\s*TU_(1491)\s+build/i // Rotor Tablets - ], [MODEL, [VENDOR, 'Rotor'], [TYPE, TABLET]], [ + /smart-tv.+(samsung)/i // Samsung + ], [VENDOR, [TYPE, SMARTTV]], [ + /hbbtv.+maple;(\d+)/i + ], [[MODEL, /^/, 'SmartTV'], [VENDOR, 'Samsung'], [TYPE, SMARTTV]], [ + /(?:linux;\snetcast.+smarttv|lg\snetcast\.tv-201\d)/i, // LG SmartTV + ], [[VENDOR, 'LG'], [TYPE, SMARTTV]], [ + /(apple)\s?tv/i // Apple TV + ], [VENDOR, [MODEL, 'Apple TV'], [TYPE, SMARTTV]], [ + /crkey/i // Google Chromecast + ], [[MODEL, 'Chromecast'], [VENDOR, 'Google'], [TYPE, SMARTTV]], [ + /droid.+aft([\w])(\sbuild\/|\))/i // Fire TV + ], [MODEL, [VENDOR, 'Amazon'], [TYPE, SMARTTV]], [ + /\(dtv[\);].+(aquos)/i // Sharp + ], [MODEL, [VENDOR, 'Sharp'], [TYPE, SMARTTV]], [ + /hbbtv\/\d+\.\d+\.\d+\s+\([\w\s]*;\s*(\w[^;]*);([^;]*)/i // HbbTV devices + ], [[VENDOR, util.trim], [MODEL, util.trim], [TYPE, SMARTTV]], [ + /[\s\/\(](android\s|smart[-\s]?|opera\s)tv[;\)\s]/i // SmartTV from Unidentified Vendors + ], [[TYPE, SMARTTV]], [ - /android.+(KS(.+))\s+build/i // Amazon Kindle Tablets - ], [MODEL, [VENDOR, 'Amazon'], [TYPE, TABLET]], [ + /////////////////// + // WEARABLES + /////////////////// - /android.+(Gigaset)[\s\-]+(Q\w{1,9})\s+build/i // Gigaset Tablets - ], [VENDOR, MODEL, [TYPE, TABLET]], [ + /((pebble))app\/[\d\.]+\s/i // Pebble + ], [VENDOR, MODEL, [TYPE, WEARABLE]], [ + /droid.+;\s(glass)\s\d/i // Google Glass + ], [MODEL, [VENDOR, 'Google'], [TYPE, WEARABLE]], [ + /droid\s[\d\.]+;\s(wt63?0{2,3})\)/i + ], [MODEL, [VENDOR, 'Zebra'], [TYPE, WEARABLE]], [ - /\s(tablet|tab)[;\/]/i, // Unidentifiable Tablet - /\s(mobile)(?:[;\/]|\ssafari)/i // Unidentifiable Mobile - ], [[TYPE, util.lowerize], VENDOR, MODEL], [ + /////////////////// + // EMBEDDED + /////////////////// - /[\s\/\(](smart-?tv)[;\)]/i // SmartTV - ], [[TYPE, SMARTTV]], [ + /(tesla)(?:\sqtcarbrowser|\/20[12]\d\.[\w\.-]+)/i // Tesla + ], [VENDOR, [TYPE, EMBEDDED]], [ + + //////////////////// + // MIXED (GENERIC) + /////////////////// + /droid .+?; ([^;]+?)(?: build|\) applewebkit).+? mobile safari/i // Android Phones from Unidentified Vendors + ], [MODEL, [TYPE, MOBILE]], [ + /droid .+?;\s([^;]+?)(?: build|\) applewebkit).+?(?! mobile) safari/i // Android Tablets from Unidentified Vendors + ], [MODEL, [TYPE, TABLET]], [ + /\s(tablet|tab)[;\/]/i, // Unidentifiable Tablet + /\s(mobile)(?:[;\/]|\ssafari)/i // Unidentifiable Mobile + ], [[TYPE, util.lowerize]], [ /(android[\w\.\s\-]{0,9});.+build/i // Generic Android Device - ], [MODEL, [VENDOR, 'Generic']] + ], [MODEL, [VENDOR, 'Generic']], [ + /(phone)/i + ], [[TYPE, MOBILE]] ], engine : [[ @@ -669,87 +674,86 @@ /windows.+\sedge\/([\w\.]+)/i // EdgeHTML ], [VERSION, [NAME, 'EdgeHTML']], [ - /webkit\/537\.36.+chrome\/(?!27)/i // Blink - ], [[NAME, 'Blink']], [ + /webkit\/537\.36.+chrome\/(?!27)([\w\.]+)/i // Blink + ], [VERSION, [NAME, 'Blink']], [ /(presto)\/([\w\.]+)/i, // Presto - /(webkit|trident|netfront|netsurf|amaya|lynx|w3m|goanna)\/([\w\.]+)/i, - // WebKit/Trident/NetFront/NetSurf/Amaya/Lynx/w3m/Goanna + /(webkit|trident|netfront|netsurf|amaya|lynx|w3m|goanna)\/([\w\.]+)/i, // WebKit/Trident/NetFront/NetSurf/Amaya/Lynx/w3m/Goanna + /ekioh(flow)\/([\w\.]+)/i, // Flow /(khtml|tasman|links)[\/\s]\(?([\w\.]+)/i, // KHTML/Tasman/Links /(icab)[\/\s]([23]\.[\d\.]+)/i // iCab ], [NAME, VERSION], [ - /rv\:([\w\.]{1,9}).+(gecko)/i // Gecko + /rv\:([\w\.]{1,9})\b.+(gecko)/i // Gecko ], [VERSION, NAME] ], os : [[ - // Windows based + // Windows /microsoft\s(windows)\s(vista|xp)/i // Windows (iTunes) ], [NAME, VERSION], [ /(windows)\snt\s6\.2;\s(arm)/i, // Windows RT /(windows\sphone(?:\sos)*)[\s\/]?([\d\.\s\w]*)/i, // Windows Phone - /(windows\smobile|windows)[\s\/]?([ntce\d\.\s]+\w)/i + /(windows\smobile|windows)[\s\/]?([ntce\d\.\s]+\w)(?!.+xbox)/i ], [NAME, [VERSION, mapper.str, maps.os.windows.version]], [ /(win(?=3|9|n)|win\s9x\s)([nt\d\.]+)/i ], [[NAME, 'Windows'], [VERSION, mapper.str, maps.os.windows.version]], [ - // Mobile/Embedded OS - /\((bb)(10);/i // BlackBerry 10 - ], [[NAME, 'BlackBerry'], VERSION], [ - /(blackberry)\w*\/?([\w\.]*)/i, // Blackberry - /(tizen)[\/\s]([\w\.]+)/i, // Tizen - /(android|webos|palm\sos|qnx|bada|rim\stablet\sos|meego|sailfish|contiki)[\/\s-]?([\w\.]*)/i - // Android/WebOS/Palm/QNX/Bada/RIM/MeeGo/Contiki/Sailfish OS - ], [NAME, VERSION], [ - /(symbian\s?os|symbos|s60(?=;))[\/\s-]?([\w\.]*)/i // Symbian - ], [[NAME, 'Symbian'], VERSION], [ + // iOS/macOS + /ip[honead]{2,4}\b(?:.*os\s([\w]+)\slike\smac|;\sopera)/i, // iOS + /cfnetwork\/.+darwin/i + ], [[VERSION, /_/g, '.'], [NAME, 'iOS']], [ + /(mac\sos\sx)\s?([\w\s\.]*)/i, + /(macintosh|mac(?=_powerpc)\s)(?!.+haiku)/i // Mac OS + ], [[NAME, 'Mac OS'], [VERSION, /_/g, '.']], [ + + // Mobile OSes // Android/WebOS/Palm/QNX/Bada/RIM/MeeGo/Contiki/Sailfish OS + /(android|webos|palm\sos|qnx|bada|rim\stablet\sos|meego|sailfish|contiki)[\/\s-]?([\w\.]*)/i, + /(blackberry)\w*\/([\w\.]*)/i, // Blackberry + /(tizen|kaios)[\/\s]([\w\.]+)/i, // Tizen/KaiOS /\((series40);/i // Series 40 - ], [NAME], [ + ], [NAME, VERSION], [ + /\(bb(10);/i // BlackBerry 10 + ], [VERSION, [NAME, 'BlackBerry']], [ + /(?:symbian\s?os|symbos|s60(?=;)|series60)[\/\s-]?([\w\.]*)/i // Symbian + ], [VERSION, [NAME, 'Symbian']], [ /mozilla.+\(mobile;.+gecko.+firefox/i // Firefox OS - ], [[NAME, 'Firefox OS'], VERSION], [ + ], [[NAME, 'Firefox OS']], [ + /web0s;.+rt(tv)/i, + /\b(?:hp)?wos(?:browser)?\/([\w\.]+)/i // WebOS + ], [VERSION, [NAME, 'webOS']], [ + + // Google Chromecast + /crkey\/([\d\.]+)/i // Google Chromecast + ], [VERSION, [NAME, 'Chromecast']], [ + /(cros)\s[\w]+\s([\w\.]+\w)/i // Chromium OS + ], [[NAME, 'Chromium OS'], VERSION],[ // Console - /(nintendo|playstation)\s([wids34portablevu]+)/i, // Nintendo/Playstation + /(nintendo|playstation)\s([wids345portablevuch]+)/i, // Nintendo/Playstation + /(xbox);\s+xbox\s([^\);]+)/i, // Microsoft Xbox (360, One, X, S, Series X, Series S) // GNU/Linux based - /(mint)[\/\s\(]?(\w*)/i, // Mint + /(mint)[\/\s\(\)]?(\w*)/i, // Mint /(mageia|vectorlinux)[;\s]/i, // Mageia/VectorLinux - /(joli|[kxln]?ubuntu|debian|suse|opensuse|gentoo|(?=\s)arch|slackware|fedora|mandriva|centos|pclinuxos|redhat|zenwalk|linpus)[\/\s-]?(?!chrom)([\w\.-]*)/i, + /(joli|[kxln]?ubuntu|debian|suse|opensuse|gentoo|arch(?=\slinux)|slackware|fedora|mandriva|centos|pclinuxos|redhat|zenwalk|linpus|raspbian)(?:\sgnu\/linux)?(?:\slinux)?[\/\s-]?(?!chrom|package)([\w\.-]*)/i, // Joli/Ubuntu/Debian/SUSE/Gentoo/Arch/Slackware // Fedora/Mandriva/CentOS/PCLinuxOS/RedHat/Zenwalk/Linpus /(hurd|linux)\s?([\w\.]*)/i, // Hurd/Linux - /(gnu)\s?([\w\.]*)/i // GNU - ], [NAME, VERSION], [ - - /(cros)\s[\w]+\s([\w\.]+\w)/i // Chromium OS - ], [[NAME, 'Chromium OS'], VERSION],[ - - // Solaris - /(sunos)\s?([\w\.\d]*)/i // Solaris - ], [[NAME, 'Solaris'], VERSION], [ + /(gnu)\s?([\w\.]*)/i, // GNU // BSD based - /\s([frentopc-]{0,4}bsd|dragonfly)\s?([\w\.]*)/i // FreeBSD/NetBSD/OpenBSD/PC-BSD/DragonFly - ], [NAME, VERSION],[ - + /\s([frentopc-]{0,4}bsd|dragonfly)\s?(?!amd|[ix346]{1,2}86)([\w\.]*)/i, // FreeBSD/NetBSD/OpenBSD/PC-BSD/DragonFly /(haiku)\s(\w+)/i // Haiku - ], [NAME, VERSION],[ - - /cfnetwork\/.+darwin/i, - /ip[honead]{2,4}(?:.*os\s([\w]+)\slike\smac|;\sopera)/i // iOS - ], [[VERSION, /_/g, '.'], [NAME, 'iOS']], [ - - /(mac\sos\sx)\s?([\w\s\.]*)/i, - /(macintosh|mac(?=_powerpc)\s)/i // Mac OS - ], [[NAME, 'Mac OS'], [VERSION, /_/g, '.']], [ + ], [NAME, VERSION], [ // Other + /(sunos)\s?([\w\.\d]*)/i // Solaris + ], [[NAME, 'Solaris'], VERSION], [ /((?:open)?solaris)[\/\s-]?([\w\.]*)/i, // Solaris /(aix)\s((\d)(?=\.|\)|\s)[\w\.])*/i, // AIX - /(plan\s9|minix|beos|os\/2|amigaos|morphos|risc\sos|openvms|fuchsia)/i, - // Plan9/Minix/BeOS/OS2/AmigaOS/MorphOS/RISCOS/OpenVMS/Fuchsia + /(plan\s9|minix|beos|os\/2|amigaos|morphos|risc\sos|openvms|fuchsia)/i, // Plan9/Minix/BeOS/OS2/AmigaOS/MorphOS/RISCOS/OpenVMS/Fuchsia /(unix)\s?([\w\.]*)/i // UNIX ], [NAME, VERSION] ] @@ -759,45 +763,45 @@ ///////////////// // Constructor //////////////// - var UAParser = function (uastring, extensions) { + var UAParser = function (ua, extensions) { - if (typeof uastring === 'object') { - extensions = uastring; - uastring = undefined; + if (typeof ua === 'object') { + extensions = ua; + ua = undefined; } if (!(this instanceof UAParser)) { - return new UAParser(uastring, extensions).getResult(); + return new UAParser(ua, extensions).getResult(); } - var ua = uastring || ((window && window.navigator && window.navigator.userAgent) ? window.navigator.userAgent : EMPTY); - var rgxmap = extensions ? util.extend(regexes, extensions) : regexes; + var _ua = ua || ((typeof window !== 'undefined' && window.navigator && window.navigator.userAgent) ? window.navigator.userAgent : EMPTY); + var _rgxmap = extensions ? util.extend(regexes, extensions) : regexes; this.getBrowser = function () { - var browser = { name: undefined, version: undefined }; - mapper.rgx.call(browser, ua, rgxmap.browser); - browser.major = util.major(browser.version); // deprecated - return browser; + var _browser = { name: undefined, version: undefined }; + mapper.rgx.call(_browser, _ua, _rgxmap.browser); + _browser.major = util.major(_browser.version); // deprecated + return _browser; }; this.getCPU = function () { - var cpu = { architecture: undefined }; - mapper.rgx.call(cpu, ua, rgxmap.cpu); - return cpu; + var _cpu = { architecture: undefined }; + mapper.rgx.call(_cpu, _ua, _rgxmap.cpu); + return _cpu; }; this.getDevice = function () { - var device = { vendor: undefined, model: undefined, type: undefined }; - mapper.rgx.call(device, ua, rgxmap.device); - return device; + var _device = { vendor: undefined, model: undefined, type: undefined }; + mapper.rgx.call(_device, _ua, _rgxmap.device); + return _device; }; this.getEngine = function () { - var engine = { name: undefined, version: undefined }; - mapper.rgx.call(engine, ua, rgxmap.engine); - return engine; + var _engine = { name: undefined, version: undefined }; + mapper.rgx.call(_engine, _ua, _rgxmap.engine); + return _engine; }; this.getOS = function () { - var os = { name: undefined, version: undefined }; - mapper.rgx.call(os, ua, rgxmap.os); - return os; + var _os = { name: undefined, version: undefined }; + mapper.rgx.call(_os, _ua, _rgxmap.os); + return _os; }; this.getResult = function () { return { @@ -810,12 +814,13 @@ }; }; this.getUA = function () { - return ua; + return _ua; }; - this.setUA = function (uastring) { - ua = uastring; + this.setUA = function (ua) { + _ua = (typeof ua === STR_TYPE && ua.length > UA_MAX_LENGTH) ? util.trim(ua, UA_MAX_LENGTH) : ua; return this; }; + this.setUA(_ua); return this; }; @@ -866,7 +871,7 @@ define(function () { return UAParser; }); - } else if (window) { + } else if (typeof window !== 'undefined') { // browser env window.UAParser = UAParser; } @@ -877,8 +882,8 @@ // In AMD env the global scope should be kept clean, but jQuery is an exception. // jQuery always exports to global scope, unless jQuery.noConflict(true) is used, // and we should catch that. - var $ = window && (window.jQuery || window.Zepto); - if (typeof $ !== UNDEF_TYPE && !$.ua) { + var $ = typeof window !== 'undefined' && (window.jQuery || window.Zepto); + if ($ && !$.ua) { var parser = new UAParser(); $.ua = parser.getResult(); $.ua.get = function () { diff --git a/test/browser-test.json b/test/browser-test.json index 58ef6cc5..c3b70d07 100644 --- a/test/browser-test.json +++ b/test/browser-test.json @@ -1,4 +1,14 @@ [ + { + "desc" : "360 Browser on iOS", + "ua" : "Mozilla/5.0 (iPhone; CPU iPhone OS 12_4_1 like Mac OS X) AppleWebKit/607.3.9 (KHTML, like Gecko) Mobile/16G102 QHBrowser/317 QihooBrowser/4.0.10", + "expect" : + { + "name" : "360 Browser", + "version" : "undefined", + "major" : "undefined" + } + }, { "desc" : "Android Browser on Galaxy Nexus", "ua" : "Mozilla/5.0 (Linux; U; Android 4.0.2; en-us; Galaxy Nexus Build/ICL53F) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30", @@ -89,12 +99,32 @@ "major" : "undefined" } }, + { + "desc" : "Avast Secure Browser", + "ua" : "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36 Avast/72.0.1174.122", + "expect" : + { + "name" : "Avast Secure Browser", + "version" : "72.0.1174.122", + "major" : "72" + } + }, + { + "desc" : "AVG Secure Browser", + "ua" : "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36 AVG/72.0.719.123", + "expect" : + { + "name" : "AVG Secure Browser", + "version" : "72.0.719.123", + "major" : "72" + } + }, { "desc" : "Baidu", "ua" : "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; baidubrowser 1.x)", "expect" : { - "name" : "baidu", + "name" : "baidubrowser", "version" : "1.x", "major" : "1" } @@ -209,6 +239,16 @@ "major" : "16" } }, + { + "desc" : "Coc Coc Browser", + "ua" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) coc_coc_browser/78.0.129 Chrome/72.0.3626.129 Safari/537.36", + "expect" : + { + "name" : "Coc Coc", + "version" : "78.0.129", + "major" : "78" + } + }, { "desc" : "Dillo", "ua" : "Dillo/2.2", @@ -249,6 +289,16 @@ "major" : "1" } }, + { + "desc" : "Flow", + "ua" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_0) EkiohFlow/5.7.4.30559 Flow/5.7.4 (like Gecko Firefox/53.0 rv:53.0)", + "expect" : + { + "name" : "Flow", + "version" : "5.7.4", + "major" : "5" + } + }, { "desc" : "Waterfox", "ua" : "Mozilla/5.0 (X11; Linux x86_64; rv:55.0) Gecko/20100101 Firefox/55.2.2 Waterfox/55.2.2", @@ -280,7 +330,7 @@ } }, { - "desc" : "Facebook in-App Browser for Android", + "desc" : "Facebook in-App Browser for Android with version", "ua" : "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/43.0.2357.121 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/35.0.0.48.273;]", "expect" : { @@ -290,7 +340,7 @@ } }, { - "desc" : "Facebook in-App Browser for iOS", + "desc" : "Facebook in-App Browser for iOS with version", "ua" : "Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Mobile/14E304 [FBAN/FBIOS;FBAV/91.0.0.41.73;FBBV/57050710;FBDV/iPhone8,1;FBMD/iPhone;FBSN/iOS;FBSV/10.3.1;FBSS/2;FBCR/Telekom.de;FBID/phone;FBLC/de_DE;FBOP/5;FBRV/0])", "expect" : { @@ -299,6 +349,26 @@ "major" : "91" } }, + { + "desc" : "Facebook in-App Browser for iOS without version", + "ua" : "Mozilla/5.0 (iPhone; CPU iPhone OS 13_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 [FBAN/FBIOS;FBDV/iPhone10,2;FBMD/iPhone;FBSN/iOS;FBSV/13.3.1;FBSS/3;FBID/phone;FBLC/en_US;FBOP/5;FBCR/]", + "expect" : + { + "name" : "Facebook", + "version" : "undefined", + "major" : "undefined" + } + }, + { + "desc" : "Instagram in-App Browser for iOS", + "ua" : "Mozilla/5.0 (iPhone; CPU iPhone OS 14_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 Instagram 142.0.0.22.109 (iPhone12,5; iOS 14_1; en_US; en-US; scale=3.00; 1242x2688; 214888322) NW/1", + "expect" : + { + "name" : "Instagram", + "version" : "142.0.0.22.109", + "major" : "142" + } + }, { "desc" : "Falkon", "ua" : "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Falkon/3.0.0 Chrome/61.0.3163.140 Safari/537.36", @@ -329,6 +399,26 @@ "major" : "15" } }, + { + "desc" : "Firefox Reality", + "ua" : "Mozilla/5.0 (Android 7.1.2; Mobile VR; rv:65.0) Gecko/65.0 Firefox/65.0", + "expect" : + { + "name" : "Firefox Reality", + "version" : "65.0", + "major" : "65" + } + }, + { + "desc" : "Firefox-based browser", + "ua" : "Mozilla/5.0 (X11; Linux x86_64; rv:80.0) Gecko/20100101 Firefox/80.0 AppName/1.0", + "expect" : + { + "name" : "Firefox", + "version" : "80.0", + "major" : "80" + } + }, { "desc" : "Fennec", "ua" : "Mozilla/5.0 (X11; U; Linux armv61; en-US; rv:1.9.1b2pre) Gecko/20081015 Fennec/1.0a1", @@ -908,6 +998,26 @@ "major" : "undefined" } }, + { + "desc" : "Tesla", + "ua" : "Mozilla/5.0 (X11; GNU/Linux) AppleWebKit/601.1 (KHTML, like Gecko) Tesla QtCarBrowser Safari/601.1", + "expect" : + { + "name" : "Tesla", + "version" : "undefined", + "major" : "undefined" + } + }, + { + "desc" : "Tesla", + "ua" : "Mozilla/5.0 (X11; GNU/Linux) AppleWebKit/537.36 (KHTML, like Gecko) Chromium/79.0.3945.130 Chrome/79.0.3945.130 Safari/537.36 Tesla/2020.16.2.1-e99c70fff409", + "expect" : + { + "name" : "Tesla", + "version" : "2020.16.2.1-e99c70fff409", + "major" : "2020" + } + }, { "desc" : "Tizen Browser", "ua" : "Mozilla/5.0 (Linux; U; Tizen/1.0 like Android; en-us; AppleWebKit/534.46 (KHTML, like Gecko) Tizen Browser/1.0 Mobile", @@ -998,6 +1108,16 @@ "major": "6" } }, + { + "desc": "WeChat on Android", + "ua": "Mozilla/5.0 (iPhone; CPU iPhone OS 12_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/16A366 Weibo (iPhone8,2__weibo__8.9.3__iphone__os12.0)", + "expect": + { + "name": "weibo", + "version": "8.9.3", + "major": "8" + } + }, { "desc" : "Vivaldi", "ua" : "Mozilla/5.0 (Windows NT 6.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.89 Vivaldi/1.0.83.38 Safari/537.36", @@ -1029,7 +1149,7 @@ } }, { - "desc" : "Microsoft Edge", + "desc" : "Microsoft Edge 0.1", "ua" : "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36 Edge/12.0", "expect" : { @@ -1038,6 +1158,26 @@ "major" : "12" } }, + { + "desc" : "Microsoft Edge 42", + "ua" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36 Edge/17.17134", + "expect" : + { + "name" : "Edge", + "version" : "17.17134", + "major" : "17" + } + }, + { + "desc" : "Microsoft Edge 44", + "ua" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36 Edge/18.17763", + "expect" : + { + "name" : "Edge", + "version" : "18.17763", + "major" : "18" + } + }, { "desc" : "Microsoft Edge on iOS", "ua" : "Mozilla/5.0 (iPhone; CPU iPhone OS 11_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/11.0 EdgiOS/42.1.1.0 Mobile/15F79 Safari/605.1.15", @@ -1108,6 +1248,26 @@ "major" : "6" } }, + { + "desc" : "baidu app on iOS", + "ua" : "Mozilla/5.0 (iPhone; CPU iPhone OS 12_1_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/16C101 main%2F1.0 baiduboxapp/11.12.0.18 (Baidu; P2 12.1.2)", + "expect" : + { + "name" : "baiduboxapp", + "version" : "11.12.0.18", + "major" : "11" + } + }, + { + "desc" : "baidu app on Android", + "ua" : "Mozilla/5.0 (Linux; Android 8.1.0; BKK-AL10 Build/HONORBKK-AL10; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/63.0.3239.83 Mobile Safari/537.36 T7/11.11 baiduboxapp/11.11.0.0 (Baidu; P1 8.1.0)", + "expect" : + { + "name" : "baiduboxapp", + "version" : "11.11.0.0", + "major" : "11" + } + }, { "desc" : "WeChat Desktop for Windows Built-in Browser", "ua" : "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 MicroMessenger/6.5.2.501 NetType/WIFI WindowsWechat QBCore/3.43.901.400 QQBrowser/9.0.2524.400", @@ -1118,6 +1278,16 @@ "major" : "3" } }, + { + "desc" : "WeChat Desktop for Windows Built-in Browser major version in 4", + "ua" : "mozilla/5.0 (windows nt 10.0; wow64) applewebkit/537.36 (khtml, like gecko) chrome/53.0.2785.116 safari/537.36 qbcore/4.0.1301.400 qqbrowser/9.0.2524.400 mozilla/5.0 (windows nt 6.1; wow64) applewebkit/537.36 (khtml, like gecko) chrome/81.0.4044.138 safari/537.36 nettype/wifi micromessenger/7.0.20.1781(0x6700143b) windowswechat", + "expect" : + { + "name" : "WeChat(Win) Desktop", + "version" : "4.0.1301.400", + "major" : "4" + } + }, { "desc" : "GSA on iOS", "ua" : "Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_2 like Mac OS X) AppleWebKit/602.1.50 (KHTML, like Gecko) GSA/30.1.161623614 Mobile/14F89 Safari/602.1", @@ -1150,7 +1320,7 @@ "expect" : { "name" : "BIDUBrowser", - "version" : "8.7", + "version" : "8.7", "major" : "8" } }, @@ -1183,5 +1353,25 @@ "version" : "4.5.16", "major" : "4" } + }, + { + "desc" : "Whale Browser", + "ua" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.146 Whale/2.6.90.14 Safari/537.36", + "expect" : + { + "name" : "Whale", + "version" : "2.6.90.14", + "major" : "2" + } + }, + { + "desc" : "Electron", + "ua" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Atom/1.41.0 Chrome/69.0.3497.128 Electron/4.2.7 Safari/537.36", + "expect" : + { + "name" : "Electron", + "version" : "4.2.7", + "major" : "4" + } } ] diff --git a/test/cpu-test.json b/test/cpu-test.json index f42ee76d..773c9f6d 100644 --- a/test/cpu-test.json +++ b/test/cpu-test.json @@ -40,7 +40,15 @@ } }, { - "desc" : "ARMv6", + "desc" : "ARM", + "ua" : "Mozilla/5.0 (Mobile; Windows Phone 8.1; Android 4.0; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 635) like iPhone OS 7_0_3 Mac OS X AppleWebKit/537 (KHTML, like Gecko) Mobile Safari/537", + "expect" : + { + "architecture" : "arm" + } + }, + { + "desc" : "ARMv61", "ua" : "Mozilla/5.0 (X11; U; Linux armv61; en-US; rv:1.9.1b2pre) Gecko/20081015 Fennec/1.0a1", "expect" : { @@ -49,12 +57,52 @@ }, { "desc" : "ARMv7", + "ua" : "Mozilla/5.0 (Linux ARMv7) WebKitGTK+/3.4.9 vimprobable2", + "expect" : + { + "architecture" : "arm" + } + }, + { + "desc" : "ARMv7l", + "ua" : "Mozilla/5.0 (SMART-TV; X11; Linux armv7l) AppleWebKit/537.42 (KHTML, like Gecko) Chromium/25.0.1349.2 Chrome/25.0.1349.2 Safari/537.42", + "expect" : + { + "architecture" : "arm" + } + }, + { + "desc" : "ARMv7l", "ua" : "Mozilla/5.0 (X11; CrOS armv7l 9765.85.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.123 Safari/537.36", "expect" : { "architecture" : "arm" } }, + { + "desc" : "ARMEABI", + "ua" : "[FBAN/FB4A;FBAV/237.0.0.44.120;FBBV/170693408;FBDM/{density=1.75,width=720,height=1280};FBLC/en_US;FBRV/172067074;FBCR/ ;FBMF/samsung;FBBD/samsung;FBPN/com.facebook.katana;FBDV/SM-S367VL;FBSV/9;FBBK/1;FBOP/19;FBCA/armeabi-v7a:armeabi;]", + "expect" : + { + "architecture" : "arm" + } + }, + { + "desc" : "ARMv8", + "ua" : "Mozilla/5.0 (X11; Linux armv8l; rv:45.0) Gecko/20100101 Firefox/45.0", + "expect" : + { + "architecture" : "arm64" + } + }, + { + "desc" : "AARCH64", + "ua" : "Mozilla/5.0 (X11; CrOS aarch64 13310.93.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.133 Safari/537.36", + "expect" : + { + "architecture" : "arm64" + } + }, { "desc" : "Pocket PC", "ua" : "Opera/9.7 (Windows Mobile; PPC; Opera Mobi/35166; U; en) Presto/2.2.1", @@ -95,6 +143,14 @@ "architecture" : "sparc" } }, + { + "desc" : "sparc64", + "ua" : "ELinks (0.4.3; NetBSD 3.0.2PATCH sparc64; 141x19)", + "expect" : + { + "architecture" : "sparc64" + } + }, { "desc" : "QuickTime", "ua" : "QuickTime/7.5.6 (qtver=7.5.6;cpu=IA32;os=Mac 10.5.8)", @@ -110,5 +166,13 @@ { "architecture" : "amd64" } + }, + { + "desc" : "IRIX64", + "ua" : "Mozilla/4.8C-SGI [en] (X11; U; IRIX64 6.5 IP27", + "expect" : + { + "architecture" : "irix64" + } } ] diff --git a/test/device-test.json b/test/device-test.json index 60746659..fb4b9143 100644 --- a/test/device-test.json +++ b/test/device-test.json @@ -1,30 +1,138 @@ [{ - "desc": "Asus Nexus 7", + "desc": "ASUS Nexus 7", "ua": "Mozilla/5.0 (Linux; Android 4.4.2; Nexus 7 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.99 Safari/537.36", "expect": { - "vendor": "Asus", + "vendor": "ASUS", "model": "Nexus 7", "type": "tablet" } }, { - "desc": "Asus Padfone", + "desc": "ASUS Padfone", "ua": "Mozilla/5.0 (Linux; Android 4.1.1; PadFone 2 Build/JRO03L) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.117 Safari/537.36", "expect": { - "vendor": "Asus", + "vendor": "ASUS", "model": "PadFone", "type": "tablet" } }, { - "desc": "Asus ZenPad 10", + "desc": "ASUS ZenPad 10", "ua": "Mozilla/5.0 (Linux; Android 6.0; P00C Build/MRA58K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.76 Safari/537.36", "expect": { - "vendor": "Asus", + "vendor": "ASUS", "model": "P00C", "type": "tablet" } }, + { + "desc": "ASUS ZenPad Z8s", + "ua": "Mozilla/5.0 (Linux; Android 7.0; ASUS_P00J) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.111 Safari/537.36\n", + "expect": { + "vendor": "ASUS", + "model": "P00J", + "type": "tablet" + } + }, + { + "desc": "ASUS ROG", + "ua": "Mozilla/5.0 (Linux; Android 8.1; ZS600KL Build/OPM1.171019.026) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.126 Mobile Safari/537.36", + "expect": { + "vendor": "ASUS", + "model": "ZS600KL", + "type": "mobile" + } + }, + { + "desc": "ASUS ROG II", + "ua": "Mozilla/5.0 (Linux; Android 9; ASUS_I001DA Build/PKQ1.190414.001; xx-xx) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/74.0.3729.136 Mobile Safari/537.36", + "expect": { + "vendor": "ASUS", + "model": "I001DA", + "type": "mobile" + } + }, + { + "desc": "ASUS Zenfone 2", + "ua": "Mozilla/5.0 (Linux; Android 5.0; ASUS ZenFone 2 Build/LRX22C) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/37.0.0.0 Mobile Safari/537.36", + "expect": { + "vendor": "ASUS", + "model": "ZenFone 2", + "type": "mobile" + } + }, + { + "desc": "ASUS Zenfone 3 Deluxe", + "ua": "Mozilla/5.0 (Linux; Android 6.0; ASUS_Z016D Build/MXB48T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.132 Mobile Safari/537.36", + "expect": { + "vendor": "ASUS", + "model": "Z016D", + "type": "mobile" + } + }, + { + "desc": "ASUS Zenfone 5", + "ua": "Mozilla/5.0 (Linux; Android 8.0; ZE620KL Build/OPR1.170623.032) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.158 Mobile Safari/537.36", + "expect": { + "vendor": "ASUS", + "model": "ZE620KL", + "type": "mobile" + } + }, + { + "desc": "ASUS Zenfone 7", + "ua": "Mozilla/5.0 (Linux; Android 10; ASUS_I002D) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.81 Mobile Safari/537.36", + "expect": { + "vendor": "ASUS", + "model": "I002D", + "type": "mobile" + } + }, + { + "desc": "ASUS Zenfone 7 Pro", + "ua": "Mozilla/5.0 (Linux; Android 10; ZS671KS) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.72 Mobile Safari/537.36", + "expect": { + "vendor": "ASUS", + "model": "ZS671KS", + "type": "mobile" + } + }, + { + "desc": "ASUS Zenfone Max Pro (M1)", + "ua": "Mozilla/5.0 (Linux; Android 8.1; ASUS_X00TD Build/OPM1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.137 Mobile Safari/537.36", + "expect": { + "vendor": "ASUS", + "model": "X00TD", + "type": "mobile" + } + }, + { + "desc": "ASUS Zenfone Max M2", + "ua": "Mozilla/5.0 (Linux; Android 8.1; ASUS_X01AD) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.99 Mobile Safari/537.36", + "expect": { + "vendor": "ASUS", + "model": "X01AD", + "type": "mobile" + } + }, + { + "desc": "ASUS Zenfone Max Pro M2", + "ua": "Mozilla/5.0 (Linux; Android 8.1; ASUS_X01BDA) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.99 Mobile Safari/537.36", + "expect": { + "vendor": "ASUS", + "model": "X01BDA", + "type": "mobile" + } + }, + { + "desc": "ASUS Zenfone Go", + "ua": "Mozilla/5.0 (Linux; Android 6.0; ASUS_X009DA Build/MMB29M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Mobile Safari/537.36", + "expect": { + "vendor": "ASUS", + "model": "X009DA", + "type": "mobile" + } + }, { "desc": "Acer Iconia A1-810", "ua": "Mozilla/5.0 (Linux; Android 4.2.2; A1-810 Build/JDQ39) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.109 Safari/537.36", @@ -34,6 +142,42 @@ "type": "tablet" } }, + { + "desc": "BlackBerry Priv", + "ua": "User-Agent: Mozilla/5.0 (Linux; Android 5.1.1; STV100-1 Build/LMY47V; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/46.0.2490.76 Mobile Safari/537.36", + "expect": { + "vendor": "BlackBerry", + "model": "STV100-1", + "type": "mobile" + } + }, + { + "desc": "BlackBerry Keyone", + "ua": "Mozilla/5.0 (Linux; Android 8.1.0; BBB100-1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.111 Mobile Safari/537.36", + "expect": { + "vendor": "BlackBerry", + "model": "BBB100-1", + "type": "mobile" + } + }, + { + "desc": "BlackBerry Key2", + "ua": "Mozilla/5.0 (Linux; Android 8.1.0; BBF100-1 Build/OPM1.171019.026) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.91 Mobile Safari/537.36", + "expect": { + "vendor": "BlackBerry", + "model": "BBF100-1", + "type": "mobile" + } + }, + { + "desc": "BlackBerry Key2 LE", + "ua": "User-Agent: Mozilla/5.0 (Linux; Android 8.1.0; BBE100-1 Build/OPM1.171019.026) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497 Mobile Safari/537.36", + "expect": { + "vendor": "BlackBerry", + "model": "BBE100-1", + "type": "mobile" + } + }, { "desc": "Desktop (IE11 with Tablet string)", "ua": "Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; .NET4.0E; .NET4.0C; .NET CLR 3.5.30729; .NET CLR 2.0.50727; .NET CLR 3.0.30729; Tablet PC 2.0; GWX:MANAGED; rv:11.0) like Gecko", @@ -52,6 +196,15 @@ "type": "mobile" } }, + { + "desc": "Fairphone 1U", + "ua": "Mozilla/5.0 (Linux; U; Android 4.2.2; FP1U Build/JDQ39) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30", + "expect": { + "vendor": "Fairphone", + "model": "FP1U", + "type": "mobile" + } + }, { "desc": "HTC Desire 820", "ua": "Mozilla/5.0 (Linux; Android 6.0.1; HTC Desire 820 Build/MMB29M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.76 Mobile Safari/537.36", @@ -65,8 +218,8 @@ "desc": "HTC Evo Shift 4G", "ua": "Mozilla/5.0 (Linux; U; Android 2.3.4; en-us; Sprint APA7373KT Build/GRJ22) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0", "expect": { - "vendor": "HTC", - "model": "Evo Shift 4G", + "vendor": "Sprint", + "model": "APA7373KT", "type": "mobile" } }, @@ -125,216 +278,738 @@ } }, { - "desc": "iPod", - "ua": "Mozilla/5.0 (iPod touch; CPU iPhone OS 7_0_4 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11B554a Safari/9537.53", + "desc": "iPad Air", + "ua": "Mozilla/5.0 (iPad; CPU OS 12_4_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 [FBAN/FBIOS;FBDV/iPad4,1;FBMD/iPad;FBSN/iOS;FBSV/12.4.5;FBSS/2;FBID/tablet;FBLC/en_US;FBOP/5;FBCR/]", + "expect": { + "vendor": "Apple", + "model": "iPad", + "type": "tablet" + } + }, + { + "desc": "iPad using Facebook Browser", + "ua": "Mozilla/5.0 (iPad; CPU OS 14_4_2 like Mac OS X) WebKit/8610 (KHTML, like Gecko) Mobile/18D70 [FBAN/FBIOS;FBDV/iPad7,11;FBMD/iPad;FBSN/iOS;FBSV/14.4.2;FBSS/2;FBID/tablet;FBLC/en_US;FBOP/5]", + "expect": { + "vendor": "Apple", + "model": "iPad", + "type": "tablet" + } + }, + { + "desc": "iPod", + "ua": "Mozilla/5.0 (iPod touch; CPU iPhone OS 7_0_4 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11B554a Safari/9537.53", + "expect": { + "vendor": "Apple", + "model": "iPod touch", + "type": "mobile" + } + }, + { + "desc": "Lenovo Tab 2", + "ua": "Mozilla/5.0 (Linux; Android 5.0.1; Lenovo TAB 2 A7-30HC Build/LRX21M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/74.0.3729.157 Safari/537.36", + "expect": { + "vendor": "Lenovo", + "model": "TAB 2 A7", + "type": "tablet" + } + }, + { + "desc": "Lenovo Phone", + "ua": "Mozilla/5.0 (Linux; Android 6.0; Lenovo PB2-650M Build/MRA58K; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/89.0.4389.105 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/311.0.0.44.117;]", + "expect": { + "vendor": "Lenovo", + "model": "PB2-650M", + "type": "mobile" + } + }, + { + "desc": "Lenovo Tab 3 Pro", + "ua": "Mozilla/5.0 (Linux; Android 6.0.1; Lenovo YT3-X90F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.99 Safari/537.36", + "expect": { + "vendor": "Lenovo", + "model": "YT3-X90F", + "type": "tablet" + } + }, + { + "desc": "Lenovo Tab 4", + "ua": "Mozilla/5.0 (Linux; Android 7.1.1; Lenovo TB-X304F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.99 Safari/537.36", + "expect": { + "vendor": "Lenovo", + "model": "TB-X304F", + "type": "tablet" + } + }, + { + "desc": "Lenovo Tab 4", + "ua": "Mozilla/5.0 (Linux; Android 4.4.2; Lenovo TAB 2 A7-30HC) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36", + "expect": { + "vendor": "Lenovo", + "model": "TAB 2 A7", + "type": "tablet" + } + }, + { + "desc": "Lenovo Tab 7 Essential", + "ua": "Mozilla/5.0 (Linux; Android 7.0; Lenovo TB-7304X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36", + "expect": { + "vendor": "Lenovo", + "model": "TB-7304X", + "type": "tablet" + } + }, + { + "desc": "Lenovo Tab M10", + "ua": "Mozilla/5.0 (Linux; arm_64; Android 9; Lenovo TB-X606F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.127 YaBrowser/20.9.4.99.01 Safari/537.36", + "expect": { + "vendor": "Lenovo", + "model": "TB-X606F", + "type": "tablet" + } + }, + { + "desc": "LG K500", + "ua": "Mozilla/5.0 (Linux; Android 6.0.1; LG-K500 Build/MMB29M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.111 Mobile Safari/537.36", + "expect": { + "vendor": "LG", + "model": "K500", + "type": "mobile" + } + }, + { + "desc": "LG Nexus 4", + "ua": "Mozilla/5.0 (Linux; Android 4.2.1; Nexus 4 Build/JOP40D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Mobile Safari/535.19", + "expect": { + "vendor": "LG", + "model": "Nexus 4", + "type": "mobile" + } + }, + { + "desc": "LG Nexus 4", + "ua": "Mozilla/5.0 (Linux; U; Android 4.3; en-us; Google Nexus 4 - 4.3 - API 18 - 768x1280 Build/JLS36G) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30", + "expect": { + "vendor": "LG", + "model": "Nexus 4", + "type": "mobile" + } + }, + { + "desc": "LG Nexus 5", + "ua": "Mozilla/5.0 (Linux; Android 4.2.1; en-us; Nexus 5 Build/JOP40D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Mobile Safari/535.19", + "expect": { + "vendor": "LG", + "model": "Nexus 5", + "type": "mobile" + } + }, + { + "desc": "LG Wing", + "ua": "Mozilla/5.0 (Linux; Android 10; LM-F100N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.101 Mobile Safari/537.36", + "expect": { + "vendor": "LG", + "model": "LM-F100N", + "type": "mobile" + } + }, + { + "desc": "LG Smart TV", + "ua": "Mozilla/5.0 (DirectFB; U; Linux mips; en) AppleWebKit/528.5+ (KHTML, like Gecko, Safari/528.5+) LG Browser (; LG NetCast.TV-2011)", + "expect": { + "vendor": "LG", + "model": "undefined", + "type": "smarttv" + } + }, + { + "desc": "LG Smart TV", + "ua": "Mozilla/5.0 (Linux; NetCast; U) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/53.0.2785 34 Safari/537.31 SmartTV/8.5", + "expect": { + "vendor": "LG", + "model": "undefined", + "type": "smarttv" + } + }, + { + "desc": "Meizu M5 Note", + "ua": "Mozilla/5.0 (Linux; Android 6.0; M5 Note Build/MRA58K; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/53.0.2785.49 Mobile MQQBrowser/6.2 TBS/043024 Safari/537.36 MicroMessenger/6.5.7.1040 NetType/WIFI Language/zh_CN", + "expect": { + "vendor": "Meizu", + "model": "M5 Note", + "type": "mobile" + } + }, + { + "desc": "Microsoft Lumia 950", + "ua": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Mobile Safari/537.36 Edge/13.10586", + "expect": { + "vendor": "Microsoft", + "model": "Lumia 950", + "type": "mobile" + } + }, + { + "desc": "Microsoft Surface Duo", + "ua": "Dalvik/2.1.0 (Linux; U; Android 10; Surface Duo Build/2020.1014.61)", + "expect": { + "vendor": "Microsoft", + "model": "Surface Duo", + "type": "tablet" + } + }, + { + "desc": "Motorola Moto X", + "ua": "Mozilla/5.0 (Linux; Android 4.4.4; XT1097 Build/KXE21.187-38) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.109 Mobile Safari/537.36", + "expect": { + "vendor": "Motorola", + "model": "XT1097", + "type": "mobile" + } + }, + { + "desc" : "Meizu M3S", + "ua" : "Mozilla/5.0 (X11; Linux; Android 5.1; MZ-M3s Build/LMY47I) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrom/45.0.2454.94 Mobile Safari/537.36", + "expect" : + { + "vendor" : "Meizu", + "model" : "M3s", + "type" : "mobile" + } + }, + { + "desc" : "Microsoft Lumia 950", + "ua" : "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Mobile Safari/537.36 Edge/13.10586", + "expect" : + { + "vendor" : "Microsoft", + "model" : "Lumia 950", + "type" : "mobile" + } + }, + { + "desc": "Motorola Nexus 6", + "ua": "Mozilla/5.0 (Linux; Android 5.1.1; Nexus 6 Build/LYZ28E) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.20 Mobile Safari/537.36", + "expect": { + "vendor": "Motorola", + "model": "Nexus 6", + "type": "mobile" + } + }, + { + "desc": "Motorola Droid RAZR 4G", + "ua": "Mozilla/5.0 (Linux; U; Android 2.3; xx-xx; DROID RAZR 4G Build/6.5.1-73_DHD-11_M1-29) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1", + "expect": { + "vendor": "Motorola", + "model": "DROID RAZR 4G", + "type": "mobile" + } + }, + { + "desc": "Motorola RAZR 2019", + "ua": "Mozilla/5.0 (Linux; Android 9; motorola razr) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/11.1 Chrome/75.0.3770.143 Mobile Safari/537.36", + "expect": { + "vendor": "Motorola", + "model": "razr", + "type": "mobile" + } + }, + { + "desc": "iPhone", + "ua": "Mozilla/5.0 (iPhone; CPU iPhone OS 7_0 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11A465 Safari/9537.53", + "expect": { + "vendor": "Apple", + "model": "iPhone", + "type": "mobile" + } + }, + { + "desc": "iPhone SE", + "ua": "Mozilla/5.0 (iPhone; CPU iPhone OS 13_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 [FBAN/FBIOS;FBDV/iPhone8,4;FBMD/iPhone;FBSN/iOS;FBSV/13.3.1;FBSS/2;FBID/phone;FBLC/en_US;FBOP/5;FBCR/]", + "expect": { + "vendor": "Apple", + "model": "iPhone", + "type": "mobile" + } + }, + { + "desc": "iPhone SE using Facebook App", + "ua": "Mozilla/5.0 (iPhone; CPU iPhone OS 13_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 [FBAN/FBIOS;FBDV/iPhone8,4;FBMD/iPhone;FBSN/iOS;FBSV/13.3.1;FBSS/2;FBID/phone;FBLC/en_US;FBOP/5;FBCR/]", + "expect": { + "vendor": "Apple", + "model": "iPhone", + "type": "mobile" + } + }, + { + "desc": "iPhone 11 Pro Max", + "ua": "Mozilla/5.0 (iPhone; CPU iPhone OS 13_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 [FBAN/FBIOS;FBDV/iPhone12,5;FBMD/iPhone;FBSN/iOS;FBSV/13.3.1;FBSS/3;FBID/phone;FBLC/en_US;FBOP/5;FBCR/]", + "expect": { + "vendor": "Apple", + "model": "iPhone", + "type": "mobile" + } + }, + { + "desc": "iPhone XS", + "ua": "Mozilla/5.0 (iPhone; CPU iPhone OS 13_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 [FBAN/FBIOS;FBDV/iPhone11,2;FBMD/iPhone;FBSN/iOS;FBSV/13.3.1;FBSS/3;FBID/phone;FBLC/en_US;FBOP/5;FBCR/]", + "expect": { + "vendor": "Apple", + "model": "iPhone", + "type": "mobile" + } + }, + { + "desc": "iPod touch", + "ua": "Mozilla/5.0 (iPod touch; CPU iPhone OS 7_0_2 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11A501 Safari/9537.53", + "expect": { + "vendor": "Apple", + "model": "iPod touch", + "type": "mobile" + } + }, + { + "desc": "Moto X", + "ua": "Mozilla/5.0 (Linux; U; Android 4.2; xx-xx; XT1058 Build/13.9.0Q2.X-70-GHOST-ATT_LE-2) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30", + "expect": { + "vendor": "Motorola", + "model": "XT1058", + "type": "mobile" + } + }, + { + "desc": "Motorola Moto g(6) Play", + "ua": "Mozilla/5.0 (Linux; Android 9; moto g(6) play) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.136 Mobile Safari/537.36", + "expect": { + "vendor": "Motorola", + "model": "moto g(6) play", + "type": "mobile" + } + }, + { + "desc": "Motorola Moto g(7) Supra", + "ua": "Mozilla/5.0 (Linux; Android 9; moto g(7) supra Build/PCOS29.114-134-2; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/73.0.3683.90 Mobile Safari/537.36", + "expect": { + "vendor": "Motorola", + "model": "moto g(7) supra", + "type": "mobile" + } + }, + { + "desc": "Motorola Moto E", + "ua": "Mozilla/5.0 (Linux; Android 7.1.1; Moto E (4) Build/NDQS26.69-64-11-7; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/56.0.2924.87 Mobile Safari/537.36", + "expect": { + "vendor": "Motorola", + "model": "Moto E (4)", + "type": "mobile" + } + }, + { + "desc": "Nokia3xx", + "ua": "Nokia303/14.87 CLDC-1.1", + "expect": { + "vendor": "Nokia", + "model": "303", + "type": "mobile" + } + }, + { + "desc": "Nokia 3.2", + "ua": "Mozilla/5.0 (Linux; Android 10; Nokia 3.2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Mobile Safari/537.36", + "expect": { + "vendor": "Nokia", + "model": "3.2", + "type": "mobile" + } + }, + { + "desc": "Nokia N9", + "ua": "Mozilla/5.0 (MeeGo; NokiaN9) AppleWebKit/534.13 (KHTML, like Gecko) NokiaBrowser/8.5.0 Mobile Safari/534.13", + "expect": { + "vendor": "Nokia", + "model": "N9", + "type": "mobile" + } + }, + { + "desc": "Nokia 2720 Flip", + "ua": "Mozilla/5.0 (Mobile; Nokia_2720_Flip; rv:48.0) Gecko/48.0 Firefox/48.0 KAIOS/2.5.2", + "expect": { + "vendor": "Nokia", + "model": "2720 Flip", + "type": "mobile" + } + }, + { + "desc": "OnePlus One", + "ua": "Mozilla/5.0 (Linux; Android 4.4.4; A0001 Build/KTU84Q) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.59 Mobile Safari/537.36", + "expect": { + "vendor": "OnePlus", + "model": "1", + "type": "mobile" + } + }, + { + "desc": "OnePlus One", + "ua": "Mozilla/5.0 (Linux; Android 4.4.2; OnePlus One A0001 Build/KVT49L) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.117 Mobile Safari/537.36", + "expect": { + "vendor": "OnePlus", + "model": "1", + "type": "mobile" + } + }, + { + "desc": "OnePlus 3", + "ua": "Mozilla/5.0 (Linux; Android 7.1.1; ONEPLUS A3000 Build/NMF26F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.98 Mobile Safari/537.36", + "expect": { + "vendor": "OnePlus", + "model": "A3000", + "type": "mobile" + } + }, + { + "desc": "OnePlus 6", + "ua": "Mozilla/5.0 (Linux; Android 9; ONEPLUS A6003) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.89 Mobile Safari/537.36", + "expect": { + "vendor": "OnePlus", + "model": "A6003", + "type": "mobile" + } + }, + { + "desc": "OnePlus 6T", + "ua": "Mozilla/5.0 (Linux; Android 9; ONEPLUS A6010) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.96 Mobile Safari/537.36", + "expect": { + "vendor": "OnePlus", + "model": "A6010", + "type": "mobile" + } + }, + { + "desc": "OnePlus 8T", + "ua": "Mozilla/5.0 (Linux; Android 11; KB2005) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.127 Mobile Safari/537.36", + "expect": { + "vendor": "OnePlus", + "model": "KB2005", + "type": "mobile" + } + }, + { + "desc": "OnePlus 8 Pro", + "ua": "Mozilla/5.0 (Linux; Android 10; IN2025) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.119 Mobile Safari/537.36", + "expect": { + "vendor": "OnePlus", + "model": "IN2025", + "type": "mobile" + } + }, + { + "desc": "OnePlus Nord N100", + "ua": "Mozilla/5.0 (Linux; Android 10; BE2015 Build/QKQ1.200719.002; xx-xx) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/83.0.4103.106 Mobile Safari/537.36", + "expect": { + "vendor": "OnePlus", + "model": "BE2015", + "type": "mobile" + } + }, + { + "desc": "OnePlus Nord N10 5G", + "ua": "Mozilla/5.0 (Linux; Android 10; BE2029) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.185 Mobile Safari/537.36", + "expect": { + "vendor": "OnePlus", + "model": "BE2029", + "type": "mobile" + } + }, + { + "desc": "OPPO Neo", + "ua": "Mozilla/5.0 (Linux; U; Android 4.2.2; zh-cn; R831T Build/JDQ39) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 OppoBrowser/3.3.2 Mobile Safari/534.30", + "expect": { + "vendor": "OPPO", + "model": "R831T", + "type": "mobile" + } + }, + { + "desc": "OPPO R7s", + "ua": "Mozilla/5.0 (Linux; U; Android 4.4.4; zh-cn; OPPO R7s Build/KTU84P) AppleWebKit/537.36 (KHTML, like Gecko)Version/4.0 Chrome/37.0.0.0 MQQBrowser/7.1 Mobile Safari/537.36", + "expect": { + "vendor": "OPPO", + "model": "R7s", + "type": "mobile" + } + }, + { + "desc": "OPPO A3s", + "ua": "Mozilla/5.0 (Linux; Android 8.1; CPH1803 Build/OPM1.171019.026; xx-xx) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.126 Mobile Safari/537.36", + "expect": { + "vendor": "OPPO", + "model": "CPH1803", + "type": "mobile" + } + }, + { + "desc": "OPPO A12", + "ua": "Mozilla/5.0 (Linux; Android 9; CPH2083) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.116 Mobile Safari/537.36", + "expect": { + "vendor": "OPPO", + "model": "CPH2083", + "type": "mobile" + } + }, + { + "desc": "OPPO Reno", + "ua": "Mozilla/5.0 (Linux; Android 9; PCAT00 Build/PKQ1.190101.001; xx-xx) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/70.0.3538.110 Mobile Safari/537.36", + "expect": { + "vendor": "OPPO", + "model": "PCAT00", + "type": "mobile" + } + }, + { + "desc": "OPPO Reno3 Pro 5G", + "ua": "Mozilla/5.0 (Linux; Android 10; PCLM50) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.117 Mobile Safari/537.36", + "expect": { + "vendor": "OPPO", + "model": "PCLM50", + "type": "mobile" + } + }, + { + "desc": "OPPO Reno4 SE", + "ua": "Mozilla/5.0 (Linux; U; Android 10; xx-xx; PEAM00 Build/QP1A.190711.020) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/70.0.3538.80 Mobile Safari/537.36", + "expect": { + "vendor": "OPPO", + "model": "PEAM00", + "type": "mobile" + } + }, + { + "desc": "OPPO Reno4 5G", + "ua": "Mozilla/5.0 (Linux; Android 10; PDPM00 Build/QKQ1.200216.002; xx-xx) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/76.0.3809.89 Mobile Safari/537.36", + "expect": { + "vendor": "OPPO", + "model": "PDPM00", + "type": "mobile" + } + }, + { + "desc": "OPPO Reno4 Pro 5G", + "ua": "Mozilla/5.0 (Linux; U; Android 10; xx-xx; PDNT00 Build/QKQ1.200216.002) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/70.0.3538.80 Mobile Safari/537.36", "expect": { - "vendor": "Apple", - "model": "iPod touch", + "vendor": "OPPO", + "model": "PDNT00", "type": "mobile" } }, { - "desc": "Lenovo Tab 2", - "ua": "Mozilla/5.0 (Linux; Android 5.0.1; Lenovo TAB 2 A7-30HC Build/LRX21M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/74.0.3729.157 Safari/537.36", + "desc": "OPPO Find X", + "ua": "Mozilla/5.0 (Linux; Android 8.1; PAFM00 Build/OPM1.171019.026) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Mobile Safari/537.36", "expect": { - "vendor": "Lenovo", - "model": "TAB 2 A7", - "type": "tablet" + "vendor": "OPPO", + "model": "PAFM00", + "type": "mobile" } }, { - "desc": "LG Nexus 4", - "ua": "Mozilla/5.0 (Linux; Android 4.2.1; Nexus 4 Build/JOP40D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Mobile Safari/535.19", + "desc": "OPPO Find 7a", + "ua": "Mozilla/5.0 (Linux; U; Android 4.3; xx-xx; X9007 Build/JLS36C) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30", "expect": { - "vendor": "LG", - "model": "Nexus 4", + "vendor": "OPPO", + "model": "X9007", "type": "mobile" } }, { - "desc": "LG Nexus 5", - "ua": "Mozilla/5.0 (Linux; Android 4.2.1; en-us; Nexus 5 Build/JOP40D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Mobile Safari/535.19", + "desc": "Realme C1", + "ua": "Mozilla/5.0 (Linux; Android 8.1; RMX1811 Build/OPM1.171019.026) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.126 Mobile Safari/537.36", "expect": { - "vendor": "LG", - "model": "Nexus 5", + "vendor": "Realme", + "model": "RMX1811", "type": "mobile" } }, { - "desc": "Meizu M5 Note", - "ua": "Mozilla/5.0 (Linux; Android 6.0; M5 Note Build/MRA58K; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/53.0.2785.49 Mobile MQQBrowser/6.2 TBS/043024 Safari/537.36 MicroMessenger/6.5.7.1040 NetType/WIFI Language/zh_CN", + "desc": "Realme Narzo 20", + "ua": "Mozilla/5.0 (Linux; U; Android 10; xx-xx; RMX2193 Build/QP1A.190711.020) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/70.0.3538.80 Mobile Safari/537.36", "expect": { - "vendor": "Meizu", - "model": "M5 Note", + "vendor": "Realme", + "model": "RMX2193", "type": "mobile" } }, { - "desc": "Microsoft Lumia 950", - "ua": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Mobile Safari/537.36 Edge/13.10586", + "desc": "Philips SmartTV", + "ua": "Opera/9.80 HbbTV/1.1.1 (; Philips; ; ; ; ) NETTV/4.0.2; en) Version/11.60", "expect": { - "vendor": "Microsoft", - "model": "Lumia 950", - "type": "mobile" + "vendor": "Philips", + "model": "", + "type": "smarttv" } }, { - "desc": "Motorola Moto X", - "ua": "Mozilla/5.0 (Linux; Android 4.4.4; XT1097 Build/KXE21.187-38) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.109 Mobile Safari/537.36", + "desc": "Kindle Fire HD", + "ua": "Mozilla/5.0 (Linux; U; Android 4.0.3; en-us; KFTT Build/IML74K) AppleWebKit/535.19 (KHTML, like Gecko) Silk/3.4 Mobile Safari/535.19 Silk-Accelerated=true", "expect": { - "vendor": "Motorola", - "model": "XT1097", - "type": "mobile" + "vendor": "Amazon", + "model": "KFTT", + "type": "tablet" } }, { - "desc" : "Meizu M3S", - "ua" : "Mozilla/5.0 (X11; Linux; Android 5.1; MZ-M3s Build/LMY47I) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrom/45.0.2454.94 Mobile Safari/537.36", - "expect" : - { - "vendor" : "Meizu", - "model" : "M3s", - "type" : "mobile" + "desc": "Kindle Fire HD", + "ua": "Mozilla/5.0 (Linux; U; Android 4.0.3; en-us; KFTT) AppleWebKit/535.19 (KHTML, like Gecko) Silk/3.4 Mobile Safari/535.19 Silk-Accelerated=true", + "expect": { + "vendor": "Amazon", + "model": "KFTT", + "type": "tablet" } }, { - "desc" : "Microsoft Lumia 950", - "ua" : "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Mobile Safari/537.36 Edge/13.10586", - "expect" : - { - "vendor" : "Microsoft", - "model" : "Lumia 950", - "type" : "mobile" + "desc": "Samsung Galaxy A21s", + "ua": "Mozilla/5.0 (Linux; Android 10; SAMSUNG SM-A217F) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/11.0 Chrome/75.0.3770.143 Mobile Safari/537.36", + "expect": { + "vendor": "Samsung", + "model": "SM-A217F", + "type": "mobile" } }, { - "desc": "Motorola Nexus 6", - "ua": "Mozilla/5.0 (Linux; Android 5.1.1; Nexus 6 Build/LYZ28E) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.20 Mobile Safari/537.36", + "desc": "Samsung Galaxy A31", + "ua": "Mozilla/5.0 (Linux; Android 10; SM-A315G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Mobile Safari/537.36", "expect": { - "vendor": "Motorola", - "model": "Nexus 6", + "vendor": "Samsung", + "model": "SM-A315G", "type": "mobile" } }, { - "desc": "Motorola Droid RAZR 4G", - "ua": "Mozilla/5.0 (Linux; U; Android 2.3; xx-xx; DROID RAZR 4G Build/6.5.1-73_DHD-11_M1-29) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1", + "desc": "Samsung Galaxy A50", + "ua": "Mozilla/5.0 (Linux; Android 9; SM-A505F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.105 Mobile Safari/537.36", "expect": { - "vendor": "Motorola", - "model": "DROID RAZR 4G", + "vendor": "Samsung", + "model": "SM-A505F", "type": "mobile" } }, { - "desc": "iPhone", - "ua": "Mozilla/5.0 (iPhone; CPU iPhone OS 7_0 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11A465 Safari/9537.53", + "desc": "Samsung Galaxy A80", + "ua": "Mozilla/5.0 (Linux; Android 9; SM-A805F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.112 Mobile Safari/537.36", "expect": { - "vendor": "Apple", - "model": "iPhone", + "vendor": "Samsung", + "model": "SM-A805F", "type": "mobile" } }, { - "desc": "Motorola Droid RAZR 4G", - "ua": "Mozilla/5.0 (iPod touch; CPU iPhone OS 7_0_2 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11A501 Safari/9537.53", + "desc": "Samsung Galaxy Fold", + "ua": "Mozilla/5.0 (Linux; Android 9; SAMSUNG SM-F900U Build/PPR1.180610.011) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/9.2 Chrome/67.0.3396.87 Mobile Safari/537.36", "expect": { - "vendor": "Apple", - "model": "iPod touch", + "vendor": "Samsung", + "model": "SM-F900U", "type": "mobile" } }, { - "desc": "Moto X", - "ua": "Mozilla/5.0 (Linux; U; Android 4.2; xx-xx; XT1058 Build/13.9.0Q2.X-70-GHOST-ATT_LE-2) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30", + "desc": "Samsung Galaxy Z Flip", + "ua": "Mozilla/5.0 (Linux; Android 10; SM-F700N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.136 Mobile Safari/537.36", "expect": { - "vendor": "Motorola", - "model": "XT1058", + "vendor": "Samsung", + "model": "SM-F700N", "type": "mobile" } }, { - "desc": "Nokia3xx", - "ua": "Nokia303/14.87 CLDC-1.1", + "desc": "Samsung Galaxy Z Fold2", + "ua": "Mozilla/5.0 (Linux; Android 10; SM-F916B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Mobile Safari/537.36", "expect": { - "vendor": "Nokia", - "model": "303", + "vendor": "Samsung", + "model": "SM-F916B", "type": "mobile" } }, { - "desc": "OnePlus One", - "ua": "Mozilla/5.0 (Linux; Android 4.4.4; A0001 Build/KTU84Q) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.59 Mobile Safari/537.36", + "desc": "Samsung Galaxy S10E", + "ua": "Mozilla/5.0 (Linux; Android 9; SM-G970F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Mobile Safari/537.36", "expect": { - "vendor": "OnePlus", - "model": "1", + "vendor": "Samsung", + "model": "SM-G970F", "type": "mobile" } }, { - "desc": "OnePlus 3", - "ua": "Mozilla/5.0 (Linux; Android 7.1.1; ONEPLUS A3000 Build/NMF26F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.98 Mobile Safari/537.36", + "desc": "Samsung Galaxy Note 10+", + "ua": "Mozilla/5.0 (Linux; Android 9; SM-N976V) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.89 Mobile Safari/537.36", "expect": { - "vendor": "OnePlus", - "model": "A3000", + "vendor": "Samsung", + "model": "SM-N976V", "type": "mobile" } }, { - "desc": "OPPO R7s", - "ua": "Mozilla/5.0 (Linux; U; Android 4.4.4; zh-cn; OPPO R7s Build/KTU84P) AppleWebKit/537.36 (KHTML, like Gecko)Version/4.0 Chrome/37.0.0.0 MQQBrowser/7.1 Mobile Safari/537.36", + "desc": "Samsung SM-C5000", + "ua": "Mozilla/5.0 (Linux; Android 6.0.1; SM-C5000 Build/MMB29M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/51.0.2704.81 Mobile Safari/537.36 wkbrowser 4.1.35 3065", "expect": { - "vendor": "OPPO", - "model": "R7s", + "vendor": "Samsung", + "model": "SM-C5000", "type": "mobile" } }, { - "desc": "Philips SmartTV", - "ua": "Opera/9.80 HbbTV/1.1.1 (; Philips; ; ; ; ) NETTV/4.0.2; en) Version/11.60", + "desc": "Samsung Galaxy Note 8", + "ua": "Mozilla/5.0 (Linux; Android 4.2.2; GT-N5100 Build/JDQ39) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.141 Safari/537.36", "expect": { - "vendor": "Philips", - "model": "", - "type": "smarttv" + "vendor": "Samsung", + "model": "GT-N5100", + "type": "tablet" } }, { - "desc": "Kindle Fire HD", - "ua": "Mozilla/5.0 (Linux; U; Android 4.0.3; en-us; KFTT Build/IML74K) AppleWebKit/535.19 (KHTML, like Gecko) Silk/3.4 Mobile Safari/535.19 Silk-Accelerated=true", + "desc": "Samsung SM-T231", + "ua": "Mozilla/5.0 (Linux; Android 4.4.2; SM-T231 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.135 Safari/537.36", "expect": { - "vendor": "Amazon", - "model": "KFTT", + "vendor": "Samsung", + "model": "SM-T231", "type": "tablet" } }, { - "desc": "Samsung Galaxy Note 8", - "ua": "Mozilla/5.0 (Linux; Android 4.2.2; GT-N5100 Build/JDQ39) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.141 Safari/537.36", + "desc": "Samsung Galaxy Tab 6 Lite", + "ua": "Mozilla/5.0 (Linux; Android 10; SAMSUNG SM-P610) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/12.0 Chrome/79.0.3945.136 Safari/537.36", "expect": { "vendor": "Samsung", - "model": "GT-N5100", + "model": "SM-P610", "type": "tablet" } }, { - "desc": "Samsung SM-C5000", - "ua": "Mozilla/5.0 (Linux; Android 6.0.1; SM-C5000 Build/MMB29M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/51.0.2704.81 Mobile Safari/537.36 wkbrowser 4.1.35 3065", + "desc": "Samsung Galaxy Tab A 9.7", + "ua": "Mozilla/5.0 (Linux; Android 7.1.1; SM-P550 Build/NMF26X; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/89.0.4389.90 Safari/537.36", "expect": { "vendor": "Samsung", - "model": "SM-C5000", - "type": "mobile" + "model": "SM-P550", + "type": "tablet" } }, { - "desc": "Samsung SM-T231", - "ua": "Mozilla/5.0 (Linux; Android 4.4.2; SM-T231 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.135 Safari/537.36", + "desc": "Samsung Galaxy Tab A 10.1", + "ua": " Mozilla/5.0 (Linux; Android 10; SAMSUNG SM-T515) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/13.0 Chrome/83.0.4103.106 Safari/537.36", "expect": { "vendor": "Samsung", - "model": "SM-T231", + "model": "SM-T515", + "type": "tablet" + } + }, + { + "desc": "Samsung Galaxy Tab S7", + "ua": "Mozilla/5.0 (Linux; Android 10; SM-T870) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36", + "expect": { + "vendor": "Samsung", + "model": "SM-T870", "type": "tablet" } }, { - "desc": "Samsung SM-T700", + "desc": "Samsung Galaxy Tab S", "ua": "Mozilla/5.0 (Linux; Android 4.4.2; SM-T700 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.135 Safari/537.36", "expect": { "vendor": "Samsung", @@ -343,7 +1018,7 @@ } }, { - "desc": "Samsung SM-T520", + "desc": "Samsung Galaxy Tab Pro 10.1", "ua": "Mozilla/5.0 (Linux; Android 4.4.2; SM-T520 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.135 Safari/537.36", "expect": { "vendor": "Samsung", @@ -351,6 +1026,15 @@ "type": "tablet" } }, + { + "desc": "Samsung Note 10.1", + "ua": "Mozilla/5.0 (Linux; Android 5.1.1; SM-P605) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36", + "expect": { + "vendor": "Samsung", + "model": "SM-P605", + "type": "tablet" + } + }, { "desc": "Samsung SmartTV2011", "ua": "HbbTV/1.1.1 (;;;;;) Maple;2011", @@ -450,6 +1134,42 @@ "type": "mobile" } }, + { + "desc": "Sony Xperia L4", + "ua": "Mozilla/5.0 (Linux; Android 9; XQ-AD51) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.83 Mobile Safari/537.36", + "expect": { + "vendor": "Sony", + "model": "XQ-AD51", + "type": "mobile" + } + }, + { + "desc": "Sony Xperia 1ii", + "ua": "Mozilla/5.0 (Linux; Android 10; XQ-AT51) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Mobile Safari/537.36", + "expect": { + "vendor": "Sony", + "model": "XQ-AT51", + "type": "mobile" + } + }, + { + "desc": "Sony Xperia 10ii", + "ua": "Mozilla/5.0 (Linux; Android 10; XQ-AU52) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Mobile Safari/537.36", + "expect": { + "vendor": "Sony", + "model": "XQ-AU52", + "type": "mobile" + } + }, + { + "desc": "Sony Xperia Pro", + "ua": "Mozilla/5.0 (Linux; Android 10; XQ-AQ52) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.185 Mobile Safari/537.36", + "expect": { + "vendor": "Sony", + "model": "XQ-AQ52", + "type": "mobile" + } + }, { "desc": "Sony SGP521 (Xperia Z2 Tablet)", "ua": "Mozilla/5.0 (Linux; Android 4.4; SGP521 Build/17.1.A.0.432) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.99 Safari/537.36", @@ -459,6 +1179,15 @@ "type": "tablet" } }, + { + "desc": "Sony Xperia Z2 Tablet", + "ua": "Mozilla/5.0 (Linux; Android 5.1.1; SGP561) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.99 Safari/537.36", + "expect": { + "vendor": "Sony", + "model": "Xperia Tablet", + "type": "tablet" + } + }, { "desc": "Sony Tablet S", "ua": "Mozilla/5.0 (Linux; U; Android 3.1; Sony Tablet S Build/THMAS10000) AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13", @@ -477,6 +1206,26 @@ "type": "tablet" } }, + { + "desc" : "Tesla", + "ua" : "Mozilla/5.0 (X11; GNU/Linux) AppleWebKit/601.1 (KHTML, like Gecko) Tesla QtCarBrowser Safari/601.1", + "expect" : + { + "vendor": "Tesla", + "model": "undefined", + "type": "embedded" + } + }, + { + "desc" : "Tesla", + "ua" : "Mozilla/5.0 (X11; GNU/Linux) AppleWebKit/537.36 (KHTML, like Gecko) Chromium/79.0.3945.130 Chrome/79.0.3945.130 Safari/537.36 Tesla/2020.16.2.1-e99c70fff409", + "expect" : + { + "vendor": "Tesla", + "model": "undefined", + "type": "embedded" + } + }, { "desc": "Xiaomi 2013023", "ua": "Mozilla/5.0 (Linux; U; Android 4.2.2; en-US; 2013023 Build/HM2013023) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 UCBrowser/10.0.1.512 U3/0.8.0 Mobile Safari/533.1", @@ -527,34 +1276,106 @@ "ua": "Mozilla/5.0 (Linux; U; Android 6.0.1; zh-cn; MI 5s Plus Build/MXB48T) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/53.0.2785.146 Mobile Safari/537.36 XiaoMi/MiuiBrowser/8.7.1", "expect": { "vendor": "Xiaomi", - "model": "MI 5s Plus", + "model": "MI 5s Plus", + "type": "mobile" + } + }, + { + "desc": "Xiaomi Mi A1", + "ua": "Mozilla/5.0 (Linux; Android 8.0.0; Mi A1 Build/OPR1.170623.026) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.111 Mobile Safari/537.36", + "expect": { + "vendor": "Xiaomi", + "model": "Mi A1", + "type": "mobile" + } + }, + { + "desc": "Xiaomi Mi Note", + "ua": "Mozilla/5.0 (Linux; Android 4.4.4; MI NOTE LTE Build/KTU84P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.76 Mobile Safari/537.36", + "expect": { + "vendor": "Xiaomi", + "model": "MI NOTE LTE", + "type": "mobile" + } + }, + { + "desc": "Xiaomi Mi One Plus", + "ua": "Mozilla/5.0 (Linux; U; Android 4.0.4; en-us; MI-ONE Plus Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30", + "expect": { + "vendor": "Xiaomi", + "model": "MI-ONE Plus", + "type": "mobile" + } + }, + { + "desc": "Xiaomi MI PAD 2", + "ua": "Mozilla/5.0 (Linux; Android 5.1; MI PAD 2 Build/LMY47I; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/60.0.3112.107 Safari/537.36 [FB_IAB/FB4A;FBAV/137.0.0.24.91;]", + "expect": { + "vendor": "Xiaomi", + "model": "MI PAD 2", + "type": "tablet" + } + }, + { + "desc": "Xiaomi MI PAD 4 PLUS", + "ua": "Mozilla/5.0 (Linux; Android 8.1; MI PAD 4 PLUS) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36", + "expect": { + "vendor": "Xiaomi", + "model": "MI PAD 4 PLUS", + "type": "tablet" + } + }, + { + "desc": "Xiaomi POCO X2", + "ua": "Mozilla/5.0 (Linux; Android 10; POCO X2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.136 Mobile Safari/537.36", + "expect": { + "vendor": "Xiaomi", + "model": "POCO X2", + "type": "mobile" + } + }, + { + "desc": "Xiaomi Redmi 4A", + "ua": "Mozilla/5.0 (Linux; Android 6.0; Redmi 4A Build/MMB29M; xx-xx) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/56.0.2924.87 Mobile Safari/537.36", + "expect": { + "vendor": "Xiaomi", + "model": "Redmi 4A", + "type": "mobile" + } + }, + { + "desc": "Xiaomi Redmi K30 5G", + "ua": "Mozilla/5.0 (Linux; Android 10; Redmi K30 5G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.96 Mobile Safari/537.36", + "expect": { + "vendor": "Xiaomi", + "model": "Redmi K30 5G", "type": "mobile" } }, { - "desc": "Xiaomi Mi A1", - "ua": "Mozilla/5.0 (Linux; Android 8.0.0; Mi A1 Build/OPR1.170623.026) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.111 Mobile Safari/537.36", + "desc": "Xiaomi Redmi K30 Pro", + "ua": "Mozilla/5.0 (Linux; Android 10; Redmi K30 Pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Mobile Safari/537.36", "expect": { "vendor": "Xiaomi", - "model": "Mi A1", + "model": "Redmi K30 Pro", "type": "mobile" } }, { - "desc": "Xiaomi Mi Note", - "ua": "Mozilla/5.0 (Linux; Android 4.4.4; MI NOTE LTE Build/KTU84P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.76 Mobile Safari/537.36", + "desc": "Xiaomi Redmi Note 3", + "ua": "Mozilla/5.0 (Linux; Android 6.0.1; Redmi Note 3 Build/MMB29M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.116 Mobile Safari/537.36", "expect": { "vendor": "Xiaomi", - "model": "MI NOTE LTE", + "model": "Redmi Note 3", "type": "mobile" } }, { - "desc": "Xiaomi Mi One Plus", - "ua": "Mozilla/5.0 (Linux; U; Android 4.0.4; en-us; MI-ONE Plus Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30", + "desc": "Xiaomi Redmi Note 9 Pro Max", + "ua": "Mozilla/5.0 (Linux; Android 10; Redmi Note 9 Pro Max) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.99 Mobile Safari/537.36", "expect": { "vendor": "Xiaomi", - "model": "MI-ONE Plus", + "model": "Redmi Note 9 Pro Max", "type": "mobile" } }, @@ -567,6 +1388,69 @@ "type": "console" } }, + { + "desc": "PlayStation 5", + "ua": "Mozilla/5.0 (Playstation; Playstation 5/1.05) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0 Safari/605.1.15", + "expect": { + "vendor": "Sony", + "model": "Playstation 5", + "type": "console" + } + }, + { + "desc": "PlayStation Vita", + "ua": "Mozilla/5.0 (PlayStation Vita 3.52) AppleWebKit/537.73 (KHTML, like Gecko) Silk/3.2", + "expect": { + "vendor": "Sony", + "model": "PlayStation Vita", + "type": "console" + } + }, + { + "desc": "Nintendo Switch", + "ua": "Mozilla/5.0 (Nintendo Switch; WifiWebAuthApplet) AppleWebKit/606.4 (KHTML, like Gecko) NF/6.0.1.15.4 NintendoBrowser/5.1.0.20393", + "expect": { + "vendor": "Nintendo", + "model": "Switch", + "type": "console" + } + }, + { + "desc": "Nintendo WiiU", + "ua": "Mozilla/5.0 (Nintendo WiiU) AppleWebKit/536.30 (KHTML, like Gecko) NX/3.0.4.2.9 NintendoBrowser/4.2.0.11146.EU", + "expect": { + "vendor": "Nintendo", + "model": "WiiU", + "type": "console" + } + }, + { + "desc": "Nintendo Wii", + "ua": "Opera/9.10 (Nintendo Wii; U; ; 1621; en)", + "expect": { + "vendor": "Nintendo", + "model": "Wii", + "type": "console" + } + }, + { + "desc": "Nintendo 3DS", + "ua": "Mozilla/5.0 (Nintendo 3DS; U; ; en) Version/1.7610.EU", + "expect": { + "vendor": "Nintendo", + "model": "3DS", + "type": "console" + } + }, + { + "desc": "Nintendo 3DS", + "ua": "Mozilla/5.0 (New Nintendo 3DS like iPhone) AppleWebKit/536.30 (KHTML, like Gecko) NX/3.0.0.5.15 Mobile NintendoBrowser/1.3.10126.EU", + "expect": { + "vendor": "Nintendo", + "model": "3DS", + "type": "console" + } + }, { "desc": "Galaxy Nexus", "ua": "Mozilla/5.0 (Linux; Android 4.0.4; Galaxy Nexus Build/IMM76B) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.133 Mobile Safari/535.19", @@ -635,7 +1519,8 @@ "ua": "Mozilla/5.0 (X11; Linux armv7l) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.84 Safari/537.36 CrKey/1.22.79313", "expect": { "vendor": "Google", - "model": "Chromecast" + "model": "Chromecast", + "type": "smarttv" } }, { @@ -737,14 +1622,100 @@ "type": "mobile" } }, + { + "desc": "Google Pixel 3a", + "ua": "Mozilla/5.0 (Linux; Android 10; Pixel 3a) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Mobile Safari/537.36", + "expect": { + "vendor": "Google", + "model": "Pixel 3a", + "type": "mobile" + } + }, + { + "desc": "Google Pixel 3a XL", + "ua": "Mozilla/5.0 (Linux; Android 10; Pixel 3a XL) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Mobile Safari/537.36", + "expect": { + "vendor": "Google", + "model": "Pixel 3a XL", + "type": "mobile" + } + }, + { + "desc": "Google Pixel 4", + "ua": "Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Mobile Safari/537.36", + "expect": { + "vendor": "Google", + "model": "Pixel 4", + "type": "mobile" + } + }, + { + "desc": "Google Pixel 4a", + "ua": "Mozilla/5.0 (Linux; Android 10; Pixel 4a) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.83 Mobile Safari/537.36", + "expect": { + "vendor": "Google", + "model": "Pixel 4a", + "type": "mobile" + } + }, + { + "desc": "Google Pixel 4 XL", + "ua": "Mozilla/5.0 (Linux; Android 10; Pixel 4 XL) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Mobile Safari/537.36", + "expect": { + "vendor": "Google", + "model": "Pixel 4 XL", + "type": "mobile" + } + }, + { + "desc": "Google Pixel 5", + "ua": "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.120 Mobile Safari/537.36", + "expect": { + "vendor": "Google", + "model": "Pixel 5", + "type": "mobile" + } + }, { "desc": "Generic Android Device", - "ua": "Mozilla/5.0 (Linux; U; Android 6.0.1; i980 Build/MRA58K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36", + "ua": "Mozilla/5.0 (Linux; U; Android 6.0.1; i980 Build/MRA58K)", "expect": { "vendor": "Generic", "model": "Android 6.0.1" } }, + { + "desc": "Android Phone Unidentified Vendor (docomo F-04K)", + "ua": "Mozilla/5.0 (Linux; Android 8.1.0; F-04K Build/V15R060P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.137 Mobile Safari/537.36", + "expect": { + "model": "F-04K", + "type": "mobile" + } + }, + { + "desc": "Android Phone Unidentified Vendor (docomo SH-02M)", + "ua": "Mozilla/5.0 (Linux; Android 9; SH-02M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.136 Mobile Safari/537.36", + "expect": { + "model": "SH-02M", + "type": "mobile" + } + }, + { + "desc": "Android Tablet Unidentified Vendor (docomo F-02K)", + "ua": "Mozilla/5.0 (Linux; Android 8.1.0; F-02K Build/V44R059G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.109 Safari/537.36", + "expect": { + "model": "F-02K", + "type": "tablet" + } + }, + { + "desc": "Android Tablet Unidentified Vendor (docomo d-02K)", + "ua": "Mozilla/5.0 (Linux; Android 9; d-02K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.136 Safari/537.36", + "expect": { + "model": "d-02K", + "type": "tablet" + } + }, { "desc": "LG VK Series Tablet", "ua": "Mozilla/5.0 (Linux; Android 5.0.2; VK700 Build/LRX22G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.84 Safari/537.36", @@ -853,6 +1824,24 @@ "type": "tablet" } }, + { + "desc": "ZTE-Z431", + "ua": "ZTE-Z431/1.4.0 NetFront/4.2 QTV5.1 Profile/MIDP-2.1 Configuration/CLDC-1.1", + "expect": { + "vendor": "ZTE", + "model": "Z431", + "type": "mobile" + } + }, + { + "desc": "ZTE", + "ua": "Mozilla/5.0 (Linux; U; Android 4.1.2; en-us; ZTE-Z740G Build/JZO54K) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30", + "expect": { + "vendor": "ZTE", + "model": "Z740G", + "type": "mobile" + } + }, { "desc": "ZTE K Series Tablet", "ua": "Mozilla/5.0 (Linux; Android 6.0.1; K88 Build/MMB29M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36", @@ -862,6 +1851,15 @@ "type": "tablet" } }, + { + "desc": "ZTE Nubia Red Magic 3", + "ua": "Mozilla/5.0 (Linux; Android 9; NX629J Build/PKQ1.190321.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.126 MQQBrowser/6.2 TBS/45016 Mobile Safari/537.36 MMWEBID/4064 MicroMessenger/7.0.10.1580(0x27000A34) Process/tools NetType/WIFI Language/zh_CN ABI/arm64", + "expect": { + "vendor": "ZTE", + "model": "NX629J", + "type": "mobile" + } + }, { "desc": "Swizz GEN610", "ua": "Mozilla/5.0 (Linux; Android 4.4.2; GEN610 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.83 Mobile Safari/537.36", @@ -997,6 +1995,15 @@ "type": "tablet" } }, + { + "desc": "Amazon Alexa Echo Show", + "ua": "AlexaWebMediaPlayer/1.0.200641.0 (Linux;Android 5.1.1)", + "expect": { + "vendor": "Amazon", + "model": "Alexa", + "type": "tablet" + } + }, { "desc": "Amazon Kindle Fire Tablet", "ua": "Mozilla/5.0 (Linux; U; Android 4.4.3; en-us; KFSAWI Build/KTU84M) AppleWebKit/537.36 (KHTML, like Gecko) Silk/3.66 like Chrome/39.0.2171.93 Safari/537.36", @@ -1006,6 +2013,24 @@ "type": "tablet" } }, + { + "desc": "Amazon Kindle Fire Tablet", + "ua": "Mozilla/5.0 (Linux; U; Android 4.4.3; en-us; KFSAWI) AppleWebKit/537.36 (KHTML, like Gecko) Silk/3.66 like Chrome/39.0.2171.93 Safari/537.36", + "expect": { + "vendor": "Amazon", + "model": "KFSAWI", + "type": "tablet" + } + }, + { + "desc": "Amazon Kindle Fire Tablet", + "ua": "Mozilla/5.0 (Linux; Android 9; KFMAWI Build/PS7312; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/70.0.3538.110 Safari/537.36", + "expect": { + "vendor": "Amazon", + "model": "KFMAWI", + "type": "tablet" + } + }, { "desc": "Amazon Fire TV", "ua": "Mozilla/5.0 (Linux; Android 4.2.2; AFTB Build/JDQ39) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.173 Mobile Safari/537.22", @@ -1015,6 +2040,24 @@ "type": "smarttv" } }, + { + "desc": "Amazon Fire TV", + "ua": "Mozilla/5.0 (Linux; Android 5.1.1; AFTT) AppleWebKit/537.36 (KHTML, like Gecko) Silk/86.3.20 like Chrome/86.0.4240.198 Safari/537.36", + "expect": { + "vendor": "Amazon", + "model": "T", + "type": "smarttv" + } + }, + { + "desc": "Android TV", + "ua": "Mozilla/5.0 (Linux; Android 10; 2020/2021 UHD Android TV Build/QTG3.201102.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) version/4.0 Chrome/83.0.4103.101 Mobile Safari/537.36", + "expect": { + "vendor": "undefined", + "model": "undefined", + "type": "smarttv" + } + }, { "desc": "Gigaset Tablet", "ua": "Mozilla/5.0 (Linux; Android 4.2.2; Gigaset QV830 Build/JDQ39) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36", @@ -1025,21 +2068,379 @@ } }, { - "desc": "Redmi Note 3", - "ua": "Mozilla/5.0 (Linux; Android 6.0.1; Redmi Note 3 Build/MMB29M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.116 Mobile Safari/537.36", + "desc": "HUAWEI MediaPad M3 Lite 10", + "ua": "Mozilla/5.0 (Linux; Android 7.0; BAH-L09) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.80 Safari/537.36", "expect": { - "vendor": "Xiaomi", - "model": "Redmi Note 3", - "type": "mobile" + "vendor": "Huawei", + "model": "BAH-L09", + "type": "tablet" } }, { - "desc": "MI PAD 2", - "ua": "Mozilla/5.0 (Linux; Android 5.1; MI PAD 2 Build/LMY47I; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/60.0.3112.107 Safari/537.36 [FB_IAB/FB4A;FBAV/137.0.0.24.91;]", + "desc": "HUAWEI MediaPad M5 Lite", + "ua": "Mozilla/5.0 (Linux; Android 8.0.0; BAH2-W19 Build/HUAWEIBAH2-W19; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/83.0.4103.106 Safari/537.36", "expect": { - "vendor": "Xiaomi", - "model": "MI PAD 2", + "vendor": "Huawei", + "model": "BAH2-W19", + "type": "tablet" + } + }, + { + "desc": "HUAWEI MediaPad M5", + "ua": "Mozilla/5.0 (Linux; Android 9; SHT-AL09 Build/HUAWEISHT-AL09; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/89.0.4389.90 Mobile Safari/537.36", + "expect": { + "vendor": "Huawei", + "model": "SHT-AL09", + "type": "tablet" + } + }, + { + "desc": "HUAWEI MediaPad T5", + "ua": "Mozilla/5.0 (Linux; Android 8.0.0; AGS2-L09 Build/HUAWEIAGS2-L09; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/84.0.4147.125 Safari/537.36", + "expect": { + "vendor": "Huawei", + "model": "AGS2-L09", + "type": "tablet" + } + }, + { + "desc": "HUAWEI MediaPad T10", + "ua": "Mozilla/5.0 (Linux; Android 10; AGR-W09 Build/HUAWEIAGR-W09; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/78.0.3904.108 Safari/537.36", + "expect": { + "vendor": "Huawei", + "model": "AGR-W09", + "type": "tablet" + } + }, + { + "desc": "HUAWEI MediaPad T10s", + "ua": "Mozilla/5.0 (Linux; Android 10; AGS3-W09 Build/HUAWEIAGS3-W09; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/78.0.3904.108 Safari/537.36", + "expect": { + "vendor": "Huawei", + "model": "AGS3-W09", + "type": "tablet" + } + }, + { + "desc": "Huawei MatePad T 10", + "ua": "Mozilla/5.0 (Linux; Android 10; AGR-L09; HMSCore 5.0.4.301) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 HuaweiBrowser/11.0.3.304 Safari/537.36", + "expect": { + "vendor": "Huawei", + "model": "AGR-L09", "type": "tablet" } + }, + { + "desc": "Huawei Mate 10 Pro", + "ua": "Mozilla/5.0 (Linux; Android 8.0; BLA-L29 Build/HUAWEIBLA-L29) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3236.6 Mobile Safari/537.36", + "expect": { + "vendor": "Huawei", + "model": "BLA-L29", + "type": "mobile" + } + }, + { + "desc": "Huawei Mate X", + "ua": "Mozilla/5.0 (Linux; Android 9; TAH-AN00) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.111 Safari/537.36", + "expect": { + "vendor": "Huawei", + "model": "TAH-AN00", + "type": "mobile" + } + }, + { + "desc": "Huawei Mate X2", + "ua": "Mozilla/5.0 (Linux; Android 10; TET-AN00) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.96 Mobile Safari/537.36", + "expect": { + "vendor": "Huawei", + "model": "TET-AN00", + "type": "mobile" + } + }, + { + "desc": "Huawei Mate 20 X", + "ua": "Mozilla/5.0 (Linux; Android 9; EVR-L29 Build/HUAWEIEVR-L29; xx-xx) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/70.0.3538.110 Mobile Safari/537.36", + "expect": { + "vendor": "Huawei", + "model": "EVR-L29", + "type": "mobile" + } + }, + { + "desc": "Huawei Mate 20 Pro", + "ua": "Mozilla/5.0 (Linux; Android 9; LYA-L09) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.90 Mobile Safari/537.36", + "expect": { + "vendor": "Huawei", + "model": "LYA-L09", + "type": "mobile" + } + }, + { + "desc": "Huawei Mate 20 Pro", + "ua": "Mozilla/5.0 (Linux; Android 9; LYA-AL00) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.90 Mobile Safari/537.36", + "expect": { + "vendor": "Huawei", + "model": "LYA-AL00", + "type": "mobile" + } + }, + { + "desc": "Huawei P20 Lite", + "ua": "Mozilla/5.0 (Linux; Android 8.0.0; ANE-LX1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.143 Mobile Safari/537.36", + "expect": { + "vendor": "Huawei", + "model": "ANE-LX1", + "type": "mobile" + } + }, + { + "desc": "Huawei P20", + "ua": "Mozilla/5.0 (Linux; Android 8.1.0; EML-L29) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Mobile Safari/537.36", + "expect": { + "vendor": "Huawei", + "model": "EML-L29", + "type": "mobile" + } + }, + { + "desc": "Huawei P20 Pro", + "ua": "Mozilla/5.0 (Linux; Android 9; CLT-L29) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.90 Mobile Safari/537.36", + "expect": { + "vendor": "Huawei", + "model": "CLT-L29", + "type": "mobile" + } + }, + { + "desc": "Huawei P30", + "ua": "Mozilla/5.0 (Linux; Android 9; ELE-L29) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.90 Mobile Safari/537.36", + "expect": { + "vendor": "Huawei", + "model": "ELE-L29", + "type": "mobile" + } + }, + { + "desc": "Huawei P30 Pro", + "ua": "Mozilla/5.0 (Linux; Android 9; VOG-L29) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.143 Mobile Safari/537.36", + "expect": { + "vendor": "Huawei", + "model": "VOG-L29", + "type": "mobile" + } + }, + { + "desc": "Huawei P40", + "ua": "Mozilla/5.0 (Linux; Android 10; ANA-AN00 Build/HUAWEIANA-AN00; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/76.0.3809.89 Mobile Safari/537.36 T7/11.26 SP-engine/2.22.0 baiduboxapp/11.26.0.10 (Baidu; P1 10) NABar/1.0", + "expect": { + "vendor": "Huawei", + "model": "ANA-AN00", + "type": "mobile" + } + }, + { + "desc": "Huawei P40 Pro", + "ua": "Mozilla/5.0 (Linux; Android 10; ELS-AN00 Build/HUAWEIELS-AN00; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/78.0.3904.108 Mobile Safari/537.36 mailapp/6.0.0", + "expect": { + "vendor": "Huawei", + "model": "ELS-AN00", + "type": "mobile" + } + }, + { + "desc": "Huawei 30 Pro+", + "ua": "Mozilla/5.0 (Linux; Android 10; EBG-AN10 Build/HUAWEIEBG-AN10) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.86 Mobile Safari/537.36 EdgA/42.0.0.2741", + "expect": { + "vendor": "Huawei", + "model": "EBG-AN10", + "type": "mobile" + } + }, + { + "desc": "Huawei 30S", + "ua": "Mozilla/5.0 (Linux; Android 10; CDY-AN90 Build/HUAWEICDY-AN90; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/78.0.3904.108 Mobile Safari/537.36 mailapp/5.8.0", + "expect": { + "vendor": "Huawei", + "model": "CDY-AN90", + "type": "mobile" + } + }, + { + "desc": "Huawei Enjoy10e", + "ua": "Dalvik/2.1.0 (Linux; U; Android 10; MED-AL00 Build/HUAWEIMED-AL00)", + "expect": { + "vendor": "Huawei", + "model": "MED-AL00", + "type": "mobile" + } + }, + { + "desc": "Amazon Fire 7", + "ua": "Mozilla/5.0 (Linux; Android 5.1.1; KFAUWI) AppleWebKit/537.36 (KHTML, like Gecko) Silk/80.5.3 like Chrome/80.0.3987.162 Safari/537.36", + "expect": { + "vendor": "Amazon", + "model": "KFAUWI", + "type": "tablet" + } + }, + { + "desc": "AT&T Radiant Core U304AA", + "ua": "Dalvik/2.1.0 (Linux; U; Android 9; U304AA Build/P00610)", + "expect": { + "vendor": "AT&T", + "model": "U304AA", + "type": "mobile" + } + }, + { + "desc": "Vodafone Smart Tab 4G", + "ua": "Mozilla/5.0 (Linux; Android 4.4.4; Vodafone Smart Tab 4G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36", + "expect": { + "vendor": "Vodafone", + "model": "Smart Tab 4G", + "type": "tablet" + } + }, + { + "desc": "Vodafone Smart ultra 6", + "ua": "Mozilla/5.0 (Linux; Android 5.0.2; Vodafone Smart ultra 6 Build/LRX22G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.133 Mobile Safari/537.36", + "expect": { + "vendor": "Vodafone", + "model": "Smart ultra 6", + "type": "tablet" + } + }, + { + "desc": "4ife 4K Smart TV Box", + "ua": "Mozilla/5.0 (Linux; Android 4.4.2; 4ife 4K Smart TV Box Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/30.0.0.0 Safari/537.36 Vinebre", + "expect": { + "vendor": "undefined", + "model": "undefined", + "type": "smarttv" + } + }, + { + "desc": "FaceBook Mobile App", + "ua": "[FBAN/FBIOS;FBAV/283.0.0.44.117;FBBV/238386386;FBDV/iPhone12,1;FBMD/iPhone;FBSN/iOS;FBSV/13.6.1;FBSS/2;FBID/phone;FBLC/en_US;FBOP/5;FBRV/240127608]", + "expect": { + "type": "mobile" + } + }, + { + "desc": "Issue #454", + "ua": "Mosamzilla/5.0 (Windows; U; Win98; en-US; rv:1.7.5) Gecko/20050603 Netscape/8.0.2", + "expect": { + "vendor": "undefined", + "model": "undefined", + "type": "undefined" + } + }, + { + "desc": "Alcatel", + "ua": "Mozilla/5.0 (Linux; Android 4.4.2; ALCATEL A564C Build/KVT49L) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.133 Mobile Safari/537.36", + "expect": { + "vendor": "ALCATEL", + "model": "A564C", + "type": "mobile" + } + }, + { + "desc": "Alcatel Go Flip", + "ua": "Mozilla/5.0 (Mobile; ALCATEL4044T; rv:37.0) Gecko/37.0 Firefox/37.0 KaiOS/1.0", + "expect": { + "vendor": "ALCATEL", + "model": "4044T", + "type": "mobile" + } + }, + { + "desc": "Jolla", + "ua": "Mozilla/5.0 (Maemo; Linux; U; Jolla; Sailfish; Mobile; rv:31.0) Gecko/31.0 Firefox/31.0 SailfishBrowser/1.0", + "expect": { + "vendor": "Jolla", + "model": "undefined", + "type": "mobile" + } + }, + { + "desc": "Xbox One", + "ua": "Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; IEMobile/10.0; Xbox; Xbox One)", + "expect": { + "vendor": "Microsoft", + "model": "Xbox One", + "type": "console" + } + }, + { + "desc": "Xbox", + "ua": "Mozilla/5.0 (compatible; MSIE 9.0; Windows Phone OS 7.5; Trident/5.0; IEMobile/9.0; Xbox)", + "expect": { + "vendor": "Microsoft", + "model": "Xbox", + "type": "console" + } + }, + { + "desc": "Nvidia Shield Tablet", + "ua": "Mozilla/5.0 (Linux; Android 5.1.1; SHIELD Tablet Build/LVY48E; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/45.0.2454.19 Safari/537.36", + "expect": { + "vendor": "Nvidia", + "model": "SHIELD Tablet", + "type": "tablet" + } + }, + { + "desc": "Ouya", + "ua": "Mozilla/5.0 (Linux; Android 4.1.2; OUYA Console Build/JZO54L-OUYA) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Safari/537.36", + "expect": { + "vendor": "OUYA", + "model": "undefined", + "type": "console" + } + }, + { + "desc": "Vivo Y52s", + "ua": "Mozilla/5.0 (Linux; Android 10; V2057A Build/QP1A.190711.020; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/76.0.3809.89 Mobile Safari/537.36 T7/12.10 SP-engine/2.28.0 baiduboxapp/12.10.0.10 (Baidu; P1 10) NABar/1.0", + "expect": { + "vendor": "Vivo", + "model": "V2057A", + "type": "mobile" + } + }, + { + "desc": "Vivo X60", + "ua": "Mozilla/5.0 (Linux; Android 11; V2046A; wv) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.84 Mobile Safari/537.36 VivoBrowser/8.8.71.0", + "expect": { + "vendor": "Vivo", + "model": "V2046A", + "type": "mobile" + } + }, + { + "desc": "Vivo Y79A", + "ua": "Mozilla/5.0 (Linux; Android 7.1.2; vivo Y79A Build/N2G47H; wv) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.84 Mobile Safari/537.36 VivoBrowser/9.0.14.0", + "expect": { + "vendor": "Vivo", + "model": "Y79A", + "type": "mobile" + } + }, + { + "desc": "Vivo Y97", + "ua": "Mozilla/5.0 (Linux; Android 8.1.0; V1813T Build/O11019; wv) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.84 Mobile Safari/537.36 VivoBrowser/9.0.14.0", + "expect": { + "vendor": "Vivo", + "model": "V1813T", + "type": "mobile" + } + }, + { + "desc": "Vivo iQOO Pro", + "ua": "Mozilla/5.0 (Linux; Android 11; V1916A; wv) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.84 Mobile Safari/537.36 VivoBrowser/9.1.10.6", + "expect": { + "vendor": "Vivo", + "model": "V1916A", + "type": "mobile" } + } ] diff --git a/test/engine-test.json b/test/engine-test.json index c1afba37..6726d27d 100644 --- a/test/engine-test.json +++ b/test/engine-test.json @@ -5,7 +5,7 @@ "expect" : { "name" : "Blink", - "version" : "undefined" + "version" : "57.0.2987.146" } }, { @@ -17,6 +17,15 @@ "version" : "12.0" } }, + { + "desc" : "Flow", + "ua" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_0) EkiohFlow/5.7.4.30559 Flow/5.7.4 (like Gecko Firefox/53.0 rv:53.0)", + "expect" : + { + "name" : "Flow", + "version" : "5.7.4.30559" + } + }, { "desc" : "Gecko", "ua" : "Mozilla/5.0 (X11; Linux x86_64; rv:2.0b9pre) Gecko/20110111 Firefox/4.0b9pre", @@ -97,5 +106,50 @@ "name" : "WebKit", "version" : "537.36" } + }, + { + "desc" : "WebOS TV 5.x", + "ua" : "Mozilla/5.0 (Web0S; Linux/SmartTV) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36 WebAppManager", + "expect" : + { + "name" : "Blink", + "version" : "68.0.3440.106" + } + }, + { + "desc" : "WebOS TV 4.x", + "ua" : "Mozilla/5.0 (Web0S; Linux/SmartTV) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.34 Safari/537.36 WebAppManager", + "expect" : + { + "name" : "Blink", + "version" : "53.0.2785.34" + } + }, + { + "desc" : "WebOS TV 3.x", + "ua" : "Mozilla/5.0 (Web0S; Linux/SmartTV) AppleWebKit/537.36 (KHTML, like Gecko) QtWebEngine/5.2.1 Chrome/38.0.2125.122 Safari/537.36 WebAppManager", + "expect" : + { + "name" : "Blink", + "version" : "38.0.2125.122" + } + }, + { + "desc" : "WebOS TV 2.x", + "ua" : "Mozilla/5.0 (Web0S; Linux/SmartTV) AppleWebKit/538.2 (KHTML, like Gecko) Large Screen WebAppManager Safari/538.2", + "expect" : + { + "name" : "WebKit", + "version" : "538.2" + } + }, + { + "desc" : "WebOS TV 1.x", + "ua" : "Mozilla/5.0 (Web0S; Linux/SmartTV) AppleWebKit/537.41 (KHTML, like Gecko) Large Screen WebAppManager Safari/537.41", + "expect" : + { + "name" : "WebKit", + "version" : "537.41" + } } ] diff --git a/test/os-test.json b/test/os-test.json index a2a2411f..27c5427b 100644 --- a/test/os-test.json +++ b/test/os-test.json @@ -152,6 +152,15 @@ "version" : "10" } }, + { + "desc" : "Tizen", + "ua" : "Mozilla/5.0 (SMART-TV; Linux; Tizen 2.3) AppleWebkit/538.1 (KHTML, like Gecko) SamsungBrowser/1.0 TV Safari/538.1", + "expect" : + { + "name" : "Tizen", + "version" : "2.3" + } + }, { "desc" : "Tizen", "ua" : "Mozilla/5.0 (Linux; Tizen 2.3; SAMSUNG SM-Z130H) AppleWebKit/537.3 (KHTML, like Gecko) Version/2.3 Mobile Safari/537.3", @@ -181,65 +190,128 @@ }, { "desc" : "WebOS", - "ua" : "", + "ua" : "Mozilla/5.0 (hp-tablet; Linux; hpwOS/3.0.5; U; en-US) AppleWebKit/534.6 (KHTML, like Gecko) wOSBrowser/234.83 Safari/534.6 TouchPad/1.0", "expect" : { - "name" : "", - "version" : "" + "name" : "webOS", + "version" : "3.0.5" } }, { - "desc" : "Palm OS", - "ua" : "", + "desc" : "WebOS", + "ua" : "Mozilla/5.0 (webOS/1.4.5; U; en-US) AppleWebKit/532.2 (KHTML, like Gecko) Version/1.0 Safari/532.2 Pre/1.0", "expect" : { - "name" : "", - "version" : "" + "name" : "webOS", + "version" : "1.4.5" + } + }, + { + "desc" : "WebOS TV 5.x", + "ua" : "Mozilla/5.0 (Web0S; Linux/SmartTV) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36 WebAppManager", + "expect" : + { + "name" : "webOS", + "version" : "TV" + } + }, + { + "desc" : "WebOS TV 4.x", + "ua" : "Mozilla/5.0 (Web0S; Linux/SmartTV) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.34 Safari/537.36 WebAppManager", + "expect" : + { + "name" : "webOS", + "version" : "TV" + } + }, + { + "desc" : "WebOS TV 3.x", + "ua" : "Mozilla/5.0 (Web0S; Linux/SmartTV) AppleWebKit/537.36 (KHTML, like Gecko) QtWebEngine/5.2.1 Chrome/38.0.2125.122 Safari/537.36 WebAppManager", + "expect" : + { + "name" : "webOS", + "version" : "TV" + } + }, + { + "desc" : "WebOS TV 2.x", + "ua" : "Mozilla/5.0 (Web0S; Linux/SmartTV) AppleWebKit/538.2 (KHTML, like Gecko) Large Screen WebAppManager Safari/538.2", + "expect" : + { + "name" : "webOS", + "version" : "TV" + } + }, + { + "desc" : "WebOS TV 1.x", + "ua" : "Mozilla/5.0 (Web0S; Linux/SmartTV) AppleWebKit/537.41 (KHTML, like Gecko) Large Screen WebAppManager Safari/537.41", + "expect" : + { + "name" : "webOS", + "version" : "TV" } }, { "desc" : "QNX", - "ua" : "", + "ua" : "Mozilla/5.0 (Photon; U; QNX x86pc; en-US; rv:1.8.1.20) Gecko/20090127 BonEcho/2.0.0.20", "expect" : { - "name" : "", - "version" : "" + "name" : "QNX", + "version" : "x86pc" } }, { "desc" : "Bada", - "ua" : "", + "ua" : "Mozilla/5.0 (SAMSUNG; SAMSUNG-GT-S5253/S5253DDKC1; U; Bada/1.0; en-us) AppleWebKit/533.1 (KHTML, like Gecko) Dolfin/2.0 Mobile WQVGA SMM-MMS/1.2.0 OPN-B", "expect" : { - "name" : "", - "version" : "" + "name" : "Bada", + "version" : "1.0" } }, { "desc" : "RIM Tablet OS", - "ua" : "", + "ua" : "Mozilla/5.0 (PlayBook; U; RIM Tablet OS 2.1.0; en-US) AppleWebKit/536.2+ (KHTML like Gecko) Version/7.2.1.0 Safari/536.2+", "expect" : { - "name" : "", - "version" : "" + "name" : "RIM Tablet OS", + "version" : "2.1.0" } }, { "desc" : "MeeGo", - "ua" : "", + "ua" : "Mozilla/5.0 (MeeGo; NokiaN9) AppleWebKit/534.13 (KHTML, like Gecko) NokiaBrowser/8.5.0 Mobile Safari/534.13", "expect" : { - "name" : "", - "version" : "" + "name" : "MeeGo", + "version" : "undefined" } }, { "desc" : "Symbian", - "ua" : "", + "ua" : "Nokia5250/10.0.011 (SymbianOS/9.4; U; Series60/5.0 Mozilla/5.0; Profile/MIDP-2.1 Configuration/CLDC-1.1 ) AppleWebKit/525 (KHTML, like Gecko) Safari/525 3gpp-gba", "expect" : { - "name" : "", - "version" : "" + "name" : "Symbian", + "version" : "9.4" + } + }, + { + "desc" : "Symbian", + "ua" : "Mozilla/5.0 (Symbian/3; Series60/5.2 NokiaC7-00/024.001; Profile/MIDP-2.1 Configuration/CLDC-1.1 ) AppleWebKit/533.4 (KHTML, like Gecko) NokiaBrowser/7.3.1.37 Mobile Safari/533.4 3gpp-gba", + "expect" : + { + "name" : "Symbian", + "version" : "5.2" + } + }, + { + "desc" : "Series40", + "ua" : "Mozilla/5.0 (Series40; Nokia2055/03.20; Profile/MIDP-2.1 Configuration/CLDC-1.1) Gecko/20100401 S40OviBrowser/2.2.0.0.34", + "expect" : + { + "name" : "Series40", + "version" : "undefined" } }, { @@ -252,21 +324,21 @@ } }, { - "desc" : "Nintendo", - "ua" : "", + "desc" : "Google Chromecast", + "ua" : "Mozilla/5.0 (X11; Linux aarch64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.81 Safari/537.36 CrKey/1.42.183786", "expect" : { - "name" : "", - "version" : "" + "name" : "Chromecast", + "version" : "1.42.183786" } }, { - "desc" : "PlayStation", - "ua" : "", + "desc" : "Nintendo Switch", + "ua" : "Mozilla/5.0 (Nintendo Switch; WifiWebAuthApplet) AppleWebKit/606.4 (KHTML, like Gecko) NF/6.0.1.15.4 NintendoBrowser/5.1.0.20393", "expect" : { - "name" : "", - "version" : "" + "name" : "Nintendo", + "version" : "Switch" } }, { @@ -278,22 +350,67 @@ "version" : "4" } }, + { + "desc" : "Xbox 360", + "ua" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64; Xbox; Xbox 360) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36", + "expect" : + { + "name" : "Xbox", + "version" : "360" + } + }, + { + "desc" : "Xbox One", + "ua" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64; Xbox; Xbox One; WebView/3.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.19041", + "expect" : + { + "name" : "Xbox", + "version" : "One" + } + }, + { + "desc" : "Xbox X", + "ua" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64; Xbox; Xbox X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.82 Safari/537.36 Edge/20.02", + "expect" : + { + "name" : "Xbox", + "version" : "X" + } + }, + { + "desc" : "Xbox Series X", + "ua" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64; Xbox; Xbox Series X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.82 Safari/537.36 Edge/20.02 ", + "expect" : + { + "name" : "Xbox", + "version" : "Series X" + } + }, { "desc" : "Mint", - "ua" : "", + "ua" : "Opera/9.80 (X11; Linux x86_64; Edition Linux Mint) Presto/2.12.388 Version/12.16", "expect" : { - "name" : "", - "version" : "" + "name" : "Mint", + "version" : "undefined" } }, { - "desc" : "Joli", - "ua" : "", + "desc" : "Mint", + "ua" : "Opera/9.64 (X11; Linux i686; U; Linux Mint; nb) Presto/2.1.1", "expect" : { - "name" : "", - "version" : "" + "name" : "Mint", + "version" : "undefined" + } + }, + { + "desc" : "Mint", + "ua" : "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.5) Gecko/2008121622 Linux Mint/6 (Felicia) Firefox/3.0.4", + "expect" : + { + "name" : "Mint", + "version" : "6" } }, { @@ -314,116 +431,125 @@ "version" : "undefined" } }, + { + "desc" : "Kubuntu", + "ua" : "Mozilla/5.0 (compatible; Konqueror/4.4; Linux 2.6.32-22-generic; X11; en_US) KHTML/4.4.3 (like Gecko) Kubuntu", + "expect" : + { + "name" : "Kubuntu", + "version" : "undefined" + } + }, { "desc" : "Debian", - "ua" : "", + "ua" : "Mozilla/5.0 (compatible; Konqueror/3.5; Linux) KHTML/3.5.7 (like Gecko) (Debian)", "expect" : { - "name" : "", - "version" : "" + "name" : "Debian", + "version" : "undefined" } }, { - "desc" : "OpenSUSE", - "ua" : "", + "desc" : "Debian", + "ua" : "Mozilla/5.0 (X11; Linux x86_64; Debian GNU/Linux 8.1 (jessie)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.0 Maxthon/1.0.5.3 Safari/537.36", "expect" : { - "name" : "", - "version" : "" + "name" : "Debian", + "version" : "8.1" } }, { - "desc" : "Gentoo", - "ua" : "", + "desc" : "Debian", + "ua" : "ELinks/0.12~pre5-4 (textmode; Debian; Linux 3.2.0-4-amd64 x86_64 192x47-2)", "expect" : { - "name" : "", - "version" : "" + "name" : "Debian", + "version" : "undefined" } }, { - "desc" : "Arch", - "ua" : "", + "desc" : "Debian", + "ua" : "w3m/0.5.3+debian-19", "expect" : { - "name" : "", - "version" : "" + "name" : "debian", + "version" : "19" } }, { - "desc" : "Slackware", - "ua" : "", + "desc" : "Debian", + "ua" : "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.0.3) Gecko/2008092814 (Debian-3.0.1-1)", "expect" : { - "name" : "", - "version" : "" + "name" : "Debian", + "version" : "3.0.1-1" } }, { - "desc" : "Fedora", - "ua" : "", + "desc" : "Debian", + "ua" : "Mozilla/5.0 (compatible; Konqueror/3.5; Linux 2.6.24.4; X11) KHTML/3.5.9 (like Gecko) (Debian package 4:3.5.9.dfsg.1-2+b1)", "expect" : { - "name" : "", - "version" : "" + "name" : "Debian", + "version" : "undefined" } }, { - "desc" : "Mandriva", - "ua" : "", + "desc" : "OpenSUSE", + "ua" : "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.17) Gecko/20110420 SUSE/3.6.17-0.2.1 Firefox/3.6.17", "expect" : { - "name" : "", - "version" : "" + "name" : "SUSE", + "version" : "3.6.17-0.2.1" } }, { - "desc" : "CentOS", - "ua" : "", + "desc" : "Gentoo", + "ua" : "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.16) Gecko/20080716 (Gentoo) Galeon/2.0.6", "expect" : { - "name" : "", - "version" : "" + "name" : "Gentoo", + "version" : "undefined" } }, { - "desc" : "PCLinuxOS", - "ua" : "", + "desc" : "Gentoo", + "ua" : "Xombrero (X11; U; Gentoo Linux amd64; en-US) Webkit/2.8.5", "expect" : { - "name" : "", - "version" : "" + "name" : "Gentoo", + "version" : "amd64" } }, { - "desc" : "RedHat", - "ua" : "", + "desc" : "Gentoo", + "ua" : "Xombrero/1.6.4 (Linux amd64; en; Gentoo)", "expect" : { - "name" : "", - "version" : "" + "name" : "Gentoo", + "version" : "undefined" } }, { - "desc" : "Zenwalk", - "ua" : "", + "desc" : "Gentoo", + "ua" : "Links (2.8; Linux 3.17.2-gentoo-x86 i686; GNU C 4.8.2; x)", "expect" : { - "name" : "", - "version" : "" + "name" : "gentoo", + "version" : "x86" } }, { - "desc" : "Hurd", - "ua" : "", + "desc" : "Arch", + "ua" : "Uzbl (Webkit 1.1.10) (Arch Linux)", "expect" : { - "name" : "", - "version" : "" + "name" : "Arch", + "version" : "undefined" } }, { - "desc" : "Linux", + "desc" : "Slackware", "ua" : "", "expect" : { @@ -432,12 +558,39 @@ } }, { - "desc" : "GNU", - "ua" : "", + "desc" : "Fedora", + "ua" : "Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:40.0) Gecko/20100101 Firefox/40.0", "expect" : { - "name" : "", - "version" : "" + "name" : "Fedora", + "version" : "undefined" + } + }, + { + "desc" : "Fedora", + "ua" : "Mozilla/5.0 (X11; U; Linux i686; en-GB; rv:2.0) Gecko/20110404 Fedora/16-dev Firefox/4.0", + "expect" : + { + "name" : "Fedora", + "version" : "16-dev" + } + }, + { + "desc" : "Fedora", + "ua" : "Mozilla/5.0 (X11; U; Linux i686; sk; rv:1.9.0.4) Gecko/2008111217 Fedora/3.0.4-1.fc10 Firefox/3.0.4", + "expect" : + { + "name" : "Fedora", + "version" : "3.0.4-1.fc10" + } + }, + { + "desc" : "Mandriva", + "ua" : "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.22) Gecko/20110907 Mandriva Linux/1.9.2.22-0.1mdv2010.2 (2010.2) Firefox/3.6.22", + "expect" : + { + "name" : "Mandriva", + "version" : "1.9.2.22-0.1mdv2010.2" } }, { @@ -469,29 +622,29 @@ }, { "desc" : "FreeBSD", - "ua" : "", + "ua" : "Mozilla/5.0 (X11; U; FreeBSD x86_64; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.204 Safari/534.16", "expect" : { - "name" : "", - "version" : "" + "name" : "FreeBSD", + "version" : "undefined" } }, { "desc" : "OpenBSD", - "ua" : "", + "ua" : "Mozilla/5.0 (X11; U; OpenBSD i386; en-US; rv:1.9.1) Gecko/20090702 Firefox/3.5", "expect" : { - "name" : "", - "version" : "" + "name" : "OpenBSD", + "version" : "undefined" } }, { "desc" : "NetBSD", - "ua" : "", + "ua" : "ELinks (0.4.3; NetBSD 3.0.2PATCH sparc64; 141x19)", "expect" : { - "name" : "", - "version" : "" + "name" : "NetBSD", + "version" : "3.0.2PATCH" } }, { @@ -548,6 +701,69 @@ "version" : "R1" } }, + { + "desc" : "KaiOS", + "ua" : "Mozilla/5.0 (Mobile; Nokia_8110_4G; rv:48.0) Gecko/48.0 Firefox/48.0 KAIOS/2.5", + "expect" : + { + "name" : "KAIOS", + "version" : "2.5" + } + }, + { + "desc" : "iTunes Windows Vista", + "ua" : "iTunes/10.7 (Windows; Microsoft Windows Vista Home Premium Edition Service Pack 1 (Build 6001)) AppleWebKit/536.26.9", + "expect" : + { + "name" : "Windows", + "version" : "Vista" + } + }, + { + "desc" : "iOS BE App", + "ua" : "APP-BE Test/1.0 (iPad; Apple; CPU iPhone OS 7_0_2 like Mac OS X)", + "expect" : + { + "name" : "iOS", + "version" : "7.0.2" + } + }, + { + "desc" : "KTB-Nexus 5", + "ua" : "APP-My App/1.0 (Linux; Android 4.2.1; Nexus 5 Build/JOP40D)", + "expect" : + { + "name" : "Android", + "version" : "4.2.1" + } + }, + { + "desc" : "Solaris", + "ua" : "NCSA Mosaic/1.0 (X11;SunOS 4.1.4 sun4m)", + "expect" : + { + "name" : "Solaris", + "version" : "4.1.4" + } + }, + { + "desc" : "Raspbian", + "ua" : "Mozilla/5.0 (X11; Linux armv7l) AppleWebKit/537.36 (KHTML, like Gecko) Raspbian Chromium/72.0.3626.121 HeadlessChrome/72.0.3626.121 Safari/537.36", + "expect" : + { + "name" : "Raspbian", + "version" : "undefined" + } + }, + { + "desc" : "Raspbian", + "ua" : "Mozilla/5.0 (X11; Linux armv7l) AppleWebKit/538.15 (KHTML, like Gecko) Version/8.0 Safari/538.15 Raspbian/9.0 (1:3.8.2.0-0rpi28) Epiphany/3.8.2", + "expect" : + { + "name" : "Raspbian", + "version" : "9.0" + } + }, { "desc" : "AIX", "ua" : "", @@ -621,16 +837,16 @@ } }, { - "desc" : "iTunes Windows Vista", - "ua" : "iTunes/10.7 (Windows; Microsoft Windows Vista Home Premium Edition Service Pack 1 (Build 6001)) AppleWebKit/536.26.9", + "desc" : "Joli", + "ua" : "", "expect" : { - "name" : "Windows", - "version" : "Vista" + "name" : "", + "version" : "" } }, { - "desc" : "", + "desc" : "CentOS", "ua" : "", "expect" : { @@ -639,21 +855,66 @@ } }, { - "desc" : "iOS BE App", - "ua" : "APP-BE Test/1.0 (iPad; Apple; CPU iPhone OS 7_0_2 like Mac OS X)", + "desc" : "PCLinuxOS", + "ua" : "", "expect" : { - "name" : "iOS", - "version" : "7.0.2" + "name" : "", + "version" : "" } }, { - "desc" : "KTB-Nexus 5", - "ua" : "APP-My App/1.0 (Linux; Android 4.2.1; Nexus 5 Build/JOP40D)", + "desc" : "RedHat", + "ua" : "", "expect" : { - "name" : "Android", - "version" : "4.2.1" + "name" : "", + "version" : "" + } + }, + { + "desc" : "Zenwalk", + "ua" : "", + "expect" : + { + "name" : "", + "version" : "" + } + }, + { + "desc" : "Hurd", + "ua" : "", + "expect" : + { + "name" : "", + "version" : "" + } + }, + { + "desc" : "Linux", + "ua" : "", + "expect" : + { + "name" : "", + "version" : "" + } + }, + { + "desc" : "GNU", + "ua" : "", + "expect" : + { + "name" : "", + "version" : "" + } + }, + { + "desc" : "Palm OS", + "ua" : "", + "expect" : + { + "name" : "", + "version" : "" } } ] diff --git a/test/test.js b/test/test.js index 99e53ffb..ad54ef43 100644 --- a/test/test.js +++ b/test/test.js @@ -1,3 +1,5 @@ +var fs = require('fs'); +var safe = require('safe-regex'); var assert = require('assert'); var requirejs = require('requirejs'); var UAParser = require('./../src/ua-parser'); @@ -41,7 +43,15 @@ var methods = [ describe('UAParser()', function () { var ua = 'Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1090.0 Safari/536.6'; - assert.deepEqual(UAParser(ua), new UAParser().setUA(ua).getResult()); + assert.deepStrictEqual(UAParser(ua), new UAParser().setUA(ua).getResult()); +}); + +describe('UAParser() constructor does not throw with undefined ua argument', function () { + assert.doesNotThrow(() => new UAParser(undefined).getResult()); +}); + +describe('UAParser.setUA method does not throw with undefined ua argument', function () { + assert.doesNotThrow(() => new UAParser().setUA(undefined).getResult()); }); for (var i in methods) { @@ -55,7 +65,7 @@ for (var i in methods) { methods[i]['properties'].forEach(function(m) { it('should return ' + methods[i]['label'] + ' ' + m + ': ' + expect[m], function () { - assert.equal(result[m], expect[m] != 'undefined' ? expect[m] : undefined); + assert.strictEqual(result[m], expect[m] != 'undefined' ? expect[m] : undefined); }); }); }); @@ -67,7 +77,7 @@ for (var i in methods) { describe('Returns', function () { it('getResult() should returns JSON', function(done) { - assert.deepEqual(new UAParser('').getResult(), + assert.deepStrictEqual(new UAParser('').getResult(), { ua : '', browser: { name: undefined, version: undefined, major: undefined }, @@ -85,15 +95,26 @@ describe('Extending Regex', function () { var myOwnBrowser = [[/(myownbrowser)\/((\d+)?[\w\.]+)/i], [UAParser.BROWSER.NAME, UAParser.BROWSER.VERSION, UAParser.BROWSER.MAJOR]]; var parser1 = new UAParser(uaString, {browser: myOwnBrowser}); - assert.equal(parser1.getBrowser().name, 'MyOwnBrowser'); - assert.equal(parser1.getBrowser().version, '1.3'); - assert.equal(parser1.getBrowser().major, '1'); + assert.strictEqual(parser1.getBrowser().name, 'MyOwnBrowser'); + assert.strictEqual(parser1.getBrowser().version, '1.3'); + assert.strictEqual(parser1.getBrowser().major, '1'); var parser2 = new UAParser({browser: myOwnBrowser}); - assert.equal(parser2.getBrowser().name, undefined); + assert.strictEqual(parser2.getBrowser().name, undefined); parser2.setUA(uaString); - assert.equal(parser2.getBrowser().name, 'MyOwnBrowser'); - assert.equal(parser1.getBrowser().version, '1.3'); + assert.strictEqual(parser2.getBrowser().name, 'MyOwnBrowser'); + assert.strictEqual(parser1.getBrowser().version, '1.3'); +}); + +describe('User-agent length', function () { + var UA_MAX_LENGTH = 255; + + // Real data from https://stackoverflow.com/questions/654921/how-big-can-a-user-agent-string-get#answer-6595973 + var uaString = 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; (R1 1.6); SLCC1; .NET CLR 2.0.50727; InfoPath.2; OfficeLiveConnector.1.3; OfficeLivePatch.0.0; .NET CLR 3.5.30729; .NET CLR 3.0.30618; 66760635803; runtime 11.00294; 876906799603; 97880703; 669602703; 9778063903; 877905603; 89670803; 96690803; 8878091903; 7879040603; 999608065603; 799808803; 6666059903; 669602102803; 888809342903; 696901603; 788907703; 887806555703; 97690214703; 66760903; 968909903; 796802422703; 8868026703; 889803611803; 898706903; 977806408603; 976900799903; 9897086903; 88780803; 798802301603; 9966008603; 66760703; 97890452603; 9789064803; 96990759803; 99960107703; 8868087903; 889801155603; 78890703; 8898070603; 89970603; 89970539603; 89970488703; 8789007603; 87890903; 877904603; 9887077703; 798804903; 97890264603; 967901703; 87890703; 97690420803; 79980706603; 9867086703; 996602846703; 87690803; 6989010903; 977809603; 666601903; 876905337803; 89670603; 89970200903; 786903603; 696901911703; 788905703; 896709803; 96890703; 998601903; 88980703; 666604769703; 978806603; 7988020803; 996608803; 788903297903; 98770043603; 899708803; 66960371603; 9669088903; 69990703; 99660519903; 97780603; 888801803; 9867071703; 79780803; 9779087603; 899708603; 66960456803; 898706824603; 78890299903; 99660703; 9768079803; 977901591603; 89670605603; 787903608603; 998607934903; 799808573903; 878909603; 979808146703; 9996088603; 797803154903; 69790603; 99660565603; 7869028603; 896707703; 97980965603; 976907191703; 88680703; 888809803; 69690903; 889805523703; 899707703; 997605035603; 89970029803; 9699094903; 877906803; 899707002703; 786905857603; 69890803; 97980051903; 997603978803; 9897097903; 66960141703; 7968077603; 977804603; 88980603; 989700803; 999607887803; 78690772803; 96990560903; 98970961603; 9996032903; 9699098703; 69890655603; 978903803; 698905066803; 977806903; 9789061703; 967903747703; 976900550903; 88980934703; 8878075803; 8977028703; 97980903; 9769006603; 786900803; 98770682703; 78790903; 878906967903; 87690399603; 99860976703; 796805703; 87990603; 968906803; 967904724603; 999606603; 988705903; 989702842603; 96790603; 99760703; 88980166703; 9799038903; 98670903; 697905248603; 7968043603; 66860703; 66860127903; 9779048903; 89670123903; 78890397703; 97890603; 87890803; 8789030603; 69990603; 88880763703; 9769000603; 96990203903; 978900405903; 7869022803; 699905422903; 97890703; 87990903; 878908703; 7998093903; 898702507603; 97780637603; 966907903; 896702603; 9769004803; 7869007903; 99660158803; 7899099603; 8977055803; 99660603; 7889080903; 66660981603; 997604603; 6969089803; 899701903; 9769072703; 666603903; 99860803; 997608803; 69790903; 88680756703; 979805677903; 9986047703; 89970803; 66660603; 96690903; 8997051603; 789901209803; 8977098903; 968900326803; 87790703; 98770024803; 697901794603; 69990803; 887805925803; 968908903; 97880603; 897709148703; 877909476903; 66760197703; 977908603; 698902703; 988706504803; 977802026603; 88680964703; 8878068703; 987705107903; 978902878703; 8898069803; 9768031703; 79680803; 79980803; 669609328703; 89870238703; 99960593903; 969904218703; 78890603; 9788000703; 69690630903; 889800982903; 988709748803; 7968052803; 99960007803; 969900800803; 668604817603; 66960903; 78790734603; 8868007703; 79780034903; 8878085903; 976907603; 89670830803; 877900903; 969904889703; 7978033903; 8987043903; 99860703; 979805903; 667603803; 976805348603; 999604127603; 97790701603; 78990342903; 98770672903; 87990253903; 9877027703; 97790803; 877901895603; 8789076903; 896708595603; 997601903; 799806903; 97690603; 87790371703; 667605603; 99760303703; 97680283803; 788902750803; 787909803; 79780603; 79880866903; 9986050903; 87890543903; 979800803; 97690179703; 876901603; 699909903; 96990192603; 878904903; 877904734903; 796801446903; 977904803; 9887044803; 797805565603; 98870789703; 7869093903; 87790727703; 797801232803; 666604803; 9778071903; 9799086703; 6969000903; 89670903; 8799075903; 897708903; 88680903; 97980362603; 97980503903; 889803256703; 88980388703; 789909376803; 69690703; 6969025903; 89970309903; 96690703; 877901847803; 968901903; 96690603; 88680607603; 7889001703; 789904761803; 976807703; 976902903; 878907889703; 9897014903; 896707046603; 696909903; 666603998903; 969902703; 79680421803; 9769075603; 798800192703; 97990903; 9689024903; 668604803; 969908671903; 9996094703; 69990642703; 97890895903; 977805619903; 79980859903; 88980443803; 98970649603; 997602703; 888802169903; 699907803; 667602028803; 786903283903; 997607703; 969909803; 798809925903; 9976045603; 97790903; 9789001903; 966903603; 9789069603; 968906603; 6989091803; 896701603; 6979059803; 978803903; 997606362603; 88980803; 98970803; 88880921703; 8997065703; 899700703; 698908703; 797801027903; 7889050903; 87890603; 78690703; 99660069703; 97980309903; 976800603; 666606803; 898707703; 79880019803; 66960250803; 7978049803; 88780602603; 79680903; 88880792703; 96990903; 667608603; 87790730903; 98970903; 9699032903; 8987004803; 88880703; 89770046603; 978800803; 969908903; 9798022603; 696901903; 799803703; 989703703; 668605903; 79780903; 998601371703; 796803339703; 87890922603; 898708903; 9966061903; 66960891903; 96790903; 8779050803; 98870858803; 976909298603; 9887029903; 669608703; 979806903; 878903803; 99960703; 9789086703; 979801803; 66960008703; 979806830803; 99760212703; 786906603; 797807603; 789907297703; 96990703; 786901603; 796807766603; 896702651603; 789902585603; 66660925903; 9986085703; 66960302703; 69890703; 789900703; 89970903; 9679060703; 9789002903; 979908821603; 986708140803; 976809828703; 7988082803; 79680997903; 99960803; 9788081903; 979805703; 787908603; 66960602803; 9887098703; 978803237703; 888806804603; 999604703; 977904703; 966904635703; 97680291703; 977809345603; 8878046703; 988709803; 976900773603; 989703903; 88780198603; 87790603; 986708703; 78890604703; 87790544803; 976809850903; 887806703; 987707527603; 79880803; 9897059603; 897709820603; 97880804803; 66960026703; 9789062803; 9867090803; 669600603; 8967087703; 78890903; 89770903; 97980703; 976802687603; 66860400803; 979901288603; 96990160903; 99860228903; 966900703; 66760603; 9689035703; 9779064703; 7968023603; 87890791903; 98770870603; 9798005803; 6969087903; 9779097903; 6979065703; 699903252603; 79780989703; 87690901803; 978905763903; 977809703; 97790369703; 899703269603; 8878012703; 78790803; 87690395603; 8888042803; 667607689903; 8977041803; 6666085603; 6999080703; 69990797803; 88680721603; 99660519803; 889807603; 87890146703; 699906325903; 89770603; 669608615903; 9779028803; 88880603; 97790703; 79780703; 97680355603; 6696024803; 78790784703; 97880329903; 9699077703; 89870803; 79680227903; 976905852703; 8997098903; 896704796703; 66860598803; 9897036703; 66960703; 9699094703; 9699008703; 97780485903; 999603179903; 89770834803; 96790445603; 79680460903; 9867009603; 89870328703; 799801035803; 989702903; 66960758903; 66860150803; 6686088603; 9877092803; 96990603; 99860603; 987703663603; 98870903; 699903325603; 87790803; 97680703; 8868030703; 9799030803; 89870703; 97680803; 9669054803; 6979097603; 987708046603; 999608603; 878904803; 998607408903; 968903903; 696900703; 977907491703; 6686033803; 669601803; 99960290603; 887809169903; 979803703; 69890903; 699901447903; 8987064903; 799800603; 98770903; 8997068703; 967903603; 66760146803; 978805087903; 697908138603; 799801603; 88780964903; 989708339903; 8967048603; 88880981603; 789909703; 796806603; 977905977603; 989700603; 97780703; 9669062603; 88980714603; 897709545903; 988701916703; 667604694903; 786905664603; 877900803; 886805490903; 89970559903; 99960531803; 7998033903; 98770803; 78890418703; 669600872803; 996605216603; 78690962703; 667604903; 996600903; 999608903; 9699083803; 787901803; 97780707603; 787905312703; 977805803; 8977033703; 97890708703; 989705521903; 978800703; 698905703; 78890376903; 878907703; 999602903; 986705903; 668602719603; 979901803; 997606903; 66760393903; 987703603; 78790338903; 96890803; 97680596803; 666601603; 977902178803; 877902803; 78790038603; 8868075703; 99960060603)'; + + it('greater than ' + UA_MAX_LENGTH + ' should be trimmed down', function () { + assert.strictEqual(UAParser(uaString).ua.length, UA_MAX_LENGTH); + }); }); describe('Using Require.js', function () { @@ -106,8 +127,33 @@ describe('Using Require.js', function () { }); requirejs(['ua-parser-js'], function(ua) { var parser = new ua('Dillo/1.0'); - assert.deepEqual(parser.getBrowser().name, 'Dillo'); + assert.deepStrictEqual(parser.getBrowser().name, 'Dillo'); done(); }); }); -}); \ No newline at end of file +}); + +describe('Testing regexes', function () { + + var regexes; + + // todo: use AST-based instead of grep + before('Read main js file', function (done) { + fs.readFile('src/ua-parser.js', 'utf8', function (err, data) { + regexes = data.match(/(\/.+\/[ig]+)(?=[,\s\n])/g); + done(); + }); + }); + + describe('Begin testing', function () { + it('all regexes in main file', function () { + regexes.forEach(function (regex) { + describe('Test against `safe-regex` : ' + regex, function () { + it('should be safe from potentially vulnerable regex', function () { + assert.strictEqual(safe(regex), true); + }); + }); + }); + }); + }); +}) \ No newline at end of file