browser 4.0.0 → 5.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/tests.yml +57 -0
- data/.prettierignore +1 -0
- data/.rubocop.yml +6 -0
- data/CHANGELOG.md +51 -1
- data/FUNDING.yml +3 -0
- data/README.md +97 -61
- data/bots.yml +300 -296
- data/browser.gemspec +4 -2
- data/lib/browser/accept_language.rb +4 -4
- data/lib/browser/alipay.rb +1 -1
- data/lib/browser/base.rb +76 -12
- data/lib/browser/blackberry.rb +1 -1
- data/lib/browser/bot/keyword_matcher.rb +1 -1
- data/lib/browser/browser.rb +24 -3
- data/lib/browser/chrome.rb +10 -3
- data/lib/browser/device.rb +12 -5
- data/lib/browser/device/android.rb +1 -1
- data/lib/browser/device/blackberry_playbook.rb +1 -1
- data/lib/browser/device/ipad.rb +1 -1
- data/lib/browser/device/iphone.rb +1 -1
- data/lib/browser/device/ipod_touch.rb +1 -1
- data/lib/browser/device/kindle.rb +1 -1
- data/lib/browser/device/kindle_fire.rb +1 -1
- data/lib/browser/device/playstation3.rb +1 -1
- data/lib/browser/device/playstation4.rb +1 -1
- data/lib/browser/device/psp.rb +1 -1
- data/lib/browser/device/psvita.rb +1 -1
- data/lib/browser/device/samsung.rb +33 -0
- data/lib/browser/device/surface.rb +1 -1
- data/lib/browser/device/switch.rb +1 -1
- data/lib/browser/device/tv.rb +1 -1
- data/lib/browser/device/unknown.rb +1 -1
- data/lib/browser/device/wii.rb +1 -1
- data/lib/browser/device/wiiu.rb +1 -1
- data/lib/browser/device/xbox_360.rb +1 -1
- data/lib/browser/device/xbox_one.rb +1 -1
- data/lib/browser/duck_duck_go.rb +1 -1
- data/lib/browser/edge.rb +3 -3
- data/lib/browser/electron.rb +1 -1
- data/lib/browser/facebook.rb +1 -1
- data/lib/browser/firefox.rb +1 -1
- data/lib/browser/google_search_app.rb +21 -0
- data/lib/browser/huawei_browser.rb +21 -0
- data/lib/browser/instagram.rb +1 -1
- data/lib/browser/internet_explorer.rb +2 -2
- data/lib/browser/maxthon.rb +21 -0
- data/lib/browser/micro_messenger.rb +1 -1
- data/lib/browser/miui_browser.rb +21 -0
- data/lib/browser/nokia.rb +1 -1
- data/lib/browser/opera.rb +1 -1
- data/lib/browser/otter.rb +1 -1
- data/lib/browser/phantom_js.rb +1 -1
- data/lib/browser/platform.rb +21 -15
- data/lib/browser/platform/adobe_air.rb +1 -1
- data/lib/browser/platform/android.rb +1 -1
- data/lib/browser/platform/blackberry.rb +1 -1
- data/lib/browser/platform/chrome_os.rb +1 -1
- data/lib/browser/platform/firefox_os.rb +1 -1
- data/lib/browser/platform/ios.rb +2 -2
- data/lib/browser/platform/kai_os.rb +23 -0
- data/lib/browser/platform/linux.rb +1 -1
- data/lib/browser/platform/mac.rb +2 -2
- data/lib/browser/platform/{other.rb → unknown.rb} +3 -3
- data/lib/browser/platform/windows.rb +2 -2
- data/lib/browser/platform/windows_mobile.rb +1 -1
- data/lib/browser/platform/windows_phone.rb +1 -1
- data/lib/browser/qq.rb +1 -1
- data/lib/browser/safari.rb +12 -3
- data/lib/browser/samsung_browser.rb +21 -0
- data/lib/browser/snapchat.rb +1 -1
- data/lib/browser/sougou_browser.rb +24 -0
- data/lib/browser/sputnik.rb +1 -1
- data/lib/browser/uc_browser.rb +1 -1
- data/lib/browser/{generic.rb → unknown.rb} +3 -3
- data/lib/browser/version.rb +1 -1
- data/lib/browser/weibo.rb +1 -1
- data/lib/browser/yandex.rb +1 -1
- data/samsung.yml +138 -0
- data/test/browser_test.rb +37 -6
- data/test/ua.yml +20 -2
- data/test/ua_bots.yml +7 -3
- data/test/unit/adobe_air_test.rb +1 -1
- data/test/unit/alipay_test.rb +6 -0
- data/test/unit/bots_test.rb +1 -1
- data/test/unit/console_test.rb +2 -2
- data/test/unit/device_test.rb +30 -3
- data/test/unit/duck_duck_go_test.rb +2 -0
- data/test/unit/edge_test.rb +34 -2
- data/test/unit/google_search_app_test.rb +54 -0
- data/test/unit/huawei_browser_test.rb +25 -0
- data/test/unit/kai_os_test.rb +31 -0
- data/test/unit/maxthon_test.rb +25 -0
- data/test/unit/meta_test.rb +10 -1
- data/test/unit/micro_messenger_test.rb +21 -6
- data/test/unit/miui_browser_test.rb +25 -0
- data/test/unit/opera_test.rb +1 -0
- data/test/unit/platform_test.rb +7 -7
- data/test/unit/qq_test.rb +12 -0
- data/test/unit/safari_test.rb +12 -7
- data/test/unit/samsung_browser_test.rb +23 -0
- data/test/unit/sougou_browser_test.rb +41 -0
- metadata +41 -15
- data/.travis.yml +0 -23
data/browser.gemspec
CHANGED
@@ -8,11 +8,13 @@ Gem::Specification.new do |s|
|
|
8
8
|
s.platform = Gem::Platform::RUBY
|
9
9
|
s.authors = ["Nando Vieira"]
|
10
10
|
s.email = ["fnando.vieira@gmail.com"]
|
11
|
-
s.homepage = "
|
11
|
+
s.homepage = "https://github.com/fnando/browser"
|
12
12
|
s.summary = "Do some browser detection with Ruby."
|
13
13
|
s.description = s.summary
|
14
14
|
s.license = "MIT"
|
15
15
|
|
16
|
+
s.metadata["changelog_uri"] = "https://github.com/fnando/browser/blob/main/CHANGELOG.md"
|
17
|
+
|
16
18
|
s.files = `git ls-files`.split("\n")
|
17
19
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
20
|
s.executables = `git ls-files -- exe/*`
|
@@ -29,6 +31,6 @@ Gem::Specification.new do |s|
|
|
29
31
|
s.add_development_dependency "rails"
|
30
32
|
s.add_development_dependency "rake"
|
31
33
|
s.add_development_dependency "rubocop"
|
32
|
-
s.add_development_dependency "rubocop-fnando"
|
34
|
+
s.add_development_dependency "rubocop-fnando"
|
33
35
|
s.add_development_dependency "simplecov"
|
34
36
|
end
|
@@ -48,15 +48,15 @@ module Browser
|
|
48
48
|
def quality
|
49
49
|
@quality ||= begin
|
50
50
|
Float(quality_value || 1.0)
|
51
|
-
|
52
|
-
|
51
|
+
rescue ArgumentError
|
52
|
+
0.1
|
53
53
|
end
|
54
54
|
end
|
55
55
|
|
56
56
|
private def quality_value
|
57
57
|
qvalue = part[/;q=([\d.]+)/, 1]
|
58
|
-
qvalue =
|
59
|
-
qvalue = qvalue.
|
58
|
+
qvalue = /\A0\.0?\z/.match?(qvalue) ? "0.0" : qvalue
|
59
|
+
qvalue = qvalue.squeeze(".") if qvalue
|
60
60
|
qvalue
|
61
61
|
end
|
62
62
|
end
|
data/lib/browser/alipay.rb
CHANGED
data/lib/browser/base.rb
CHANGED
@@ -6,12 +6,11 @@ module Browser
|
|
6
6
|
|
7
7
|
attr_reader :ua
|
8
8
|
|
9
|
-
# Return an array with all preferred languages that this browser accepts.
|
10
|
-
attr_reader :accept_language
|
11
|
-
|
12
9
|
def initialize(ua, accept_language: nil)
|
10
|
+
validate_size(:user_agent, ua.to_s)
|
11
|
+
|
13
12
|
@ua = ua
|
14
|
-
@
|
13
|
+
@accept_language_raw = accept_language.to_s
|
15
14
|
end
|
16
15
|
|
17
16
|
# Return a meta info about this browser.
|
@@ -19,6 +18,14 @@ module Browser
|
|
19
18
|
Meta.get(self)
|
20
19
|
end
|
21
20
|
|
21
|
+
# Return an array with all preferred languages that this browser accepts.
|
22
|
+
def accept_language
|
23
|
+
@accept_language ||= begin
|
24
|
+
validate_size(:accept_language, @accept_language_raw)
|
25
|
+
AcceptLanguage.parse(@accept_language_raw)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
22
29
|
alias_method :to_a, :meta
|
23
30
|
|
24
31
|
# Return meta representation as string.
|
@@ -99,19 +106,20 @@ module Browser
|
|
99
106
|
|
100
107
|
# Detect if browser is WebKit-based.
|
101
108
|
def webkit?(expected_version = nil)
|
102
|
-
ua
|
109
|
+
ua.match?(/AppleWebKit/i) &&
|
103
110
|
(!edge? || Edge.new(ua).chrome_based?) &&
|
104
111
|
detect_version?(webkit_full_version, expected_version)
|
105
112
|
end
|
106
113
|
|
107
114
|
# Detect if browser is QuickTime
|
108
115
|
def quicktime?(expected_version = nil)
|
109
|
-
ua
|
116
|
+
ua.match?(/QuickTime/i) && detect_version?(full_version, expected_version)
|
110
117
|
end
|
111
118
|
|
112
119
|
# Detect if browser is Apple CoreMedia.
|
113
120
|
def core_media?(expected_version = nil)
|
114
|
-
ua
|
121
|
+
ua.include?("CoreMedia") && detect_version?(full_version,
|
122
|
+
expected_version)
|
115
123
|
end
|
116
124
|
|
117
125
|
# Detect if browser is PhantomJS
|
@@ -122,11 +130,11 @@ module Browser
|
|
122
130
|
|
123
131
|
# Detect if browser is Safari.
|
124
132
|
def safari?(expected_version = nil)
|
125
|
-
Safari.new(ua).match? && detect_version?(
|
133
|
+
Safari.new(ua).match? && detect_version?(full_version, expected_version)
|
126
134
|
end
|
127
135
|
|
128
136
|
def safari_webapp_mode?
|
129
|
-
(device.ipad? || device.iphone?) && ua
|
137
|
+
(device.ipad? || device.iphone?) && ua.include?("AppleWebKit")
|
130
138
|
end
|
131
139
|
|
132
140
|
# Detect if browser is Firefox.
|
@@ -184,12 +192,53 @@ module Browser
|
|
184
192
|
|
185
193
|
# Detect if browser is Opera Mini.
|
186
194
|
def opera_mini?(expected_version = nil)
|
187
|
-
ua
|
195
|
+
ua.include?("Opera Mini") && detect_version?(full_version,
|
196
|
+
expected_version)
|
188
197
|
end
|
189
198
|
|
190
199
|
# Detect if browser is DuckDuckGo.
|
191
200
|
def duck_duck_go?(expected_version = nil)
|
192
|
-
ua
|
201
|
+
ua.include?("DuckDuckGo") && detect_version?(full_version,
|
202
|
+
expected_version)
|
203
|
+
end
|
204
|
+
|
205
|
+
# Detect if browser is Samsung.
|
206
|
+
def samsung_browser?(expected_version = nil)
|
207
|
+
ua.include?("SamsungBrowser") && detect_version?(full_version,
|
208
|
+
expected_version)
|
209
|
+
end
|
210
|
+
|
211
|
+
# Detect if browser is Huawei.
|
212
|
+
def huawei_browser?(expected_version = nil)
|
213
|
+
HuaweiBrowser.new(ua).match? &&
|
214
|
+
detect_version?(full_version, expected_version)
|
215
|
+
end
|
216
|
+
|
217
|
+
# Detect if browser is Xiaomi Miui.
|
218
|
+
def miui_browser?(expected_version = nil)
|
219
|
+
MiuiBrowser.new(ua).match? &&
|
220
|
+
detect_version?(full_version, expected_version)
|
221
|
+
end
|
222
|
+
|
223
|
+
# Detect if browser is Maxthon.
|
224
|
+
def maxthon?(expected_version = nil)
|
225
|
+
Maxthon.new(ua).match? && detect_version?(full_version, expected_version)
|
226
|
+
end
|
227
|
+
|
228
|
+
# Detect if browser is QQ.
|
229
|
+
def qq?(expected_version = nil)
|
230
|
+
QQ.new(ua).match? && detect_version?(full_version, expected_version)
|
231
|
+
end
|
232
|
+
|
233
|
+
# Detect if browser is Sougou.
|
234
|
+
def sougou_browser?(expected_version = nil)
|
235
|
+
SougouBrowser.new(ua).match? &&
|
236
|
+
detect_version?(full_version, expected_version)
|
237
|
+
end
|
238
|
+
|
239
|
+
# Detect if browser is Google Search App
|
240
|
+
def google_search_app?(expected_version = nil)
|
241
|
+
ua.include?("GSA") && detect_version?(full_version, expected_version)
|
193
242
|
end
|
194
243
|
|
195
244
|
def webkit_full_version
|
@@ -197,7 +246,11 @@ module Browser
|
|
197
246
|
end
|
198
247
|
|
199
248
|
def known?
|
200
|
-
|
249
|
+
!unknown?
|
250
|
+
end
|
251
|
+
|
252
|
+
def unknown?
|
253
|
+
id == :unknown_browser
|
201
254
|
end
|
202
255
|
|
203
256
|
# Detect if browser is a proxy browser.
|
@@ -209,5 +262,16 @@ module Browser
|
|
209
262
|
def electron?(expected_version = nil)
|
210
263
|
Electron.new(ua).match? && detect_version?(full_version, expected_version)
|
211
264
|
end
|
265
|
+
|
266
|
+
private def validate_size(subject, input)
|
267
|
+
actual_bytesize = input.bytesize
|
268
|
+
size_limit = Browser.public_send("#{subject}_size_limit")
|
269
|
+
|
270
|
+
return if actual_bytesize < size_limit
|
271
|
+
|
272
|
+
raise Error,
|
273
|
+
"#{subject} cannot be larger than #{size_limit} bytes; " \
|
274
|
+
"actual size is #{actual_bytesize} bytes"
|
275
|
+
end
|
212
276
|
end
|
213
277
|
end
|
data/lib/browser/blackberry.rb
CHANGED
data/lib/browser/browser.rb
CHANGED
@@ -15,7 +15,7 @@ require_relative "firefox"
|
|
15
15
|
require_relative "edge"
|
16
16
|
require_relative "opera"
|
17
17
|
require_relative "blackberry"
|
18
|
-
require_relative "
|
18
|
+
require_relative "unknown"
|
19
19
|
require_relative "phantom_js"
|
20
20
|
require_relative "uc_browser"
|
21
21
|
require_relative "nokia"
|
@@ -31,6 +31,12 @@ require_relative "yandex"
|
|
31
31
|
require_relative "sputnik"
|
32
32
|
require_relative "snapchat"
|
33
33
|
require_relative "duck_duck_go"
|
34
|
+
require_relative "samsung_browser"
|
35
|
+
require_relative "huawei_browser"
|
36
|
+
require_relative "miui_browser"
|
37
|
+
require_relative "maxthon"
|
38
|
+
require_relative "sougou_browser"
|
39
|
+
require_relative "google_search_app"
|
34
40
|
|
35
41
|
require_relative "bot"
|
36
42
|
require_relative "bot/empty_user_agent_matcher"
|
@@ -45,10 +51,19 @@ require_relative "meta"
|
|
45
51
|
module Browser
|
46
52
|
EMPTY_STRING = ""
|
47
53
|
|
54
|
+
Error = Class.new(StandardError)
|
55
|
+
|
48
56
|
def self.root
|
49
57
|
@root ||= Pathname.new(File.expand_path("../..", __dir__))
|
50
58
|
end
|
51
59
|
|
60
|
+
class << self
|
61
|
+
attr_accessor :user_agent_size_limit, :accept_language_size_limit
|
62
|
+
end
|
63
|
+
|
64
|
+
self.user_agent_size_limit = 2048
|
65
|
+
self.accept_language_size_limit = 2048
|
66
|
+
|
52
67
|
# Hold the list of browser matchers.
|
53
68
|
# Order is important.
|
54
69
|
def self.matchers
|
@@ -66,16 +81,22 @@ module Browser
|
|
66
81
|
Instagram, # must be placed before Chrome and Safari
|
67
82
|
Snapchat, # must be placed before Chrome and Safari
|
68
83
|
Weibo, # must be placed before Chrome and Safari
|
84
|
+
MicroMessenger, # must be placed before QQ
|
69
85
|
QQ, # must be placed before Chrome and Safari
|
70
86
|
Alipay, # must be placed before Chrome and Safari
|
71
87
|
Electron, # must be placed before Chrome and Safari
|
72
88
|
Yandex, # must be placed before Chrome and Safari
|
73
89
|
Sputnik, # must be placed before Chrome and Safari
|
74
90
|
DuckDuckGo, # must be placed before Chrome and Safari
|
91
|
+
SamsungBrowser, # must be placed before Chrome and Safari
|
92
|
+
HuaweiBrowser, # must be placed before Chrome and Safari
|
93
|
+
MiuiBrowser, # must be placed before Chrome and Safari
|
94
|
+
Maxthon, # must be placed before Chrome and Safari
|
95
|
+
SougouBrowser, # must be placed before Chrome and Safari
|
96
|
+
GoogleSearchApp, # must be placed before Chrome and Safari
|
75
97
|
Chrome,
|
76
98
|
Safari,
|
77
|
-
|
78
|
-
Generic
|
99
|
+
Unknown
|
79
100
|
]
|
80
101
|
end
|
81
102
|
|
data/lib/browser/chrome.rb
CHANGED
@@ -20,13 +20,20 @@ module Browser
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def match?
|
23
|
-
ua
|
24
|
-
ua
|
23
|
+
ua.match?(/Chrome|CriOS/) &&
|
24
|
+
!ua.match?(/PhantomJS|FxiOS|ArchiveBot/) &&
|
25
25
|
!opera? &&
|
26
26
|
!edge? &&
|
27
27
|
!duck_duck_go? &&
|
28
28
|
!yandex? &&
|
29
|
-
!sputnik?
|
29
|
+
!sputnik? &&
|
30
|
+
!samsung_browser? &&
|
31
|
+
!huawei_browser? &&
|
32
|
+
!miui_browser? &&
|
33
|
+
!maxthon? &&
|
34
|
+
!qq? &&
|
35
|
+
!sougou_browser? &&
|
36
|
+
!google_search_app?
|
30
37
|
end
|
31
38
|
end
|
32
39
|
end
|
data/lib/browser/device.rb
CHANGED
@@ -20,6 +20,7 @@ require_relative "device/switch"
|
|
20
20
|
require_relative "device/tv"
|
21
21
|
require_relative "device/xbox_one"
|
22
22
|
require_relative "device/xbox_360"
|
23
|
+
require_relative "device/samsung"
|
23
24
|
|
24
25
|
module Browser
|
25
26
|
class Device
|
@@ -29,6 +30,7 @@ module Browser
|
|
29
30
|
# Order is important.
|
30
31
|
def self.matchers
|
31
32
|
@matchers ||= [
|
33
|
+
Samsung,
|
32
34
|
XboxOne,
|
33
35
|
Xbox360,
|
34
36
|
Surface,
|
@@ -88,7 +90,7 @@ module Browser
|
|
88
90
|
end
|
89
91
|
|
90
92
|
def unknown?
|
91
|
-
id == :
|
93
|
+
id == :unknown_device
|
92
94
|
end
|
93
95
|
|
94
96
|
def ipod_touch?
|
@@ -158,12 +160,12 @@ module Browser
|
|
158
160
|
|
159
161
|
# Detect if browser is Silk.
|
160
162
|
def silk?
|
161
|
-
ua
|
163
|
+
ua.include?("Silk")
|
162
164
|
end
|
163
165
|
|
164
166
|
# Detect if browser is running under Xbox.
|
165
167
|
def xbox?
|
166
|
-
ua
|
168
|
+
ua.include?("Xbox")
|
167
169
|
end
|
168
170
|
|
169
171
|
# Detect if browser is running under Xbox 360.
|
@@ -191,13 +193,18 @@ module Browser
|
|
191
193
|
xbox? || playstation? || nintendo?
|
192
194
|
end
|
193
195
|
|
196
|
+
# Detect if device is a Samsung.
|
197
|
+
def samsung?
|
198
|
+
id == :samsung
|
199
|
+
end
|
200
|
+
|
194
201
|
# Regex taken from http://detectmobilebrowsers.com
|
195
202
|
# rubocop:disable Layout/LineLength
|
196
203
|
private def detect_mobile?
|
197
204
|
psp? ||
|
198
|
-
/zunewp7/i.match(ua) ||
|
205
|
+
/zunewp7/i.match?(ua) ||
|
199
206
|
%r{(android|bb\d+|meego).+mobile|avantgo|bada/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino}i.match(ua) ||
|
200
|
-
%r{1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s
|
207
|
+
%r{1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw-(n|u)|c55/|capi|ccwa|cdm-|cell|chtm|cldc|cmd-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc-s|devi|dica|dmob|do(c|p)o|ds(12|-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(-|_)|g1 u|g560|gene|gf-5|g-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd-(m|p|t)|hei-|hi(pt|ta)|hp( i|ip)|hs-c|ht(c(-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i-(20|go|ma)|i230|iac( |-|/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |/)|klon|kpt |kwc-|kyo(c|k)|le(no|xi)|lg( g|/(k|l|u)|50|54|-[a-w])|libw|lynx|m1-w|m3ga|m50/|ma(te|ui|xo)|mc(01|21|ca)|m-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|-([1-8]|c))|phil|pire|pl(ay|uc)|pn-2|po(ck|rt|se)|prox|psio|pt-g|qa-a|qc(07|12|21|32|60|-[2-7]|i-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55/|sa(ge|ma|mm|ms|ny|va)|sc(01|h-|oo|p-)|sdk/|se(c(-|0|1)|47|mc|nd|ri)|sgh-|shar|sie(-|m)|sk-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h-|v-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl-|tdg-|tel(i|m)|tim-|t-mo|to(pl|sh)|ts(70|m-|m3|m5)|tx-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas-|your|zeto|zte-}i.match?(ua[0..3])
|
201
208
|
end
|
202
209
|
# rubocop:enable Layout/LineLength
|
203
210
|
|
data/lib/browser/device/ipad.rb
CHANGED