browser 3.0.2 → 5.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/ISSUE_TEMPLATE.md +1 -1
- data/.prettierignore +1 -0
- data/.rubocop.yml +9 -0
- data/.travis.yml +3 -3
- data/CHANGELOG.md +81 -18
- data/FUNDING.yml +3 -0
- data/README.md +113 -88
- data/bots.yml +300 -294
- data/browser.gemspec +3 -1
- data/lib/browser/base.rb +63 -7
- data/lib/browser/browser.rb +27 -26
- data/lib/browser/chrome.rb +12 -2
- data/lib/browser/device.rb +2 -2
- data/lib/browser/device/unknown.rb +1 -1
- data/lib/browser/duck_duck_go.rb +22 -0
- data/lib/browser/edge.rb +2 -2
- data/lib/browser/google_search_app.rb +21 -0
- data/lib/browser/huawei_browser.rb +21 -0
- data/lib/browser/maxthon.rb +21 -0
- data/lib/browser/meta.rb +0 -1
- data/lib/browser/meta/base.rb +0 -1
- data/lib/browser/miui_browser.rb +21 -0
- data/lib/browser/platform.rb +5 -5
- data/lib/browser/platform/base.rb +3 -2
- data/lib/browser/platform/ios.rb +1 -1
- data/lib/browser/platform/mac.rb +4 -2
- data/lib/browser/platform/{other.rb → unknown.rb} +3 -3
- data/lib/browser/platform/windows.rb +1 -1
- data/lib/browser/safari.rb +16 -1
- data/lib/browser/samsung_browser.rb +21 -0
- data/lib/browser/sougou_browser.rb +24 -0
- data/lib/browser/{generic.rb → unknown.rb} +3 -3
- data/lib/browser/version.rb +1 -1
- data/test/browser_test.rb +23 -6
- data/test/test_helper.rb +8 -0
- data/test/ua.yml +17 -1
- data/test/ua_bots.yml +8 -2
- data/test/unit/adobe_air_test.rb +1 -1
- data/test/unit/alipay_test.rb +6 -0
- data/test/unit/console_test.rb +2 -2
- data/test/unit/device_test.rb +2 -2
- data/test/unit/duck_duck_go_test.rb +37 -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/maxthon_test.rb +25 -0
- data/test/unit/meta_test.rb +9 -0
- 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 +12 -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 +33 -10
- data/lib/browser/meta/modern.rb +0 -11
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/master/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/*`
|
data/lib/browser/base.rb
CHANGED
@@ -10,6 +10,9 @@ module Browser
|
|
10
10
|
attr_reader :accept_language
|
11
11
|
|
12
12
|
def initialize(ua, accept_language: nil)
|
13
|
+
validate_size(:user_agent, ua.to_s)
|
14
|
+
validate_size(:accept_language, accept_language.to_s)
|
15
|
+
|
13
16
|
@ua = ua
|
14
17
|
@accept_language = AcceptLanguage.parse(accept_language)
|
15
18
|
end
|
@@ -50,11 +53,6 @@ module Browser
|
|
50
53
|
@device ||= Device.new(ua)
|
51
54
|
end
|
52
55
|
|
53
|
-
# Return true if browser is modern (Webkit, Firefox 17+, IE9+, Opera 12+).
|
54
|
-
def modern?
|
55
|
-
Browser.modern_rules.any? {|rule| rule === self } # rubocop:disable Style/CaseEquality
|
56
|
-
end
|
57
|
-
|
58
56
|
# Detect if browser is Microsoft Internet Explorer.
|
59
57
|
def ie?(expected_version = nil)
|
60
58
|
InternetExplorer.new(ua).match? &&
|
@@ -127,7 +125,7 @@ module Browser
|
|
127
125
|
|
128
126
|
# Detect if browser is Safari.
|
129
127
|
def safari?(expected_version = nil)
|
130
|
-
Safari.new(ua).match? && detect_version?(
|
128
|
+
Safari.new(ua).match? && detect_version?(full_version, expected_version)
|
131
129
|
end
|
132
130
|
|
133
131
|
def safari_webapp_mode?
|
@@ -192,12 +190,59 @@ module Browser
|
|
192
190
|
ua =~ /Opera Mini/ && detect_version?(full_version, expected_version)
|
193
191
|
end
|
194
192
|
|
193
|
+
# Detect if browser is DuckDuckGo.
|
194
|
+
def duck_duck_go?(expected_version = nil)
|
195
|
+
ua =~ /DuckDuckGo/ && detect_version?(full_version, expected_version)
|
196
|
+
end
|
197
|
+
|
198
|
+
# Detect if browser is Samsung.
|
199
|
+
def samsung_browser?(expected_version = nil)
|
200
|
+
ua =~ /SamsungBrowser/ && detect_version?(full_version, expected_version)
|
201
|
+
end
|
202
|
+
|
203
|
+
# Detect if browser is Huawei.
|
204
|
+
def huawei_browser?(expected_version = nil)
|
205
|
+
HuaweiBrowser.new(ua).match? &&
|
206
|
+
detect_version?(full_version, expected_version)
|
207
|
+
end
|
208
|
+
|
209
|
+
# Detect if browser is Xiaomi Miui.
|
210
|
+
def miui_browser?(expected_version = nil)
|
211
|
+
MiuiBrowser.new(ua).match? &&
|
212
|
+
detect_version?(full_version, expected_version)
|
213
|
+
end
|
214
|
+
|
215
|
+
# Detect if browser is Maxthon.
|
216
|
+
def maxthon?(expected_version = nil)
|
217
|
+
Maxthon.new(ua).match? && detect_version?(full_version, expected_version)
|
218
|
+
end
|
219
|
+
|
220
|
+
# Detect if browser is QQ.
|
221
|
+
def qq?(expected_version = nil)
|
222
|
+
QQ.new(ua).match? && detect_version?(full_version, expected_version)
|
223
|
+
end
|
224
|
+
|
225
|
+
# Detect if browser is Sougou.
|
226
|
+
def sougou_browser?(expected_version = nil)
|
227
|
+
SougouBrowser.new(ua).match? &&
|
228
|
+
detect_version?(full_version, expected_version)
|
229
|
+
end
|
230
|
+
|
231
|
+
# Detect if browser is Google Search App
|
232
|
+
def google_search_app?(expected_version = nil)
|
233
|
+
ua =~ /GSA/ && detect_version?(full_version, expected_version)
|
234
|
+
end
|
235
|
+
|
195
236
|
def webkit_full_version
|
196
237
|
ua[%r{AppleWebKit/([\d.]+)}, 1] || "0.0"
|
197
238
|
end
|
198
239
|
|
199
240
|
def known?
|
200
|
-
|
241
|
+
!unknown?
|
242
|
+
end
|
243
|
+
|
244
|
+
def unknown?
|
245
|
+
id == :unknown_browser
|
201
246
|
end
|
202
247
|
|
203
248
|
# Detect if browser is a proxy browser.
|
@@ -209,5 +254,16 @@ module Browser
|
|
209
254
|
def electron?(expected_version = nil)
|
210
255
|
Electron.new(ua).match? && detect_version?(full_version, expected_version)
|
211
256
|
end
|
257
|
+
|
258
|
+
private def validate_size(subject, input)
|
259
|
+
actual_bytesize = input.bytesize
|
260
|
+
size_limit = Browser.public_send("#{subject}_size_limit")
|
261
|
+
|
262
|
+
return if actual_bytesize < size_limit
|
263
|
+
|
264
|
+
raise Error,
|
265
|
+
"#{subject} cannot be larger than #{size_limit} bytes; " \
|
266
|
+
"actual size is #{actual_bytesize}"
|
267
|
+
end
|
212
268
|
end
|
213
269
|
end
|
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"
|
@@ -30,6 +30,13 @@ require_relative "instagram"
|
|
30
30
|
require_relative "yandex"
|
31
31
|
require_relative "sputnik"
|
32
32
|
require_relative "snapchat"
|
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"
|
33
40
|
|
34
41
|
require_relative "bot"
|
35
42
|
require_relative "bot/empty_user_agent_matcher"
|
@@ -44,10 +51,20 @@ require_relative "meta"
|
|
44
51
|
module Browser
|
45
52
|
EMPTY_STRING = ""
|
46
53
|
|
54
|
+
Error = Class.new(StandardError)
|
55
|
+
|
47
56
|
def self.root
|
48
57
|
@root ||= Pathname.new(File.expand_path("../..", __dir__))
|
49
58
|
end
|
50
59
|
|
60
|
+
class << self
|
61
|
+
attr_accessor :user_agent_size_limit
|
62
|
+
attr_accessor :accept_language_size_limit
|
63
|
+
end
|
64
|
+
|
65
|
+
self.user_agent_size_limit = 512
|
66
|
+
self.accept_language_size_limit = 256
|
67
|
+
|
51
68
|
# Hold the list of browser matchers.
|
52
69
|
# Order is important.
|
53
70
|
def self.matchers
|
@@ -65,41 +82,25 @@ module Browser
|
|
65
82
|
Instagram, # must be placed before Chrome and Safari
|
66
83
|
Snapchat, # must be placed before Chrome and Safari
|
67
84
|
Weibo, # must be placed before Chrome and Safari
|
85
|
+
MicroMessenger, # must be placed before QQ
|
68
86
|
QQ, # must be placed before Chrome and Safari
|
69
87
|
Alipay, # must be placed before Chrome and Safari
|
70
88
|
Electron, # must be placed before Chrome and Safari
|
71
89
|
Yandex, # must be placed before Chrome and Safari
|
72
90
|
Sputnik, # must be placed before Chrome and Safari
|
91
|
+
DuckDuckGo, # must be placed before Chrome and Safari
|
92
|
+
SamsungBrowser, # must be placed before Chrome and Safari
|
93
|
+
HuaweiBrowser, # must be placed before Chrome and Safari
|
94
|
+
MiuiBrowser, # must be placed before Chrome and Safari
|
95
|
+
Maxthon, # must be placed before Chrome and Safari
|
96
|
+
SougouBrowser, # must be placed before Chrome and Safari
|
97
|
+
GoogleSearchApp, # must be placed before Chrome and Safari
|
73
98
|
Chrome,
|
74
99
|
Safari,
|
75
|
-
|
76
|
-
Generic
|
100
|
+
Unknown
|
77
101
|
]
|
78
102
|
end
|
79
103
|
|
80
|
-
# Define the rules which define a modern browser.
|
81
|
-
# A rule must be a proc/lambda or any object that implements the method
|
82
|
-
# === and accepts the browser object.
|
83
|
-
#
|
84
|
-
# To redefine all rules, clear the existing rules before adding your own.
|
85
|
-
#
|
86
|
-
# # Only Chrome Canary is considered modern.
|
87
|
-
# Browser.modern_rules.clear
|
88
|
-
# Browser.modern_rules << -> b { b.chrome? && b.version >= "37" }
|
89
|
-
#
|
90
|
-
def self.modern_rules
|
91
|
-
@modern_rules ||= []
|
92
|
-
end
|
93
|
-
|
94
|
-
modern_rules.tap do |rules|
|
95
|
-
rules << ->(b) { b.chrome? && b.version.to_i >= 65 }
|
96
|
-
rules << ->(b) { b.safari? && b.version.to_i >= 10 }
|
97
|
-
rules << ->(b) { b.firefox? && b.version.to_i >= 52 }
|
98
|
-
rules << ->(b) { b.ie? && b.version.to_i >= 11 && !b.compatibility_view? }
|
99
|
-
rules << ->(b) { b.edge? && b.version.to_i >= 15 }
|
100
|
-
rules << ->(b) { b.opera? && b.version.to_i >= 50 }
|
101
|
-
end
|
102
|
-
|
103
104
|
def self.new(user_agent, **kwargs)
|
104
105
|
matchers
|
105
106
|
.map {|klass| klass.new(user_agent || EMPTY_STRING, **kwargs) }
|
data/lib/browser/chrome.rb
CHANGED
@@ -21,9 +21,19 @@ module Browser
|
|
21
21
|
|
22
22
|
def match?
|
23
23
|
ua =~ /Chrome|CriOS/ &&
|
24
|
-
ua !~ /PhantomJS|FxiOS|
|
24
|
+
ua !~ /PhantomJS|FxiOS|ArchiveBot/ &&
|
25
25
|
!opera? &&
|
26
|
-
!edge?
|
26
|
+
!edge? &&
|
27
|
+
!duck_duck_go? &&
|
28
|
+
!yandex? &&
|
29
|
+
!sputnik? &&
|
30
|
+
!samsung_browser? &&
|
31
|
+
!huawei_browser? &&
|
32
|
+
!miui_browser? &&
|
33
|
+
!maxthon? &&
|
34
|
+
!qq? &&
|
35
|
+
!sougou_browser? &&
|
36
|
+
!google_search_app?
|
27
37
|
end
|
28
38
|
end
|
29
39
|
end
|
data/lib/browser/device.rb
CHANGED
@@ -88,7 +88,7 @@ module Browser
|
|
88
88
|
end
|
89
89
|
|
90
90
|
def unknown?
|
91
|
-
id == :
|
91
|
+
id == :unknown_device
|
92
92
|
end
|
93
93
|
|
94
94
|
def ipod_touch?
|
@@ -197,7 +197,7 @@ module Browser
|
|
197
197
|
psp? ||
|
198
198
|
/zunewp7/i.match(ua) ||
|
199
199
|
%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
|
200
|
+
%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
201
|
end
|
202
202
|
# rubocop:enable Layout/LineLength
|
203
203
|
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Browser
|
4
|
+
class DuckDuckGo < Base
|
5
|
+
def id
|
6
|
+
:duckduckgo
|
7
|
+
end
|
8
|
+
|
9
|
+
def name
|
10
|
+
"DuckDuckGo"
|
11
|
+
end
|
12
|
+
|
13
|
+
def full_version
|
14
|
+
ua[%r{DuckDuckGo/([\d.]+)}, 1] ||
|
15
|
+
"0.0"
|
16
|
+
end
|
17
|
+
|
18
|
+
def match?
|
19
|
+
ua =~ /DuckDuckGo/
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/browser/edge.rb
CHANGED
@@ -11,11 +11,11 @@ module Browser
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def full_version
|
14
|
-
ua[%r{(?:Edge|Edg)/([\d.]+)}, 1] || super
|
14
|
+
ua[%r{(?:Edge|Edg|EdgiOS|EdgA)/([\d.]+)}, 1] || super
|
15
15
|
end
|
16
16
|
|
17
17
|
def match?
|
18
|
-
ua =~ %r{((?:Edge|Edg)/[\d.]+|Trident/8)}
|
18
|
+
ua =~ %r{((?:Edge|Edg|EdgiOS|EdgA)/[\d.]+|Trident/8)}
|
19
19
|
end
|
20
20
|
|
21
21
|
def chrome_based?
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Browser
|
4
|
+
class GoogleSearchApp < Chrome
|
5
|
+
def id
|
6
|
+
:google_search_app
|
7
|
+
end
|
8
|
+
|
9
|
+
def name
|
10
|
+
"Google Search App"
|
11
|
+
end
|
12
|
+
|
13
|
+
def full_version
|
14
|
+
ua[%r{GSA/([\d.]+\d)}, 1] || super
|
15
|
+
end
|
16
|
+
|
17
|
+
def match?
|
18
|
+
ua =~ /GSA/
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Browser
|
4
|
+
class HuaweiBrowser < Base
|
5
|
+
def id
|
6
|
+
:huawei_browser
|
7
|
+
end
|
8
|
+
|
9
|
+
def name
|
10
|
+
"Huawei Browser"
|
11
|
+
end
|
12
|
+
|
13
|
+
def full_version
|
14
|
+
ua[%r{(?:HuaweiBrowser)/([\d.]+)}i, 1] || "0.0"
|
15
|
+
end
|
16
|
+
|
17
|
+
def match?
|
18
|
+
ua =~ /HuaweiBrowser/i
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Browser
|
4
|
+
class Maxthon < Base
|
5
|
+
def id
|
6
|
+
:maxthon
|
7
|
+
end
|
8
|
+
|
9
|
+
def name
|
10
|
+
"Maxthon"
|
11
|
+
end
|
12
|
+
|
13
|
+
def full_version
|
14
|
+
ua[%r{(?:Maxthon)/([\d.]+)}i, 1] || "0.0"
|
15
|
+
end
|
16
|
+
|
17
|
+
def match?
|
18
|
+
ua =~ /Maxthon/i
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/browser/meta.rb
CHANGED
data/lib/browser/meta/base.rb
CHANGED
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Browser
|
4
|
+
class MiuiBrowser < Base
|
5
|
+
def id
|
6
|
+
:miui_browser
|
7
|
+
end
|
8
|
+
|
9
|
+
def name
|
10
|
+
"Miui Browser"
|
11
|
+
end
|
12
|
+
|
13
|
+
def full_version
|
14
|
+
ua[%r{MiuiBrowser/([\d.]+)}, 1] || "0.0"
|
15
|
+
end
|
16
|
+
|
17
|
+
def match?
|
18
|
+
ua =~ /MiuiBrowser/
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/browser/platform.rb
CHANGED
@@ -10,7 +10,7 @@ require_relative "platform/windows_mobile"
|
|
10
10
|
require_relative "platform/firefox_os"
|
11
11
|
require_relative "platform/blackberry"
|
12
12
|
require_relative "platform/android"
|
13
|
-
require_relative "platform/
|
13
|
+
require_relative "platform/unknown"
|
14
14
|
require_relative "platform/chrome_os"
|
15
15
|
require_relative "platform/adobe_air"
|
16
16
|
|
@@ -35,7 +35,7 @@ module Browser
|
|
35
35
|
FirefoxOS,
|
36
36
|
Windows,
|
37
37
|
Linux,
|
38
|
-
|
38
|
+
Unknown
|
39
39
|
]
|
40
40
|
end
|
41
41
|
|
@@ -45,7 +45,7 @@ module Browser
|
|
45
45
|
|
46
46
|
def subject
|
47
47
|
@subject ||= self.class.matchers
|
48
|
-
.map {|matcher| matcher.new(ua) }
|
48
|
+
.map {|matcher| matcher.new(ua, self) }
|
49
49
|
.find(&:match?)
|
50
50
|
end
|
51
51
|
|
@@ -61,8 +61,8 @@ module Browser
|
|
61
61
|
id == :android && detect_version?(version, expected_version)
|
62
62
|
end
|
63
63
|
|
64
|
-
def
|
65
|
-
id == :
|
64
|
+
def unknown?
|
65
|
+
id == :unknown_platform
|
66
66
|
end
|
67
67
|
|
68
68
|
def linux?
|