browser 0.1.6 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +2 -1
- data/.travis.yml +8 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +70 -38
- data/README.md +114 -0
- data/Rakefile +12 -10
- data/browser.gemspec +2 -4
- data/config.ru +2 -0
- data/gemfiles/rails3.gemfile +4 -0
- data/gemfiles/rails3.gemfile.lock +111 -0
- data/lib/browser.rb +57 -283
- data/lib/browser/action_controller.rb +9 -7
- data/lib/browser/meta/base.rb +20 -0
- data/lib/browser/meta/generic_browser.rb +9 -0
- data/lib/browser/meta/id.rb +9 -0
- data/lib/browser/meta/ie.rb +18 -0
- data/lib/browser/meta/ios.rb +9 -0
- data/lib/browser/meta/mobile.rb +9 -0
- data/lib/browser/meta/modern.rb +9 -0
- data/lib/browser/meta/platform.rb +9 -0
- data/lib/browser/meta/safari.rb +9 -0
- data/lib/browser/meta/webkit.rb +9 -0
- data/lib/browser/methods/devices.rb +33 -0
- data/lib/browser/methods/ie.rb +40 -0
- data/lib/browser/methods/language.rb +131 -0
- data/lib/browser/methods/mobile.rb +23 -0
- data/lib/browser/methods/platform.rb +54 -0
- data/lib/browser/middleware.rb +43 -0
- data/lib/browser/middleware/context.rb +20 -0
- data/lib/browser/middleware/context/additions.rb +16 -0
- data/lib/browser/middleware/context/url_methods.rb +13 -0
- data/lib/browser/rails.rb +14 -0
- data/lib/browser/version.rb +2 -2
- data/test/browser_test.rb +220 -74
- data/test/middleware_test.rb +32 -0
- data/test/sample_app.rb +27 -0
- data/test/test_helper.rb +2 -1
- metadata +43 -57
- data/README.rdoc +0 -75
data/lib/browser.rb
CHANGED
@@ -1,15 +1,35 @@
|
|
1
1
|
require "set"
|
2
2
|
|
3
|
+
require "browser/middleware"
|
4
|
+
require "browser/middleware/context"
|
5
|
+
require "browser/rails" if defined?(::Rails)
|
6
|
+
|
7
|
+
require "browser/methods/ie"
|
8
|
+
require "browser/methods/platform"
|
9
|
+
require "browser/methods/mobile"
|
10
|
+
require "browser/methods/devices"
|
11
|
+
require "browser/methods/language"
|
12
|
+
|
13
|
+
require "browser/meta/base"
|
14
|
+
require "browser/meta/generic_browser"
|
15
|
+
require "browser/meta/id"
|
16
|
+
require "browser/meta/ie"
|
17
|
+
require "browser/meta/ios"
|
18
|
+
require "browser/meta/mobile"
|
19
|
+
require "browser/meta/modern"
|
20
|
+
require "browser/meta/platform"
|
21
|
+
require "browser/meta/safari"
|
22
|
+
require "browser/meta/webkit"
|
23
|
+
|
3
24
|
class Browser
|
4
|
-
|
5
|
-
|
25
|
+
include IE
|
26
|
+
include Platform
|
27
|
+
include Mobile
|
28
|
+
include Devices
|
29
|
+
include Language
|
6
30
|
|
7
31
|
# Set browser's UA string.
|
8
32
|
attr_accessor :user_agent
|
9
|
-
|
10
|
-
# Set browser's preferred language
|
11
|
-
attr_writer :accept_language
|
12
|
-
|
13
33
|
alias :ua :user_agent
|
14
34
|
alias :ua= :user_agent=
|
15
35
|
|
@@ -17,141 +37,25 @@ class Browser
|
|
17
37
|
:android => "Android",
|
18
38
|
:blackberry => "BlackBerry",
|
19
39
|
:chrome => "Chrome",
|
40
|
+
:core_media => "Apple CoreMedia",
|
20
41
|
:firefox => "Firefox",
|
21
42
|
:ie => "Internet Explorer",
|
22
43
|
:ipad => "iPad",
|
23
44
|
:iphone => "iPhone",
|
24
45
|
:ipod => "iPod Touch",
|
25
46
|
:opera => "Opera",
|
26
|
-
:
|
27
|
-
:safari => "Safari",
|
47
|
+
:phantom_js => "PhantomJS",
|
28
48
|
:psp => "PlayStation Portable",
|
29
49
|
:quicktime => "QuickTime",
|
30
|
-
:
|
31
|
-
}
|
50
|
+
:safari => "Safari",
|
32
51
|
|
33
|
-
|
34
|
-
:
|
35
|
-
:opera => /Opera\/.*? Version\/([\d.]+)/
|
52
|
+
# This must be last item, since Ruby 1.9+ has ordered keys.
|
53
|
+
:other => "Other",
|
36
54
|
}
|
37
55
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
"af" => "Afrikaans",
|
42
|
-
"sq" => "Albanian",
|
43
|
-
"eu" => "Basque",
|
44
|
-
"bg" => "Bulgarian",
|
45
|
-
"be" => "Byelorussian",
|
46
|
-
"ca" => "Catalan",
|
47
|
-
"zh" => "Chinese",
|
48
|
-
"zh-cn" => "Chinese/China",
|
49
|
-
"zh-tw" => "Chinese/Taiwan",
|
50
|
-
"zh-hk" => "Chinese/Hong Kong",
|
51
|
-
"zh-sg" => "Chinese/singapore",
|
52
|
-
"hr" => "Croatian",
|
53
|
-
"cs" => "Czech",
|
54
|
-
"da" => "Danish",
|
55
|
-
"nl" => "Dutch",
|
56
|
-
"nl-nl" => "Dutch/Netherlands",
|
57
|
-
"nl-be" => "Dutch/Belgium",
|
58
|
-
"en" => "English",
|
59
|
-
"en-gb" => "English/United Kingdom",
|
60
|
-
"en-us" => "English/United States",
|
61
|
-
"en-au" => "English/Australian",
|
62
|
-
"en-ca" => "English/Canada",
|
63
|
-
"en-nz" => "English/New Zealand",
|
64
|
-
"en-ie" => "English/Ireland",
|
65
|
-
"en-za" => "English/South Africa",
|
66
|
-
"en-jm" => "English/Jamaica",
|
67
|
-
"en-bz" => "English/Belize",
|
68
|
-
"en-tt" => "English/Trinidad",
|
69
|
-
"et" => "Estonian",
|
70
|
-
"fo" => "Faeroese",
|
71
|
-
"fa" => "Farsi",
|
72
|
-
"fi" => "Finnish",
|
73
|
-
"fr" => "French",
|
74
|
-
"fr-be" => "French/Belgium",
|
75
|
-
"fr-fr" => "French/France",
|
76
|
-
"fr-ch" => "French/Switzerland",
|
77
|
-
"fr-ca" => "French/Canada",
|
78
|
-
"fr-lu" => "French/Luxembourg",
|
79
|
-
"gd" => "Gaelic",
|
80
|
-
"gl" => "Galician",
|
81
|
-
"de" => "German",
|
82
|
-
"de-at" => "German/Austria",
|
83
|
-
"de-de" => "German/Germany",
|
84
|
-
"de-ch" => "German/Switzerland",
|
85
|
-
"de-lu" => "German/Luxembourg",
|
86
|
-
"de-li" => "German/Liechtenstein",
|
87
|
-
"el" => "Greek",
|
88
|
-
"he" => "Hebrew",
|
89
|
-
"he-il" => "Hebrew/Israel",
|
90
|
-
"hi" => "Hindi",
|
91
|
-
"hu" => "Hungarian",
|
92
|
-
"ie-ee" => "Internet Explorer/Easter Egg",
|
93
|
-
"is" => "Icelandic",
|
94
|
-
"id" => "Indonesian",
|
95
|
-
"in" => "Indonesian",
|
96
|
-
"ga" => "Irish",
|
97
|
-
"it" => "Italian",
|
98
|
-
"it-ch" => "Italian/ Switzerland",
|
99
|
-
"ja" => "Japanese",
|
100
|
-
"km" => "Khmer",
|
101
|
-
"km-kh" => "Khmer/Cambodia",
|
102
|
-
"ko" => "Korean",
|
103
|
-
"lv" => "Latvian",
|
104
|
-
"lt" => "Lithuanian",
|
105
|
-
"mk" => "Macedonian",
|
106
|
-
"ms" => "Malaysian",
|
107
|
-
"mt" => "Maltese",
|
108
|
-
"no" => "Norwegian",
|
109
|
-
"pl" => "Polish",
|
110
|
-
"pt" => "Portuguese",
|
111
|
-
"pt-br" => "Portuguese/Brazil",
|
112
|
-
"rm" => "Rhaeto-Romanic",
|
113
|
-
"ro" => "Romanian",
|
114
|
-
"ro-mo" => "Romanian/Moldavia",
|
115
|
-
"ru" => "Russian",
|
116
|
-
"ru-mo" => "Russian /Moldavia",
|
117
|
-
"gd" => "Scots Gaelic",
|
118
|
-
"sr" => "Serbian",
|
119
|
-
"sk" => "Slovack",
|
120
|
-
"sl" => "Slovenian",
|
121
|
-
"sb" => "Sorbian",
|
122
|
-
"es" => "Spanish",
|
123
|
-
"es-do" => "Spanish",
|
124
|
-
"es-ar" => "Spanish/Argentina",
|
125
|
-
"es-co" => "Spanish/Colombia",
|
126
|
-
"es-mx" => "Spanish/Mexico",
|
127
|
-
"es-es" => "Spanish/Spain",
|
128
|
-
"es-gt" => "Spanish/Guatemala",
|
129
|
-
"es-cr" => "Spanish/Costa Rica",
|
130
|
-
"es-pa" => "Spanish/Panama",
|
131
|
-
"es-ve" => "Spanish/Venezuela",
|
132
|
-
"es-pe" => "Spanish/Peru",
|
133
|
-
"es-ec" => "Spanish/Ecuador",
|
134
|
-
"es-cl" => "Spanish/Chile",
|
135
|
-
"es-uy" => "Spanish/Uruguay",
|
136
|
-
"es-py" => "Spanish/Paraguay",
|
137
|
-
"es-bo" => "Spanish/Bolivia",
|
138
|
-
"es-sv" => "Spanish/El salvador",
|
139
|
-
"es-hn" => "Spanish/Honduras",
|
140
|
-
"es-ni" => "Spanish/Nicaragua",
|
141
|
-
"es-pr" => "Spanish/Puerto Rico",
|
142
|
-
"sx" => "Sutu",
|
143
|
-
"sv" => "Swedish",
|
144
|
-
"sv-se" => "Swedish/Sweden",
|
145
|
-
"sv-fi" => "Swedish/Finland",
|
146
|
-
"ts" => "Thai",
|
147
|
-
"tn" => "Tswana",
|
148
|
-
"tr" => "Turkish",
|
149
|
-
"uk" => "Ukrainian",
|
150
|
-
"ur" => "Urdu",
|
151
|
-
"vi" => "Vietnamese",
|
152
|
-
"xh" => "Xshosa",
|
153
|
-
"ji" => "Yiddish",
|
154
|
-
"zu" => "Zulu"
|
56
|
+
VERSIONS = {
|
57
|
+
:default => %r[(?:Version|MSIE|Firefox|Chrome|CriOS|QuickTime|BlackBerry[^/]+|CoreMedia v|PhantomJS)[/ ]?([a-z0-9.]+)]i,
|
58
|
+
:opera => %r[(?:Opera/.*? Version/([\d.]+)|Chrome/([\d.]+).*?OPR)]
|
155
59
|
}
|
156
60
|
|
157
61
|
# Create a new browser instance and set
|
@@ -163,8 +67,8 @@ class Browser
|
|
163
67
|
# })
|
164
68
|
#
|
165
69
|
def initialize(options = {}, &block)
|
166
|
-
|
167
|
-
|
70
|
+
self.user_agent = (options[:user_agent] || options[:ua]).to_s
|
71
|
+
self.accept_language = options[:accept_language].to_s
|
168
72
|
|
169
73
|
yield self if block_given?
|
170
74
|
end
|
@@ -174,30 +78,10 @@ class Browser
|
|
174
78
|
NAMES[id]
|
175
79
|
end
|
176
80
|
|
177
|
-
#
|
81
|
+
# Get the browser identifier.
|
178
82
|
def id
|
179
|
-
|
180
|
-
|
181
|
-
when iphone? then :iphone
|
182
|
-
when ipad? then :ipad
|
183
|
-
when ipod? then :ipod
|
184
|
-
when ie? then :ie
|
185
|
-
when opera? then :opera
|
186
|
-
when firefox? then :firefox
|
187
|
-
when android? then :android
|
188
|
-
when blackberry? then :blackberry
|
189
|
-
when safari? then :safari
|
190
|
-
when psp? then :psp
|
191
|
-
when quicktime? then :quicktime
|
192
|
-
when core_media? then :core_media
|
193
|
-
else
|
194
|
-
:other
|
195
|
-
end
|
196
|
-
end
|
197
|
-
|
198
|
-
# Return an array with all preferred languages that this browser accepts.
|
199
|
-
def accept_language
|
200
|
-
@accept_language.gsub(/;q=[\d.]+/, "").split(",").collect {|l| l.downcase.gsub(/\s/m, "")}
|
83
|
+
NAMES.keys
|
84
|
+
.find {|id| respond_to?("#{id}?") ? public_send("#{id}?") : id }
|
201
85
|
end
|
202
86
|
|
203
87
|
# Return major version.
|
@@ -207,17 +91,16 @@ class Browser
|
|
207
91
|
|
208
92
|
# Return the full version.
|
209
93
|
def full_version
|
210
|
-
_, v = *ua.match(VERSIONS.fetch(id, VERSIONS[:default]))
|
211
|
-
v || "0.0"
|
94
|
+
_, *v = *ua.match(VERSIONS.fetch(id, VERSIONS[:default]))
|
95
|
+
v.compact.first || "0.0"
|
212
96
|
end
|
213
97
|
|
214
|
-
# Return true if browser
|
215
|
-
def
|
216
|
-
webkit? ||
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
ie? && ua.match(TRIDENT_VERSION_REGEX) && version.to_i < ($1.to_i + 4)
|
98
|
+
# Return true if browser is modern (Webkit, Firefox 17+, IE9+, Opera 12+).
|
99
|
+
def modern?
|
100
|
+
webkit? ||
|
101
|
+
(firefox? && version.to_i >= 17) ||
|
102
|
+
(ie? && version.to_i >= 9) ||
|
103
|
+
(opera? && version.to_i >= 12)
|
221
104
|
end
|
222
105
|
|
223
106
|
# Detect if browser is WebKit-based.
|
@@ -225,54 +108,24 @@ class Browser
|
|
225
108
|
!!(ua =~ /AppleWebKit/i)
|
226
109
|
end
|
227
110
|
|
228
|
-
# Detect if browser is ios?.
|
229
|
-
def ios?
|
230
|
-
ipod? || ipad? || iphone?
|
231
|
-
end
|
232
|
-
|
233
|
-
# Detect if browser is mobile.
|
234
|
-
def mobile?
|
235
|
-
!!(ua =~ /(Mobi(le)?|Symbian|MIDP|Windows CE)/) || blackberry? || psp? || opera_mini?
|
236
|
-
end
|
237
|
-
|
238
111
|
# Detect if browser is QuickTime
|
239
112
|
def quicktime?
|
240
113
|
!!(ua =~ /QuickTime/i)
|
241
114
|
end
|
242
115
|
|
243
|
-
# Detect if browser is BlackBerry
|
244
|
-
def blackberry?
|
245
|
-
!!(ua =~ /BlackBerry/)
|
246
|
-
end
|
247
|
-
|
248
|
-
# Detect if browser is Android.
|
249
|
-
def android?
|
250
|
-
!!(ua =~ /Android/ && !opera?)
|
251
|
-
end
|
252
|
-
|
253
116
|
# Detect if browser is Apple CoreMedia.
|
254
117
|
def core_media?
|
255
118
|
!!(ua =~ /CoreMedia/)
|
256
119
|
end
|
257
120
|
|
258
|
-
# Detect if browser is
|
259
|
-
def
|
260
|
-
!!(ua =~ /
|
261
|
-
end
|
262
|
-
|
263
|
-
# Detect if browser is iPad.
|
264
|
-
def ipad?
|
265
|
-
!!(ua =~ /iPad/)
|
266
|
-
end
|
267
|
-
|
268
|
-
# Detect if browser is iPod.
|
269
|
-
def ipod?
|
270
|
-
!!(ua =~ /iPod/)
|
121
|
+
# Detect if browser is PhantomJS
|
122
|
+
def phantom_js?
|
123
|
+
!!(ua =~ /PhantomJS/)
|
271
124
|
end
|
272
125
|
|
273
126
|
# Detect if browser is Safari.
|
274
127
|
def safari?
|
275
|
-
ua =~ /Safari/ && ua !~ /Chrome|CriOS/
|
128
|
+
ua =~ /Safari/ && ua !~ /Chrome|CriOS|PhantomJS/
|
276
129
|
end
|
277
130
|
|
278
131
|
# Detect if browser is Firefox.
|
@@ -282,99 +135,20 @@ class Browser
|
|
282
135
|
|
283
136
|
# Detect if browser is Chrome.
|
284
137
|
def chrome?
|
285
|
-
!!(ua =~ /Chrome|CriOS/)
|
286
|
-
end
|
287
|
-
|
288
|
-
# Detect if browser is Internet Explorer.
|
289
|
-
def ie?
|
290
|
-
!!(ua =~ /MSIE/ && ua !~ /Opera/)
|
291
|
-
end
|
292
|
-
|
293
|
-
# Detect if browser is Internet Explorer 6.
|
294
|
-
def ie6?
|
295
|
-
ie? && version == "6"
|
296
|
-
end
|
297
|
-
|
298
|
-
# Detect if browser is Internet Explorer 7.
|
299
|
-
def ie7?
|
300
|
-
ie? && version == "7"
|
301
|
-
end
|
302
|
-
|
303
|
-
# Detect if browser is Internet Explorer 8.
|
304
|
-
def ie8?
|
305
|
-
ie? && version == "8"
|
306
|
-
end
|
307
|
-
|
308
|
-
# Detect if browser is Internet Explorer 9.
|
309
|
-
def ie9?
|
310
|
-
ie? && version == "9"
|
311
|
-
end
|
312
|
-
|
313
|
-
# Detect if browser is running from PSP.
|
314
|
-
def psp?
|
315
|
-
!!(ua =~ /PSP/)
|
138
|
+
!!(ua =~ /Chrome|CriOS/) && !opera?
|
316
139
|
end
|
317
140
|
|
318
141
|
# Detect if browser is Opera.
|
319
142
|
def opera?
|
320
|
-
!!(ua =~ /Opera/)
|
321
|
-
end
|
322
|
-
|
323
|
-
# Detect if browser is Opera Mini.
|
324
|
-
def opera_mini?
|
325
|
-
!!(ua =~ /Opera Mini/)
|
326
|
-
end
|
327
|
-
|
328
|
-
# Detect if current platform is Macintosh.
|
329
|
-
def mac?
|
330
|
-
!!(ua =~ /Mac OS X/)
|
331
|
-
end
|
332
|
-
|
333
|
-
# Detect if current platform is Windows.
|
334
|
-
def windows?
|
335
|
-
!!(ua =~ /Windows/)
|
336
|
-
end
|
337
|
-
|
338
|
-
# Detect if current platform is Linux flavor.
|
339
|
-
def linux?
|
340
|
-
!!(ua =~ /Linux/)
|
341
|
-
end
|
342
|
-
|
343
|
-
# Detect if browser is tablet (currently just iPad or Android).
|
344
|
-
def tablet?
|
345
|
-
!!(ipad? || (android? && !mobile?))
|
346
|
-
end
|
347
|
-
|
348
|
-
# Detect if browser is Kindle.
|
349
|
-
def kindle?
|
350
|
-
!!(ua =~ /Kindle/)
|
351
|
-
end
|
352
|
-
|
353
|
-
# Return the platform.
|
354
|
-
def platform
|
355
|
-
case
|
356
|
-
when linux? then :linux
|
357
|
-
when mac? then :mac
|
358
|
-
when windows? then :windows
|
359
|
-
else
|
360
|
-
:other
|
361
|
-
end
|
143
|
+
!!(ua =~ /(Opera|OPR)/)
|
362
144
|
end
|
363
145
|
|
364
146
|
# Return a meta info about this browser.
|
365
147
|
def meta
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
m.merge(%W[safari safari#{version}]) if safari?
|
371
|
-
m << "#{id}#{version}" unless safari? || chrome?
|
372
|
-
m << platform.to_s
|
373
|
-
m << "capable" if capable?
|
374
|
-
m << "mobile" if mobile?
|
375
|
-
end
|
376
|
-
|
377
|
-
set.to_a
|
148
|
+
Meta.constants.each_with_object(Set.new) do |meta_name, meta|
|
149
|
+
meta_class = Meta.const_get(meta_name)
|
150
|
+
meta.merge(meta_class.new(self).to_a)
|
151
|
+
end.to_a
|
378
152
|
end
|
379
153
|
|
380
154
|
alias_method :to_a, :meta
|
@@ -1,17 +1,19 @@
|
|
1
|
+
require "action_controller/railtie"
|
2
|
+
|
1
3
|
class Browser
|
2
|
-
module ActionController
|
3
|
-
|
4
|
-
|
4
|
+
module ActionController
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
helper_method :browser
|
5
9
|
end
|
6
10
|
|
7
11
|
private
|
8
12
|
def browser
|
9
13
|
@browser ||= Browser.new(
|
10
|
-
:
|
11
|
-
:
|
14
|
+
accept_language: request.headers["Accept-Language"],
|
15
|
+
ua: request.headers["User-Agent"]
|
12
16
|
)
|
13
17
|
end
|
14
18
|
end
|
15
19
|
end
|
16
|
-
|
17
|
-
ActionController::Base.send :include, Browser::ActionController
|