browser 3.0.2 → 5.0.0

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.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE.md +1 -1
  3. data/.prettierignore +1 -0
  4. data/.rubocop.yml +9 -0
  5. data/.travis.yml +3 -3
  6. data/CHANGELOG.md +81 -18
  7. data/FUNDING.yml +3 -0
  8. data/README.md +113 -88
  9. data/bots.yml +300 -294
  10. data/browser.gemspec +3 -1
  11. data/lib/browser/base.rb +63 -7
  12. data/lib/browser/browser.rb +27 -26
  13. data/lib/browser/chrome.rb +12 -2
  14. data/lib/browser/device.rb +2 -2
  15. data/lib/browser/device/unknown.rb +1 -1
  16. data/lib/browser/duck_duck_go.rb +22 -0
  17. data/lib/browser/edge.rb +2 -2
  18. data/lib/browser/google_search_app.rb +21 -0
  19. data/lib/browser/huawei_browser.rb +21 -0
  20. data/lib/browser/maxthon.rb +21 -0
  21. data/lib/browser/meta.rb +0 -1
  22. data/lib/browser/meta/base.rb +0 -1
  23. data/lib/browser/miui_browser.rb +21 -0
  24. data/lib/browser/platform.rb +5 -5
  25. data/lib/browser/platform/base.rb +3 -2
  26. data/lib/browser/platform/ios.rb +1 -1
  27. data/lib/browser/platform/mac.rb +4 -2
  28. data/lib/browser/platform/{other.rb → unknown.rb} +3 -3
  29. data/lib/browser/platform/windows.rb +1 -1
  30. data/lib/browser/safari.rb +16 -1
  31. data/lib/browser/samsung_browser.rb +21 -0
  32. data/lib/browser/sougou_browser.rb +24 -0
  33. data/lib/browser/{generic.rb → unknown.rb} +3 -3
  34. data/lib/browser/version.rb +1 -1
  35. data/test/browser_test.rb +23 -6
  36. data/test/test_helper.rb +8 -0
  37. data/test/ua.yml +17 -1
  38. data/test/ua_bots.yml +8 -2
  39. data/test/unit/adobe_air_test.rb +1 -1
  40. data/test/unit/alipay_test.rb +6 -0
  41. data/test/unit/console_test.rb +2 -2
  42. data/test/unit/device_test.rb +2 -2
  43. data/test/unit/duck_duck_go_test.rb +37 -0
  44. data/test/unit/edge_test.rb +34 -2
  45. data/test/unit/google_search_app_test.rb +54 -0
  46. data/test/unit/huawei_browser_test.rb +25 -0
  47. data/test/unit/maxthon_test.rb +25 -0
  48. data/test/unit/meta_test.rb +9 -0
  49. data/test/unit/micro_messenger_test.rb +21 -6
  50. data/test/unit/miui_browser_test.rb +25 -0
  51. data/test/unit/opera_test.rb +1 -0
  52. data/test/unit/platform_test.rb +12 -7
  53. data/test/unit/qq_test.rb +12 -0
  54. data/test/unit/safari_test.rb +12 -7
  55. data/test/unit/samsung_browser_test.rb +23 -0
  56. data/test/unit/sougou_browser_test.rb +41 -0
  57. metadata +33 -10
  58. data/lib/browser/meta/modern.rb +0 -11
@@ -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 = "http://github.com/fnando/browser"
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/*`
@@ -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?(version, expected_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
- id != :generic
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
@@ -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 "generic"
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
- MicroMessenger,
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) }
@@ -21,9 +21,19 @@ module Browser
21
21
 
22
22
  def match?
23
23
  ua =~ /Chrome|CriOS/ &&
24
- ua !~ /PhantomJS|FxiOS|YaBrowser|SputnikBrowser|ArchiveBot/ &&
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
@@ -88,7 +88,7 @@ module Browser
88
88
  end
89
89
 
90
90
  def unknown?
91
- id == :unknown
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\-)|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])
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
 
@@ -4,7 +4,7 @@ module Browser
4
4
  class Device
5
5
  class Unknown < Base
6
6
  def id
7
- :unknown
7
+ :unknown_device
8
8
  end
9
9
 
10
10
  def name
@@ -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
@@ -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
@@ -6,7 +6,6 @@ require_relative "meta/id"
6
6
  require_relative "meta/ie"
7
7
  require_relative "meta/ios"
8
8
  require_relative "meta/mobile"
9
- require_relative "meta/modern"
10
9
  require_relative "meta/platform"
11
10
  require_relative "meta/proxy"
12
11
  require_relative "meta/safari"
@@ -10,7 +10,6 @@ module Browser
10
10
  IE,
11
11
  IOS,
12
12
  Mobile,
13
- Modern,
14
13
  Platform,
15
14
  Proxy,
16
15
  Safari,
@@ -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
@@ -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/other"
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
- Other
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 other?
65
- id == :other
64
+ def unknown?
65
+ id == :unknown_platform
66
66
  end
67
67
 
68
68
  def linux?