device_detector 1.0.7 → 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -3,29 +3,65 @@
3
3
  class DeviceDetector
4
4
  class Browser
5
5
  AVAILABLE_BROWSERS = {
6
+ 'V1' => 'Via',
7
+ '1P' => 'Pure Mini Browser',
8
+ '4P' => 'Pure Lite Browser',
9
+ '1R' => 'Raise Fast Browser',
10
+ 'R1' => 'Rabbit Private Browser',
11
+ 'FQ' => 'Fast Browser UC Lite',
12
+ 'FJ' => 'Fast Explorer',
13
+ '1L' => 'Lightning Browser',
14
+ '1C' => 'Cake Browser',
15
+ '1I' => 'IE Browser Fast',
16
+ '1V' => 'Vegas Browser',
17
+ '1O' => 'OH Browser',
18
+ '3O' => 'OH Private Browser',
19
+ '1X' => 'XBrowser Mini',
20
+ '1S' => 'Sharkee Browser',
21
+ '2L' => 'Lark Browser',
22
+ '3P' => 'Pluma',
23
+ '1A' => 'Anka Browser',
24
+ 'AZ' => 'Azka Browser',
25
+ '1D' => 'Dragon Browser',
26
+ '1E' => 'Easy Browser',
27
+ 'DW' => 'Dark Web Browser',
28
+ '18' => '18+ Privacy Browser',
6
29
  '1B' => '115 Browser',
30
+ 'DM' => '1DM Browser',
31
+ '1M' => '1DM+ Browser',
7
32
  '2B' => '2345 Browser',
8
- '36' => '360 Phone Browser',
9
33
  '3B' => '360 Browser',
34
+ '36' => '360 Phone Browser',
10
35
  '7B' => '7654 Browser',
11
36
  'AA' => 'Avant Browser',
12
37
  'AB' => 'ABrowse',
38
+ 'BW' => 'AdBlock Browser',
39
+ 'A7' => 'Adult Browser',
13
40
  'AF' => 'ANT Fresco',
14
41
  'AG' => 'ANTGalio',
15
42
  'AL' => 'Aloha Browser',
16
43
  'AH' => 'Aloha Browser Lite',
17
44
  'AM' => 'Amaya',
45
+ 'A3' => 'Amaze Browser',
46
+ 'A5' => 'Amerigo',
18
47
  'AO' => 'Amigo',
19
48
  'AN' => 'Android Browser',
20
49
  'AE' => 'AOL Desktop',
21
50
  'AD' => 'AOL Shield',
51
+ 'A4' => 'AOL Shield Pro',
52
+ 'A6' => 'AppBrowzer',
53
+ 'AP' => 'APUS Browser',
22
54
  'AR' => 'Arora',
23
55
  'AX' => 'Arctic Fox',
24
56
  'AV' => 'Amiga Voyager',
25
57
  'AW' => 'Amiga Aweb',
58
+ 'PN' => 'APN Browser',
26
59
  'AI' => 'Arvin',
60
+ 'AK' => 'Ask.com',
61
+ 'AU' => 'Asus Browser',
27
62
  'A0' => 'Atom',
28
63
  'AT' => 'Atomic Web Browser',
64
+ 'A2' => 'Atlas',
29
65
  'AS' => 'Avast Secure Browser',
30
66
  'VG' => 'AVG Secure Browser',
31
67
  'AC' => 'Avira Scout',
@@ -33,24 +69,40 @@ class DeviceDetector
33
69
  'BA' => 'Beaker Browser',
34
70
  'BM' => 'Beamrise',
35
71
  'BB' => 'BlackBerry Browser',
72
+ 'H1' => 'BrowseHere',
73
+ 'B8' => 'Browser Hup Pro',
36
74
  'BD' => 'Baidu Browser',
37
75
  'BS' => 'Baidu Spark',
76
+ 'B9' => 'Bangla Browser',
38
77
  'BI' => 'Basilisk',
78
+ 'BV' => 'Belva Browser',
79
+ 'B5' => 'Beyond Private Browser',
39
80
  'BE' => 'Beonex',
81
+ 'B2' => 'Berry Browser',
82
+ 'BT' => 'Bitchute Browser',
40
83
  'BH' => 'BlackHawk',
84
+ 'B0' => 'Bloket',
41
85
  'BJ' => 'Bunjalloo',
42
86
  'BL' => 'B-Line',
87
+ 'B6' => 'Black Lion Browser',
43
88
  'BU' => 'Blue Browser',
89
+ 'BO' => 'Bonsai',
44
90
  'BN' => 'Borealis Navigator',
45
91
  'BR' => 'Brave',
46
92
  'BK' => 'BriskBard',
93
+ 'B3' => 'Browspeed Browser',
47
94
  'BX' => 'BrowseX',
48
95
  'BZ' => 'Browzar',
96
+ 'B7' => 'Browlser',
49
97
  'BY' => 'Biyubi',
50
98
  'BF' => 'Byffox',
99
+ 'B4' => 'BF Browser',
51
100
  'CA' => 'Camino',
52
101
  'CL' => 'CCleaner',
102
+ 'C8' => 'CG Browser',
103
+ 'CJ' => 'ChanjetCloud',
53
104
  'C6' => 'Chedot',
105
+ 'C9' => 'Cherry Browser',
54
106
  'C0' => 'Centaury',
55
107
  'CC' => 'Coc Coc',
56
108
  'C4' => 'CoolBrowser',
@@ -59,14 +111,17 @@ class DeviceDetector
59
111
  'C1' => 'Coast',
60
112
  'CX' => 'Charon',
61
113
  'CE' => 'CM Browser',
114
+ 'C7' => 'CM Mini',
62
115
  'CF' => 'Chrome Frame',
63
116
  'HC' => 'Headless Chrome',
64
117
  'CH' => 'Chrome',
65
118
  'CI' => 'Chrome Mobile iOS',
66
119
  'CK' => 'Conkeror',
67
120
  'CM' => 'Chrome Mobile',
121
+ '3C' => 'Chowbo',
68
122
  'CN' => 'CoolNovo',
69
123
  'CO' => 'CometBird',
124
+ '2C' => 'Comfort Browser',
70
125
  'CB' => 'COS Browser',
71
126
  'CW' => 'Cornowser',
72
127
  'C3' => 'Chim Lac',
@@ -80,30 +135,41 @@ class DeviceDetector
80
135
  'CZ' => 'Crazy Browser',
81
136
  'CU' => 'Cunaguaro',
82
137
  'CV' => 'Chrome Webview',
138
+ 'YC' => 'CyBrowser',
83
139
  'DB' => 'dbrowser',
140
+ 'PD' => 'Peeps dBrowser',
141
+ 'D1' => 'Debuggable Browser',
142
+ 'DC' => 'Decentr',
84
143
  'DE' => 'Deepnet Explorer',
85
144
  'DG' => 'deg-degan',
86
145
  'DA' => 'Deledao',
87
146
  'DT' => 'Delta Browser',
147
+ 'D0' => 'Desi Browser',
88
148
  'DS' => 'DeskBrowse',
89
149
  'DF' => 'Dolphin',
150
+ 'DZ' => 'Dolphin Zero',
90
151
  'DO' => 'Dorado',
91
152
  'DR' => 'Dot Browser',
92
153
  'DL' => 'Dooble',
93
154
  'DI' => 'Dillo',
155
+ 'DU' => 'DUC Browser',
94
156
  'DD' => 'DuckDuckGo Privacy Browser',
95
157
  'EC' => 'Ecosia',
96
158
  'EW' => 'Edge WebView',
97
159
  'EI' => 'Epic',
98
160
  'EL' => 'Elinks',
161
+ 'EN' => 'EinkBro',
99
162
  'EB' => 'Element Browser',
100
163
  'EE' => 'Elements Browser',
164
+ 'EX' => 'Explore Browser',
101
165
  'EZ' => 'eZ Browser',
102
166
  'EU' => 'EUI Browser',
103
167
  'EP' => 'GNOME Web',
168
+ 'G1' => 'G Browser',
104
169
  'ES' => 'Espial TV Browser',
105
170
  'FA' => 'Falkon',
106
171
  'FX' => 'Faux Browser',
172
+ 'F4' => 'Fiery Browser',
107
173
  'F1' => 'Firefox Mobile iOS',
108
174
  'FB' => 'Firebird',
109
175
  'FD' => 'Fluid',
@@ -112,27 +178,47 @@ class DeviceDetector
112
178
  'FK' => 'Firefox Focus',
113
179
  'FY' => 'Firefox Reality',
114
180
  'FR' => 'Firefox Rocket',
181
+ '1F' => 'Firefox Klar',
182
+ 'F0' => 'Float Browser',
115
183
  'FL' => 'Flock',
184
+ 'FP' => 'Floorp',
116
185
  'FO' => 'Flow',
186
+ 'F2' => 'Flow Browser',
117
187
  'FM' => 'Firefox Mobile',
118
188
  'FW' => 'Fireweb',
119
189
  'FN' => 'Fireweb Navigator',
190
+ 'FH' => 'Flash Browser',
120
191
  'FS' => 'Flast',
192
+ 'F5' => 'Flyperlink',
121
193
  'FU' => 'FreeU',
194
+ 'F3' => 'Frost+',
195
+ 'FI' => 'Fulldive',
122
196
  'GA' => 'Galeon',
197
+ 'G8' => 'Gener8',
123
198
  'GH' => 'Ghostery Privacy Browser',
124
199
  'GI' => 'GinxDroid Browser',
125
200
  'GB' => 'Glass Browser',
126
201
  'GE' => 'Google Earth',
202
+ 'GP' => 'Google Earth Pro',
127
203
  'GO' => 'GOG Galaxy',
128
204
  'GR' => 'GoBrowser',
205
+ 'HB' => 'Harman Browser',
129
206
  'HS' => 'HasBrowser',
130
207
  'HA' => 'Hawk Turbo Browser',
208
+ 'HQ' => 'Hawk Quick Browser',
131
209
  'HE' => 'Helio',
210
+ 'HX' => 'Hexa Web Browser',
211
+ 'HI' => 'Hi Browser',
132
212
  'HO' => 'hola! Browser',
133
213
  'HJ' => 'HotJava',
134
- 'HU' => 'Huawei Browser',
214
+ 'HT' => 'HTC Browser',
215
+ 'HU' => 'Huawei Browser Mobile',
216
+ 'HP' => 'Huawei Browser',
217
+ 'H3' => 'HUB Browser',
218
+ 'IO' => 'iBrowser',
219
+ 'IS' => 'iBrowser Mini',
135
220
  'IB' => 'IBrowse',
221
+ 'I6' => 'iDesktop PC Browser',
136
222
  'IC' => 'iCab',
137
223
  'I2' => 'iCab Mobile',
138
224
  'I1' => 'Iridium',
@@ -140,17 +226,25 @@ class DeviceDetector
140
226
  'I4' => 'IceCat',
141
227
  'ID' => 'IceDragon',
142
228
  'IV' => 'Isivioo',
229
+ 'I8' => 'IVVI Browser',
143
230
  'IW' => 'Iceweasel',
231
+ 'IN' => 'Inspect Browser',
144
232
  'IE' => 'Internet Explorer',
233
+ 'I7' => 'Internet Browser Secure',
234
+ 'I5' => 'Indian UC Mini Browser',
145
235
  'IM' => 'IE Mobile',
146
236
  'IR' => 'Iron',
147
237
  'JB' => 'Japan Browser',
148
238
  'JS' => 'Jasmine',
149
239
  'JA' => 'JavaFX',
240
+ 'JL' => 'Jelly',
150
241
  'JI' => 'Jig Browser',
151
242
  'JP' => 'Jig Browser Plus',
152
243
  'JO' => 'Jio Browser',
244
+ 'J1' => 'JioPages',
153
245
  'KB' => 'K.Browser',
246
+ 'KF' => 'Keepsafe Browser',
247
+ 'KS' => 'Kids Safe Browser',
154
248
  'KI' => 'Kindle Browser',
155
249
  'KM' => 'K-meleon',
156
250
  'KO' => 'Konqueror',
@@ -158,60 +252,78 @@ class DeviceDetector
158
252
  'KN' => 'Kinza',
159
253
  'KW' => 'Kiwi',
160
254
  'KD' => 'Kode Browser',
255
+ 'KT' => 'KUTO Mini Browser',
161
256
  'KY' => 'Kylo',
162
257
  'KZ' => 'Kazehakase',
163
258
  'LB' => 'Cheetah Browser',
259
+ 'LA' => 'Lagatos Browser',
260
+ 'LR' => 'Lexi Browser',
261
+ 'LV' => 'Lenovo Browser',
164
262
  'LF' => 'LieBaoFast',
165
263
  'LG' => 'LG Browser',
166
264
  'LH' => 'Light',
265
+ 'L1' => 'Lilo',
167
266
  'LI' => 'Links',
168
267
  'IF' => 'Lolifox',
169
268
  'LO' => 'Lovense Browser',
269
+ 'LT' => 'LT Browser',
170
270
  'LU' => 'LuaKit',
171
271
  'LL' => 'Lulumi',
172
272
  'LS' => 'Lunascape',
173
273
  'LN' => 'Lunascape Lite',
174
274
  'LX' => 'Lynx',
275
+ 'L2' => 'Lynket Browser',
175
276
  'MD' => 'Mandarin',
176
277
  'M1' => 'mCent',
177
278
  'MB' => 'MicroB',
178
279
  'MC' => 'NCSA Mosaic',
179
280
  'MZ' => 'Meizu Browser',
180
281
  'ME' => 'Mercury',
282
+ 'M2' => 'Me Browser',
181
283
  'MF' => 'Mobile Safari',
182
284
  'MI' => 'Midori',
285
+ 'M3' => 'Midori Lite',
183
286
  'MO' => 'Mobicip',
184
287
  'MU' => 'MIUI Browser',
185
288
  'MS' => 'Mobile Silk',
186
289
  'MN' => 'Minimo',
187
290
  'MT' => 'Mint Browser',
188
291
  'MX' => 'Maxthon',
292
+ 'M4' => 'MaxTube Browser',
189
293
  'MA' => 'Maelstrom',
294
+ 'MM' => 'Mmx Browser',
190
295
  'NM' => 'MxNitro',
191
296
  'MY' => 'Mypal',
192
297
  'MR' => 'Monument Browser',
193
298
  'MW' => 'MAUI WAP Browser',
194
299
  'NW' => 'Navigateur Web',
300
+ 'NK' => 'Naked Browser',
301
+ 'NA' => 'Naked Browser Pro',
195
302
  'NR' => 'NFS Browser',
196
303
  'NB' => 'Nokia Browser',
197
304
  'NO' => 'Nokia OSS Browser',
198
305
  'NV' => 'Nokia Ovi Browser',
199
306
  'NX' => 'Nox Browser',
307
+ 'N1' => 'NOMone VR Browser',
200
308
  'NE' => 'NetSurf',
201
309
  'NF' => 'NetFront',
202
310
  'NL' => 'NetFront Life',
203
311
  'NP' => 'NetPositive',
204
312
  'NS' => 'Netscape',
313
+ 'WR' => 'NextWord Browser',
205
314
  'NT' => 'NTENT Browser',
206
315
  'OC' => 'Oculus Browser',
207
316
  'O1' => 'Opera Mini iOS',
208
317
  'OB' => 'Obigo',
209
318
  'O2' => 'Odin',
319
+ '2O' => 'Odin Browser',
210
320
  'H2' => 'OceanHero',
211
321
  'OD' => 'Odyssey Web Browser',
212
322
  'OF' => 'Off By One',
323
+ 'O5' => 'Office Browser',
213
324
  'HH' => 'OhHai Browser',
214
325
  'OE' => 'ONE Browser',
326
+ 'Y1' => 'Opera Crypto',
215
327
  'OX' => 'Opera GX',
216
328
  'OG' => 'Opera Neon',
217
329
  'OH' => 'Opera Devices',
@@ -227,30 +339,43 @@ class DeviceDetector
227
339
  'OY' => 'Origyn Web Browser',
228
340
  'OV' => 'Openwave Mobile Browser',
229
341
  'O3' => 'OpenFin',
342
+ 'O4' => 'Open Browser',
343
+ '4U' => 'Open Browser 4U',
344
+ '5G' => 'Open Browser fast 5G',
230
345
  'OW' => 'OmniWeb',
231
346
  'OT' => 'Otter Browser',
232
347
  'PL' => 'Palm Blazer',
233
348
  'PM' => 'Pale Moon',
234
349
  'PY' => 'Polypane',
235
350
  'PP' => 'Oppo Browser',
351
+ 'P6' => 'Opus Browser',
236
352
  'PR' => 'Palm Pre',
237
353
  'PU' => 'Puffin',
354
+ '2P' => 'Puffin Web Browser',
238
355
  'PW' => 'Palm WebPro',
239
356
  'PA' => 'Palmscape',
240
357
  'PE' => 'Perfect Browser',
358
+ 'P1' => 'Phantom.me',
241
359
  'PH' => 'Phantom Browser',
242
360
  'PX' => 'Phoenix',
243
361
  'PB' => 'Phoenix Browser',
244
362
  'PF' => 'PlayFree Browser',
363
+ 'PK' => 'PocketBook Browser',
245
364
  'PO' => 'Polaris',
246
365
  'PT' => 'Polarity',
247
366
  'LY' => 'PolyBrowser',
248
367
  'PI' => 'PrivacyWall',
368
+ 'P4' => 'Privacy Explorer Fast Safe',
369
+ 'P2' => 'Pi Browser',
370
+ 'P0' => 'PronHub Browser',
371
+ 'PC' => 'PSI Secure Browser',
372
+ 'RW' => 'Reqwireless WebViewer',
249
373
  'PS' => 'Microsoft Edge',
250
374
  'QA' => 'Qazweb',
251
375
  'Q2' => 'QQ Browser Lite',
252
376
  'Q1' => 'QQ Browser Mini',
253
377
  'QQ' => 'QQ Browser',
378
+ 'QS' => 'Quick Browser',
254
379
  'QT' => 'Qutebrowser',
255
380
  'QU' => 'Quark',
256
381
  'QZ' => 'QupZilla',
@@ -264,76 +389,123 @@ class DeviceDetector
264
389
  'S8' => 'Seewo Browser',
265
390
  'SC' => 'SEMC-Browser',
266
391
  'SE' => 'Sogou Explorer',
392
+ 'SO' => 'Sogou Mobile Browser',
393
+ 'RF' => 'SOTI Surf',
394
+ '2S' => 'Soul Browser',
395
+ 'T0' => 'Soundy Browser',
267
396
  'SF' => 'Safari',
397
+ 'PV' => 'Safari Technology Preview',
268
398
  'S5' => 'Safe Exam Browser',
269
399
  'SW' => 'SalamWeb',
400
+ 'VN' => 'Savannah Browser',
401
+ 'SD' => 'SavySoda',
270
402
  'S9' => 'Secure Browser',
271
403
  'SV' => 'SFive',
272
404
  'SH' => 'Shiira',
405
+ 'K1' => 'Sidekick',
273
406
  'S1' => 'SimpleBrowser',
407
+ '3S' => 'SilverMob US',
274
408
  'SY' => 'Sizzy',
275
409
  'SK' => 'Skyfire',
276
410
  'SS' => 'Seraphic Sraf',
411
+ 'KK' => 'SiteKiosk',
277
412
  'SL' => 'Sleipnir',
278
413
  'S6' => 'Slimjet',
279
414
  'S7' => 'SP Browser',
415
+ '9S' => 'Sony Small Browser',
416
+ '8S' => 'Secure Private Browser',
280
417
  'T1' => 'Stampy Browser',
281
418
  '7S' => '7Star',
419
+ 'SQ' => 'Smart Browser',
420
+ '6S' => 'Smart Search & Web Browser',
282
421
  'LE' => 'Smart Lenovo Browser',
283
422
  'OZ' => 'Smooz',
284
423
  'SN' => 'Snowshoe',
285
- 'SO' => 'Sogou Mobile Browser',
424
+ 'B1' => 'Spectre Browser',
286
425
  'S2' => 'Splash',
287
426
  'SI' => 'Sputnik Browser',
288
427
  'SR' => 'Sunrise',
289
428
  'SP' => 'SuperBird',
290
429
  'SU' => 'Super Fast Browser',
430
+ '5S' => 'SuperFast Browser',
431
+ 'HR' => 'Sushi Browser',
291
432
  'S3' => 'surf',
433
+ '4S' => 'Surf Browser',
292
434
  'SG' => 'Stargon',
293
435
  'S0' => 'START Internet Browser',
294
436
  'S4' => 'Steam In-Game Overlay',
295
437
  'ST' => 'Streamy',
296
438
  'SX' => 'Swiftfox',
297
439
  'SZ' => 'Seznam Browser',
440
+ 'W1' => 'Sweet Browser',
441
+ '2X' => 'SX Browser',
442
+ 'TP' => 'T+Browser',
298
443
  'TR' => 'T-Browser',
299
444
  'TO' => 't-online.de Browser',
300
445
  'TA' => 'Tao Browser',
301
446
  'TF' => 'TenFourFox',
302
447
  'TB' => 'Tenta Browser',
448
+ 'TE' => 'Tesla Browser',
303
449
  'TZ' => 'Tizen Browser',
450
+ 'TI' => 'Tint Browser',
451
+ 'TC' => 'TUC Mini Browser',
304
452
  'TU' => 'Tungsten',
305
453
  'TG' => 'ToGate',
306
454
  'TS' => 'TweakStyle',
307
455
  'TV' => 'TV Bro',
456
+ 'U0' => 'U Browser',
308
457
  'UB' => 'UBrowser',
309
458
  'UC' => 'UC Browser',
310
459
  'UH' => 'UC Browser HD',
311
460
  'UM' => 'UC Browser Mini',
312
461
  'UT' => 'UC Browser Turbo',
462
+ 'UI' => 'Ui Browser Mini',
313
463
  'UR' => 'UR Browser',
314
464
  'UZ' => 'Uzbl',
465
+ 'UE' => 'Ume Browser',
466
+ 'V0' => 'vBrowser',
467
+ 'VA' => 'Vast Browser',
315
468
  'VE' => 'Venus Browser',
469
+ 'N0' => 'Nova Video Downloader Pro',
470
+ 'VS' => 'Viasat Browser',
316
471
  'VI' => 'Vivaldi',
317
472
  'VV' => 'vivo Browser',
473
+ 'V2' => 'Vivid Browser Mini',
318
474
  'VB' => 'Vision Mobile Browser',
319
475
  'VM' => 'VMware AirWatch',
320
476
  'WI' => 'Wear Internet Browser',
321
477
  'WP' => 'Web Explorer',
478
+ 'W3' => 'Web Browser & Explorer',
322
479
  'WE' => 'WebPositive',
323
480
  'WF' => 'Waterfox',
481
+ 'WB' => 'Wave Browser',
482
+ 'WA' => 'Wavebox',
324
483
  'WH' => 'Whale Browser',
325
484
  'WO' => 'wOSBrowser',
326
485
  'WT' => 'WeTab Browser',
486
+ 'WL' => 'Wolvic',
487
+ 'YG' => 'YAGI',
327
488
  'YJ' => 'Yahoo! Japan Browser',
328
489
  'YA' => 'Yandex Browser',
329
490
  'YL' => 'Yandex Browser Lite',
330
491
  'YN' => 'Yaani Browser',
492
+ 'Y2' => 'Yo Browser',
331
493
  'YB' => 'Yolo Browser',
494
+ 'YO' => 'YouCare',
495
+ 'YZ' => 'Yuzu Browser',
496
+ 'XR' => 'xBrowser',
497
+ 'XB' => 'X Browser Lite',
498
+ 'X0' => 'X-VPN',
499
+ 'X1' => 'xBrowser Pro Super Fast',
500
+ 'XN' => 'XNX Browser',
501
+ 'XT' => 'XtremeCast',
332
502
  'XS' => 'xStand',
333
503
  'XI' => 'Xiino',
504
+ 'XO' => 'Xooloo Internet',
334
505
  'XV' => 'Xvast',
335
506
  'ZE' => 'Zetakey',
336
- 'ZV' => 'Zvu'
507
+ 'ZV' => 'Zvu',
508
+ 'ZI' => 'Zirco Browser'
337
509
 
338
510
  # detected browsers in older versions
339
511
  # 'IA' => 'Iceape', => pim
@@ -350,7 +522,14 @@ class DeviceDetector
350
522
  MN MZ NX OC OI OM OZ PU PI
351
523
  PE QU RE S0 S7 SA SB SG SK
352
524
  ST SU T1 UH UM UT VE VV WI
353
- WP YN
525
+ WP YN IO IS HQ RW HI PN BW
526
+ YO PK MR AP AK UI SD VN 4S
527
+ RF LR SQ BV L1 F0 KS V0 C8
528
+ AZ MM BT N0 P0 F3 DU D0 P1
529
+ O4 XO U0 B0 VA X0 A5 X1 18
530
+ B5 B6 TC A6 2X F4 YG WR NA
531
+ DM 1M A7 XN XT XB W1 HT B7
532
+ B9
354
533
  ]
355
534
  ).freeze
356
535
 
@@ -0,0 +1,181 @@
1
+ # frozen_string_literal: true
2
+
3
+ class DeviceDetector
4
+ class ClientHint
5
+ ROOT = File.expand_path('../..', __dir__)
6
+
7
+ REGEX_CACHE = ::DeviceDetector::MemoryCache.new({})
8
+ private_constant :REGEX_CACHE
9
+
10
+ class HintBrowser < Struct.new(:name, :version)
11
+ end
12
+
13
+ def initialize(headers)
14
+ return if headers.nil?
15
+
16
+ @headers = headers
17
+ @full_version = headers['Sec-CH-UA-Full-Version']
18
+ @browser_list = extract_browser_list
19
+ @app_name = extract_app_name
20
+ @platform = headers['Sec-CH-UA-Platform']
21
+ @platform_version = extract_platform_version
22
+ @mobile = headers['Sec-CH-UA-Mobile']
23
+ @model = extract_model
24
+ end
25
+
26
+ attr_reader :app_name, :browser_list, :full_version, :headers, :mobile, :model, :platform,
27
+ :platform_version
28
+
29
+ def browser_name
30
+ return 'Iridium' if is_iridium?
31
+
32
+ browser_name_from_list || app_name
33
+ end
34
+
35
+ def os_version
36
+ return windows_version if platform == 'Windows'
37
+
38
+ platform_version
39
+ end
40
+
41
+ def os_name
42
+ return 'Android' if android_app?
43
+ return unless ['Windows', 'Chromium OS'].include?(platform)
44
+
45
+ platform
46
+ end
47
+
48
+ def os_short_name
49
+ return if os_name.nil?
50
+
51
+ DeviceDetector::OS::DOWNCASED_OPERATING_SYSTEMS[os_name.downcase]
52
+ end
53
+
54
+ def os_family
55
+ return if os_short_name.nil?
56
+
57
+ DeviceDetector::OS::FAMILY_TO_OS[os_short_name]
58
+ end
59
+
60
+ private
61
+
62
+ def extract_platform_version
63
+ return if headers['Sec-CH-UA-Platform-Version'].nil?
64
+ return if headers['Sec-CH-UA-Platform-Version'] == ''
65
+
66
+ headers['Sec-CH-UA-Platform-Version']
67
+ end
68
+
69
+ # https://github.com/matomo-org/device-detector/blob/28211c6f411528abf41304e07b886fdf322a49b7/Parser/OperatingSystem.php#L330
70
+ def android_app?
71
+ %w[com.hisense.odinbrowser com.seraphic.openinet.pre
72
+ com.appssppa.idesktoppcbrowser].include?(app_name_from_headers)
73
+ end
74
+
75
+ def browser_name_from_list
76
+ @browser_name_from_list ||= browser_list&.reject { |b| b.name == 'Chromium' }&.last&.name
77
+ end
78
+
79
+ def available_browsers
80
+ DeviceDetector::Browser::AVAILABLE_BROWSERS.values
81
+ end
82
+
83
+ def available_osses
84
+ DeviceDetector::OS::OPERATING_SYSTEMS.values
85
+ end
86
+
87
+ # https://github.com/matomo-org/device-detector/blob/28211c6f411528abf41304e07b886fdf322a49b7/Parser/OperatingSystem.php#L434
88
+ def windows_version
89
+ return if platform_version.nil?
90
+
91
+ major_version = platform_version.split('.').first.to_i
92
+ return if major_version < 1
93
+
94
+ major_version < 11 ? '10' : '11'
95
+ end
96
+
97
+ # https://github.com/matomo-org/device-detector/blob/be1c9ef486c247dc4886668da5ed0b1c49d90ba8/Parser/Client/Browser.php#L749
98
+ # If version from client hints report 2022 or 2022.04, then is the Iridium browser
99
+ # https://iridiumbrowser.de/news/2022/05/16/version-2022-04-released
100
+ def is_iridium?
101
+ return if browser_list.nil?
102
+
103
+ !browser_list.find do |browser|
104
+ browser.name == 'Chromium' && %w[2021.12 2022.04 2022].include?(browser.version)
105
+ end.nil?
106
+ end
107
+
108
+ def app_name_from_headers
109
+ return if headers.nil?
110
+
111
+ headers['http-x-requested-with'] ||
112
+ headers['X-Requested-With'] ||
113
+ headers['x-requested-with']
114
+ end
115
+
116
+ def extract_app_name
117
+ requested_with = app_name_from_headers
118
+ return if requested_with.nil?
119
+
120
+ hint_app_names[requested_with]
121
+ end
122
+
123
+ def hint_app_names
124
+ DeviceDetector.cache.get_or_set('hint_app_names') do
125
+ load_hint_app_names.flatten.reduce({}, :merge)
126
+ end
127
+ end
128
+
129
+ def hint_filenames
130
+ %w[client/hints/browsers.yml client/hints/apps.yml]
131
+ end
132
+
133
+ def hint_filepaths
134
+ hint_filenames.map do |filename|
135
+ [filename.to_sym, File.join(ROOT, 'regexes', filename)]
136
+ end
137
+ end
138
+
139
+ def load_hint_app_names
140
+ hint_filepaths.map { |_, full_path| YAML.load_file(full_path) }
141
+ end
142
+
143
+ def extract_browser_list
144
+ return if headers['Sec-CH-UA'].nil?
145
+
146
+ headers['Sec-CH-UA'].split(', ').map do |component|
147
+ name_and_version = extract_browser_name_and_version(component)
148
+ next if name_and_version[:name].nil?
149
+
150
+ HintBrowser.new(name_and_version[:name], name_and_version[:version])
151
+ end.compact
152
+ end
153
+
154
+ def extract_browser_name_and_version(component)
155
+ component_and_version = component.gsub('"', '').split("\;v=")
156
+ name = name_from_known_browsers(component_and_version.first)
157
+ browser_version = full_version&.gsub('"', '') || component_and_version.last
158
+ { name: name, version: browser_version }
159
+ end
160
+
161
+ # https://github.com/matomo-org/device-detector/blob/be1c9ef486c247dc4886668da5ed0b1c49d90ba8/Parser/Client/Browser.php#L865
162
+ def name_from_known_browsers(name)
163
+ # https://github.com/matomo-org/device-detector/blob/be1c9ef486c247dc4886668da5ed0b1c49d90ba8/Parser/Client/Browser.php#L628
164
+ return 'Chrome' if name == 'Google Chrome'
165
+
166
+ available_browsers.find do |i|
167
+ i == name ||
168
+ i.gsub(' ', '') == name.gsub(' ', '') ||
169
+ i == name.gsub('Browser', '') ||
170
+ i == name.gsub(' Browser', '') ||
171
+ i == "#{name} Browser"
172
+ end
173
+ end
174
+
175
+ def extract_model
176
+ return if headers['Sec-CH-UA-Model'].nil? || headers['Sec-CH-UA-Model'] == ''
177
+
178
+ headers['Sec-CH-UA-Model']
179
+ end
180
+ end
181
+ end