mirror of
https://github.com/faisalman/ua-parser-js.git
synced 2025-09-27 16:08:47 +03:00
[helpers] Add new method: unfreezeUA()
, construct new unfreezed user-agent string using real data from client hints
This commit is contained in:
parent
73a936001a
commit
3dd4b60ee9
@ -1,9 +1,9 @@
|
|||||||
{
|
{
|
||||||
"title": "UAParser.js Helpers",
|
"title": "UAParser.js Helpers",
|
||||||
"name": "@ua-parser-js/helpers",
|
"name": "@ua-parser-js/helpers",
|
||||||
"version": "2.0.0-alpha.3",
|
"version": "0.0.1",
|
||||||
"author": "Faisal Salman <f@faisalman.com>",
|
"author": "Faisal Salman <f@faisalman.com>",
|
||||||
"description": "Helpers for UAParser.js",
|
"description": "A collection of utility methods for UAParser.js",
|
||||||
"main": "ua-parser-helpers.js",
|
"main": "ua-parser-helpers.js",
|
||||||
"module": "ua-parser-helpers.mjs",
|
"module": "ua-parser-helpers.mjs",
|
||||||
"scripts" : {
|
"scripts" : {
|
||||||
|
65
src/helpers/readme.md
Normal file
65
src/helpers/readme.md
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
# @ua-parser-js/helpers
|
||||||
|
|
||||||
|
This package contains a collection of utility methods for [UAParser.js](https://github.com/faisalman/ua-parser-js)
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm i @ua-parser-js/helpers
|
||||||
|
```
|
||||||
|
|
||||||
|
### * `isFrozenUA(ua:string):boolean`
|
||||||
|
|
||||||
|
Check whether a user-agent string match with [frozen user-agent pattern](https://www.chromium.org/updates/ua-reduction/)
|
||||||
|
|
||||||
|
### * `unfreezeUA():Promise<string>`
|
||||||
|
|
||||||
|
construct new unfreezed user-agent string using real data from client hints
|
||||||
|
|
||||||
|
## Code Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { isFrozenUA } from '@ua-parser-js/helpers';
|
||||||
|
|
||||||
|
const regularMobileUA = "Mozilla/5.0 (Linux; Android 9; SM-A205U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.1234.56 Mobile Safari/537.36";
|
||||||
|
const freezedMobileUA = "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.0.0 Mobile Safari/537.36";
|
||||||
|
|
||||||
|
console.log(isFrozenUA(regularMobileUA));
|
||||||
|
// false
|
||||||
|
|
||||||
|
console.log(isFrozenUA(freezedMobileUA));
|
||||||
|
// true
|
||||||
|
```
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { unfreezeUA } from '@ua-parser-js/helpers';
|
||||||
|
|
||||||
|
/*
|
||||||
|
Suppose we're in a browser having this client hints data:
|
||||||
|
|
||||||
|
{
|
||||||
|
fullVersionList: [
|
||||||
|
{
|
||||||
|
brand: 'New Browser',
|
||||||
|
version: '110.1.2.3'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
brand: 'Chromium',
|
||||||
|
version: '110.1.2.3'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
brand: 'Not(A:Brand',
|
||||||
|
version: '110'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
platform: 'Windows',
|
||||||
|
platformVersion: '13.0.0'
|
||||||
|
}
|
||||||
|
|
||||||
|
And a freezed user-agent:
|
||||||
|
|
||||||
|
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.0.0 Safari/537.36'
|
||||||
|
*/
|
||||||
|
|
||||||
|
unfreezeUA();
|
||||||
|
|
||||||
|
// 'Mozilla/5.0 (Windows NT 11.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) New Browser/110.1.2.3 Chromium/110.1.2.3 Safari/537.36'
|
||||||
|
```
|
2
src/helpers/ua-parser-helpers.d.ts
vendored
Normal file
2
src/helpers/ua-parser-helpers.d.ts
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export function isFrozenUA(ua: string): boolean;
|
||||||
|
export function unfreezeUA(): Promise<string>;
|
@ -1,11 +1,11 @@
|
|||||||
///////////////////////////////////////////////
|
///////////////////////////////////////////////
|
||||||
/* Helpers for UAParser.js
|
/* A collection of utility methods for UAParser.js
|
||||||
https://github.com/faisalman/ua-parser-js
|
https://github.com/faisalman/ua-parser-js
|
||||||
Author: Faisal Salman <f@faisalman.com>
|
Author: Faisal Salman <f@faisalman.com>
|
||||||
MIT License */
|
MIT License */
|
||||||
//////////////////////////////////////////////
|
//////////////////////////////////////////////
|
||||||
|
|
||||||
/*jshint esversion: 6 */
|
/*jshint esversion: 11 */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
# Reference:
|
# Reference:
|
||||||
@ -33,8 +33,63 @@
|
|||||||
- "" (empty string for Tablets & Desktop)
|
- "" (empty string for Tablets & Desktop)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const isFrozenUA = ua => /Mozilla\/5\.0 \((Windows NT 10\.0; Win64; x64|Macintosh; Intel Mac OS X 10_15_7|X11; Linux x86_64|X11; CrOS x86_64 14541\.0\.0|Fuchsia|Linux; Android 10; K)\) AppleWebKit\/537\.36 \(KHTML, like Gecko\) Chrome\/\d+\.0\.0\.0 (Mobile )?Safari\/537\.36/.test(ua);
|
const isFrozenUA = ua => /^Mozilla\/5\.0 \((Windows NT 10\.0; Win64; x64|Macintosh; Intel Mac OS X 10_15_7|X11; Linux x86_64|X11; CrOS x86_64 14541\.0\.0|Fuchsia|Linux; Android 10; K)\) AppleWebKit\/537\.36 \(KHTML, like Gecko\) Chrome\/\d+\.0\.0\.0 (Mobile )?Safari\/537\.36$/.test(ua);
|
||||||
|
|
||||||
|
const unfreezeUA = async () => {
|
||||||
|
if (!navigator) {
|
||||||
|
throw new Error('Currently only support browser environment');
|
||||||
|
} else {
|
||||||
|
let ua = navigator.userAgent;
|
||||||
|
if (navigator.userAgentData && isFrozenUA(ua)) {
|
||||||
|
const ch = await navigator.userAgentData.getHighEntropyValues(['architecture', 'bitness', 'fullVersionList', 'model', 'platform', 'platformVersion', 'wow64']);
|
||||||
|
switch (ch.platform) {
|
||||||
|
case 'Windows':
|
||||||
|
let [major, minor] = ch.platformVersion?.split('.').map(i => parseInt(i, 10));
|
||||||
|
let osReplacer = (major < 1) ?
|
||||||
|
`$<OS> 6.${minor}` :
|
||||||
|
(major >= 13) ?
|
||||||
|
`$<OS> 11.${minor}` :
|
||||||
|
`$<OS> 10.${minor}`;
|
||||||
|
let archReplacer = (ch.architecture == 'arm') ?
|
||||||
|
'; ARM' :
|
||||||
|
(ch.wow64) ?
|
||||||
|
'; WOW64' :
|
||||||
|
(ch.architecture == 'x86' && ch.bitness == '64') ?
|
||||||
|
'; $<ARCH>' : '';
|
||||||
|
ua = ua.replace(/(?<OS>Windows NT) 10\.0/, osReplacer)
|
||||||
|
.replace(/; (?<ARCH>Win64; x64)/, archReplacer);
|
||||||
|
break;
|
||||||
|
case 'Android':
|
||||||
|
ua = ua.replace(/(?<OS>Android) 10; K/, `$<OS> ${ch.platformVersion}; ${ch.model}`);
|
||||||
|
break;
|
||||||
|
case 'Linux':
|
||||||
|
case 'Chrome OS':
|
||||||
|
archReplacer = (ch.architecture == 'arm') ?
|
||||||
|
((ch.bitness == '64') ? 'arm64' : 'arm') :
|
||||||
|
(ch.architecture == 'x86' && ch.bitness == '64') ?
|
||||||
|
'$<ARCH>' : 'x86';
|
||||||
|
|
||||||
|
ua = ua.replace(/(?<ARCH>x86_64)/, archReplacer);
|
||||||
|
break;
|
||||||
|
case 'macOS':
|
||||||
|
ua = ua.replace(/(?<OS>Mac OS X) 10_15_7/, `$<OS> ${ch.platformVersion.replace(/\./, '_')}`);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
let browserReplacer = '';
|
||||||
|
ch.fullVersionList?.forEach((browser) => {
|
||||||
|
if (!/not.a.brand/i.test(browser.brand)) {
|
||||||
|
browserReplacer += `${browser.brand}/${browser.version} `;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (browserReplacer) {
|
||||||
|
ua = ua.replace(/Chrome\/\d+\.0\.0\.0 /, browserReplacer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ua;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
isFrozenUA
|
isFrozenUA,
|
||||||
|
unfreezeUA
|
||||||
};
|
};
|
@ -1,4 +1,4 @@
|
|||||||
const { isFrozenUA } = require('ua-parser-js/helpers');
|
const { isFrozenUA } = require('@ua-parser-js/helpers');
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
|
|
||||||
describe('isFrozenUA', () => {
|
describe('isFrozenUA', () => {
|
||||||
|
47
test/playwright-test-helpers.spec.mjs
Normal file
47
test/playwright-test-helpers.spec.mjs
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
// @ts-check
|
||||||
|
import { test, expect } from '@playwright/test';
|
||||||
|
import { unfreezeUA } from '@ua-parser-js/helpers';
|
||||||
|
|
||||||
|
test('test for unfreezeUA() method', async ({ page }) => {
|
||||||
|
|
||||||
|
|
||||||
|
await page.addInitScript(() => {
|
||||||
|
Object.defineProperty(navigator, 'userAgentData', {
|
||||||
|
value: {
|
||||||
|
brands: [],
|
||||||
|
platform: 'Windows',
|
||||||
|
mobile: false,
|
||||||
|
getHighEntropyValues: () => {
|
||||||
|
return Promise.resolve({
|
||||||
|
architecture: 'x86',
|
||||||
|
bitness: '64',
|
||||||
|
fullVersionList: [
|
||||||
|
{
|
||||||
|
brand: 'New Browser',
|
||||||
|
version: '110.1.2.3'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
brand: 'Chromium',
|
||||||
|
version: '110.1.2.3'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
brand: 'Not(A:Brand',
|
||||||
|
version: '110'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
platform: 'Windows',
|
||||||
|
platformVersion: '0.3'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Object.defineProperty(navigator, 'userAgent', {
|
||||||
|
value: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.0.0 Safari/537.36'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
await page.goto('about:blank');
|
||||||
|
await page.addScriptTag({ path: './src/helpers/ua-parser-helpers.js' });
|
||||||
|
// @ts-ignore
|
||||||
|
const ua = await page.evaluate(async () => await unfreezeUA());
|
||||||
|
expect(ua).toBe('Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) New Browser/110.1.2.3 Chromium/110.1.2.3 Safari/537.36');
|
||||||
|
});
|
Loading…
x
Reference in New Issue
Block a user