device_detector 1.0.7 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -49,6 +49,8 @@ class DeviceDetector
49
49
  OPERATING_SYSTEMS = {
50
50
  'AIX' => 'AIX',
51
51
  'AND' => 'Android',
52
+ 'ADR' => 'Android TV',
53
+ 'AMZ' => 'Amazon Linux',
52
54
  'AMG' => 'AmigaOS',
53
55
  'ATV' => 'tvOS',
54
56
  'ARL' => 'Arch Linux',
@@ -57,10 +59,15 @@ class DeviceDetector
57
59
  'BEO' => 'BeOS',
58
60
  'BLB' => 'BlackBerry OS',
59
61
  'QNX' => 'BlackBerry Tablet OS',
62
+ 'BOS' => 'Bliss OS',
60
63
  'BMP' => 'Brew',
61
64
  'CAI' => 'Caixa Mágica',
62
65
  'CES' => 'CentOS',
66
+ 'CST' => 'CentOS Stream',
67
+ 'CLR' => 'ClearOS Mobile',
63
68
  'COS' => 'Chrome OS',
69
+ 'CRS' => 'Chromium OS',
70
+ 'CHN' => 'China OS',
64
71
  'CYN' => 'CyanogenMod',
65
72
  'DEB' => 'Debian',
66
73
  'DEE' => 'Deepin',
@@ -70,9 +77,11 @@ class DeviceDetector
70
77
  'FEN' => 'Fenix',
71
78
  'FOS' => 'Firefox OS',
72
79
  'FIR' => 'Fire OS',
80
+ 'FOR' => 'Foresight Linux',
73
81
  'FRE' => 'Freebox',
74
82
  'BSD' => 'FreeBSD',
75
83
  'FYD' => 'FydeOS',
84
+ 'FUC' => 'Fuchsia',
76
85
  'GNT' => 'Gentoo',
77
86
  'GRI' => 'GridOS',
78
87
  'GTV' => 'Google TV',
@@ -85,9 +94,14 @@ class DeviceDetector
85
94
  'INF' => 'Inferno',
86
95
  'JME' => 'Java ME',
87
96
  'KOS' => 'KaiOS',
97
+ 'KAN' => 'Kanotix',
88
98
  'KNO' => 'Knoppix',
99
+ 'KTV' => 'KreaTV',
89
100
  'KBT' => 'Kubuntu',
90
101
  'LIN' => 'GNU/Linux',
102
+ 'LND' => 'LindowsOS',
103
+ 'LNS' => 'Linspire',
104
+ 'LEN' => 'Lineage OS',
91
105
  'LBT' => 'Lubuntu',
92
106
  'LOS' => 'Lumin OS',
93
107
  'VLN' => 'VectorLinux',
@@ -97,6 +111,7 @@ class DeviceDetector
97
111
  'MDR' => 'Mandriva',
98
112
  'SMG' => 'MeeGo',
99
113
  'MCD' => 'MocorDroid',
114
+ 'MON' => 'moonOS',
100
115
  'MIN' => 'Mint',
101
116
  'MLD' => 'MildWild',
102
117
  'MOR' => 'MorphOS',
@@ -105,25 +120,34 @@ class DeviceDetector
105
120
  'MRE' => 'MRE',
106
121
  'WII' => 'Nintendo',
107
122
  'NDS' => 'Nintendo Mobile',
123
+ 'NOV' => 'Nova',
108
124
  'OS2' => 'OS/2',
109
125
  'T64' => 'OSF1',
110
126
  'OBS' => 'OpenBSD',
111
127
  'OWR' => 'OpenWrt',
128
+ 'OTV' => 'Opera TV',
112
129
  'ORD' => 'Ordissimo',
130
+ 'PAR' => 'Pardus',
113
131
  'PCL' => 'PCLinuxOS',
132
+ 'PLA' => 'Plasma Mobile',
114
133
  'PSP' => 'PlayStation Portable',
115
134
  'PS3' => 'PlayStation',
135
+ 'PUR' => 'PureOS',
116
136
  'RHT' => 'Red Hat',
137
+ 'REV' => 'Revenge OS',
117
138
  'ROS' => 'RISC OS',
118
139
  'ROK' => 'Roku OS',
119
140
  'RSO' => 'Rosa',
141
+ 'ROU' => 'RouterOS',
120
142
  'REM' => 'Remix OS',
143
+ 'RRS' => 'Resurrection Remix OS',
121
144
  'REX' => 'REX',
122
145
  'RZD' => 'RazoDroiD',
123
146
  'SAB' => 'Sabayon',
124
147
  'SSE' => 'SUSE',
125
148
  'SAF' => 'Sailfish OS',
126
149
  'SEE' => 'SeewoOS',
150
+ 'SIR' => 'Sirin OS',
127
151
  'SLW' => 'Slackware',
128
152
  'SOS' => 'Solaris',
129
153
  'SYL' => 'Syllable',
@@ -132,6 +156,7 @@ class DeviceDetector
132
156
  'S40' => 'Symbian OS Series 40',
133
157
  'S60' => 'Symbian OS Series 60',
134
158
  'SY3' => 'Symbian^3',
159
+ 'TEN' => 'TencentOS',
135
160
  'TDX' => 'ThreadX',
136
161
  'TIZ' => 'Tizen',
137
162
  'TOS' => 'TmaxOS',
@@ -148,6 +173,8 @@ class DeviceDetector
148
173
  'XBX' => 'Xbox',
149
174
  'XBT' => 'Xubuntu',
150
175
  'YNS' => 'YunOS',
176
+ 'ZEN' => 'Zenwalk',
177
+ 'ZOR' => 'ZorinOS',
151
178
  'IOS' => 'iOS',
152
179
  'POS' => 'palmOS',
153
180
  'WOS' => 'webOS'
@@ -158,12 +185,13 @@ class DeviceDetector
158
185
  end.freeze
159
186
 
160
187
  OS_FAMILIES = {
161
- 'Android' => %w[AND CYN FIR REM RZD MLD MCD YNS GRI HAR],
188
+ 'Android' => %w[ AND CYN FIR REM RZD MLD MCD YNS GRI HAR
189
+ ADR CLR BOS REV LEN SIR RRS],
162
190
  'AmigaOS' => %w[AMG MOR],
163
191
  'BlackBerry' => %w[BLB QNX],
164
192
  'Brew' => ['BMP'],
165
193
  'BeOS' => %w[BEO HAI],
166
- 'Chrome OS' => %w[COS FYD SEE],
194
+ 'Chrome OS' => %w[COS CRS FYD SEE],
167
195
  'Firefox OS' => %w[FOS KOS],
168
196
  'Gaming Console' => %w[WII PS3],
169
197
  'Google TV' => ['GTV'],
@@ -174,7 +202,9 @@ class DeviceDetector
174
202
  LIN ARL DEB KNO MIN UBT KBT XBT LBT FED
175
203
  RHT VLN MDR GNT SAB SLW SSE CES BTR SAF
176
204
  ORD TOS RSO DEE FRE MAG FEN CAI PCL HAS
177
- LOS DVK ROK OWR
205
+ LOS DVK ROK OWR OTV KTV PUR PLA FUC PAR
206
+ FOR MON KAN ZEN LND LNS CHN AMZ TEN CST
207
+ NOV ROU ZOR
178
208
  ],
179
209
  'Mac' => ['MAC'],
180
210
  'Mobile Gaming Console' => %w[PSP NDS XBX],
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class DeviceDetector
4
- VERSION = '1.0.7'
4
+ VERSION = '1.1.0'
5
5
  end
@@ -14,36 +14,46 @@ require 'device_detector/client'
14
14
  require 'device_detector/device'
15
15
  require 'device_detector/os'
16
16
  require 'device_detector/browser'
17
+ require 'device_detector/client_hint'
17
18
 
18
19
  class DeviceDetector
19
- attr_reader :user_agent
20
+ attr_reader :client_hint, :user_agent
20
21
 
21
- def initialize(user_agent)
22
+ def initialize(user_agent, headers = nil)
23
+ @client_hint = ClientHint.new(headers)
22
24
  @user_agent = user_agent
23
25
  end
24
26
 
25
27
  def name
26
- client.name
28
+ return client.name if mobile_fix?
29
+
30
+ client_hint.browser_name || client.name
27
31
  end
28
32
 
29
33
  def full_version
30
- client.full_version
34
+ client_hint.platform_version || client.full_version
31
35
  end
32
36
 
33
37
  def os_family
34
- os.family
38
+ return 'GNU/Linux' if linux_fix?
39
+
40
+ client_hint.os_family || os.family || client_hint.platform
35
41
  end
36
42
 
37
43
  def os_name
38
- os.name
44
+ return 'GNU/Linux' if linux_fix?
45
+
46
+ client_hint.os_name || os.name || client_hint.platform
39
47
  end
40
48
 
41
49
  def os_full_version
42
- os.full_version
50
+ return if skip_os_version?
51
+
52
+ client_hint.os_version || os.full_version
43
53
  end
44
54
 
45
55
  def device_name
46
- device.name
56
+ device.name || client_hint.model || fix_for_x_music
47
57
  end
48
58
 
49
59
  def device_brand
@@ -62,7 +72,7 @@ class DeviceDetector
62
72
  # Note: We do not check for browser (family) here, as there might be mobile apps using Chrome,
63
73
  # that won't have a detected browser, but can still be detected. So we check the useragent for
64
74
  # Chrome instead.
65
- if t.nil? && os.family == 'Android' && user_agent =~ build_regex('Chrome\/[\.0-9]*')
75
+ if t.nil? && os_family == 'Android' && user_agent =~ build_regex('Chrome\/[\.0-9]*')
66
76
  if user_agent =~ build_regex('(?:Mobile|eliboM) Safari\/')
67
77
  t = 'smartphone'
68
78
  elsif user_agent =~ build_regex('(?!Mobile )Safari\/')
@@ -97,7 +107,7 @@ class DeviceDetector
97
107
  end
98
108
 
99
109
  # All detected feature phones running android are more likely a smartphone
100
- t = 'smartphone' if t == 'feature phone' && os.family == 'Android'
110
+ t = 'smartphone' if t == 'feature phone' && os_family == 'Android'
101
111
 
102
112
  # All unknown devices under running Java ME are more likely a features phones
103
113
  t = 'feature phone' if t.nil? && os_name == 'Java ME'
@@ -111,19 +121,25 @@ class DeviceDetector
111
121
  # assume that all Windows 8 touch devices are tablets.
112
122
  if t.nil? && touch_enabled? &&
113
123
  (os_name == 'Windows RT' ||
114
- (os_name == 'Windows' && os.full_version &&
115
- Gem::Version.new(os.full_version) >= VersionExtractor::MAJOR_VERSION_8))
124
+ (os_name == 'Windows' && os_full_version &&
125
+ Gem::Version.new(os_full_version) >= VersionExtractor::MAJOR_VERSION_8))
116
126
  t = 'tablet'
117
127
  end
118
128
 
119
129
  # All devices running Opera TV Store are assumed to be a tv
120
130
  t = 'tv' if opera_tv_store?
121
131
 
132
+ # All devices that contain Andr0id in string are assumed to be a tv
133
+ t = 'tv' if user_agent =~ build_regex('Andr0id|Android TV')
134
+
122
135
  # All devices running Tizen TV or SmartTV are assumed to be a tv
123
136
  t = 'tv' if t.nil? && tizen_samsung_tv?
124
137
 
125
138
  # Devices running Kylo or Espital TV Browsers are assumed to be a TV
126
- t = 'tv' if t.nil? && ['Kylo', 'Espial TV Browser'].include?(client.name)
139
+ t = 'tv' if t.nil? && ['Kylo', 'Espial TV Browser'].include?(name)
140
+
141
+ # All devices containing TV fragment are assumed to be a tv
142
+ t = 'tv' if t.nil? && user_agent =~ build_regex('\(TV;')
127
143
 
128
144
  has_desktop = t != 'desktop' && desktop_string? && desktop_fragment?
129
145
  t = 'desktop' if has_desktop
@@ -190,12 +206,31 @@ class DeviceDetector
190
206
  @os ||= OS.new(user_agent)
191
207
  end
192
208
 
209
+ # https://github.com/matomo-org/device-detector/blob/be1c9ef486c247dc4886668da5ed0b1c49d90ba8/Parser/Client/Browser.php#L772
210
+ # Fix mobile browser names e.g. Chrome => Chrome Mobile
211
+ def mobile_fix?
212
+ client.name == "#{client_hint.browser_name} Mobile"
213
+ end
214
+
215
+ def linux_fix?
216
+ client_hint.platform == 'Linux' && os.name == 'Android' && client_hint.mobile == '?0'
217
+ end
218
+
219
+ # Related to issue mentionned in device.rb#1562
220
+ def fix_for_x_music
221
+ user_agent.include?('X-music Ⅲ') ? 'X-Music III' : nil
222
+ end
223
+
224
+ def skip_os_version?
225
+ !client_hint.os_family.nil? && client_hint.os_family != os.family
226
+ end
227
+
193
228
  def android_tablet_fragment?
194
- user_agent =~ build_regex('Android(?: \d.\d(?:.\d)?)?; Tablet;')
229
+ user_agent =~ build_regex('Android( [\.0-9]+)?; Tablet;')
195
230
  end
196
231
 
197
232
  def android_mobile_fragment?
198
- user_agent =~ build_regex('Android(?: \d.\d(?:.\d)?)?; Mobile;')
233
+ user_agent =~ build_regex('Android( [\.0-9]+)?; Mobile;')
199
234
  end
200
235
 
201
236
  def desktop_fragment?