device_detector 1.0.3 → 1.0.7
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 +5 -5
- data/CHANGELOG.md +15 -0
- data/README.md +8 -7
- data/lib/device_detector/bot.rb +2 -2
- data/lib/device_detector/browser.rb +364 -0
- data/lib/device_detector/client.rb +11 -2
- data/lib/device_detector/device.rb +1247 -22
- data/lib/device_detector/memory_cache.rb +5 -5
- data/lib/device_detector/metadata_extractor.rb +7 -8
- data/lib/device_detector/model_extractor.rb +3 -3
- data/lib/device_detector/name_extractor.rb +2 -2
- data/lib/device_detector/os.rb +150 -116
- data/lib/device_detector/parser.rb +23 -10
- data/lib/device_detector/version.rb +1 -1
- data/lib/device_detector/version_extractor.rb +29 -2
- data/lib/device_detector.rb +73 -40
- data/regexes/bots.yml +868 -62
- data/regexes/client/browser_engine.yml +11 -2
- data/regexes/client/browsers.yml +1132 -112
- data/regexes/client/feed_readers.yml +5 -11
- data/regexes/client/libraries.yml +86 -2
- data/regexes/client/mediaplayers.yml +39 -3
- data/regexes/client/mobile_apps.yml +940 -66
- data/regexes/client/pim.yml +66 -3
- data/regexes/device/cameras.yml +6 -6
- data/regexes/device/car_browsers.yml +23 -3
- data/regexes/device/consoles.yml +15 -3
- data/regexes/device/mobiles.yml +18351 -3566
- data/regexes/device/notebooks.yml +114 -0
- data/regexes/device/portable_media_player.yml +36 -9
- data/regexes/device/shell_tv.yml +117 -0
- data/regexes/device/televisions.yml +440 -35
- data/regexes/oss.yml +635 -284
- data/regexes/vendorfragments.yml +5 -1
- metadata +21 -118
- data/.gitignore +0 -14
- data/.travis.yml +0 -14
- data/Gemfile +0 -8
- data/Rakefile +0 -96
- data/device_detector.gemspec +0 -26
- data/spec/device_detector/bot_fixtures_spec.rb +0 -30
- data/spec/device_detector/client_fixtures_spec.rb +0 -31
- data/spec/device_detector/concrete_user_agent_spec.rb +0 -135
- data/spec/device_detector/detector_fixtures_spec.rb +0 -100
- data/spec/device_detector/device_fixtures_spec.rb +0 -36
- data/spec/device_detector/device_spec.rb +0 -151
- data/spec/device_detector/memory_cache_spec.rb +0 -148
- data/spec/device_detector/model_extractor_spec.rb +0 -63
- data/spec/device_detector/os_fixtures_spec.rb +0 -26
- data/spec/device_detector/version_extractor_spec.rb +0 -79
- data/spec/device_detector_spec.rb +0 -189
- data/spec/fixtures/client/browser.yml +0 -2206
- data/spec/fixtures/client/feed_reader.yml +0 -199
- data/spec/fixtures/client/library.yml +0 -175
- data/spec/fixtures/client/mediaplayer.yml +0 -163
- data/spec/fixtures/client/mobile_app.yml +0 -193
- data/spec/fixtures/client/pim.yml +0 -115
- data/spec/fixtures/detector/bots.yml +0 -3260
- data/spec/fixtures/detector/camera.yml +0 -121
- data/spec/fixtures/detector/car_browser.yml +0 -21
- data/spec/fixtures/detector/console.yml +0 -281
- data/spec/fixtures/detector/desktop.yml +0 -5361
- data/spec/fixtures/detector/feature_phone.yml +0 -891
- data/spec/fixtures/detector/feed_reader.yml +0 -551
- data/spec/fixtures/detector/mediaplayer.yml +0 -210
- data/spec/fixtures/detector/mobile_apps.yml +0 -456
- data/spec/fixtures/detector/phablet.yml +0 -3785
- data/spec/fixtures/detector/portable_media_player.yml +0 -178
- data/spec/fixtures/detector/smart_display.yml +0 -61
- data/spec/fixtures/detector/smartphone-1.yml +0 -9953
- data/spec/fixtures/detector/smartphone-10.yml +0 -9924
- data/spec/fixtures/detector/smartphone-11.yml +0 -9889
- data/spec/fixtures/detector/smartphone-12.yml +0 -8655
- data/spec/fixtures/detector/smartphone-2.yml +0 -9967
- data/spec/fixtures/detector/smartphone-3.yml +0 -9887
- data/spec/fixtures/detector/smartphone-4.yml +0 -9911
- data/spec/fixtures/detector/smartphone-5.yml +0 -9933
- data/spec/fixtures/detector/smartphone-6.yml +0 -9923
- data/spec/fixtures/detector/smartphone-7.yml +0 -9892
- data/spec/fixtures/detector/smartphone-8.yml +0 -9896
- data/spec/fixtures/detector/smartphone-9.yml +0 -9928
- data/spec/fixtures/detector/smartphone.yml +0 -9984
- data/spec/fixtures/detector/tablet-1.yml +0 -10023
- data/spec/fixtures/detector/tablet-2.yml +0 -9968
- data/spec/fixtures/detector/tablet-3.yml +0 -7787
- data/spec/fixtures/detector/tablet.yml +0 -9951
- data/spec/fixtures/detector/tv.yml +0 -3333
- data/spec/fixtures/detector/unknown.yml +0 -3283
- data/spec/fixtures/device/camera.yml +0 -19
- data/spec/fixtures/device/car_browser.yml +0 -7
- data/spec/fixtures/device/console.yml +0 -79
- data/spec/fixtures/parser/oss.yml +0 -1047
- data/spec/fixtures/parser/vendorfragments.yml +0 -162
- data/spec/spec_helper.rb +0 -9
data/lib/device_detector.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'yaml'
|
2
4
|
|
3
5
|
require 'device_detector/version'
|
@@ -11,9 +13,9 @@ require 'device_detector/bot'
|
|
11
13
|
require 'device_detector/client'
|
12
14
|
require 'device_detector/device'
|
13
15
|
require 'device_detector/os'
|
16
|
+
require 'device_detector/browser'
|
14
17
|
|
15
18
|
class DeviceDetector
|
16
|
-
|
17
19
|
attr_reader :user_agent
|
18
20
|
|
19
21
|
def initialize(user_agent)
|
@@ -45,7 +47,10 @@ class DeviceDetector
|
|
45
47
|
end
|
46
48
|
|
47
49
|
def device_brand
|
48
|
-
|
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
|
49
54
|
end
|
50
55
|
|
51
56
|
def device_type
|
@@ -54,21 +59,24 @@ class DeviceDetector
|
|
54
59
|
# Chrome on Android passes the device type based on the keyword 'Mobile'
|
55
60
|
# If it is present the device should be a smartphone, otherwise it's a tablet
|
56
61
|
# See https://developer.chrome.com/multidevice/user-agent#chrome_for_android_user_agent
|
57
|
-
|
58
|
-
|
62
|
+
# Note: We do not check for browser (family) here, as there might be mobile apps using Chrome,
|
63
|
+
# that won't have a detected browser, but can still be detected. So we check the useragent for
|
64
|
+
# Chrome instead.
|
65
|
+
if t.nil? && os.family == 'Android' && user_agent =~ build_regex('Chrome\/[\.0-9]*')
|
66
|
+
if user_agent =~ build_regex('(?:Mobile|eliboM) Safari\/')
|
59
67
|
t = 'smartphone'
|
60
|
-
elsif user_agent =~ build_regex('
|
68
|
+
elsif user_agent =~ build_regex('(?!Mobile )Safari\/')
|
61
69
|
t = 'tablet'
|
62
70
|
end
|
63
71
|
end
|
64
72
|
|
65
|
-
|
66
|
-
|
67
|
-
|
73
|
+
# Some UA contain the fragment 'Android; Tablet;' or 'Opera Tablet', so we assume those devices
|
74
|
+
# as tablets
|
75
|
+
t = 'tablet' if t.nil? && android_tablet_fragment? || opera_tablet?
|
68
76
|
|
69
|
-
|
70
|
-
|
71
|
-
|
77
|
+
# Some user agents simply contain the fragment 'Android; Mobile;', so we assume those devices
|
78
|
+
# as smartphones
|
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,
|
74
82
|
# which was tablet only, was published too late, there were a
|
@@ -78,46 +86,53 @@ 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
|
88
98
|
|
89
99
|
# All detected feature phones running android are more likely a smartphone
|
90
|
-
if t == 'feature phone' && os.family == 'Android'
|
91
|
-
|
92
|
-
|
100
|
+
t = 'smartphone' if t == 'feature phone' && os.family == 'Android'
|
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'
|
93
104
|
|
94
105
|
# According to http://msdn.microsoft.com/en-us/library/ie/hh920767(v=vs.85).aspx
|
95
|
-
# Internet Explorer 10 introduces the "Touch" UA string token. If this token is present at the
|
96
|
-
# UA string, the computer has touch capability, and is running Windows 8 (or later).
|
106
|
+
# Internet Explorer 10 introduces the "Touch" UA string token. If this token is present at the
|
107
|
+
# end of the UA string, the computer has touch capability, and is running Windows 8 (or later).
|
97
108
|
# This UA string will be transmitted on a touch-enabled system running Windows 8 (RT)
|
98
109
|
#
|
99
|
-
# As most touch enabled devices are tablets and only a smaller part are desktops/notebooks we
|
100
|
-
# all Windows 8 touch devices are tablets.
|
110
|
+
# As most touch enabled devices are tablets and only a smaller part are desktops/notebooks we
|
111
|
+
# assume that all Windows 8 touch devices are tablets.
|
101
112
|
if t.nil? && touch_enabled? &&
|
102
|
-
(
|
113
|
+
(os_name == 'Windows RT' ||
|
114
|
+
(os_name == 'Windows' && os.full_version &&
|
115
|
+
Gem::Version.new(os.full_version) >= VersionExtractor::MAJOR_VERSION_8))
|
103
116
|
t = 'tablet'
|
104
117
|
end
|
105
118
|
|
106
|
-
|
107
|
-
|
108
|
-
end
|
119
|
+
# All devices running Opera TV Store are assumed to be a tv
|
120
|
+
t = 'tv' if opera_tv_store?
|
109
121
|
|
110
|
-
|
111
|
-
|
112
|
-
end
|
122
|
+
# All devices running Tizen TV or SmartTV are assumed to be a tv
|
123
|
+
t = 'tv' if t.nil? && tizen_samsung_tv?
|
113
124
|
|
114
|
-
#
|
115
|
-
|
116
|
-
if t.nil? && os.desktop? && !puffin_browser?
|
117
|
-
t = 'desktop'
|
118
|
-
end
|
125
|
+
# 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)
|
119
127
|
|
120
|
-
t
|
128
|
+
has_desktop = t != 'desktop' && desktop_string? && desktop_fragment?
|
129
|
+
t = 'desktop' if has_desktop
|
130
|
+
|
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'
|
121
136
|
end
|
122
137
|
|
123
138
|
def known?
|
@@ -133,7 +148,6 @@ class DeviceDetector
|
|
133
148
|
end
|
134
149
|
|
135
150
|
class << self
|
136
|
-
|
137
151
|
class Configuration
|
138
152
|
attr_accessor :max_cache_keys
|
139
153
|
|
@@ -152,11 +166,10 @@ class DeviceDetector
|
|
152
166
|
@cache ||= MemoryCache.new(config.to_hash)
|
153
167
|
end
|
154
168
|
|
155
|
-
def configure
|
169
|
+
def configure
|
156
170
|
@config = Configuration.new
|
157
171
|
yield(config)
|
158
172
|
end
|
159
|
-
|
160
173
|
end
|
161
174
|
|
162
175
|
private
|
@@ -185,6 +198,10 @@ class DeviceDetector
|
|
185
198
|
user_agent =~ build_regex('Android(?: \d.\d(?:.\d)?)?; Mobile;')
|
186
199
|
end
|
187
200
|
|
201
|
+
def desktop_fragment?
|
202
|
+
user_agent =~ build_regex('Desktop (x(?:32|64)|WOW64);')
|
203
|
+
end
|
204
|
+
|
188
205
|
def touch_enabled?
|
189
206
|
user_agent =~ build_regex('Touch')
|
190
207
|
end
|
@@ -197,13 +214,29 @@ class DeviceDetector
|
|
197
214
|
user_agent =~ build_regex('Opera Tablet')
|
198
215
|
end
|
199
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
|
+
|
200
225
|
# This is a workaround until we support detecting mobile only browsers
|
201
|
-
def
|
202
|
-
|
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?
|
203
237
|
end
|
204
238
|
|
205
239
|
def build_regex(src)
|
206
240
|
Regexp.new('(?:^|[^A-Z0-9\_\-])(?:' + src + ')', Regexp::IGNORECASE)
|
207
241
|
end
|
208
|
-
|
209
242
|
end
|