node-device-detector
Advanced tools
Comparing version 2.1.4 to 2.1.5
@@ -5,5 +5,45 @@ export default class ClientHints { | ||
parse(hints: JSONObject, meta: JSONObject): JSONObject; | ||
parse(hints: JSONObject, meta: JSONObject): ResultClientHints; | ||
} | ||
export interface ResultMetaClientHints { | ||
width?: string; | ||
height?: string; | ||
gpu?: string; | ||
gamut?: string; | ||
ram?: string; | ||
colorDepth?: string; | ||
cpuCores?: number; | ||
} | ||
export interface ResultPrefersClientHints { | ||
colorScheme: string; | ||
} | ||
export interface ResultClientPropClientHints { | ||
brands: string[]; | ||
version: string; | ||
} | ||
export interface ResultOsPropClientHints { | ||
name: string; | ||
platform: string; | ||
bitness: string; | ||
version: string; | ||
} | ||
export interface ResultDevicePropClientHints { | ||
model: string; | ||
} | ||
export interface ResultClientHints { | ||
upgradeHeader: boolean; | ||
formFactors?: string[]; | ||
meta?: ResultMetaClientHints; | ||
prefers?: ResultPrefersClientHints; | ||
os: ResultOsPropClientHints; | ||
client: ResultClientPropClientHints; | ||
device: ResultDevicePropClientHints; | ||
} | ||
export type JSONValue = | ||
@@ -10,0 +50,0 @@ | string |
@@ -13,2 +13,3 @@ | ||
const CH_UA_PREFERS_COLOR_SCHEME = 'sec-ch-prefers-color-scheme'; | ||
const CH_UA_FORM_FACTORS = 'sec-ch-ua-form-factors'; | ||
@@ -49,2 +50,3 @@ /* | ||
'sec-ch-viewport-width', | ||
'sec-ch-ua-from-factors', | ||
'sec-ch-width', | ||
@@ -72,6 +74,6 @@ 'ua', | ||
* ```js | ||
const hintHeaders = ClientHints.getHeaderClientHints(); | ||
for (let name in hintHeaders) { | ||
res.setHeader(name, hintHeaders[headerName]); | ||
} | ||
* const hintHeaders = ClientHints.getHeaderClientHints(); | ||
* for (let name in hintHeaders) { | ||
* res.setHeader(name, hintHeaders[headerName]); | ||
* } | ||
* ``` | ||
@@ -89,3 +91,4 @@ */ | ||
CH_BITNESS, | ||
CH_UA_PREFERS_COLOR_SCHEME | ||
CH_UA_PREFERS_COLOR_SCHEME, | ||
CH_UA_FORM_FACTORS | ||
].join(', ') | ||
@@ -108,10 +111,10 @@ }; | ||
/** | ||
* @param {{}} hints | ||
* @param {{}} result | ||
* @param {JSONObject|{}} hints | ||
* @param {ResultClientHints|JSONObject} result | ||
* @private | ||
*/ | ||
__parseHints(hints, result) { | ||
#parseHints(hints, result) { | ||
for (let key in hints) { | ||
let value = hints[key]; | ||
let lowerCaseKey = key.toLowerCase().replace('_', '-'); | ||
const lowerCaseKey = key.toLowerCase().replace('_', '-'); | ||
@@ -123,3 +126,3 @@ switch (lowerCaseKey) { | ||
case 'architecture': | ||
result.os.platform = helper.trimChars(value, '"'); | ||
result.os.platform = this.#trim(value); | ||
break; | ||
@@ -129,3 +132,3 @@ case 'http-sec-ch-ua-bitness': | ||
case 'bitness': | ||
result.os.bitness = helper.trimChars(value, '"'); | ||
result.os.bitness = this.#trim(value); | ||
break; | ||
@@ -135,3 +138,3 @@ case 'http-sec-ch-ua-mobile': | ||
case 'mobile': | ||
result.isMobile = true === value || '1' === value || '?1' === value; | ||
result.isMobile = this.#bool(value); | ||
break; | ||
@@ -141,3 +144,3 @@ case 'http-sec-ch-ua-model': | ||
case 'model': | ||
result.device.model = helper.trimChars(value, '"'); | ||
result.device.model = this.#trim(value); | ||
break; | ||
@@ -148,3 +151,3 @@ case 'http-sec-ch-ua-full-version': | ||
result.upgradeHeader = true; | ||
result.client.version = helper.trimChars(value, '"'); | ||
result.client.version = this.#trim(value); | ||
break; | ||
@@ -154,3 +157,3 @@ case 'http-sec-ch-ua-platform': | ||
case 'platform': | ||
result.os.name = helper.trimChars(value, '"'); | ||
result.os.name = this.#trim(value); | ||
break; | ||
@@ -160,3 +163,3 @@ case 'http-sec-ch-ua-platform-version': | ||
case 'platformversion': | ||
result.os.version = helper.trimChars(value, '"'); | ||
result.os.version = this.#trim(value); | ||
break; | ||
@@ -181,13 +184,3 @@ case 'brands': | ||
case 'sec-ch-ua-full-version-list': | ||
let pattern = new RegExp('"([^"]+)"; ?v="([^"]+)"(?:, )?', 'gi'); | ||
let items = []; | ||
let matches = null; | ||
while (matches = pattern.exec(value)) { | ||
let brand = matches[1]; | ||
let skip = brand.indexOf('Not;A') !== -1 || brand.indexOf('Not A;') !== -1 || brand.indexOf('Not.A') !== -1; | ||
if (skip) { | ||
continue; | ||
} | ||
items.push({ brand, version: helper.trimChars(matches[2], '"') }); | ||
} | ||
const items = this.#parseFullVersionList(value); | ||
if (items.length > 0) { | ||
@@ -199,7 +192,9 @@ result.client.brands = items; | ||
case 'http-x-requested-with': | ||
result.app = value; | ||
if (value.toLowerCase() === 'xmlhttprequest') { | ||
result.app = ''; | ||
} | ||
result.app = this.#parseApp(value) | ||
break; | ||
case 'formfactors': | ||
case 'http-sec-ch-ua-form-factors': | ||
case 'sec-ch-ua-form-factors': | ||
result.formFactors = this.#parseFormFactor(value); | ||
break; | ||
} | ||
@@ -210,7 +205,65 @@ } | ||
/** | ||
* @param {{}} meta | ||
* @param {{}} result | ||
* @param {boolean|string} value | ||
* @return {boolean} | ||
*/ | ||
#bool(value) { | ||
return true === value || '1' === value || '?1' === value; | ||
} | ||
/** | ||
* @param {string} value | ||
* @return {string} | ||
*/ | ||
#trim(value) { | ||
return helper.trimChars(value, '"'); | ||
} | ||
/** | ||
* @param {string} value | ||
* @return {string} | ||
*/ | ||
#parseApp(value) { | ||
return value.toLowerCase() === 'xmlhttprequest' ? '' : value; | ||
} | ||
/** | ||
* @param {string} value | ||
* @return {[]} | ||
*/ | ||
#parseFullVersionList(value) { | ||
const skipBrands = ['Not;A', 'Not A;', 'Not.A']; | ||
const pattern = new RegExp('"([^"]+)"; ?v="([^"]+)"(?:, )?', 'gi'); | ||
const items = []; | ||
let matches = null; | ||
while ((matches = pattern.exec(value)) !== null) { | ||
const brand = matches[1]; | ||
if (skipBrands.some(item => brand.includes(item))) { | ||
continue; | ||
} | ||
items.push({ brand, version: helper.trimChars(matches[2], '"') }); | ||
} | ||
return items; | ||
} | ||
/** | ||
* @param {string|string[]} value | ||
* @return {string[]} | ||
*/ | ||
#parseFormFactor(value) { | ||
if (Array.isArray(value)) { | ||
return value.map(val => val.toLowerCase()); | ||
} | ||
const matches = value.toLowerCase().match(/"([a-z]+)"/gi); | ||
return matches!== null ? matches.map(formFactor => { | ||
return helper.trimChars(formFactor, '"') | ||
}): []; | ||
} | ||
/** | ||
* @param {JSONObject|{}} meta | ||
* @param {ResultClientHints} result | ||
* @private | ||
*/ | ||
__parseMeta(meta, result) { | ||
#parseMeta(meta, result) { | ||
for (let key in meta) { | ||
@@ -245,9 +298,10 @@ let value = meta[key]; | ||
/** | ||
* @param {{}} hints - headers or client-hints params | ||
* @param {{}} meta - client custom js metric params | ||
* @return {ResultClientHints|JSONObject|{}} | ||
* @private | ||
*/ | ||
parse(hints, meta = {}) { | ||
let result = { | ||
#blank() { | ||
return { | ||
upgradeHeader: false, | ||
isMobile: false, | ||
formFactors: [], | ||
meta: { | ||
@@ -267,5 +321,13 @@ width: '', | ||
}; | ||
this.__parseHints(hints, result); | ||
this.__parseMeta(meta, result); | ||
} | ||
/** | ||
* @param {JSONObject|{}} hints - headers or client-hints params | ||
* @param {JSONObject|{}} meta - client custom js metric params | ||
* @return {ResultClientHints} | ||
*/ | ||
parse(hints, meta = {}) { | ||
let result = this.#blank() | ||
this.#parseHints(hints, result); | ||
this.#parseMeta(meta, result); | ||
return result; | ||
@@ -272,0 +334,0 @@ } |
@@ -1,2 +0,2 @@ | ||
import { JSONObject } from './client-hints'; | ||
import { JSONObject, ResultClientHints } from './client-hints'; | ||
@@ -9,8 +9,8 @@ export default class DeviceDetector { | ||
detect: (userAgent: string, clientHints?: any) => DetectResult; | ||
detectAsync: (userAgent: string, clientHints?: any) => Promise<DetectResult>; | ||
parseBot: (userAgent: string, clientHints?: any) => ResultBot; | ||
parseOs: (userAgent: string, clientHints?: any) => ResultOs; | ||
parseClient: (userAgent: string, clientHints?: any) => ResultClient; | ||
parseDevice: (userAgent: string, clientHints?: any) => ResultDevice; | ||
detect: (userAgent: string, clientHints?: ResultClientHints|JSONObject) => DetectResult; | ||
detectAsync: (userAgent: string, clientHints?: ResultClientHints|JSONObject) => Promise<DetectResult>; | ||
parseBot: (userAgent: string, clientHints?: ResultClientHints|JSONObject) => ResultBot; | ||
parseOs: (userAgent: string, clientHints?: ResultClientHints|JSONObject) => ResultOs; | ||
parseClient: (userAgent: string, clientHints?: ResultClientHints|JSONObject) => ResultClient; | ||
parseDevice: (userAgent: string, clientHints?: ResultClientHints|JSONObject) => ResultDevice; | ||
parseDeviceType: ( | ||
@@ -21,5 +21,5 @@ userAgent: string, | ||
deviceData?: ResultDevice, | ||
clientHints?: any | ||
clientHints?: ResultClientHints|JSONObject | ||
) => DeviceType; | ||
parseVendor: (userAgent: string) => ResultVendor; | ||
parseVendor: (userAgent: string) => ResultVendor|null; | ||
parseDeviceCode: (userAgent: string) => ResultDeviceCode; | ||
@@ -34,3 +34,3 @@ set skipBotDetection(arg: boolean); | ||
get clientIndexes(): boolean; | ||
get maxUserAgentSize(): null|number; | ||
get maxUserAgentSize(): number|null; | ||
set maxUserAgentSize(size: number); | ||
@@ -169,6 +169,6 @@ setOsVersionTruncate(value: any): void; | ||
* @param {string} userAgent | ||
* @param {JSONObject} clientHints | ||
* @param {ResultClientHints|JSONObject} clientHints | ||
* @return string | ||
*/ | ||
restoreUserAgentFromClientHints(userAgent: string, clientHints?: JSONObject): string; | ||
restoreUserAgentFromClientHints(userAgent: string, clientHints?: JSONObject|ResultClientHints): string; | ||
} | ||
@@ -232,3 +232,3 @@ | ||
export interface DeviceType { | ||
id: string; | ||
id?: string; | ||
type: string; | ||
@@ -235,0 +235,0 @@ } |
213
index.js
const helper = require('./parser/helper'); | ||
const attr = helper.getPropertyValue; | ||
const { attr } = helper; | ||
@@ -43,3 +43,5 @@ // device parsers | ||
const CLIENT_PARSER_LIST = require('./parser/const/client-parser'); | ||
const FORM_FACTORS_MAPPING = require('./parser/const/form-factor-mapping'); | ||
const MOBILE_BROWSER_LIST = require('./parser/client/browser-short-mobile'); | ||
const { hasUserAgentClientHintsFragment, hasDeviceModelByClientHints } = require('./parser/helper'); | ||
const VENDOR_FRAGMENT_PARSER = 'VendorFragment'; | ||
@@ -61,15 +63,19 @@ const OS_PARSER = 'Os'; | ||
class DeviceDetector { | ||
/** | ||
* @typedef DeviceDetectorOptions | ||
* @param {boolean} skipBotDetection | ||
* @param {number|null} osVersionTruncate | ||
* @param {number|null} clientVersionTruncate | ||
* @param {number|null} maxUserAgentSize | ||
* @param {boolean} deviceIndexes | ||
* @param {boolean} clientIndexes | ||
* @param {boolean} deviceAliasCode | ||
* @param {boolean} deviceInfo | ||
* @param {boolean} deviceTrusted | ||
*/ | ||
vendorParserList = {}; | ||
osParserList = {}; | ||
botParserList = {}; | ||
deviceParserList = {}; | ||
clientParserList = {}; | ||
#skipBotDetection = false; | ||
#deviceIndexes = false; | ||
#clientIndexes = false; | ||
#deviceAliasCode = false; | ||
#deviceTrusted = false; | ||
#deviceInfo = false; | ||
#clientVersionTruncate = null; | ||
#osVersionTruncate = null; | ||
#maxUserAgentSize = null; | ||
/** | ||
@@ -79,18 +85,2 @@ * @param {DeviceDetectorOptions} options | ||
constructor(options) { | ||
this.vendorParserList = {}; | ||
this.osParserList = {}; | ||
this.botParserList = {}; | ||
this.deviceParserList = {}; | ||
this.clientParserList = {}; | ||
this.__skipBotDetection = false; | ||
this.__deviceIndexes = false; | ||
this.__clientIndexes = false; | ||
this.__deviceAliasCode = false; | ||
this.__deviceTrusted = false; | ||
this.__deviceInfo = false; | ||
this.__clientVersionTruncate = null; | ||
this.__osVersionTruncate = null; | ||
this.__maxUserAgentSize = null; | ||
this.init(); | ||
@@ -134,15 +124,15 @@ | ||
set deviceTrusted(check) { | ||
this.__deviceTrusted = check; | ||
this.#deviceTrusted = check; | ||
} | ||
get deviceTrusted() { | ||
return this.__deviceTrusted; | ||
return this.#deviceTrusted; | ||
} | ||
set deviceInfo(stage) { | ||
this.__deviceInfo = stage; | ||
this.#deviceInfo = stage; | ||
} | ||
get deviceInfo() { | ||
return this.__deviceInfo; | ||
return this.#deviceInfo; | ||
} | ||
@@ -155,3 +145,3 @@ | ||
set maxUserAgentSize(size) { | ||
this.__maxUserAgentSize = size; | ||
this.#maxUserAgentSize = size; | ||
for (let name in this.clientParserList) { | ||
@@ -173,11 +163,11 @@ this.clientParserList[name].setMaxUserAgentSize(size); | ||
get maxUserAgentSize() { | ||
return this.__maxUserAgentSize; | ||
return this.#maxUserAgentSize; | ||
} | ||
get skipBotDetection() { | ||
return this.__skipBotDetection; | ||
return this.#skipBotDetection; | ||
} | ||
set skipBotDetection(discard) { | ||
this.__skipBotDetection = discard; | ||
this.#skipBotDetection = discard; | ||
} | ||
@@ -189,3 +179,3 @@ | ||
set deviceIndexes(status) { | ||
this.__deviceIndexes = status; | ||
this.#deviceIndexes = status; | ||
} | ||
@@ -197,10 +187,11 @@ | ||
get deviceIndexes() { | ||
return this.__deviceIndexes; | ||
return this.#deviceIndexes; | ||
} | ||
/** | ||
* @param {boolean} status - true use indexes, false not use indexes | ||
* true use indexes, false not use indexes | ||
* @param {boolean} status | ||
*/ | ||
set clientIndexes(status) { | ||
this.__clientIndexes = status; | ||
this.#clientIndexes = status; | ||
for (let name in this.clientParserList) { | ||
@@ -212,20 +203,23 @@ this.clientParserList[name].clientIndexes = status; | ||
/** | ||
* @return {boolean} - true use indexes, false not use indexes | ||
* true use indexes, false not use indexes | ||
* @return {boolean} | ||
*/ | ||
get clientIndexes() { | ||
return this.__clientIndexes; | ||
return this.#clientIndexes; | ||
} | ||
/** | ||
* @param {boolean} status - true use deviceAliasCode, false not use deviceAliasCode | ||
* true use deviceAliasCode, false not use deviceAliasCode | ||
* @param {boolean} status | ||
*/ | ||
set deviceAliasCode(status) { | ||
this.__deviceAliasCode = status; | ||
this.#deviceAliasCode = status; | ||
} | ||
/** | ||
* @return {boolean} - true use deviceAliasCode, false not use deviceAliasCode | ||
* true use deviceAliasCode, false not use deviceAliasCode | ||
* @return {boolean} | ||
*/ | ||
get deviceAliasCode() { | ||
return this.__deviceAliasCode; | ||
return this.#deviceAliasCode; | ||
} | ||
@@ -238,3 +232,3 @@ | ||
set clientVersionTruncate(value) { | ||
this.__clientVersionTruncate = value; | ||
this.#clientVersionTruncate = value; | ||
for (let name in this.clientParserList) { | ||
@@ -250,3 +244,3 @@ this.clientParserList[name].setVersionTruncation(value); | ||
get clientVersionTruncate() { | ||
return this.__clientVersionTruncate; | ||
return this.#clientVersionTruncate; | ||
} | ||
@@ -259,3 +253,3 @@ | ||
set osVersionTruncate(value) { | ||
this.__osVersionTruncate = value; | ||
this.#osVersionTruncate = value; | ||
for (let name in this.osParserList) { | ||
@@ -271,3 +265,3 @@ this.osParserList[name].setVersionTruncation(value); | ||
get osVersionTruncate() { | ||
return this.__osVersionTruncate; | ||
return this.#osVersionTruncate; | ||
} | ||
@@ -303,3 +297,3 @@ | ||
* get all brands | ||
* @returns {string[]} | ||
* @return {string[]} | ||
*/ | ||
@@ -313,3 +307,3 @@ getAvailableBrands() { | ||
* @param brand | ||
* @returns {boolean} | ||
* @return {boolean} | ||
*/ | ||
@@ -331,3 +325,3 @@ hasBrand(brand) { | ||
* @param {string} name | ||
* @return {DeviceParserAbstract} | ||
* @return {DeviceParserAbstract|null} | ||
*/ | ||
@@ -355,2 +349,3 @@ getParseDevice(name) { | ||
} | ||
/** | ||
@@ -458,3 +453,3 @@ * get os parser by name | ||
* @param {string} userAgent | ||
* @param clientHints | ||
* @param {ResultClientHints|{}} clientHints | ||
* @return {ResultOs} | ||
@@ -493,3 +488,3 @@ */ | ||
* @param {ResultDevice} deviceData | ||
* @param clientHints | ||
* @param {ResultClientHints} clientHints | ||
* @return {DeviceType} | ||
@@ -518,2 +513,19 @@ */ | ||
// client hint detect device type | ||
if ( | ||
deviceType === '' && | ||
clientHints && | ||
clientHints.device && | ||
clientHints.device.model && | ||
clientHints.formFactors.length | ||
) { | ||
for(const [type, deviceTypeName] of Object.entries(FORM_FACTORS_MAPPING)) { | ||
if (clientHints.formFactors.includes(type)) { | ||
deviceType = '' + deviceTypeName; | ||
break; | ||
} | ||
} | ||
} | ||
/** | ||
@@ -534,7 +546,5 @@ * All devices containing VR fragment are assumed to be a wearable | ||
if (deviceType === '' && osFamily === 'Android' && helper.matchUserAgent('Chrome/[.0-9]*', userAgent)) { | ||
if (helper.matchUserAgent('(Mobile|eliboM)', userAgent) !== null) { | ||
deviceType = DEVICE_TYPE.SMARTPHONE; | ||
} else{ | ||
deviceType = DEVICE_TYPE.TABLET; | ||
} | ||
deviceType = helper.matchUserAgent('(Mobile|eliboM)', userAgent) | ||
? DEVICE_TYPE.SMARTPHONE | ||
: DEVICE_TYPE.TABLET; | ||
} | ||
@@ -608,4 +618,3 @@ | ||
deviceType === '' && | ||
(osName === 'Windows RT' || | ||
(osName === 'Windows' && helper.versionCompare(osVersion, '8') >= 0)) && | ||
(osName === 'Windows RT' || (osName === 'Windows' && helper.versionCompare(osVersion, '8') >= 0)) && | ||
helper.hasTouchFragment(userAgent) | ||
@@ -616,2 +625,22 @@ ) { | ||
if (deviceType === '' && /Puffin\/\d/i.test(userAgent)) { | ||
/** | ||
* All devices running Puffin Secure Browser that contain letter 'D' are assumed to be desktops | ||
*/ | ||
if (helper.hasPuffinDesktopFragment(userAgent)) { | ||
deviceType = DEVICE_TYPE.DESKTOP; | ||
} | ||
/** | ||
* All devices running Puffin Web Browser that contain letter 'P' are assumed to be smartphones | ||
*/ | ||
if (helper.hasPuffinSmartphoneFragment(userAgent)) { | ||
deviceType = DEVICE_TYPE.SMARTPHONE; | ||
} | ||
/** | ||
* All devices running Puffin Web Browser that contain letter 'T' are assumed to be tablets | ||
*/ | ||
if (helper.hasPuffinTabletFragment(userAgent)) { | ||
deviceType = DEVICE_TYPE.TABLET; | ||
} | ||
} | ||
/** | ||
@@ -643,6 +672,5 @@ * All devices running Opera TV Store are assumed to be a tv | ||
if ( | ||
DEVICE_TYPE.DESKTOP !== deviceType && | ||
userAgent.indexOf('Desktop') !== -1 | ||
DEVICE_TYPE.DESKTOP !== deviceType && userAgent.indexOf('Desktop') !== -1 | ||
) { | ||
if (helper.hasDesktopFragment(userAgent)) { | ||
if (helper.matchUserAgent('Desktop(?: (x(?:32|64)|WOW64))?;', userAgent)) { | ||
deviceType = DEVICE_TYPE.DESKTOP; | ||
@@ -676,3 +704,3 @@ } | ||
* @param {string} deviceCode | ||
* @returns {*[]} | ||
* @returns {string[]} | ||
*/ | ||
@@ -688,2 +716,3 @@ getBrandsByDeviceCode(deviceCode) { | ||
/** | ||
* parse device model code from useragent string | ||
* @param {string} userAgent | ||
@@ -699,3 +728,3 @@ * @returns {ResultDeviceCode} | ||
* @param {string} userAgent | ||
* @param {{os:{version:''}, device: {model:''}}} clientHints | ||
* @param {ResultClientHints} clientHints | ||
*/ | ||
@@ -706,22 +735,29 @@ restoreUserAgentFromClientHints( | ||
) { | ||
if (!clientHints || !clientHints.device) { | ||
if (!helper.hasDeviceModelByClientHints(clientHints)) { | ||
return userAgent; | ||
} | ||
const deviceModel = clientHints.device.model; | ||
if (deviceModel && /Android 10[.\d]*; K(?: Build\/|[;)])/i.test(userAgent)) { | ||
if (deviceModel !== '' && helper.hasUserAgentClientHintsFragment(userAgent)) { | ||
const osHints = attr(clientHints, 'os', {}); | ||
const osVersion = attr(osHints, 'version', ''); | ||
return userAgent.replace(/(Android 10[.\d]*; K)/, | ||
`Android ${osVersion !== '' ? osVersion: '10'}; ${deviceModel}` | ||
return userAgent.replace(/(Android (?:10[.\d]*; K|1[1-5]))/, | ||
`Android ${osVersion !== '' ? osVersion : '10'}; ${deviceModel}` | ||
); | ||
} | ||
if (deviceModel !== '' && helper.hasDesktopFragment(userAgent)) { | ||
return userAgent.replace(/(X11; Linux x86_64)/, | ||
`X11; Linux x86_64; ${deviceModel}` | ||
); | ||
} | ||
return userAgent; | ||
} | ||
/** | ||
* parse device | ||
* @param {string} userAgent | ||
* @param {Object} clientHints | ||
* @param {ResultClientHints} clientHints | ||
* @return {ResultDevice} | ||
@@ -732,3 +768,2 @@ */ | ||
let brandIndexes = []; | ||
let deviceCode = ''; | ||
@@ -745,4 +780,9 @@ let result = { | ||
// skip all parse is client-hints useragent and model not exist | ||
if (!helper.hasDeviceModelByClientHints(clientHints) && helper.hasUserAgentClientHintsFragment(userAgent)) { | ||
return Object.assign({}, result); | ||
} | ||
if (this.deviceIndexes || this.deviceAliasCode || this.deviceInfo || this.deviceTrusted) { | ||
if (clientHints.device && clientHints.device.model) { | ||
if (helper.hasDeviceModelByClientHints(clientHints)) { | ||
result.code = clientHints.device.model; | ||
@@ -778,4 +818,4 @@ } else { | ||
// client hints | ||
if (result.model === '' && clientHints.device && clientHints.device.model !== '') { | ||
// client hints get model raw | ||
if (result.model === '' && helper.hasDeviceModelByClientHints(clientHints)) { | ||
result.model = clientHints.device.model; | ||
@@ -786,5 +826,4 @@ } | ||
if (this.deviceInfo || this.deviceTrusted) { | ||
result.info = this.getParseInfoDevice().info( | ||
result.brand, result.code ? result.code : result.model | ||
); | ||
let deviceModel = result.code ? result.code : result.model; | ||
result.info = this.getParseInfoDevice().info(result.brand, deviceModel); | ||
} | ||
@@ -798,3 +837,3 @@ | ||
* @param {string} userAgent | ||
* @return {{name:'', id:''}|null} | ||
* @return {ResultVendor|null} | ||
*/ | ||
@@ -809,4 +848,4 @@ parseVendor(userAgent) { | ||
* @param {string} userAgent | ||
* @param {Object} clientHints | ||
* @return {ResultBot} | ||
* @param {ResultClientHints} clientHints | ||
* @return {ResultBot|{}} | ||
*/ | ||
@@ -834,3 +873,3 @@ parseBot(userAgent, clientHints) { | ||
* @param {string} userAgent | ||
* @param clientHints | ||
* @param {ResultClientHints} clientHints | ||
* @return {ResultClient|{}} | ||
@@ -921,3 +960,3 @@ */ | ||
* @param {string} userAgent - string from request header['user-agent'] | ||
* @param clientHints | ||
* @param {ResultClientHints|{}} clientHints | ||
* @return {DetectResult} | ||
@@ -953,3 +992,3 @@ */ | ||
* @param {string} userAgent - string from request header['user-agent'] | ||
* @param {{}} clientHints | ||
* @param {ResultClientHints|{}} clientHints | ||
* @return {DetectResult} | ||
@@ -956,0 +995,0 @@ */ |
{ | ||
"name": "node-device-detector", | ||
"version": "2.1.4", | ||
"version": "2.1.5", | ||
"description": "Nodejs device detector (port matomo-org/device-detector)", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -5,2 +5,5 @@ const ParserAbstract = require('./abstract-parser'); | ||
class ClientAbstractParser extends ParserAbstract { | ||
#clientIndexes = true; | ||
constructor() { | ||
@@ -10,11 +13,10 @@ super(); | ||
this.type = ''; | ||
this.__clientIndexes = true; | ||
} | ||
get clientIndexes() { | ||
return this.__clientIndexes; | ||
return this.#clientIndexes; | ||
} | ||
set clientIndexes(stage) { | ||
this.__clientIndexes = stage; | ||
this.#clientIndexes = stage; | ||
} | ||
@@ -21,0 +23,0 @@ |
@@ -39,3 +39,3 @@ // prettier-ignore | ||
'2M', 'K7', '1N', '8A', 'H7', 'X3', 'T4', 'X4', '5O', | ||
'8C', '3M', | ||
'8C', '3M', '6I', '2P', 'PU', '7I', 'X5', 'AL', | ||
], | ||
@@ -47,3 +47,3 @@ 'Firefox': [ | ||
'PI', 'PX', 'QA', 'S5', 'SX', 'TF', 'TO', 'WF', 'ZV', | ||
'FP', 'AD', 'WL', '2I', 'P9', 'KJ', 'WY', 'VK', 'W5', | ||
'FP', 'AD', '2I', 'P9', 'KJ', 'WY', 'VK', 'W5', | ||
'7C', 'N7', 'W7', '8P', | ||
@@ -50,0 +50,0 @@ ], |
// prettier-ignore | ||
module.exports = [ | ||
'36', 'AH', 'AI', 'BL', 'C1', 'C4', 'CB', 'CW', 'DB', | ||
'DD', 'DT', 'EU', 'EZ', 'FK', 'FM', 'FR', 'FX', 'GH', | ||
'3M', 'DT', 'EU', 'EZ', 'FK', 'FM', 'FR', 'FX', 'GH', | ||
'GI', 'GR', 'HA', 'HU', 'IV', 'JB', 'KD', 'M1', 'MF', | ||
'MN', 'MZ', 'NX', 'OC', 'OI', 'OM', 'OZ', 'PU', 'PI', | ||
'MN', 'MZ', 'NX', 'OC', 'OI', 'OM', 'OZ', '2P', 'PI', | ||
'PE', 'QU', 'RE', 'S0', 'S7', 'SA', 'SB', 'SG', 'SK', | ||
@@ -25,4 +25,5 @@ 'ST', 'SU', 'T1', 'UH', 'UM', 'UT', 'VE', 'VV', 'WI', | ||
'9P', 'N8', 'VR', 'N9', 'M9', 'F9', '0P', '0A', '2F', | ||
'2M', 'K7', '1N', '8A', 'H7', 'X3', 'X4', '5O', '3M', | ||
'2M', 'K7', '1N', '8A', 'H7', 'X3', 'X4', '5O', '6I', | ||
'7I', 'X5', | ||
]; |
@@ -448,3 +448,5 @@ // prettier-ignore | ||
'PR': 'Palm Pre', | ||
'PU': 'Puffin', | ||
'7I': 'Puffin Cloud Browser', | ||
'6I': 'Puffin Incognito Browser', | ||
'PU': 'Puffin Secure Browser', | ||
'2P': 'Puffin Web Browser', | ||
@@ -474,2 +476,3 @@ 'PW': 'Palm WebPro', | ||
'P4': 'Privacy Explorer Fast Safe', | ||
'X5': 'Privacy Pioneer Browser', | ||
'P3': 'Private Internet Browser', | ||
@@ -476,0 +479,0 @@ 'P5': 'Proxy Browser', |
@@ -116,4 +116,9 @@ const ClientAbstractParser = require('./../client-abstract-parser'); | ||
} | ||
// If client hints report Chromium, but user agent detects a Chromium based browser, we favor this instead | ||
if (data.name && 'Chromium' === name && 'Chromium' !== data.name) { | ||
if ( | ||
('Chromium' === name || 'Chrome Webview' === name) && | ||
data.name !== ''&& | ||
['CR', 'CV', 'AN'].indexOf(data.short_name) === -1 | ||
) { | ||
name = data.name; | ||
@@ -175,3 +180,3 @@ short = data.short_name; | ||
} | ||
// the browser simulate ua for Android OS | ||
if ('Every Browser' === name) { | ||
@@ -182,3 +187,18 @@ family = 'Chrome'; | ||
} | ||
// This browser simulates user-agent of Firefox | ||
if ('TV-Browser Internet' === name && 'Gecko' === engine) { | ||
family = 'Chrome'; | ||
engine = 'Blink'; | ||
engineVersion = ''; | ||
} | ||
if ('Wolvic' === name) { | ||
if ('Blink' === engine) { | ||
family = 'Chrome'; | ||
} | ||
if ('Gecko' === engine) { | ||
family = 'Firefox'; | ||
} | ||
} | ||
if (name === '') { | ||
@@ -208,5 +228,5 @@ return null; | ||
userAgent = this.prepareUserAgent(userAgent); | ||
let hash = this.parseFromHashHintsApp(clientHints); | ||
let hint = this.parseFromClientHints(clientHints); | ||
let data = this.parseFromUserAgent(userAgent); | ||
const hash = this.parseFromHashHintsApp(clientHints); | ||
const hint = this.parseFromClientHints(clientHints); | ||
const data = this.parseFromUserAgent(userAgent); | ||
return this.prepareParseResult(userAgent, data, hint, hash); | ||
@@ -213,0 +233,0 @@ } |
@@ -8,9 +8,2 @@ const ParserAbstract = require('./abstract-parser'); | ||
const DESKTOP_PATTERN = '(?:Windows (?:NT|IoT)|X11; Linux x86_64)'; | ||
const DESKTOP_EXCLUDE_PATTERN = [ | ||
'CE-HTML', | ||
' Mozilla/|Andr[o0]id|Tablet|Mobile|iPhone|Windows Phone|ricoh|OculusBrowser', | ||
'PicoBrowser|Lenovo|compatible; MSIE|Trident/|Tesla/|XBOX|FBMD/|ARM; ?([^)]+)', | ||
].join('|'); | ||
class DeviceParserAbstract extends ParserAbstract { | ||
@@ -32,7 +25,7 @@ constructor() { | ||
* @param {string} userAgent | ||
* @param {array} brandIndexes | ||
* @param {string[]} brandIndexes | ||
* @returns {[]} | ||
*/ | ||
parseAll(userAgent, brandIndexes = []) { | ||
return this.__parse(userAgent, false, brandIndexes); | ||
return this.#parse(userAgent, false, brandIndexes); | ||
} | ||
@@ -44,6 +37,6 @@ | ||
* @param {string} userAgent | ||
* @returns {{model: *, id: *, type, brand}|null} | ||
* @return {{model: *, id: *, type, brand}|null} | ||
* @private | ||
*/ | ||
__parseForBrand(cursor, userAgent) { | ||
#parseForBrand(cursor, userAgent) { | ||
let item = this.collection[cursor]; | ||
@@ -109,15 +102,7 @@ if (item === void 0) { | ||
* @param {boolean} canBreak | ||
* @param {array} brandIndexes | ||
* @returns {[]} | ||
* @param {string[]} brandIndexes | ||
* @return {[]} | ||
* @private | ||
*/ | ||
__parse(userAgent, canBreak = true, brandIndexes = []) { | ||
const isDesktop = | ||
helper.matchUserAgent(DESKTOP_PATTERN, userAgent) && | ||
!helper.matchUserAgent(DESKTOP_EXCLUDE_PATTERN, userAgent); | ||
if (isDesktop) { | ||
return []; | ||
} | ||
#parse(userAgent, canBreak = true, brandIndexes = []) { | ||
@@ -128,3 +113,3 @@ const output = []; | ||
const cursor = this.getBrandNameById(cursorId); | ||
const result = this.__parseForBrand(cursor, userAgent); | ||
const result = this.#parseForBrand(cursor, userAgent); | ||
if (result === null) { | ||
@@ -140,3 +125,3 @@ continue; | ||
for (let cursor in this.collection) { | ||
const result = this.__parseForBrand(cursor, userAgent); | ||
const result = this.#parseForBrand(cursor, userAgent); | ||
if (result === null) { | ||
@@ -157,7 +142,7 @@ continue; | ||
* @param {array} brandIndexes - check the devices in this list | ||
* @returns {{model: (string|string), id: (*|string), type: string, brand: string}|null} | ||
* @return {{model: (string|string), id: (*|string), type: string, brand: string}|null} | ||
*/ | ||
parse(userAgent, brandIndexes = []) { | ||
userAgent = this.prepareUserAgent(userAgent); | ||
let result = this.__parse(userAgent, true, brandIndexes); | ||
let result = this.#parse(userAgent, true, brandIndexes); | ||
if (result.length) { | ||
@@ -182,3 +167,3 @@ // if it is fake device iphone/ipad then result empty | ||
* @param {string} brandName | ||
* @returns {string|void} | ||
* @return {string|void} | ||
*/ | ||
@@ -192,3 +177,3 @@ getBrandIdByName(brandName) { | ||
* @param {string} id | ||
* @returns {string|void} | ||
* @return {string|void} | ||
*/ | ||
@@ -195,0 +180,0 @@ getBrandNameById(id) { |
@@ -173,2 +173,3 @@ // prettier-ignore | ||
'BZ': 'Bezkam', | ||
'BEL': 'Bell', | ||
'9B': 'Bellphone', | ||
@@ -231,2 +232,3 @@ '63': 'Beyond', | ||
'BMW': 'BMW', | ||
'BYJ': 'BYJU\'S', | ||
'BYY': 'BYYBUO', | ||
@@ -240,2 +242,3 @@ 'BYD': 'BYD', | ||
'CP': 'Captiva', | ||
'CPD': 'CPDEVICE', | ||
'CF': 'Carrefour', | ||
@@ -303,2 +306,3 @@ 'CA1': 'Carbon Mobile', | ||
'9C': 'Colors', | ||
'COL': 'COLORROOM', | ||
'CO': 'Coolpad', | ||
@@ -319,2 +323,3 @@ 'COO': 'Coopers', | ||
'CM': 'Crius Mea', | ||
'CMF': 'CMF', | ||
'0C': 'Crony', | ||
@@ -329,2 +334,3 @@ 'C1': 'Crosscall', | ||
'CWO': 'Cwowdefu', | ||
'CX0': 'CX', | ||
'C4': 'Cyrus', | ||
@@ -426,2 +432,3 @@ 'D5': 'Daewoo', | ||
'E8': 'E-tel', | ||
'ETH': 'E-TACHI', | ||
'EAS': 'EAS Electric', | ||
@@ -454,2 +461,3 @@ 'EP': 'Easypix', | ||
'Z8': 'ELECTRONIA', | ||
'ELG': 'ELE-GATE', | ||
'EL1': 'Elecson', | ||
@@ -606,2 +614,3 @@ 'ELK': 'Elektroland', | ||
'GLB': 'Globmall', | ||
'GME': 'GlocalMe', | ||
'38': 'GLONYX', | ||
@@ -626,2 +635,3 @@ 'U6': 'Glofiish', | ||
'GO1': 'GOtv', | ||
'GPL': 'G-PLUS', | ||
'8G': 'Gplus', | ||
@@ -717,2 +727,3 @@ 'GR': 'Gradiente', | ||
'HX': 'Humax', | ||
'HUM': 'Humanware', | ||
'HR': 'Hurricane', | ||
@@ -727,2 +738,3 @@ 'H5': 'Huskee', | ||
'HYA': 'Hyatta', | ||
'IKL': 'I KALL', | ||
'3I': 'i-Cherry', | ||
@@ -744,2 +756,3 @@ 'IJ': 'i-Joy', | ||
'IG': 'iGet', | ||
'IHL': 'iHome Life', | ||
'IH': 'iHunt', | ||
@@ -790,2 +803,3 @@ 'IA': 'Ikea', | ||
'4I': 'Invin', | ||
'IFT': 'iFIT', | ||
'INA': 'iNavi', | ||
@@ -859,2 +873,3 @@ 'I1': 'iOcean', | ||
'KHI': 'KENSHI', | ||
'KNW': 'KENWOOD', | ||
'KX': 'Kenxinda', | ||
@@ -890,2 +905,3 @@ 'KEN': 'Kenbo', | ||
'K2': 'KRONO', | ||
'KRX': 'Korax', | ||
'KE': 'Krüger&Matz', | ||
@@ -951,2 +967,3 @@ '5K': 'KREZ', | ||
'LO': 'Loewe', | ||
'LNG': 'LongTV', | ||
'YL': 'Loview', | ||
@@ -958,2 +975,3 @@ 'LOV': 'Lovme', | ||
'LOG': 'Logik', | ||
'LGT': 'Logitech', | ||
'GY': 'LOKMAT', | ||
@@ -1068,4 +1086,6 @@ 'LPX': 'LPX-G', | ||
'M4': 'Modecom', | ||
'MEP': 'Mode Mobile', | ||
'MF': 'Mofut', | ||
'MR': 'Motorola', | ||
'MTS': 'Motorola Solutions', | ||
'MIV': 'Motiv', | ||
@@ -1084,2 +1104,3 @@ 'MV': 'Movic', | ||
'9H': 'M-Horse', | ||
'MKP': 'M-KOPA', | ||
'1R': 'Multilaser', | ||
@@ -1174,3 +1195,3 @@ 'MPS': 'MultiPOS', | ||
'7N': 'NorthTech', | ||
'NOT': 'Nothing Phone', | ||
'NOT': 'Nothing', | ||
'5N': 'Nos', | ||
@@ -1197,2 +1218,3 @@ 'NO': 'Nous', | ||
'O9': 'Ok', | ||
'OKA': 'Okapi', | ||
'OA': 'Okapia', | ||
@@ -1367,3 +1389,5 @@ 'OKI': 'Oking', | ||
'RC': 'RCA Tablets', | ||
'RCT': 'RCT', | ||
'2R': 'Reach', | ||
'RLX': 'Realix', | ||
'REL': 'RelNAT', | ||
@@ -1676,2 +1700,3 @@ 'RE4': 'Relndoo', | ||
'Q5': 'Trident', | ||
'TRB': 'Trimble', | ||
'4T': 'Tronsmart', | ||
@@ -1743,2 +1768,3 @@ '11': 'True', | ||
'VB': 'VC', | ||
'VEI': 'Veidoo', | ||
'VN': 'Venso', | ||
@@ -1892,2 +1918,3 @@ 'VNP': 'VNPT Technology', | ||
'XR': 'Xoro', | ||
'XPP': 'XPPen', | ||
'XRL': 'XREAL', | ||
@@ -1894,0 +1921,0 @@ 'XS': 'Xshitou', |
const helper = require('../helper'); | ||
const attr = helper.getPropertyValue; | ||
const { attr } = helper; | ||
@@ -12,4 +12,8 @@ /** | ||
*/ | ||
const isDeviceSizeValid = (deviceWidth, deviceHeight, metaWidth, metaHeight) => { | ||
const isDeviceSizeValid = ( | ||
deviceWidth, | ||
deviceHeight, | ||
metaWidth, | ||
metaHeight | ||
) => { | ||
if (deviceWidth && deviceHeight && metaWidth && metaHeight) { | ||
@@ -21,9 +25,27 @@ const minMetaWidth = parseInt(metaWidth) - 1; | ||
const isWidthValid = helper.fuzzyBetweenNumber(parseInt(deviceWidth), minMetaWidth, maxMetaWidth) | ||
&& helper.fuzzyBetweenNumber(parseInt(deviceHeight), minMetaHeight, maxMetaHeight); | ||
const isWidthValid = | ||
helper.fuzzyBetweenNumber( | ||
parseInt(deviceWidth), | ||
minMetaWidth, | ||
maxMetaWidth | ||
) && | ||
helper.fuzzyBetweenNumber( | ||
parseInt(deviceHeight), | ||
minMetaHeight, | ||
maxMetaHeight | ||
); | ||
const isHeightValid = helper.fuzzyBetweenNumber(parseInt(deviceWidth), minMetaHeight, maxMetaHeight) | ||
&& helper.fuzzyBetweenNumber(parseInt(deviceHeight), minMetaWidth, maxMetaWidth); | ||
const isHeightValid = | ||
helper.fuzzyBetweenNumber( | ||
parseInt(deviceWidth), | ||
minMetaHeight, | ||
maxMetaHeight | ||
) && | ||
helper.fuzzyBetweenNumber( | ||
parseInt(deviceHeight), | ||
minMetaWidth, | ||
maxMetaWidth | ||
); | ||
return (isWidthValid || isHeightValid); | ||
return isWidthValid || isHeightValid; | ||
} | ||
@@ -55,3 +77,3 @@ | ||
{ regex: /Mali-([^$,]+)/i, name: 'ARM Mali-$1' }, | ||
{ regex: /PowerVR Rogue ([^$,]+)/i, name: 'PowerVR $1' } | ||
{ regex: /PowerVR Rogue ([^$,]+)/i, name: 'PowerVR $1' }, | ||
]; | ||
@@ -69,3 +91,2 @@ | ||
/** | ||
@@ -82,3 +103,6 @@ * @param {ResultDevice} deviceData | ||
if (deviceInfo) { | ||
if (deviceInfo.display && typeof deviceInfo.display.resolution === 'string') { | ||
if ( | ||
deviceInfo.display && | ||
typeof deviceInfo.display.resolution === 'string' | ||
) { | ||
let resolution = deviceInfo.display.resolution.split('x'); | ||
@@ -88,8 +112,14 @@ deviceWidth = resolution[0]; | ||
} else { | ||
deviceWidth = deviceInfo.display && deviceInfo.display.resolution && deviceInfo.display.resolution.width | ||
? deviceInfo.display.resolution.width | ||
: null; | ||
deviceHeight = deviceInfo.display && deviceInfo.display.resolution && deviceInfo.display.resolution.height | ||
? deviceInfo.display.resolution.height | ||
: null; | ||
deviceWidth = | ||
deviceInfo.display && | ||
deviceInfo.display.resolution && | ||
deviceInfo.display.resolution.width | ||
? deviceInfo.display.resolution.width | ||
: null; | ||
deviceHeight = | ||
deviceInfo.display && | ||
deviceInfo.display.resolution && | ||
deviceInfo.display.resolution.height | ||
? deviceInfo.display.resolution.height | ||
: null; | ||
} | ||
@@ -108,8 +138,12 @@ | ||
const isGpuExistForClientHints = (clientHints) => { | ||
return clientHints.meta && clientHints.meta.gpu && clientHints.meta.gpu.length > 0; | ||
} | ||
return ( | ||
clientHints.meta && clientHints.meta.gpu && clientHints.meta.gpu.length > 0 | ||
); | ||
}; | ||
const isAppleBrandForDeviceData = (deviceData) => { | ||
return deviceData.brand === 'Apple' | ||
|| (deviceData.brand === '' && /ip(?:hone|[ao]d)/i.test(deviceData.code)) | ||
return ( | ||
deviceData.brand === 'Apple' || | ||
(deviceData.brand === '' && /ip(?:hone|[ao]d)/i.test(deviceData.code)) | ||
); | ||
}; | ||
@@ -124,5 +158,6 @@ | ||
let deviceInfo = deviceData.info; | ||
let deviceGPU = deviceInfo && deviceInfo.hardware && deviceInfo.hardware.gpu | ||
? deviceInfo.hardware.gpu.name | ||
: null; | ||
let deviceGPU = | ||
deviceInfo && deviceInfo.hardware && deviceInfo.hardware.gpu | ||
? deviceInfo.hardware.gpu.name | ||
: null; | ||
@@ -136,3 +171,3 @@ let metaGPU = attr(clientHints.meta, 'gpu', null); | ||
if (metaGPU !== null && deviceGPU !== null) { | ||
return isDeviceGpuValid(deviceGPU, metaGPU) | ||
return isDeviceGpuValid(deviceGPU, metaGPU); | ||
} | ||
@@ -143,5 +178,3 @@ | ||
class DeviceTrusted { | ||
/** | ||
@@ -155,15 +188,27 @@ * @param {ResultOs} osData | ||
static check(osData, clientData, deviceData, clientHints) { | ||
const regexAppleGpu = /GPU Apple/i; | ||
const isGpuExist = isGpuExistForClientHints(clientHints); | ||
const isAppleBrand = isAppleBrandForDeviceData(deviceData); | ||
// is Apple and lack of client-hints | ||
if (isAppleBrand && clientHints.client.brands.length > 0) { | ||
if ( | ||
isAppleBrand && | ||
clientHints && | ||
clientHints.client && | ||
clientHints.client.brands && | ||
clientHints.client.brands.length > 0 | ||
) { | ||
return false; | ||
} | ||
// is Apple and check correct gpu name | ||
if (isAppleBrand && isGpuExist && !regexAppleGpu.test(clientHints.meta.gpu)) { | ||
if ( | ||
isAppleBrand && | ||
isGpuExist && | ||
!regexAppleGpu.test(clientHints.meta.gpu) | ||
) { | ||
return false; | ||
} else if (isAppleBrand && isGpuExist && regexAppleGpu.test(clientHints.meta.gpu)) { | ||
} else if ( | ||
isAppleBrand && | ||
isGpuExist && | ||
regexAppleGpu.test(clientHints.meta.gpu) | ||
) { | ||
return true; | ||
@@ -189,2 +234,2 @@ } | ||
module.exports = DeviceTrusted; | ||
module.exports = DeviceTrusted; |
@@ -32,6 +32,5 @@ const YAML = require('js-yaml'); | ||
/** | ||
* | ||
* @param val1 | ||
* @param val2 | ||
* @returns {boolean} | ||
* @param {string|null} val1 | ||
* @param {string|null} val2 | ||
* @return {boolean} | ||
*/ | ||
@@ -43,2 +42,9 @@ function fuzzyCompare(val1, val2) { | ||
} | ||
/** | ||
* @param {number|string} value1 | ||
* @param {number|string} value2 | ||
* @param {number} num | ||
* @return {boolean} | ||
*/ | ||
function fuzzyCompareNumber(value1, value2, num = 3) { | ||
@@ -48,2 +54,8 @@ return parseFloat(value1).toFixed(num) === parseFloat(value2).toFixed(num); | ||
/** | ||
* @param {number} value | ||
* @param {number} min | ||
* @param {number} max | ||
* @return {boolean} | ||
*/ | ||
function fuzzyBetweenNumber(value, min, max) { | ||
@@ -53,4 +65,8 @@ return value >= min && value <= max; | ||
/** | ||
* @param {string} str | ||
* @return {string} | ||
*/ | ||
function createHash(str) { | ||
var hash = 0, i = 0, len = str.length; | ||
let hash = 0, i = 0, len = str.length; | ||
while (i < len) { | ||
@@ -64,5 +80,5 @@ hash = ((hash << 5) - hash + str.charCodeAt(i++)) << 0; | ||
* Compare versions | ||
* @param ver1 | ||
* @param ver2 | ||
* @returns {number} | ||
* @param {string} ver1 | ||
* @param {string} ver2 | ||
* @return {number} | ||
*/ | ||
@@ -115,3 +131,3 @@ function versionCompare(ver1, ver2) { | ||
* @param {string} userAgent | ||
* @returns {boolean} | ||
* @return {boolean} | ||
*/ | ||
@@ -126,3 +142,3 @@ function hasAndroidTableFragment(userAgent) { | ||
* @param {string} userAgent | ||
* @returns {boolean} | ||
* @return {boolean} | ||
*/ | ||
@@ -157,3 +173,3 @@ function hasOperaTableFragment(userAgent) { | ||
* @param {string} userAgent | ||
* @returns {boolean} | ||
* @return {boolean} | ||
*/ | ||
@@ -165,5 +181,31 @@ function hasOperaTVStoreFragment(userAgent) { | ||
/** | ||
* All devices running Puffin Secure Browser that contain letter 'D' are assumed to be desktops | ||
* @param {string} userAgent | ||
* @return {boolean} | ||
*/ | ||
function hasPuffinDesktopFragment(userAgent) { | ||
return matchUserAgent('Puffin/(?:\\d+[.\\d]+)[LMW]D', userAgent) !== null | ||
} | ||
/** | ||
* All devices running Puffin Web Browser that contain letter 'P' are assumed to be smartphones | ||
* @param {string} userAgent | ||
* @return {boolean} | ||
*/ | ||
function hasPuffinSmartphoneFragment(userAgent) { | ||
return matchUserAgent('Puffin/(?:\\d+[.\\d]+)[AIFLW]P', userAgent) !== null | ||
} | ||
/** | ||
* All devices running Puffin Web Browser that contain letter 'T' are assumed to be tablets | ||
* @param {string} userAgent | ||
* @return {boolean} | ||
*/ | ||
function hasPuffinTabletFragment(userAgent) { | ||
return matchUserAgent('Puffin/(?:\\d+[.\\d]+)[AILW]T', userAgent) !== null | ||
} | ||
/** | ||
* All devices containing TV fragment are assumed to be a tv | ||
* @param {string} userAgent | ||
* @returns {boolean} | ||
* @return {boolean} | ||
*/ | ||
@@ -192,6 +234,33 @@ function hasAndroidTVFragment(userAgent) { | ||
function hasDesktopFragment(userAgent) { | ||
return matchUserAgent('Desktop(?: (x(?:32|64)|WOW64))?;', userAgent) !== null; | ||
const DESKTOP_PATTERN = '(?:Windows (?:NT|IoT)|X11; Linux x86_64)'; | ||
const DESKTOP_EXCLUDE_PATTERN = [ | ||
'CE-HTML', | ||
' Mozilla/|Andr[o0]id|Tablet|Mobile|iPhone|Windows Phone|ricoh|OculusBrowser', | ||
'PicoBrowser|Lenovo|compatible; MSIE|Trident/|Tesla/|XBOX|FBMD/|ARM; ?([^)]+)', | ||
].join('|'); | ||
return matchUserAgent(DESKTOP_PATTERN, userAgent) !== null && | ||
!matchUserAgent(DESKTOP_EXCLUDE_PATTERN, userAgent) !== null; | ||
} | ||
/** | ||
* Check combinations is string that UserAgent ClientHints | ||
* @param {string} userAgent | ||
* @return {boolean} | ||
*/ | ||
function hasUserAgentClientHintsFragment(userAgent) { | ||
return /Android (?:10[.\d]*; K(?: Build\/|[;)])|1[1-5]\)) AppleWebKit/i.test(userAgent); | ||
} | ||
/** | ||
* | ||
* @param {ResultClientHints|*} clientHints | ||
* @return {boolean} | ||
*/ | ||
function hasDeviceModelByClientHints(clientHints) { | ||
return clientHints && clientHints.device && clientHints.device.model; | ||
} | ||
/** | ||
* Get value by attribute for object or default value | ||
@@ -203,3 +272,3 @@ * @param {object} options | ||
*/ | ||
function getPropertyValue(options, propName, defaultValue) { | ||
function attr(options, propName, defaultValue) { | ||
return options !== void 0 && options[propName] !== void 0 | ||
@@ -213,3 +282,3 @@ ? options[propName] | ||
/** | ||
* Values become keys, and keys become values | ||
* Values become keys, and keys become values | ||
* @param {*} obj - | ||
@@ -243,3 +312,2 @@ * @returns {*} | ||
* Remove chars for string | ||
* | ||
* @param {string} str | ||
@@ -343,5 +411,7 @@ * @param {string} chars | ||
hasDesktopFragment, | ||
hasUserAgentClientHintsFragment, | ||
hasDeviceModelByClientHints, | ||
hasTVFragment, | ||
hasTouchFragment, | ||
getPropertyValue, | ||
attr, | ||
revertObject, | ||
@@ -352,3 +422,6 @@ loadYMLFile, | ||
splitUserAgent, | ||
matchReplace | ||
matchReplace, | ||
hasPuffinDesktopFragment, | ||
hasPuffinSmartphoneFragment, | ||
hasPuffinTabletFragment | ||
}; |
@@ -6,3 +6,3 @@ // prettier-ignore | ||
'ADR', 'CLR', 'BOS', 'REV', 'LEN', 'SIR', 'RRS', 'WER', 'PIC', 'ARM', | ||
'HEL', 'BYI', 'RIS', | ||
'HEL', 'BYI', 'RIS', 'PUF', | ||
], | ||
@@ -9,0 +9,0 @@ 'AmigaOS': ['AMG', 'MOR', 'ARO'], |
@@ -119,2 +119,3 @@ // prettier-ignore | ||
'PVE': 'Proxmox VE', | ||
'PUF': 'Puffin OS', | ||
'PUR': 'PureOS', | ||
@@ -121,0 +122,0 @@ 'QTP': 'Qtopia', |
@@ -16,4 +16,4 @@ const ParserAbstract = require('./abstract-parser'); | ||
/** | ||
* @param userAgent | ||
* @returns {null|{name: string, id: string}} | ||
* @param {string} userAgent | ||
* @returns {ResultVendor|null} | ||
*/ | ||
@@ -20,0 +20,0 @@ parse(userAgent) { |
530
README.md
# [node-device-detector](https://www.npmjs.com/package/node-device-detector) | ||
_Last update: 09/09/2024_ | ||
_Last update: 08/10/2024_ | ||
@@ -414,6 +414,6 @@ ## Description | ||
### What about tests? | ||
Yes we use tests, total tests ~79.8k | ||
Yes we use tests, total tests ~80.8k | ||
### Get more information about a device (experimental) | ||
> This parser is experimental and contains few devices. (1845 devices, alias devices 3912) | ||
> This parser is experimental and contains few devices. (1862 devices, alias devices 3923) | ||
> | ||
@@ -495,9 +495,10 @@ ##### Support detail brands/models list: | ||
| supra | 1 | 0 | - | tecno mobile | 91 | 131 | | ||
| tiphone | 1 | 0 | - | utok | 1 | 0 | | ||
| uz mobile | 1 | 0 | - | vernee | 9 | 2 | | ||
| vivo | 196 | 286 | - | walton | 13 | 0 | | ||
| we | 8 | 0 | - | weimei | 1 | 0 | | ||
| wiko | 7 | 12 | - | wileyfox | 9 | 0 | | ||
| wink | 4 | 0 | - | xiaomi | 9 | 8 | | ||
| zync | 2 | 0 | - | zyq | 1 | 13 | | ||
| tiphone | 1 | 0 | - | ulefone | 8 | 0 | | ||
| utok | 1 | 0 | - | uz mobile | 1 | 0 | | ||
| vernee | 9 | 2 | - | vivo | 205 | 297 | | ||
| walton | 13 | 0 | - | we | 8 | 0 | | ||
| weimei | 1 | 0 | - | wiko | 7 | 12 | | ||
| wileyfox | 9 | 0 | - | wink | 4 | 0 | | ||
| xiaomi | 9 | 8 | - | zync | 2 | 0 | | ||
| zyq | 1 | 13 | - | | | | | ||
@@ -602,3 +603,3 @@ </details> | ||
##### Support detect brands list (1934): | ||
##### Support detect brands list (1961): | ||
@@ -633,83 +634,85 @@ <details> | ||
BDsharing | Beafon | Becker | Beeline | Beelink | Beetel | Beista | ||
Beko | Bellphone | Benco | Benesse | BenQ | BenQ-Siemens | BenWee | ||
Benzo | Beyond | Bezkam | BGH | Bigben | BIHEE | BilimLand | ||
Billion | Billow | BioRugged | Bird | Bitel | Bitmore | Bittium | ||
Bkav | Black Bear | Black Box | Black Fox | Blackpcs | Blackview | Blaupunkt | ||
Bleck | BLISS | Blloc | Blow | Blu | Bluboo | Bluebird | ||
Bluedot | Bluegood | BlueSky | Bluewave | BluSlate | BMAX | Bmobile | ||
BMW | BMXC | Bobarry | bogo | Bolva | Bookeen | Boost | ||
Botech | Boway | bq | BrandCode | Brandt | BRAVE | Bravis | ||
BrightSign | Brigmton | Brondi | BROR | BS Mobile | Bubblegum | Bundy | ||
Bush | BuzzTV | BYD | BYYBUO | C Idea | C5 Mobile | CADENA | ||
CAGI | Camfone | Canaima | Canal Digital | Canal+ | Canguro | Capitel | ||
Captiva | Carbon Mobile | Carrefour | Casio | Casper | Cat | Cavion | ||
CCIT | Cecotec | Ceibal | Celcus | Celkon | Cell-C | Cellacom | ||
CellAllure | Cellution | CENTEK | Centric | CEPTER | CG Mobile | CGV | ||
Chainway | Changhong | CHCNAV | Cherry Mobile | Chico Mobile | ChiliGreen | China Mobile | ||
China Telecom | Chuwi | CipherLab | Citycall | CKK Mobile | Claresta | Clarmin | ||
CLAYTON | ClearPHONE | Clementoni | Cloud | Cloudfone | Cloudpad | Clout | ||
Clovertek | CnM | Cobalt | Coby Kyros | Colors | Comio | Compal | ||
Compaq | COMPUMAX | ComTrade Tesla | Conceptum | Concord | ConCorde | Condor | ||
Connectce | Connex | Conquest | Continental Edison | Contixo | COOD-E | Coolpad | ||
Coopers | CORN | Cosmote | Covia | Cowon | COYOTE | CreNova | ||
Crescent | Cricket | Crius Mea | Crony | Crosscall | Crown | Ctroniq | ||
Cube | CUBOT | Cuiud | CVTE | Cwowdefu | Cyrus | D-Link | ||
D-Tech | Daewoo | Danew | DangcapHD | Dany | Daria | DASS | ||
Datalogic | Datamini | Datang | Datawind | Datsun | Dazen | DbPhone | ||
Dbtel | Dcode | DEALDIG | Dell | Denali | Denver | Desay | ||
DeWalt | DEXP | DEYI | DF | DGTEC | DIALN | Dialog | ||
Dicam | Digi | Digicel | DIGICOM | Digidragon | DIGIFORS | Digihome | ||
Digiland | Digit4G | Digma | DIJITSU | DIKOM | DIMO | Dinalink | ||
Dinax | DING DING | DIORA | DISH | Disney | Ditecma | Diva | ||
DiverMax | Divisat | DIXON | DL | DMM | DMOAO | DNS | ||
DoCoMo | Doffler | Dolamee | Dom.ru | Doogee | Doopro | Doov | ||
Dopod | Doppio | DORLAND | Doro | DPA | DRAGON | Dragon Touch | ||
Dreamgate | DreamStar | DreamTab | Droidlogic | Droxio | DSDevices | DSIC | ||
Dtac | Dune HD | DUNNS Mobile | Durabook | Duubee | Dykemann | Dyon | ||
E-Boda | E-Ceros | E-tel | Eagle | EagleSoar | EAS Electric | Easypix | ||
Beko | Bell | Bellphone | Benco | Benesse | BenQ | BenQ-Siemens | ||
BenWee | Benzo | Beyond | Bezkam | BGH | Bigben | BIHEE | ||
BilimLand | Billion | Billow | BioRugged | Bird | Bitel | Bitmore | ||
Bittium | Bkav | Black Bear | Black Box | Black Fox | Blackpcs | Blackview | ||
Blaupunkt | Bleck | BLISS | Blloc | Blow | Blu | Bluboo | ||
Bluebird | Bluedot | Bluegood | BlueSky | Bluewave | BluSlate | BMAX | ||
Bmobile | BMW | BMXC | Bobarry | bogo | Bolva | Bookeen | ||
Boost | Botech | Boway | bq | BrandCode | Brandt | BRAVE | ||
Bravis | BrightSign | Brigmton | Brondi | BROR | BS Mobile | Bubblegum | ||
Bundy | Bush | BuzzTV | BYD | BYJU'S | BYYBUO | C Idea | ||
C5 Mobile | CADENA | CAGI | Camfone | Canaima | Canal Digital | Canal+ | ||
Canguro | Capitel | Captiva | Carbon Mobile | Carrefour | Casio | Casper | ||
Cat | Cavion | CCIT | Cecotec | Ceibal | Celcus | Celkon | ||
Cell-C | Cellacom | CellAllure | Cellution | CENTEK | Centric | CEPTER | ||
CG Mobile | CGV | Chainway | Changhong | CHCNAV | Cherry Mobile | Chico Mobile | ||
ChiliGreen | China Mobile | China Telecom | Chuwi | CipherLab | Citycall | CKK Mobile | ||
Claresta | Clarmin | CLAYTON | ClearPHONE | Clementoni | Cloud | Cloudfone | ||
Cloudpad | Clout | Clovertek | CMF | CnM | Cobalt | Coby Kyros | ||
COLORROOM | Colors | Comio | Compal | Compaq | COMPUMAX | ComTrade Tesla | ||
Conceptum | Concord | ConCorde | Condor | Connectce | Connex | Conquest | ||
Continental Edison | Contixo | COOD-E | Coolpad | Coopers | CORN | Cosmote | ||
Covia | Cowon | COYOTE | CPDEVICE | CreNova | Crescent | Cricket | ||
Crius Mea | Crony | Crosscall | Crown | Ctroniq | Cube | CUBOT | ||
Cuiud | CVTE | Cwowdefu | CX | Cyrus | D-Link | D-Tech | ||
Daewoo | Danew | DangcapHD | Dany | Daria | DASS | Datalogic | ||
Datamini | Datang | Datawind | Datsun | Dazen | DbPhone | Dbtel | ||
Dcode | DEALDIG | Dell | Denali | Denver | Desay | DeWalt | ||
DEXP | DEYI | DF | DGTEC | DIALN | Dialog | Dicam | ||
Digi | Digicel | DIGICOM | Digidragon | DIGIFORS | Digihome | Digiland | ||
Digit4G | Digma | DIJITSU | DIKOM | DIMO | Dinalink | Dinax | ||
DING DING | DIORA | DISH | Disney | Ditecma | Diva | DiverMax | ||
Divisat | DIXON | DL | DMM | DMOAO | DNS | DoCoMo | ||
Doffler | Dolamee | Dom.ru | Doogee | Doopro | Doov | Dopod | ||
Doppio | DORLAND | Doro | DPA | DRAGON | Dragon Touch | Dreamgate | ||
DreamStar | DreamTab | Droidlogic | Droxio | DSDevices | DSIC | Dtac | ||
Dune HD | DUNNS Mobile | Durabook | Duubee | Dykemann | Dyon | E-Boda | ||
E-Ceros | E-TACHI | E-tel | Eagle | EagleSoar | EAS Electric | Easypix | ||
EBEN | EBEST | Echo Mobiles | ecom | ECON | ECOO | ECS | ||
Edenwood | EE | EFT | EGL | EGOTEK | Einstein | EKINOX | ||
EKO | Eks Mobility | EKT | ELARI | Elecson | Electroneum | ELECTRONIA | ||
Elekta | Elektroland | Element | Elenberg | Elephone | Elevate | Elong Mobile | ||
Eltex | Ematic | Emporia | ENACOM | Energizer | Energy Sistem | Engel | ||
ENIE | Enot | eNOVA | Entity | Envizen | Ephone | Epic | ||
Epik One | Epson | Equator | Ergo | Ericsson | Ericy | Erisson | ||
Essential | Essentielb | eSTAR | ETOE | Eton | eTouch | Etuline | ||
Eurocase | Eurostar | Evercoss | Everest | Everex | Everis | Evertek | ||
Evolio | Evolveo | Evoo | EVPAD | EvroMedia | EWIS | EXCEED | ||
Exmart | ExMobile | EXO | Explay | Express LUCK | ExtraLink | Extrem | ||
Eyemoo | EYU | Ezio | Ezze | F&U | F+ | F150 | ||
F2 Mobile | Facebook | Facetel | Facime | Fairphone | Famoco | Famous | ||
Fantec | FaRao Pro | Farassoo | FarEasTone | Fengxiang | Fenoti | FEONAL | ||
Fero | FFF SmartLife | Figgers | FiGi | FiGO | FiiO | Filimo | ||
FILIX | FinePower | Finlux | FireFly Mobile | FISE | FITCO | Fluo | ||
Fly | FLYCAT | FLYCOAY | FMT | FNB | FNF | Fobem | ||
Fondi | Fonos | FOODO | FORME | Formuler | Forstar | Fortis | ||
FortuneShip | FOSSiBOT | Four Mobile | Fourel | Foxconn | FoxxD | FPT | ||
free | Freetel | FreeYond | Frunsi | Fuego | Fujitsu | Funai | ||
Fusion5 | Future Mobile Technology | Fxtec | G-TiDE | G-Touch | Galactic | Galaxy Innovations | ||
Gamma | Garmin-Asus | Gateway | Gazer | GDL | Geanee | Geant | ||
Gear Mobile | Gemini | General Mobile | Genesis | GEOFOX | Geotel | Geotex | ||
GEOZON | Getnord | GFive | Gfone | Ghia | Ghong | Ghost | ||
Gigabyte | Gigaset | Gini | Ginzzu | Gionee | GIRASOLE | Globex | ||
Globmall | Glofiish | GLONYX | Glory Star | GLX | GOCLEVER | Gocomma | ||
GoGEN | Gol Mobile | GOLDBERG | GoldMaster | GoldStar | Goly | Gome | ||
GoMobile | GOODTEL | Google | Goophone | Gooweel | GOtv | Gplus | ||
Gradiente | Graetz | Grape | Great Asia | Gree | Green Lion | Green Orange | ||
Greentel | Gresso | Gretel | GroBerwert | Grundig | Gtel | GTMEDIA | ||
GTX | Guophone | GVC Pro | H133 | H96 | Hafury | Haier | ||
Haipai | Haixu | Hamlet | Hammer | Handheld | HannSpree | Hanseatic | ||
Hanson | HAOQIN | HAOVM | Hardkernel | Harper | Hartens | Hasee | ||
Hathway | HDC | HeadWolf | HEC | Heimat | Helio | HERO | ||
HexaByte | Hezire | Hi | Hi Nova | Hi-Level | Hiberg | HiBy | ||
High Q | Highscreen | HiGrace | HiHi | HiKing | HiMax | HIPER | ||
Hipstreet | Hiremco | Hisense | Hitachi | Hitech | HKC | HKPro | ||
HLLO | HMD | HOFER | Hoffmann | HOLLEBERG | Homatics | Hometech | ||
Homtom | Honeywell | HongTop | HONKUAHG | Hoozo | Hopeland | Horizon | ||
Horizont | Hosin | Hot Pepper | Hotel | HOTREALS | Hotwav | How | ||
HP | HTC | Huadoo | Huagan | Huavi | Huawei | Hugerock | ||
Humax | Hurricane | Huskee | Hyatta | Hykker | Hyrican | Hytera | ||
Hyundai | Hyve | i-Cherry | I-INN | i-Joy | i-mate | i-mobile | ||
I-Plus | iBall | iBerry | ibowin | iBrit | IconBIT | iData | ||
iDino | iDroid | iGet | iHunt | Ikea | IKI Mobile | iKoMo | ||
EKO | Eks Mobility | EKT | ELARI | ELE-GATE | Elecson | Electroneum | ||
ELECTRONIA | Elekta | Elektroland | Element | Elenberg | Elephone | Elevate | ||
Elong Mobile | Eltex | Ematic | Emporia | ENACOM | Energizer | Energy Sistem | ||
Engel | ENIE | Enot | eNOVA | Entity | Envizen | Ephone | ||
Epic | Epik One | Epson | Equator | Ergo | Ericsson | Ericy | ||
Erisson | Essential | Essentielb | eSTAR | ETOE | Eton | eTouch | ||
Etuline | Eurocase | Eurostar | Evercoss | Everest | Everex | Everis | ||
Evertek | Evolio | Evolveo | Evoo | EVPAD | EvroMedia | EWIS | ||
EXCEED | Exmart | ExMobile | EXO | Explay | Express LUCK | ExtraLink | ||
Extrem | Eyemoo | EYU | Ezio | Ezze | F&U | F+ | ||
F150 | F2 Mobile | Facebook | Facetel | Facime | Fairphone | Famoco | ||
Famous | Fantec | FaRao Pro | Farassoo | FarEasTone | Fengxiang | Fenoti | ||
FEONAL | Fero | FFF SmartLife | Figgers | FiGi | FiGO | FiiO | ||
Filimo | FILIX | FinePower | Finlux | FireFly Mobile | FISE | FITCO | ||
Fluo | Fly | FLYCAT | FLYCOAY | FMT | FNB | FNF | ||
Fobem | Fondi | Fonos | FOODO | FORME | Formuler | Forstar | ||
Fortis | FortuneShip | FOSSiBOT | Four Mobile | Fourel | Foxconn | FoxxD | ||
FPT | free | Freetel | FreeYond | Frunsi | Fuego | Fujitsu | ||
Funai | Fusion5 | Future Mobile Technology | Fxtec | G-PLUS | G-TiDE | G-Touch | ||
Galactic | Galaxy Innovations | Gamma | Garmin-Asus | Gateway | Gazer | GDL | ||
Geanee | Geant | Gear Mobile | Gemini | General Mobile | Genesis | GEOFOX | ||
Geotel | Geotex | GEOZON | Getnord | GFive | Gfone | Ghia | ||
Ghong | Ghost | Gigabyte | Gigaset | Gini | Ginzzu | Gionee | ||
GIRASOLE | Globex | Globmall | GlocalMe | Glofiish | GLONYX | Glory Star | ||
GLX | GOCLEVER | Gocomma | GoGEN | Gol Mobile | GOLDBERG | GoldMaster | ||
GoldStar | Goly | Gome | GoMobile | GOODTEL | Google | Goophone | ||
Gooweel | GOtv | Gplus | Gradiente | Graetz | Grape | Great Asia | ||
Gree | Green Lion | Green Orange | Greentel | Gresso | Gretel | GroBerwert | ||
Grundig | Gtel | GTMEDIA | GTX | Guophone | GVC Pro | H133 | ||
H96 | Hafury | Haier | Haipai | Haixu | Hamlet | Hammer | ||
Handheld | HannSpree | Hanseatic | Hanson | HAOQIN | HAOVM | Hardkernel | ||
Harper | Hartens | Hasee | Hathway | HDC | HeadWolf | HEC | ||
Heimat | Helio | HERO | HexaByte | Hezire | Hi | Hi Nova | ||
Hi-Level | Hiberg | HiBy | High Q | Highscreen | HiGrace | HiHi | ||
HiKing | HiMax | HIPER | Hipstreet | Hiremco | Hisense | Hitachi | ||
Hitech | HKC | HKPro | HLLO | HMD | HOFER | Hoffmann | ||
HOLLEBERG | Homatics | Hometech | Homtom | Honeywell | HongTop | HONKUAHG | ||
Hoozo | Hopeland | Horizon | Horizont | Hosin | Hot Pepper | Hotel | ||
HOTREALS | Hotwav | How | HP | HTC | Huadoo | Huagan | ||
Huavi | Huawei | Hugerock | Humanware | Humax | Hurricane | Huskee | ||
Hyatta | Hykker | Hyrican | Hytera | Hyundai | Hyve | I KALL | ||
i-Cherry | I-INN | i-Joy | i-mate | i-mobile | I-Plus | iBall | ||
iBerry | ibowin | iBrit | IconBIT | iData | iDino | iDroid | ||
iFIT | iGet | iHome Life | iHunt | Ikea | IKI Mobile | iKoMo | ||
iKon | iKonia | IKU Mobile | iLA | iLepo | iLife | iMan | ||
@@ -731,33 +734,34 @@ Imaq | iMars | iMI | IMO Mobile | Imose | Impression | iMuz | ||
Kata | KATV1 | Kazam | Kazuna | KDDI | Kempler & Strauss | Kenbo | ||
Kendo | Keneksi | KENSHI | Kenxinda | Khadas | Kiano | kidiby | ||
Kingbox | Kingstar | Kingsun | KINGZONE | Kinstone | Kiowa | Kivi | ||
Klipad | KN Mobile | Kocaso | Kodak | Kogan | Komu | Konka | ||
Konrow | Koobee | Koolnee | Kooper | KOPO | Koridy | Koslam | ||
Kraft | KREZ | KRIP | KRONO | Krüger&Matz | KT-Tech | KUBO | ||
KuGou | Kuliao | Kult | Kumai | Kurio | KVADRA | Kvant | ||
Kydos | Kyocera | Kyowon | Kzen | KZG | L-Max | LAIQ | ||
Land Rover | Landvo | Lanin | Lanix | Lark | Laser | Laurus | ||
Lava | LCT | Le Pan | Leader Phone | Leagoo | Leben | LeBest | ||
Lectrus | Ledstar | LeEco | Leelbox | Leff | Legend | Leke | ||
Lemco | LEMFO | Lemhoov | Lenco | Lenovo | Leotec | Lephone | ||
Lesia | Lexand | Lexibook | LG | Liberton | Lifemaxx | Lime | ||
Lingbo | Lingwin | Linnex | Linsar | Linsay | Listo | LNMBBS | ||
Loewe | Logic | Logic Instrument | Logicom | Logik | LOKMAT | Loview | ||
Lovme | LPX-G | LT Mobile | Lumigon | Lumitel | Lumus | Luna | ||
Luxor | Lville | LW | LYF | LYOTECH LABS | M-Horse | M-Tech | ||
M.T.T. | M3 Mobile | M4tel | MAC AUDIO | Macoox | Mafe | MAG | ||
MAGCH | Magicsee | Magnus | Majestic | Malata | Mango | Manhattan | ||
Mann | Manta Multimedia | Mantra | Mara | Marshal | Mascom | Massgo | ||
Masstel | Master-G | Mastertech | Matco Tools | Matrix | Maunfeld | Maxcom | ||
Maxfone | Maximus | Maxtron | MAXVI | Maxwell | Maxwest | MAXX | ||
Maze | Maze Speed | MBI | MBK | MBOX | MDC Store | MDTV | ||
meanIT | Mecer | Mecool | Mediacom | MediaTek | Medion | MEEG | ||
MEGA VISION | Megacable | MegaFon | Meitu | Meizu | Melrose | MeMobile | ||
Memup | MEO | MESWAO | Meta | Metz | MEU | MicroMax | ||
Microsoft | Microtech | Mightier | Minix | Mint | Mintt | Mio | ||
Mione | mipo | Miray | Mitchell & Brown | Mito | Mitsubishi | Mitsui | ||
MIVO | MIWANG | MIXC | MiXzo | MLAB | MLLED | MLS | ||
MMI | Mobell | Mobicel | MobiIoT | Mobiistar | Mobile Kingdom | Mobiola | ||
Mobistel | MobiWire | Mobo | Mobvoi | Modecom | Mofut | Moondrop | ||
Mosimosi | Motiv | Motorola | Movic | MOVISUN | Movitel | Moxee | ||
Kendo | Keneksi | KENSHI | KENWOOD | Kenxinda | Khadas | Kiano | ||
kidiby | Kingbox | Kingstar | Kingsun | KINGZONE | Kinstone | Kiowa | ||
Kivi | Klipad | KN Mobile | Kocaso | Kodak | Kogan | Komu | ||
Konka | Konrow | Koobee | Koolnee | Kooper | KOPO | Korax | ||
Koridy | Koslam | Kraft | KREZ | KRIP | KRONO | Krüger&Matz | ||
KT-Tech | KUBO | KuGou | Kuliao | Kult | Kumai | Kurio | ||
KVADRA | Kvant | Kydos | Kyocera | Kyowon | Kzen | KZG | ||
L-Max | LAIQ | Land Rover | Landvo | Lanin | Lanix | Lark | ||
Laser | Laurus | Lava | LCT | Le Pan | Leader Phone | Leagoo | ||
Leben | LeBest | Lectrus | Ledstar | LeEco | Leelbox | Leff | ||
Legend | Leke | Lemco | LEMFO | Lemhoov | Lenco | Lenovo | ||
Leotec | Lephone | Lesia | Lexand | Lexibook | LG | Liberton | ||
Lifemaxx | Lime | Lingbo | Lingwin | Linnex | Linsar | Linsay | ||
Listo | LNMBBS | Loewe | Logic | Logic Instrument | Logicom | Logik | ||
Logitech | LOKMAT | LongTV | Loview | Lovme | LPX-G | LT Mobile | ||
Lumigon | Lumitel | Lumus | Luna | Luxor | Lville | LW | ||
LYF | LYOTECH LABS | M-Horse | M-KOPA | M-Tech | M.T.T. | M3 Mobile | ||
M4tel | MAC AUDIO | Macoox | Mafe | MAG | MAGCH | Magicsee | ||
Magnus | Majestic | Malata | Mango | Manhattan | Mann | Manta Multimedia | ||
Mantra | Mara | Marshal | Mascom | Massgo | Masstel | Master-G | ||
Mastertech | Matco Tools | Matrix | Maunfeld | Maxcom | Maxfone | Maximus | ||
Maxtron | MAXVI | Maxwell | Maxwest | MAXX | Maze | Maze Speed | ||
MBI | MBK | MBOX | MDC Store | MDTV | meanIT | Mecer | ||
Mecool | Mediacom | MediaTek | Medion | MEEG | MEGA VISION | Megacable | ||
MegaFon | Meitu | Meizu | Melrose | MeMobile | Memup | MEO | ||
MESWAO | Meta | Metz | MEU | MicroMax | Microsoft | Microtech | ||
Mightier | Minix | Mint | Mintt | Mio | Mione | mipo | ||
Miray | Mitchell & Brown | Mito | Mitsubishi | Mitsui | MIVO | MIWANG | ||
MIXC | MiXzo | MLAB | MLLED | MLS | MMI | Mobell | ||
Mobicel | MobiIoT | Mobiistar | Mobile Kingdom | Mobiola | Mobistel | MobiWire | ||
Mobo | Mobvoi | Mode Mobile | Modecom | Mofut | Moondrop | Mosimosi | ||
Motiv | Motorola | Motorola Solutions | Movic | MOVISUN | Movitel | Moxee | ||
mPhone | Mpman | MSI | MStar | MTC | MTN | Multilaser | ||
@@ -776,115 +780,116 @@ MultiPOS | MwalimuPlus | MYFON | MyGica | MygPad | Mymaga | MyMobile | ||
Nomi | Nomu | Noontec | Nordfrost | Nordmende | NORMANDE | NorthTech | ||
Nos | Nothing Phone | Nous | Novacom | Novex | Novey | NoviSea | ||
Nos | Nothing | Nous | Novacom | Novex | Novey | NoviSea | ||
NOVO | NTT West | NuAns | Nubia | NUU Mobile | NuVision | Nuvo | ||
Nvidia | NYX Mobile | O+ | O2 | Oale | Oangcc | OASYS | ||
Obabox | Ober | Obi | OCEANIC | Odotpad | Odys | Oilsky | ||
OINOM | Ok | Okapia | Oking | OKSI | OKWU | Olax | ||
Olkya | Ollee | OLTO | Olympia | OMIX | Onda | OneClick | ||
OneLern | OnePlus | Onida | Onix | Onkyo | ONN | ONVO | ||
ONYX BOOX | Ookee | Ooredoo | OpelMobile | Openbox | Ophone | OPPO | ||
Opsson | Optoma | Orange | Orange Pi | Orava | Orbic | Orbita | ||
Orbsmart | Ordissimo | Orion | OSCAL | OTTO | OUJIA | Ouki | ||
Oukitel | OUYA | Overmax | Ovvi | öwn | Owwo | OX TAB | ||
OYSIN | Oysters | Oyyu | OzoneHD | P-UP | Pacific Research Alliance | Packard Bell | ||
Padpro | PAGRAER | Paladin | Palm | Panacom | Panasonic | Panavox | ||
Pano | Panodic | Panoramic | Pantech | PAPYRE | Parrot Mobile | Partner Mobile | ||
PC Smart | PCBOX | PCD | PCD Argentina | PEAQ | Pelitt | Pendoo | ||
Penta | Pentagram | Perfeo | Phicomm | Philco | Philips | Phonemax | ||
phoneOne | Pico | PINE | Pioneer | Pioneer Computers | PiPO | PIRANHA | ||
Pixela | Pixelphone | PIXPRO | Pixus | Planet Computers | Platoon | Play Now | ||
Ployer | Plum | PlusStyle | Pluzz | PocketBook | POCO | Point Mobile | ||
Point of View | Polar | PolarLine | Polaroid | Polestar | PolyPad | Polytron | ||
Pomp | Poppox | POPTEL | Porsche | Portfolio | Positivo | Positivo BGH | ||
PPTV | Premier | Premio | Prestigio | PRIME | Primepad | Primux | ||
Pritom | Prixton | PROFiLO | Proline | Prology | ProScan | PROSONIC | ||
Protruly | ProVision | PULID | Punos | Purism | PVBox | Q-Box | ||
Q-Touch | Q.Bell | QFX | Qilive | QIN | QLink | QMobile | ||
Qnet Mobile | QTECH | Qtek | Quantum | Quatro | Qubo | Quechua | ||
Quest | Quipus | Qumo | Qware | QWATT | R-TV | Rakuten | ||
Ramos | Raspberry | Ravoz | Raylandz | Razer | RCA Tablets | Reach | ||
Readboy | Realme | RED | Redbean | Redfox | RedLine | Redway | ||
Reeder | REGAL | RelNAT | Relndoo | Remdun | Renova | rephone | ||
Retroid Pocket | Revo | Revomovil | Rhino | Ricoh | Rikomagic | RIM | ||
Ringing Bells | Rinno | Ritmix | Ritzviva | Riviera | Rivo | Rizzen | ||
ROADMAX | Roadrover | Roam Cat | ROCH | Rocket | ROiK | Rokit | ||
Roku | Rombica | Ross&Moor | Rover | RoverPad | Royole | RoyQueen | ||
RT Project | RTK | RugGear | RuggeTech | Ruggex | Ruio | Runbo | ||
Rupa | Ryte | S-Color | S-TELL | S2Tel | Saba | Safaricom | ||
Sagem | Sagemcom | Saiet | SAILF | Salora | Samsung | Samtech | ||
Samtron | Sanei | Sankey | Sansui | Santin | SANY | Sanyo | ||
Savio | Sber | SCBC | Schneider | Schok | Scoole | Scosmos | ||
Seatel | SEBBE | Seeken | SEEWO | SEG | Sega | SEHMAX | ||
Selecline | Selenga | Selevision | Selfix | SEMP TCL | Sencor | Sendo | ||
Senkatel | SENNA | Senseit | Senwa | SERVO | Seuic | Sewoo | ||
SFR | SGIN | Shanling | Sharp | Shift Phones | Shivaki | Shtrikh-M | ||
Shuttle | Sico | Siemens | Sigma | Silelis | Silent Circle | Silva Schneider | ||
Simbans | simfer | Simply | Singtech | Siragon | Sirin Labs | Siswoo | ||
SK Broadband | SKG | SKK Mobile | Sky | Skyline | SkyStream | Skytech | ||
Skyworth | Smadl | Smailo | Smart | Smart Electronic | Smart Kassel | Smartab | ||
SmartBook | SMARTEC | Smartex | Smartfren | Smartisan | Smarty | Smooth Mobile | ||
Smotreshka | SMT Telecom | SMUX | SNAMI | SobieTech | Soda | Softbank | ||
Soho Style | Solas | SOLE | SOLO | Solone | Sonim | SONOS | ||
Sony | Sony Ericsson | SOSH | SoulLink | Soundmax | Soyes | Spark | ||
Sparx | SPC | Spectralink | Spectrum | Spice | Sprint | SPURT | ||
SQOOL | SSKY | Star | Starlight | Starmobile | Starway | Starwind | ||
STF Mobile | STG Telecom | STK | Stonex | Storex | StrawBerry | Stream | ||
STRONG | Stylo | Subor | Sugar | Sumvision | Sunmax | Sunmi | ||
Sunny | Sunstech | SunVan | Sunvell | SUNWIND | Super General | SuperBOX | ||
SuperSonic | SuperTab | Supra | Supraim | Surfans | Surge | Suzuki | ||
Sveon | Swipe | SWISSMOBILITY | Swisstone | Switel | SWOFY | Syco | ||
SYH | Sylvania | Symphony | Syrox | System76 | T-Mobile | T96 | ||
TADAAM | TAG Tech | Taiga System | Takara | Talius | Tambo | Tanix | ||
TAUBE | TB Touch | TCL | TD Systems | TD Tech | TeachTouch | Technicolor | ||
Technika | TechniSat | Technopc | TECHNOSAT | TechnoTrend | TechPad | TechSmart | ||
Techstorm | Techwood | Teclast | Tecno Mobile | TecToy | TEENO | Teknosa | ||
Tele2 | Telefunken | Telego | Telenor | Telia | Telit | Telkom | ||
Telly | Telma | TeloSystems | Telpo | TENPLUS | Teracube | Tesco | ||
Tesla | TETC | Tetratab | teXet | ThL | Thomson | Thuraya | ||
TIANYU | Tibuta | Tigers | Time2 | Timovi | TIMvision | Tinai | ||
Tinmo | TiPhone | Tivax | TiVo | TJC | TJD | TOKYO | ||
Tolino | Tone | TOOGO | Tooky | Top House | TopDevice | TOPDON | ||
Topelotek | Toplux | TOPSHOWS | Topsion | Topway | Torex | Torque | ||
TOSCIDO | Toshiba | Touch Plus | Touchmate | TOX | TPS | Transpeed | ||
TrekStor | Trevi | TriaPlay | Trident | Trifone | Trio | Tronsmart | ||
True | True Slim | Tsinghua Tongfang | TTEC | TTfone | TTK-TV | TuCEL | ||
Tunisie Telecom | Turbo | Turbo-X | TurboKids | TurboPad | Türk Telekom | Turkcell | ||
Tuvio | TVC | TwinMOS | TWM | Twoe | TWZ | TYD | ||
Tymes | U-Magic | U.S. Cellular | UD | UE | UGINE | Ugoos | ||
Uhans | Uhappy | Ulefone | Umax | UMIDIGI | Unblock Tech | Uniden | ||
Unihertz | Unimax | Uniqcell | Uniscope | Unistrong | Unitech | United Group | ||
UNIWA | Unknown | Unnecto | Unnion Technologies | UNNO | Unonu | Unowhy | ||
UOOGOU | Urovo | UTime | UTOK | UTStarcom | UZ Mobile | V-Gen | ||
V-HOME | V-HOPE | v-mobile | VAIO | VALE | VALEM | VALTECH | ||
VANGUARD | Vankyo | VANWIN | Vargo | Vastking | VAVA | VC | ||
VDVD | Vega | Vekta | Venso | Venstar | Venturer | VEON | ||
Verico | Verizon | Vernee | Verssed | Versus | Vertex | Vertu | ||
Verykool | Vesta | Vestel | VETAS | Vexia | VGO TEL | ViBox | ||
Victurio | VIDA | Videocon | Videoweb | ViewSonic | VIIPOO | VIKUSHA | ||
VILLAON | VIMOQ | Vinabox | Vinga | Vinsoc | Vios | Viper | ||
Vipro | Virzo | Vision Technology | Vision Touch | Visual Land | Vitelcom | Vityaz | ||
Viumee | Vivax | VIVIBright | VIVIMAGE | Vivo | VIWA | Vizio | ||
Vizmo | VK Mobile | VKworld | VNPT Technology | VOCAL | Vodacom | Vodafone | ||
VOGA | Völfen | VOLIA | VOLKANO | Volla | Volt | Vonino | ||
Vontar | Vorago | Vorcom | Vorke | Vormor | Vortex | Voto | ||
VOX | Voxtel | Voyo | Vsmart | Vsun | VUCATIMES | Vue Micro | ||
Vulcan | VVETIME | W&O | WAF | Wainyok | Walker | Walton | ||
Waltter | Wanmukang | WANSA | WE | We. by Loewe. | Web TV | Webfleet | ||
WeChip | Wecool | Weelikeit | Weiimi | Weimei | WellcoM | WELLINGTON | ||
Western Digital | Westpoint | Wexler | White Mobile | Whoop | Wieppo | Wigor | ||
Wiko | Wileyfox | Winds | Wink | Winmax | Winnovo | Winstar | ||
Wintouch | Wiseasy | WIWA | WizarPos | Wizz | Wolder | Wolfgang | ||
Wolki | WONDER | Wonu | Woo | Wortmann | Woxter | WOZIFAN | ||
WS | X-AGE | X-BO | X-Mobile | X-TIGI | X-View | X.Vision | ||
X88 | X96 | X96Q | Xcell | XCOM | Xcruiser | XElectron | ||
XGEM | XGIMI | Xgody | Xiaodu | Xiaolajiao | Xiaomi | Xion | ||
Xolo | Xoro | XREAL | Xshitou | Xsmart | Xtouch | Xtratech | ||
Xwave | XY Auto | Yandex | Yarvik | YASIN | YELLYOUTH | YEPEN | ||
Yes | Yestel | Yezz | Yoka TV | Yooz | Yota | YOTOPT | ||
Youin | Youwei | Ytone | Yu | YU Fly | Yuandao | YUHO | ||
YUMKEM | YUNDOO | Yuno | YunSong | Yusun | Yxtel | Z-Kai | ||
Zaith | Zamolxe | Zatec | Zealot | Zeblaze | Zebra | Zeeker | ||
Zeemi | Zen | Zenek | Zentality | Zfiner | ZH&K | Zidoo | ||
ZIFRO | Zigo | ZIK | Zinox | Ziox | Zonda | Zonko | ||
Zoom | ZoomSmart | Zopo | ZTE | Zuum | Zync | ZYQ | ||
Zyrex | ZZB | ||
OINOM | Ok | Okapi | Okapia | Oking | OKSI | OKWU | ||
Olax | Olkya | Ollee | OLTO | Olympia | OMIX | Onda | ||
OneClick | OneLern | OnePlus | Onida | Onix | Onkyo | ONN | ||
ONVO | ONYX BOOX | Ookee | Ooredoo | OpelMobile | Openbox | Ophone | ||
OPPO | Opsson | Optoma | Orange | Orange Pi | Orava | Orbic | ||
Orbita | Orbsmart | Ordissimo | Orion | OSCAL | OTTO | OUJIA | ||
Ouki | Oukitel | OUYA | Overmax | Ovvi | öwn | Owwo | ||
OX TAB | OYSIN | Oysters | Oyyu | OzoneHD | P-UP | Pacific Research Alliance | ||
Packard Bell | Padpro | PAGRAER | Paladin | Palm | Panacom | Panasonic | ||
Panavox | Pano | Panodic | Panoramic | Pantech | PAPYRE | Parrot Mobile | ||
Partner Mobile | PC Smart | PCBOX | PCD | PCD Argentina | PEAQ | Pelitt | ||
Pendoo | Penta | Pentagram | Perfeo | Phicomm | Philco | Philips | ||
Phonemax | phoneOne | Pico | PINE | Pioneer | Pioneer Computers | PiPO | ||
PIRANHA | Pixela | Pixelphone | PIXPRO | Pixus | Planet Computers | Platoon | ||
Play Now | Ployer | Plum | PlusStyle | Pluzz | PocketBook | POCO | ||
Point Mobile | Point of View | Polar | PolarLine | Polaroid | Polestar | PolyPad | ||
Polytron | Pomp | Poppox | POPTEL | Porsche | Portfolio | Positivo | ||
Positivo BGH | PPTV | Premier | Premio | Prestigio | PRIME | Primepad | ||
Primux | Pritom | Prixton | PROFiLO | Proline | Prology | ProScan | ||
PROSONIC | Protruly | ProVision | PULID | Punos | Purism | PVBox | ||
Q-Box | Q-Touch | Q.Bell | QFX | Qilive | QIN | QLink | ||
QMobile | Qnet Mobile | QTECH | Qtek | Quantum | Quatro | Qubo | ||
Quechua | Quest | Quipus | Qumo | Qware | QWATT | R-TV | ||
Rakuten | Ramos | Raspberry | Ravoz | Raylandz | Razer | RCA Tablets | ||
RCT | Reach | Readboy | Realix | Realme | RED | Redbean | ||
Redfox | RedLine | Redway | Reeder | REGAL | RelNAT | Relndoo | ||
Remdun | Renova | rephone | Retroid Pocket | Revo | Revomovil | Rhino | ||
Ricoh | Rikomagic | RIM | Ringing Bells | Rinno | Ritmix | Ritzviva | ||
Riviera | Rivo | Rizzen | ROADMAX | Roadrover | Roam Cat | ROCH | ||
Rocket | ROiK | Rokit | Roku | Rombica | Ross&Moor | Rover | ||
RoverPad | Royole | RoyQueen | RT Project | RTK | RugGear | RuggeTech | ||
Ruggex | Ruio | Runbo | Rupa | Ryte | S-Color | S-TELL | ||
S2Tel | Saba | Safaricom | Sagem | Sagemcom | Saiet | SAILF | ||
Salora | Samsung | Samtech | Samtron | Sanei | Sankey | Sansui | ||
Santin | SANY | Sanyo | Savio | Sber | SCBC | Schneider | ||
Schok | Scoole | Scosmos | Seatel | SEBBE | Seeken | SEEWO | ||
SEG | Sega | SEHMAX | Selecline | Selenga | Selevision | Selfix | ||
SEMP TCL | Sencor | Sendo | Senkatel | SENNA | Senseit | Senwa | ||
SERVO | Seuic | Sewoo | SFR | SGIN | Shanling | Sharp | ||
Shift Phones | Shivaki | Shtrikh-M | Shuttle | Sico | Siemens | Sigma | ||
Silelis | Silent Circle | Silva Schneider | Simbans | simfer | Simply | Singtech | ||
Siragon | Sirin Labs | Siswoo | SK Broadband | SKG | SKK Mobile | Sky | ||
Skyline | SkyStream | Skytech | Skyworth | Smadl | Smailo | Smart | ||
Smart Electronic | Smart Kassel | Smartab | SmartBook | SMARTEC | Smartex | Smartfren | ||
Smartisan | Smarty | Smooth Mobile | Smotreshka | SMT Telecom | SMUX | SNAMI | ||
SobieTech | Soda | Softbank | Soho Style | Solas | SOLE | SOLO | ||
Solone | Sonim | SONOS | Sony | Sony Ericsson | SOSH | SoulLink | ||
Soundmax | Soyes | Spark | Sparx | SPC | Spectralink | Spectrum | ||
Spice | Sprint | SPURT | SQOOL | SSKY | Star | Starlight | ||
Starmobile | Starway | Starwind | STF Mobile | STG Telecom | STK | Stonex | ||
Storex | StrawBerry | Stream | STRONG | Stylo | Subor | Sugar | ||
Sumvision | Sunmax | Sunmi | Sunny | Sunstech | SunVan | Sunvell | ||
SUNWIND | Super General | SuperBOX | SuperSonic | SuperTab | Supra | Supraim | ||
Surfans | Surge | Suzuki | Sveon | Swipe | SWISSMOBILITY | Swisstone | ||
Switel | SWOFY | Syco | SYH | Sylvania | Symphony | Syrox | ||
System76 | T-Mobile | T96 | TADAAM | TAG Tech | Taiga System | Takara | ||
Talius | Tambo | Tanix | TAUBE | TB Touch | TCL | TD Systems | ||
TD Tech | TeachTouch | Technicolor | Technika | TechniSat | Technopc | TECHNOSAT | ||
TechnoTrend | TechPad | TechSmart | Techstorm | Techwood | Teclast | Tecno Mobile | ||
TecToy | TEENO | Teknosa | Tele2 | Telefunken | Telego | Telenor | ||
Telia | Telit | Telkom | Telly | Telma | TeloSystems | Telpo | ||
TENPLUS | Teracube | Tesco | Tesla | TETC | Tetratab | teXet | ||
ThL | Thomson | Thuraya | TIANYU | Tibuta | Tigers | Time2 | ||
Timovi | TIMvision | Tinai | Tinmo | TiPhone | Tivax | TiVo | ||
TJC | TJD | TOKYO | Tolino | Tone | TOOGO | Tooky | ||
Top House | TopDevice | TOPDON | Topelotek | Toplux | TOPSHOWS | Topsion | ||
Topway | Torex | Torque | TOSCIDO | Toshiba | Touch Plus | Touchmate | ||
TOX | TPS | Transpeed | TrekStor | Trevi | TriaPlay | Trident | ||
Trifone | Trimble | Trio | Tronsmart | True | True Slim | Tsinghua Tongfang | ||
TTEC | TTfone | TTK-TV | TuCEL | Tunisie Telecom | Turbo | Turbo-X | ||
TurboKids | TurboPad | Türk Telekom | Turkcell | Tuvio | TVC | TwinMOS | ||
TWM | Twoe | TWZ | TYD | Tymes | U-Magic | U.S. Cellular | ||
UD | UE | UGINE | Ugoos | Uhans | Uhappy | Ulefone | ||
Umax | UMIDIGI | Unblock Tech | Uniden | Unihertz | Unimax | Uniqcell | ||
Uniscope | Unistrong | Unitech | United Group | UNIWA | Unknown | Unnecto | ||
Unnion Technologies | UNNO | Unonu | Unowhy | UOOGOU | Urovo | UTime | ||
UTOK | UTStarcom | UZ Mobile | V-Gen | V-HOME | V-HOPE | v-mobile | ||
VAIO | VALE | VALEM | VALTECH | VANGUARD | Vankyo | VANWIN | ||
Vargo | Vastking | VAVA | VC | VDVD | Vega | Veidoo | ||
Vekta | Venso | Venstar | Venturer | VEON | Verico | Verizon | ||
Vernee | Verssed | Versus | Vertex | Vertu | Verykool | Vesta | ||
Vestel | VETAS | Vexia | VGO TEL | ViBox | Victurio | VIDA | ||
Videocon | Videoweb | ViewSonic | VIIPOO | VIKUSHA | VILLAON | VIMOQ | ||
Vinabox | Vinga | Vinsoc | Vios | Viper | Vipro | Virzo | ||
Vision Technology | Vision Touch | Visual Land | Vitelcom | Vityaz | Viumee | Vivax | ||
VIVIBright | VIVIMAGE | Vivo | VIWA | Vizio | Vizmo | VK Mobile | ||
VKworld | VNPT Technology | VOCAL | Vodacom | Vodafone | VOGA | Völfen | ||
VOLIA | VOLKANO | Volla | Volt | Vonino | Vontar | Vorago | ||
Vorcom | Vorke | Vormor | Vortex | Voto | VOX | Voxtel | ||
Voyo | Vsmart | Vsun | VUCATIMES | Vue Micro | Vulcan | VVETIME | ||
W&O | WAF | Wainyok | Walker | Walton | Waltter | Wanmukang | ||
WANSA | WE | We. by Loewe. | Web TV | Webfleet | WeChip | Wecool | ||
Weelikeit | Weiimi | Weimei | WellcoM | WELLINGTON | Western Digital | Westpoint | ||
Wexler | White Mobile | Whoop | Wieppo | Wigor | Wiko | Wileyfox | ||
Winds | Wink | Winmax | Winnovo | Winstar | Wintouch | Wiseasy | ||
WIWA | WizarPos | Wizz | Wolder | Wolfgang | Wolki | WONDER | ||
Wonu | Woo | Wortmann | Woxter | WOZIFAN | WS | X-AGE | ||
X-BO | X-Mobile | X-TIGI | X-View | X.Vision | X88 | X96 | ||
X96Q | Xcell | XCOM | Xcruiser | XElectron | XGEM | XGIMI | ||
Xgody | Xiaodu | Xiaolajiao | Xiaomi | Xion | Xolo | Xoro | ||
XPPen | XREAL | Xshitou | Xsmart | Xtouch | Xtratech | Xwave | ||
XY Auto | Yandex | Yarvik | YASIN | YELLYOUTH | YEPEN | Yes | ||
Yestel | Yezz | Yoka TV | Yooz | Yota | YOTOPT | Youin | ||
Youwei | Ytone | Yu | YU Fly | Yuandao | YUHO | YUMKEM | ||
YUNDOO | Yuno | YunSong | Yusun | Yxtel | Z-Kai | Zaith | ||
Zamolxe | Zatec | Zealot | Zeblaze | Zebra | Zeeker | Zeemi | ||
Zen | Zenek | Zentality | Zfiner | ZH&K | Zidoo | ZIFRO | ||
Zigo | ZIK | Zinox | Ziox | Zonda | Zonko | Zoom | ||
ZoomSmart | Zopo | ZTE | Zuum | Zync | ZYQ | Zyrex | ||
ZZB | ||
@@ -920,3 +925,3 @@ | ||
##### Support detect browsers list (670): | ||
##### Support detect browsers list (673): | ||
@@ -994,32 +999,33 @@ <details> | ||
PocketBook Browser | Polaris | Polarity | PolyBrowser | Polypane | Presearch | Prism | ||
Privacy Browser | Privacy Explorer Fast Safe | PrivacyWall | Private Internet Browser | PronHub Browser | Proxy Browser | ProxyFox | ||
Proxyium | ProxyMax | Proxynet | PSI Secure Browser | Puffin | Puffin Web Browser | Pure Lite Browser | ||
Pure Mini Browser | Qazweb | Qiyu | QJY TV Browser | Qmamu | QQ Browser | QQ Browser Lite | ||
QQ Browser Mini | QtWeb | QtWebEngine | Quark | Quick Browser | Quick Search TV | QupZilla | ||
Qutebrowser | Qwant Mobile | Rabbit Private Browser | Raise Fast Browser | Rakuten Browser | Rakuten Web Search | Raspbian Chromium | ||
RCA Tor Explorer | Realme Browser | Rekonq | Reqwireless WebViewer | Roccat | RockMelt | Roku Browser | ||
Safari | Safari Technology Preview | Safe Exam Browser | Sailfish Browser | SalamWeb | Samsung Browser | Samsung Browser Lite | ||
Savannah Browser | SavySoda | SberBrowser | Secure Browser | Secure Private Browser | SecureX | Seewo Browser | ||
SEMC-Browser | Seraphic Sraf | Seznam Browser | SFive | Sharkee Browser | Shiira | Sidekick | ||
SilverMob US | SimpleBrowser | SiteKiosk | Sizzy | Skye | Skyfire | SkyLeap | ||
Sleipnir | SlimBoat | Slimjet | Smart Browser | Smart Lenovo Browser | Smart Search & Web Browser | Smooz | ||
Snowshoe | Sogou Explorer | Sogou Mobile Browser | Sony Small Browser | SOTI Surf | Soul Browser | Soundy Browser | ||
SP Browser | Spark | Spectre Browser | Splash | Sputnik Browser | Stampy Browser | Stargon | ||
START Internet Browser | Stealth Browser | Steam In-Game Overlay | Streamy | Sunflower Browser | Sunrise | Super Fast Browser | ||
SuperBird | SuperFast Browser | surf | Surf Browser | Surfy Browser | Sushi Browser | Sweet Browser | ||
Swiftfox | Swiftweasel | SX Browser | T-Browser | t-online.de Browser | T+Browser | TalkTo | ||
Tao Browser | tararia | TenFourFox | Tenta Browser | Tesla Browser | Thor | Tint Browser | ||
Tizen Browser | ToGate | Tor Browser | Total Browser | TQ Browser | TrueLocation Browser | TUC Mini Browser | ||
Tungsten | TUSK | TV Bro | TV-Browser Internet | TweakStyle | U Browser | UBrowser | ||
UC Browser | UC Browser HD | UC Browser Mini | UC Browser Turbo | Ui Browser Mini | Ume Browser | UPhone Browser | ||
UR Browser | Uzbl | Vast Browser | vBrowser | VD Browser | Veera | Vegas Browser | ||
Venus Browser | Vertex Surf | Vewd Browser | Via | Viasat Browser | VibeMate | Vision Mobile Browser | ||
Vivaldi | Vivid Browser Mini | vivo Browser | VMS Mosaic | VMware AirWatch | Vonkeror | Vuhuv | ||
w3m | Waterfox | Wave Browser | Wavebox | Wear Internet Browser | Web Browser & Explorer | Web Explorer | ||
WebDiscover | Webian Shell | WebPositive | Weltweitimnetz Browser | WeTab Browser | Wexond | Whale Browser | ||
Wolvic | World Browser | wOSBrowser | Wukong Browser | Wyzo | X Browser Lite | X-VPN | ||
xBrowser | XBrowser Mini | xBrowser Pro Super Fast | Xiino | XnBrowse | XNX Browser | Xooloo Internet | ||
xStand | XtremeCast | Xvast | Yaani Browser | YAGI | Yahoo! Japan Browser | Yandex Browser | ||
Yandex Browser Corp | Yandex Browser Lite | Yo Browser | Yolo Browser | YouBrowser | YouCare | Yuzu Browser | ||
Zetakey | Zirco Browser | Zordo Browser | ZTE Browser | Zvu | ||
Privacy Browser | Privacy Explorer Fast Safe | Privacy Pioneer Browser | PrivacyWall | Private Internet Browser | PronHub Browser | Proxy Browser | ||
ProxyFox | Proxyium | ProxyMax | Proxynet | PSI Secure Browser | Puffin Cloud Browser | Puffin Incognito Browser | ||
Puffin Secure Browser | Puffin Web Browser | Pure Lite Browser | Pure Mini Browser | Qazweb | Qiyu | QJY TV Browser | ||
Qmamu | QQ Browser | QQ Browser Lite | QQ Browser Mini | QtWeb | QtWebEngine | Quark | ||
Quick Browser | Quick Search TV | QupZilla | Qutebrowser | Qwant Mobile | Rabbit Private Browser | Raise Fast Browser | ||
Rakuten Browser | Rakuten Web Search | Raspbian Chromium | RCA Tor Explorer | Realme Browser | Rekonq | Reqwireless WebViewer | ||
Roccat | RockMelt | Roku Browser | Safari | Safari Technology Preview | Safe Exam Browser | Sailfish Browser | ||
SalamWeb | Samsung Browser | Samsung Browser Lite | Savannah Browser | SavySoda | SberBrowser | Secure Browser | ||
Secure Private Browser | SecureX | Seewo Browser | SEMC-Browser | Seraphic Sraf | Seznam Browser | SFive | ||
Sharkee Browser | Shiira | Sidekick | SilverMob US | SimpleBrowser | SiteKiosk | Sizzy | ||
Skye | Skyfire | SkyLeap | Sleipnir | SlimBoat | Slimjet | Smart Browser | ||
Smart Lenovo Browser | Smart Search & Web Browser | Smooz | Snowshoe | Sogou Explorer | Sogou Mobile Browser | Sony Small Browser | ||
SOTI Surf | Soul Browser | Soundy Browser | SP Browser | Spark | Spectre Browser | Splash | ||
Sputnik Browser | Stampy Browser | Stargon | START Internet Browser | Stealth Browser | Steam In-Game Overlay | Streamy | ||
Sunflower Browser | Sunrise | Super Fast Browser | SuperBird | SuperFast Browser | surf | Surf Browser | ||
Surfy Browser | Sushi Browser | Sweet Browser | Swiftfox | Swiftweasel | SX Browser | T-Browser | ||
t-online.de Browser | T+Browser | TalkTo | Tao Browser | tararia | TenFourFox | Tenta Browser | ||
Tesla Browser | Thor | Tint Browser | Tizen Browser | ToGate | Tor Browser | Total Browser | ||
TQ Browser | TrueLocation Browser | TUC Mini Browser | Tungsten | TUSK | TV Bro | TV-Browser Internet | ||
TweakStyle | U Browser | UBrowser | UC Browser | UC Browser HD | UC Browser Mini | UC Browser Turbo | ||
Ui Browser Mini | Ume Browser | UPhone Browser | UR Browser | Uzbl | Vast Browser | vBrowser | ||
VD Browser | Veera | Vegas Browser | Venus Browser | Vertex Surf | Vewd Browser | Via | ||
Viasat Browser | VibeMate | Vision Mobile Browser | Vivaldi | Vivid Browser Mini | vivo Browser | VMS Mosaic | ||
VMware AirWatch | Vonkeror | Vuhuv | w3m | Waterfox | Wave Browser | Wavebox | ||
Wear Internet Browser | Web Browser & Explorer | Web Explorer | WebDiscover | Webian Shell | WebPositive | Weltweitimnetz Browser | ||
WeTab Browser | Wexond | Whale Browser | Wolvic | World Browser | wOSBrowser | Wukong Browser | ||
Wyzo | X Browser Lite | X-VPN | xBrowser | XBrowser Mini | xBrowser Pro Super Fast | Xiino | ||
XnBrowse | XNX Browser | Xooloo Internet | xStand | XtremeCast | Xvast | Yaani Browser | ||
YAGI | Yahoo! Japan Browser | Yandex Browser | Yandex Browser Corp | Yandex Browser Lite | Yo Browser | Yolo Browser | ||
YouBrowser | YouCare | Yuzu Browser | Zetakey | Zirco Browser | Zordo Browser | ZTE Browser | ||
Zvu | ||
@@ -1026,0 +1032,0 @@ </details> |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
2863855
86
7816
1027