device_detector 1.0.5 → 1.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +7 -6
- data/lib/device_detector/browser.rb +364 -0
- data/lib/device_detector/client.rb +8 -0
- data/lib/device_detector/device.rb +1124 -4
- data/lib/device_detector/os.rb +36 -11
- data/lib/device_detector/version.rb +1 -1
- data/lib/device_detector/version_extractor.rb +9 -0
- data/lib/device_detector.rb +57 -13
- data/regexes/bots.yml +551 -58
- data/regexes/client/browser_engine.yml +7 -1
- data/regexes/client/browsers.yml +594 -71
- data/regexes/client/feed_readers.yml +4 -10
- data/regexes/client/libraries.yml +47 -2
- data/regexes/client/mediaplayers.yml +25 -1
- data/regexes/client/mobile_apps.yml +447 -77
- data/regexes/client/pim.yml +49 -1
- data/regexes/device/cameras.yml +5 -5
- data/regexes/device/car_browsers.yml +16 -0
- data/regexes/device/consoles.yml +6 -0
- data/regexes/device/mobiles.yml +12905 -4561
- data/regexes/device/portable_media_player.yml +20 -3
- data/regexes/device/shell_tv.yml +117 -0
- data/regexes/device/televisions.yml +426 -35
- data/regexes/oss.yml +567 -139
- data/spec/device_detector/concrete_user_agent_spec.rb +30 -42
- data/spec/device_detector/detector_fixtures_spec.rb +9 -5
- data/spec/device_detector/device_spec.rb +26 -10
- data/spec/fixtures/client/browser.yml +1463 -391
- data/spec/fixtures/client/feed_reader.yml +0 -12
- data/spec/fixtures/client/library.yml +91 -37
- data/spec/fixtures/client/mediaplayer.yml +30 -0
- data/spec/fixtures/client/mobile_app.yml +498 -45
- data/spec/fixtures/client/pim.yml +60 -0
- data/spec/fixtures/detector/bots.yml +1189 -568
- data/spec/fixtures/detector/camera.yml +12 -26
- data/spec/fixtures/detector/car_browser.yml +151 -15
- data/spec/fixtures/detector/console.yml +70 -48
- data/spec/fixtures/detector/desktop.yml +2041 -916
- data/spec/fixtures/detector/feature_phone.yml +895 -189
- data/spec/fixtures/detector/feed_reader.yml +50 -77
- data/spec/fixtures/detector/mediaplayer.yml +79 -26
- data/spec/fixtures/detector/mobile_apps.yml +726 -72
- data/spec/fixtures/detector/peripheral.yml +271 -0
- data/spec/fixtures/detector/phablet.yml +3635 -1596
- data/spec/fixtures/detector/portable_media_player.yml +355 -46
- data/spec/fixtures/detector/smart_display.yml +183 -9
- data/spec/fixtures/detector/smart_speaker.yml +13 -8
- data/spec/fixtures/detector/smartphone-1.yml +4002 -4286
- data/spec/fixtures/detector/smartphone-10.yml +3771 -4763
- data/spec/fixtures/detector/smartphone-11.yml +3615 -4692
- data/spec/fixtures/detector/smartphone-12.yml +3856 -4764
- data/spec/fixtures/detector/smartphone-13.yml +4213 -4713
- data/spec/fixtures/detector/smartphone-14.yml +4039 -4497
- data/spec/fixtures/detector/smartphone-15.yml +5642 -2956
- data/spec/fixtures/detector/smartphone-16.yml +4739 -5082
- data/spec/fixtures/detector/smartphone-17.yml +4832 -4275
- data/spec/fixtures/detector/smartphone-18.yml +9806 -0
- data/spec/fixtures/detector/smartphone-19.yml +9965 -0
- data/spec/fixtures/detector/smartphone-2.yml +4842 -2589
- data/spec/fixtures/detector/smartphone-20.yml +9710 -0
- data/spec/fixtures/detector/smartphone-21.yml +8693 -0
- data/spec/fixtures/detector/smartphone-22.yml +10178 -0
- data/spec/fixtures/detector/smartphone-23.yml +9453 -0
- data/spec/fixtures/detector/smartphone-24.yml +9843 -0
- data/spec/fixtures/detector/smartphone-25.yml +9703 -0
- data/spec/fixtures/detector/smartphone-26.yml +10007 -0
- data/spec/fixtures/detector/smartphone-27.yml +4927 -0
- data/spec/fixtures/detector/smartphone-3.yml +4387 -4427
- data/spec/fixtures/detector/smartphone-4.yml +3597 -4582
- data/spec/fixtures/detector/smartphone-5.yml +4066 -5022
- data/spec/fixtures/detector/smartphone-6.yml +3455 -4621
- data/spec/fixtures/detector/smartphone-7.yml +3574 -4574
- data/spec/fixtures/detector/smartphone-8.yml +4617 -4704
- data/spec/fixtures/detector/smartphone-9.yml +4080 -5035
- data/spec/fixtures/detector/smartphone.yml +3244 -4234
- data/spec/fixtures/detector/tablet-1.yml +4652 -4492
- data/spec/fixtures/detector/tablet-2.yml +3515 -4434
- data/spec/fixtures/detector/tablet-3.yml +3418 -4351
- data/spec/fixtures/detector/tablet-4.yml +5149 -3200
- data/spec/fixtures/detector/tablet-5.yml +9273 -0
- data/spec/fixtures/detector/tablet-6.yml +4588 -0
- data/spec/fixtures/detector/tablet.yml +1621 -2613
- data/spec/fixtures/detector/tv-1.yml +2501 -0
- data/spec/fixtures/detector/tv.yml +7826 -3114
- data/spec/fixtures/detector/unknown.yml +370 -531
- data/spec/fixtures/detector/wearable.yml +863 -9
- data/spec/fixtures/parser/oss.yml +1350 -21
- data/spec/fixtures/parser/vendorfragments.yml +53 -53
- metadata +35 -5
data/lib/device_detector/os.rb
CHANGED
|
@@ -30,7 +30,7 @@ class DeviceDetector
|
|
|
30
30
|
def os_info
|
|
31
31
|
from_cache(['os_info', self.class.name, user_agent]) do
|
|
32
32
|
os_name = NameExtractor.new(user_agent, regex_meta).call
|
|
33
|
-
if os_name && short = DOWNCASED_OPERATING_SYSTEMS[os_name.downcase]
|
|
33
|
+
if os_name && (short = DOWNCASED_OPERATING_SYSTEMS[os_name.downcase])
|
|
34
34
|
os_name = OPERATING_SYSTEMS[short]
|
|
35
35
|
else
|
|
36
36
|
short = 'UNK'
|
|
@@ -50,7 +50,7 @@ class DeviceDetector
|
|
|
50
50
|
'AIX' => 'AIX',
|
|
51
51
|
'AND' => 'Android',
|
|
52
52
|
'AMG' => 'AmigaOS',
|
|
53
|
-
'ATV' => '
|
|
53
|
+
'ATV' => 'tvOS',
|
|
54
54
|
'ARL' => 'Arch Linux',
|
|
55
55
|
'BTR' => 'BackTrack',
|
|
56
56
|
'SBA' => 'Bada',
|
|
@@ -58,29 +58,42 @@ class DeviceDetector
|
|
|
58
58
|
'BLB' => 'BlackBerry OS',
|
|
59
59
|
'QNX' => 'BlackBerry Tablet OS',
|
|
60
60
|
'BMP' => 'Brew',
|
|
61
|
+
'CAI' => 'Caixa Mágica',
|
|
61
62
|
'CES' => 'CentOS',
|
|
62
63
|
'COS' => 'Chrome OS',
|
|
63
64
|
'CYN' => 'CyanogenMod',
|
|
64
65
|
'DEB' => 'Debian',
|
|
66
|
+
'DEE' => 'Deepin',
|
|
65
67
|
'DFB' => 'DragonFly',
|
|
68
|
+
'DVK' => 'DVKBuntu',
|
|
66
69
|
'FED' => 'Fedora',
|
|
70
|
+
'FEN' => 'Fenix',
|
|
67
71
|
'FOS' => 'Firefox OS',
|
|
68
72
|
'FIR' => 'Fire OS',
|
|
73
|
+
'FRE' => 'Freebox',
|
|
69
74
|
'BSD' => 'FreeBSD',
|
|
75
|
+
'FYD' => 'FydeOS',
|
|
70
76
|
'GNT' => 'Gentoo',
|
|
77
|
+
'GRI' => 'GridOS',
|
|
71
78
|
'GTV' => 'Google TV',
|
|
72
79
|
'HPX' => 'HP-UX',
|
|
73
80
|
'HAI' => 'Haiku OS',
|
|
81
|
+
'IPA' => 'iPadOS',
|
|
82
|
+
'HAR' => 'HarmonyOS',
|
|
83
|
+
'HAS' => 'HasCodingOS',
|
|
74
84
|
'IRI' => 'IRIX',
|
|
75
85
|
'INF' => 'Inferno',
|
|
86
|
+
'JME' => 'Java ME',
|
|
76
87
|
'KOS' => 'KaiOS',
|
|
77
88
|
'KNO' => 'Knoppix',
|
|
78
89
|
'KBT' => 'Kubuntu',
|
|
79
90
|
'LIN' => 'GNU/Linux',
|
|
80
91
|
'LBT' => 'Lubuntu',
|
|
92
|
+
'LOS' => 'Lumin OS',
|
|
81
93
|
'VLN' => 'VectorLinux',
|
|
82
94
|
'MAC' => 'Mac',
|
|
83
95
|
'MAE' => 'Maemo',
|
|
96
|
+
'MAG' => 'Mageia',
|
|
84
97
|
'MDR' => 'Mandriva',
|
|
85
98
|
'SMG' => 'MeeGo',
|
|
86
99
|
'MCD' => 'MocorDroid',
|
|
@@ -89,21 +102,26 @@ class DeviceDetector
|
|
|
89
102
|
'MOR' => 'MorphOS',
|
|
90
103
|
'NBS' => 'NetBSD',
|
|
91
104
|
'MTK' => 'MTK / Nucleus',
|
|
105
|
+
'MRE' => 'MRE',
|
|
92
106
|
'WII' => 'Nintendo',
|
|
93
107
|
'NDS' => 'Nintendo Mobile',
|
|
94
108
|
'OS2' => 'OS/2',
|
|
95
109
|
'T64' => 'OSF1',
|
|
96
110
|
'OBS' => 'OpenBSD',
|
|
97
111
|
'ORD' => 'Ordissimo',
|
|
112
|
+
'PCL' => 'PCLinuxOS',
|
|
98
113
|
'PSP' => 'PlayStation Portable',
|
|
99
114
|
'PS3' => 'PlayStation',
|
|
100
115
|
'RHT' => 'Red Hat',
|
|
101
116
|
'ROS' => 'RISC OS',
|
|
117
|
+
'RSO' => 'Rosa',
|
|
102
118
|
'REM' => 'Remix OS',
|
|
119
|
+
'REX' => 'REX',
|
|
103
120
|
'RZD' => 'RazoDroiD',
|
|
104
121
|
'SAB' => 'Sabayon',
|
|
105
122
|
'SSE' => 'SUSE',
|
|
106
123
|
'SAF' => 'Sailfish OS',
|
|
124
|
+
'SEE' => 'SeewoOS',
|
|
107
125
|
'SLW' => 'Slackware',
|
|
108
126
|
'SOS' => 'Solaris',
|
|
109
127
|
'SYL' => 'Syllable',
|
|
@@ -116,7 +134,9 @@ class DeviceDetector
|
|
|
116
134
|
'TIZ' => 'Tizen',
|
|
117
135
|
'TOS' => 'TmaxOS',
|
|
118
136
|
'UBT' => 'Ubuntu',
|
|
137
|
+
'WAS' => 'watchOS',
|
|
119
138
|
'WTV' => 'WebTV',
|
|
139
|
+
'WHS' => 'Whale OS',
|
|
120
140
|
'WIN' => 'Windows',
|
|
121
141
|
'WCE' => 'Windows CE',
|
|
122
142
|
'WIO' => 'Windows IoT',
|
|
@@ -133,37 +153,42 @@ class DeviceDetector
|
|
|
133
153
|
|
|
134
154
|
DOWNCASED_OPERATING_SYSTEMS = OPERATING_SYSTEMS.each_with_object({}) do |(short, long), h|
|
|
135
155
|
h[long.downcase] = short
|
|
136
|
-
end
|
|
156
|
+
end.freeze
|
|
137
157
|
|
|
138
158
|
OS_FAMILIES = {
|
|
139
|
-
'Android' => %w[AND CYN FIR REM RZD MLD MCD YNS],
|
|
159
|
+
'Android' => %w[AND CYN FIR REM RZD MLD MCD YNS GRI HAR],
|
|
140
160
|
'AmigaOS' => %w[AMG MOR],
|
|
141
|
-
'Apple TV' => ['ATV'],
|
|
142
161
|
'BlackBerry' => %w[BLB QNX],
|
|
143
162
|
'Brew' => ['BMP'],
|
|
144
163
|
'BeOS' => %w[BEO HAI],
|
|
145
|
-
'Chrome OS' => [
|
|
164
|
+
'Chrome OS' => %w[COS FYD SEE],
|
|
146
165
|
'Firefox OS' => %w[FOS KOS],
|
|
147
166
|
'Gaming Console' => %w[WII PS3],
|
|
148
167
|
'Google TV' => ['GTV'],
|
|
149
168
|
'IBM' => ['OS2'],
|
|
150
|
-
'iOS' => [
|
|
169
|
+
'iOS' => %w[IOS ATV WAS IPA],
|
|
151
170
|
'RISC OS' => ['ROS'],
|
|
152
|
-
'GNU/Linux' => %w[
|
|
171
|
+
'GNU/Linux' => %w[
|
|
172
|
+
LIN ARL DEB KNO MIN UBT KBT XBT LBT FED
|
|
173
|
+
RHT VLN MDR GNT SAB SLW SSE CES BTR SAF
|
|
174
|
+
ORD TOS RSO DEE FRE MAG FEN CAI PCL HAS
|
|
175
|
+
LOS DVK
|
|
176
|
+
],
|
|
153
177
|
'Mac' => ['MAC'],
|
|
154
178
|
'Mobile Gaming Console' => %w[PSP NDS XBX],
|
|
155
|
-
'Real-time OS' => %w[MTK TDX],
|
|
179
|
+
'Real-time OS' => %w[MTK TDX MRE JME REX],
|
|
156
180
|
'Other Mobile' => %w[WOS POS SBA TIZ SMG MAE],
|
|
157
181
|
'Symbian' => %w[SYM SYS SY3 S60 S40],
|
|
158
182
|
'Unix' => %w[SOS AIX HPX BSD NBS OBS DFB SYL IRI T64 INF],
|
|
159
183
|
'WebTV' => ['WTV'],
|
|
160
184
|
'Windows' => ['WIN'],
|
|
161
|
-
'Windows Mobile' => %w[WPH WMO WCE WRT WIO]
|
|
185
|
+
'Windows Mobile' => %w[WPH WMO WCE WRT WIO],
|
|
186
|
+
'Other Smart TV' => ['WHS']
|
|
162
187
|
}.freeze
|
|
163
188
|
|
|
164
189
|
FAMILY_TO_OS = OS_FAMILIES.each_with_object({}) do |(family, oss), h|
|
|
165
190
|
oss.each { |os| h[os] = family }
|
|
166
|
-
end
|
|
191
|
+
end.freeze
|
|
167
192
|
|
|
168
193
|
def filenames
|
|
169
194
|
['oss.yml']
|
|
@@ -2,6 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
class DeviceDetector
|
|
4
4
|
class VersionExtractor < MetadataExtractor
|
|
5
|
+
MAJOR_VERSION_2 = Gem::Version.new('2.0')
|
|
6
|
+
MAJOR_VERSION_3 = Gem::Version.new('3.0')
|
|
7
|
+
MAJOR_VERSION_4 = Gem::Version.new('4.0')
|
|
8
|
+
MAJOR_VERSION_8 = Gem::Version.new('8.0')
|
|
9
|
+
|
|
10
|
+
def call
|
|
11
|
+
super&.chomp('.')
|
|
12
|
+
end
|
|
13
|
+
|
|
5
14
|
private
|
|
6
15
|
|
|
7
16
|
def metadata_string
|
data/lib/device_detector.rb
CHANGED
|
@@ -13,6 +13,7 @@ require 'device_detector/bot'
|
|
|
13
13
|
require 'device_detector/client'
|
|
14
14
|
require 'device_detector/device'
|
|
15
15
|
require 'device_detector/os'
|
|
16
|
+
require 'device_detector/browser'
|
|
16
17
|
|
|
17
18
|
class DeviceDetector
|
|
18
19
|
attr_reader :user_agent
|
|
@@ -46,7 +47,10 @@ class DeviceDetector
|
|
|
46
47
|
end
|
|
47
48
|
|
|
48
49
|
def device_brand
|
|
49
|
-
|
|
50
|
+
# Assume all devices running iOS / Mac OS are from Apple
|
|
51
|
+
brand = device.brand
|
|
52
|
+
brand = 'Apple' if brand.nil? && ['Apple TV', 'iOS', 'Mac'].include?(os_name)
|
|
53
|
+
brand
|
|
50
54
|
end
|
|
51
55
|
|
|
52
56
|
def device_type
|
|
@@ -59,15 +63,19 @@ class DeviceDetector
|
|
|
59
63
|
# that won't have a detected browser, but can still be detected. So we check the useragent for
|
|
60
64
|
# Chrome instead.
|
|
61
65
|
if t.nil? && os.family == 'Android' && user_agent =~ build_regex('Chrome\/[\.0-9]*')
|
|
62
|
-
if user_agent =~ build_regex('
|
|
66
|
+
if user_agent =~ build_regex('(?:Mobile|eliboM) Safari\/')
|
|
63
67
|
t = 'smartphone'
|
|
64
|
-
elsif user_agent =~ build_regex('
|
|
68
|
+
elsif user_agent =~ build_regex('(?!Mobile )Safari\/')
|
|
65
69
|
t = 'tablet'
|
|
66
70
|
end
|
|
67
71
|
end
|
|
68
72
|
|
|
73
|
+
# Some UA contain the fragment 'Android; Tablet;' or 'Opera Tablet', so we assume those devices
|
|
74
|
+
# as tablets
|
|
69
75
|
t = 'tablet' if t.nil? && android_tablet_fragment? || opera_tablet?
|
|
70
76
|
|
|
77
|
+
# Some user agents simply contain the fragment 'Android; Mobile;', so we assume those devices
|
|
78
|
+
# as smartphones
|
|
71
79
|
t = 'smartphone' if t.nil? && android_mobile_fragment?
|
|
72
80
|
|
|
73
81
|
# Android up to 3.0 was designed for smartphones only. But as 3.0,
|
|
@@ -78,10 +86,12 @@ class DeviceDetector
|
|
|
78
86
|
# So were are expecting that all devices running Android < 2 are
|
|
79
87
|
# smartphones Devices running Android 3.X are tablets. Device type
|
|
80
88
|
# of Android 2.X and 4.X+ are unknown
|
|
81
|
-
if t.nil? &&
|
|
82
|
-
|
|
89
|
+
if t.nil? && os_name == 'Android' && os.full_version && !os.full_version.empty?
|
|
90
|
+
full_version = Gem::Version.new(os.full_version)
|
|
91
|
+
if full_version < VersionExtractor::MAJOR_VERSION_2
|
|
83
92
|
t = 'smartphone'
|
|
84
|
-
elsif
|
|
93
|
+
elsif full_version >= VersionExtractor::MAJOR_VERSION_3 && \
|
|
94
|
+
full_version < VersionExtractor::MAJOR_VERSION_4
|
|
85
95
|
t = 'tablet'
|
|
86
96
|
end
|
|
87
97
|
end
|
|
@@ -89,6 +99,9 @@ class DeviceDetector
|
|
|
89
99
|
# All detected feature phones running android are more likely a smartphone
|
|
90
100
|
t = 'smartphone' if t == 'feature phone' && os.family == 'Android'
|
|
91
101
|
|
|
102
|
+
# All unknown devices under running Java ME are more likely a features phones
|
|
103
|
+
t = 'feature phone' if t.nil? && os_name == 'Java ME'
|
|
104
|
+
|
|
92
105
|
# According to http://msdn.microsoft.com/en-us/library/ie/hh920767(v=vs.85).aspx
|
|
93
106
|
# Internet Explorer 10 introduces the "Touch" UA string token. If this token is present at the
|
|
94
107
|
# end of the UA string, the computer has touch capability, and is running Windows 8 (or later).
|
|
@@ -97,19 +110,29 @@ class DeviceDetector
|
|
|
97
110
|
# As most touch enabled devices are tablets and only a smaller part are desktops/notebooks we
|
|
98
111
|
# assume that all Windows 8 touch devices are tablets.
|
|
99
112
|
if t.nil? && touch_enabled? &&
|
|
100
|
-
(
|
|
113
|
+
(os_name == 'Windows RT' ||
|
|
114
|
+
(os_name == 'Windows' && os.full_version &&
|
|
115
|
+
Gem::Version.new(os.full_version) >= VersionExtractor::MAJOR_VERSION_8))
|
|
101
116
|
t = 'tablet'
|
|
102
117
|
end
|
|
103
118
|
|
|
119
|
+
# All devices running Opera TV Store are assumed to be a tv
|
|
104
120
|
t = 'tv' if opera_tv_store?
|
|
105
121
|
|
|
122
|
+
# All devices running Tizen TV or SmartTV are assumed to be a tv
|
|
123
|
+
t = 'tv' if t.nil? && tizen_samsung_tv?
|
|
124
|
+
|
|
125
|
+
# Devices running Kylo or Espital TV Browsers are assumed to be a TV
|
|
106
126
|
t = 'tv' if t.nil? && ['Kylo', 'Espial TV Browser'].include?(client.name)
|
|
107
127
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
t = 'desktop' if t.nil? && os.desktop? && !puffin_browser?
|
|
128
|
+
has_desktop = t != 'desktop' && desktop_string? && desktop_fragment?
|
|
129
|
+
t = 'desktop' if has_desktop
|
|
111
130
|
|
|
112
|
-
|
|
131
|
+
# set device type to desktop for all devices running a desktop os that were not detected as
|
|
132
|
+
# another device type
|
|
133
|
+
return t if t || !desktop?
|
|
134
|
+
|
|
135
|
+
'desktop'
|
|
113
136
|
end
|
|
114
137
|
|
|
115
138
|
def known?
|
|
@@ -175,6 +198,10 @@ class DeviceDetector
|
|
|
175
198
|
user_agent =~ build_regex('Android(?: \d.\d(?:.\d)?)?; Mobile;')
|
|
176
199
|
end
|
|
177
200
|
|
|
201
|
+
def desktop_fragment?
|
|
202
|
+
user_agent =~ build_regex('Desktop (x(?:32|64)|WOW64);')
|
|
203
|
+
end
|
|
204
|
+
|
|
178
205
|
def touch_enabled?
|
|
179
206
|
user_agent =~ build_regex('Touch')
|
|
180
207
|
end
|
|
@@ -187,9 +214,26 @@ class DeviceDetector
|
|
|
187
214
|
user_agent =~ build_regex('Opera Tablet')
|
|
188
215
|
end
|
|
189
216
|
|
|
217
|
+
def tizen_samsung_tv?
|
|
218
|
+
user_agent =~ build_regex('SmartTV|Tizen.+ TV .+$')
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
def uses_mobile_browser?
|
|
222
|
+
client.browser? && client.mobile_only_browser?
|
|
223
|
+
end
|
|
224
|
+
|
|
190
225
|
# This is a workaround until we support detecting mobile only browsers
|
|
191
|
-
def
|
|
192
|
-
|
|
226
|
+
def desktop_string?
|
|
227
|
+
user_agent =~ /Desktop/
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
def desktop?
|
|
231
|
+
return false if os_name.nil? || os_name == '' || os_name == 'UNK'
|
|
232
|
+
|
|
233
|
+
# Check for browsers available for mobile devices only
|
|
234
|
+
return false if uses_mobile_browser?
|
|
235
|
+
|
|
236
|
+
os.desktop?
|
|
193
237
|
end
|
|
194
238
|
|
|
195
239
|
def build_regex(src)
|