browser_sniffer 1.1.3 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +4 -0
- data/browser_sniffer.gemspec +2 -0
- data/lib/browser_sniffer/patterns.rb +3 -3
- data/lib/browser_sniffer/version.rb +1 -1
- data/lib/browser_sniffer.rb +47 -0
- data/test/browser_sniffer_test.rb +52 -1
- data/test/shopify_agents_test.rb +113 -4
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c1f122e65998d2712691f2b2dfefd9cbbdb7e824ad1a5a39bab483b4274bbac3
|
4
|
+
data.tar.gz: 002eb813a2e049806a5e409035aeb8f303c4dff4797e05461993d70e372f5c18
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 266ff5af2b669e477e088b0cf2caff845e7bacdbcc2abd7a6c4380921a9343e15604c2c4975260bf53cdccc0002de45b49563aef40e790c4fe46f1abc5e497b0
|
7
|
+
data.tar.gz: 9c9620bb162e584acc189d3a6e208d67470a0d16aeefd5b331f9250e5dc1eb444fc1243fef615bf242cde1a5ba4d89c9a124a0984e56119baf4c05831c545225
|
data/.travis.yml
CHANGED
data/browser_sniffer.gemspec
CHANGED
@@ -17,6 +17,8 @@ Gem::Specification.new do |spec|
|
|
17
17
|
|
18
18
|
spec.required_ruby_version = ">= 1.9.3"
|
19
19
|
|
20
|
+
spec.metadata['allowed_push_host'] = 'https://rubygems.org'
|
21
|
+
|
20
22
|
spec.add_development_dependency "bundler"
|
21
23
|
spec.add_development_dependency "minitest"
|
22
24
|
spec.add_development_dependency "rake"
|
@@ -73,8 +73,8 @@ class BrowserSniffer
|
|
73
73
|
%r{.*(Shopify POS Next|Shopify POS)\/(?:iOS)\/([\d\.]+) \((iPhone|iPad|iPod)}i
|
74
74
|
], [[:name, 'Shopify POS'], :version], [
|
75
75
|
# Shopify Mobile for Android
|
76
|
-
%r{.*(Shopify Mobile)\/Android\/([\d\.]+(?: \(debug(?:|-push)\))?
|
77
|
-
], [[:name, 'Shopify Mobile'], :version, :build, :sdk_version], [
|
76
|
+
%r{.*(Shopify Mobile)\/Android\/([\d\.]+)(?: \((debug(?:|-push))\))? \(Build (\d+) with API (\d+)}i
|
77
|
+
], [[:name, 'Shopify Mobile'], :version, :debug_mode, :build, :sdk_version], [
|
78
78
|
# ShopifyFoundation shared library
|
79
79
|
/^(ShopifyFoundation)/i,
|
80
80
|
], [:name], [
|
@@ -332,7 +332,7 @@ class BrowserSniffer
|
|
332
332
|
/(gnu)\s?([\w\.]+)*/i # GNU
|
333
333
|
], [:name, :version, [:type, :linux]], [
|
334
334
|
/(cros)\s[\w]+\s([\w\.]+\w)/i # Chromium OS
|
335
|
-
], [[:name, 'Chromium OS'], :version],[
|
335
|
+
], [[:name, 'Chromium OS'], :version, [:type, :chromium_os]],[
|
336
336
|
# Solaris
|
337
337
|
/(sunos)\s?([\w\.]+\d)*/i # Solaris
|
338
338
|
], [[:name, 'Solaris'], :version], [
|
data/lib/browser_sniffer.rb
CHANGED
@@ -24,6 +24,15 @@ class BrowserSniffer
|
|
24
24
|
browser == :ie && major_browser_version == 11
|
25
25
|
end
|
26
26
|
|
27
|
+
# This method checks ie 11 mobile or ie11 rendering an older version in compatibility mode, in addition to `ie11?`.
|
28
|
+
# The `ie11?` method would return false in both those scenarios.
|
29
|
+
def ie11_actual?
|
30
|
+
ie11_engine = major_engine_version == 7 && engine_name == 'Trident'
|
31
|
+
ie_mobile11 = major_browser_version == 11 && browser_name == 'IEMobile'
|
32
|
+
|
33
|
+
ie11? || ie11_engine || ie_mobile11
|
34
|
+
end
|
35
|
+
|
27
36
|
def handheld?
|
28
37
|
form_factor == :handheld
|
29
38
|
end
|
@@ -153,4 +162,42 @@ class BrowserSniffer
|
|
153
162
|
end
|
154
163
|
result
|
155
164
|
end
|
165
|
+
|
166
|
+
def same_site_none_compatible?
|
167
|
+
return false unless user_agent
|
168
|
+
|
169
|
+
webkit_same_site_compatible? && same_site_recognized_browser?
|
170
|
+
end
|
171
|
+
|
172
|
+
def webkit_same_site_compatible?
|
173
|
+
return false unless os && os_version && browser
|
174
|
+
|
175
|
+
!(os == :ios && os_version.match(/^([0-9]|1[12])[\.\_]/)) &&
|
176
|
+
!(os == :mac && browser == :safari && os_version.match(/^10[\.\_]14/))
|
177
|
+
end
|
178
|
+
|
179
|
+
def same_site_recognized_browser?
|
180
|
+
return false unless major_browser_version
|
181
|
+
|
182
|
+
!(chromium_based? && major_browser_version >= 51 && major_browser_version <= 66) &&
|
183
|
+
!(uc_browser? && !uc_browser_version_at_least?(12, 13, 2))
|
184
|
+
end
|
185
|
+
|
186
|
+
def chromium_based?
|
187
|
+
browser_name ? browser_name.downcase.match(/chrom(e|ium)/) : false
|
188
|
+
end
|
189
|
+
|
190
|
+
def uc_browser?
|
191
|
+
user_agent ? user_agent.downcase.match(/uc\s?browser/) : false
|
192
|
+
end
|
193
|
+
|
194
|
+
def uc_browser_version_at_least?(major, minor, build)
|
195
|
+
return false unless browser_version
|
196
|
+
digits = browser_version.split('.').map(&:to_i)
|
197
|
+
return false unless digits.count >= 3
|
198
|
+
|
199
|
+
return digits[0] > major if digits[0] != major
|
200
|
+
return digits[1] > minor if digits[1] != minor
|
201
|
+
digits[2] >= build
|
202
|
+
end
|
156
203
|
end
|
@@ -454,6 +454,7 @@ class BrowserSnifferTest < Minitest::Test
|
|
454
454
|
:android? => false,
|
455
455
|
:desktop? => true,
|
456
456
|
:ie11? => false,
|
457
|
+
:ie11_actual? => false,
|
457
458
|
:engine => nil,
|
458
459
|
:major_engine_version => nil,
|
459
460
|
:os => :mac,
|
@@ -467,6 +468,7 @@ class BrowserSnifferTest < Minitest::Test
|
|
467
468
|
:form_factor => :desktop,
|
468
469
|
:ios? => false,
|
469
470
|
:ie11? => true,
|
471
|
+
:ie11_actual? => true,
|
470
472
|
:android? => false,
|
471
473
|
:desktop? => true,
|
472
474
|
:engine => :trident,
|
@@ -481,6 +483,7 @@ class BrowserSnifferTest < Minitest::Test
|
|
481
483
|
:form_factor => :desktop,
|
482
484
|
:ios? => false,
|
483
485
|
:ie11? => true,
|
486
|
+
:ie11_actual? => true,
|
484
487
|
:android? => false,
|
485
488
|
:desktop? => true,
|
486
489
|
:engine => :trident,
|
@@ -495,6 +498,7 @@ class BrowserSnifferTest < Minitest::Test
|
|
495
498
|
:form_factor => :desktop,
|
496
499
|
:ios? => false,
|
497
500
|
:ie11? => true,
|
501
|
+
:ie11_actual? => true,
|
498
502
|
:android? => false,
|
499
503
|
:desktop? => true,
|
500
504
|
:engine => :trident,
|
@@ -509,6 +513,7 @@ class BrowserSnifferTest < Minitest::Test
|
|
509
513
|
:form_factor => :desktop,
|
510
514
|
:ios? => false,
|
511
515
|
:ie11? => true,
|
516
|
+
:ie11_actual? => true,
|
512
517
|
:android? => false,
|
513
518
|
:desktop? => true,
|
514
519
|
:engine => :trident,
|
@@ -523,6 +528,7 @@ class BrowserSnifferTest < Minitest::Test
|
|
523
528
|
:form_factor => :desktop,
|
524
529
|
:ios? => false,
|
525
530
|
:ie11? => false,
|
531
|
+
:ie11_actual? => false,
|
526
532
|
:android? => false,
|
527
533
|
:desktop? => true,
|
528
534
|
:engine => :webkit,
|
@@ -544,7 +550,52 @@ class BrowserSnifferTest < Minitest::Test
|
|
544
550
|
:os_version => nil,
|
545
551
|
:browser => nil,
|
546
552
|
:major_browser_version => nil
|
547
|
-
}
|
553
|
+
},
|
554
|
+
:chromiumos_chrome => {
|
555
|
+
:user_agent => "Mozilla/5.0 (X11; CrOS x86_64 10066.0.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.122 Safari/537.36",
|
556
|
+
:form_factor => :desktop,
|
557
|
+
:ios? => false,
|
558
|
+
:android? => false,
|
559
|
+
:desktop? => true,
|
560
|
+
:engine => :webkit,
|
561
|
+
:major_engine_version => 537,
|
562
|
+
:os => :chromium_os,
|
563
|
+
:os_version => '10066.0.0',
|
564
|
+
:browser => :chrome,
|
565
|
+
:major_browser_version => 81,
|
566
|
+
},
|
567
|
+
:windows_phone_8_1_ie11 => {
|
568
|
+
:user_agent => "Mozilla/5.0 (Mobile; Windows Phone 8.1; Android 4.0; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; Microsoft; " \
|
569
|
+
"Lumia 640 XL) like iPhone OS 7_0_3 Mac OS X AppleWebKit/537 (KHTML, like Gecko) Mobile Safari/537",
|
570
|
+
:form_factor => :handheld,
|
571
|
+
:ios? => false,
|
572
|
+
:ie11? => false,
|
573
|
+
:ie11_actual? => true,
|
574
|
+
:android? => false,
|
575
|
+
:desktop? => false,
|
576
|
+
:engine => :webkit,
|
577
|
+
:major_engine_version => 53,
|
578
|
+
:os => :windows,
|
579
|
+
:os_version => "8.1",
|
580
|
+
:browser => nil,
|
581
|
+
:major_browser_version => 11
|
582
|
+
},
|
583
|
+
:win10_ie11_in_ie7_compatibility_mode => {
|
584
|
+
:user_agent => "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; " \
|
585
|
+
".NET CLR 3.0.30729; .NET CLR 3.5.30729; InfoPath.3; Tablet PC 2.0; Zoom 3.6.0)",
|
586
|
+
:form_factor => :desktop,
|
587
|
+
:ios? => false,
|
588
|
+
:ie11? => false,
|
589
|
+
:ie11_actual? => true,
|
590
|
+
:android? => false,
|
591
|
+
:desktop? => true,
|
592
|
+
:engine => :trident,
|
593
|
+
:major_engine_version => 7,
|
594
|
+
:os => :windows,
|
595
|
+
:os_version => "10",
|
596
|
+
:browser => :ie,
|
597
|
+
:major_browser_version => 7
|
598
|
+
},
|
548
599
|
}
|
549
600
|
|
550
601
|
AGENTS.each do |agent, attributes|
|
data/test/shopify_agents_test.rb
CHANGED
@@ -155,6 +155,7 @@ describe "Shopify agents" do
|
|
155
155
|
assert_equal ({
|
156
156
|
name: 'Shopify Mobile',
|
157
157
|
version: '5.4.4',
|
158
|
+
debug_mode: nil,
|
158
159
|
build: '12005',
|
159
160
|
sdk_version: '25',
|
160
161
|
}), sniffer.browser_info
|
@@ -174,10 +175,11 @@ describe "Shopify agents" do
|
|
174
175
|
"MobileMiddlewareSupported Mozilla/5.0 (Linux; Android 9; Android SDK built for x86 Build/PSR1.180720.075; wv) "\
|
175
176
|
"AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/69.0.3497.100 Mobile Safari/537.36"
|
176
177
|
sniffer = BrowserSniffer.new(user_agent)
|
177
|
-
|
178
|
+
|
178
179
|
assert_equal ({
|
179
180
|
name: 'Shopify Mobile',
|
180
181
|
version: '8.12.0',
|
182
|
+
debug_mode: nil,
|
181
183
|
build: '12005',
|
182
184
|
sdk_version: '28',
|
183
185
|
}), sniffer.browser_info
|
@@ -203,7 +205,8 @@ describe "Shopify agents" do
|
|
203
205
|
|
204
206
|
assert_equal ({
|
205
207
|
name: 'Shopify Mobile',
|
206
|
-
version: '6.2.0
|
208
|
+
version: '6.2.0',
|
209
|
+
debug_mode: 'debug',
|
207
210
|
build: '1',
|
208
211
|
sdk_version: '25',
|
209
212
|
}), sniffer.browser_info
|
@@ -406,6 +409,77 @@ describe "Shopify agents" do
|
|
406
409
|
}), sniffer.os_info
|
407
410
|
end
|
408
411
|
|
412
|
+
it "Shopify POS via webview can be sniffed" do
|
413
|
+
user_agent = "Mozilla/5.0 (iPhone; CPU iPhone OS 12_0 like Mac OS X) "\
|
414
|
+
"AppleWebKit/ 604.1.21 (KHTML, like Gecko) Version/ 12.0 Mobile/17A6278a Safari/602.1.26 "\
|
415
|
+
"MobileMiddlewareSupported com.jadedpixel.pos Shopify POS/5.43.1 (iPad; iOS 13.1; Scale/2.00)"
|
416
|
+
sniffer = BrowserSniffer.new(user_agent)
|
417
|
+
|
418
|
+
assert_equal ({
|
419
|
+
name: 'Shopify POS',
|
420
|
+
version: '5.43.1',
|
421
|
+
}), sniffer.browser_info
|
422
|
+
|
423
|
+
assert_equal ({
|
424
|
+
type: :tablet,
|
425
|
+
scale: '2.00',
|
426
|
+
}), sniffer.device_info
|
427
|
+
|
428
|
+
assert_equal ({
|
429
|
+
type: :ios,
|
430
|
+
version: '13.1',
|
431
|
+
name: 'iOS',
|
432
|
+
}), sniffer.os_info
|
433
|
+
end
|
434
|
+
|
435
|
+
it "Shopify POS with modern user agent via webview can be sniffed" do
|
436
|
+
user_agent = "Mozilla/5.0 (iPhone; CPU iPhone OS 12_0 like Mac OS X) "\
|
437
|
+
"AppleWebKit/ 604.1.21 (KHTML, like Gecko) Version/ 12.0 Mobile/17A6278a "\
|
438
|
+
"Safari/602.1.26 MobileMiddlewareSupported Shopify POS/iOS/3.12.1 "\
|
439
|
+
"(iPad4,7/com.jadedpixel.pos/10.3.1) - Build 1"
|
440
|
+
sniffer = BrowserSniffer.new(user_agent)
|
441
|
+
|
442
|
+
assert_equal ({
|
443
|
+
name: 'Shopify POS',
|
444
|
+
version: '3.12.1',
|
445
|
+
}), sniffer.browser_info
|
446
|
+
|
447
|
+
assert_equal ({
|
448
|
+
type: :tablet,
|
449
|
+
model: '4,7',
|
450
|
+
}), sniffer.device_info
|
451
|
+
|
452
|
+
assert_equal ({
|
453
|
+
type: :ios,
|
454
|
+
name: 'iOS',
|
455
|
+
version: '10.3.1',
|
456
|
+
}), sniffer.os_info
|
457
|
+
end
|
458
|
+
|
459
|
+
it "Shopify POS Next with modern user agent via webview can be sniffed" do
|
460
|
+
user_agent = "Mozilla/5.0 (iPhone; CPU iPhone OS 12_0 like Mac OS X) "\
|
461
|
+
"AppleWebKit/ 604.1.21 (KHTML, like Gecko) Version/ 12.0 Mobile/17A6278a "\
|
462
|
+
"Safari/602.1.26 MobileMiddlewareSupported Shopify POS Next/iOS/3.12.1 "\
|
463
|
+
"(iPad4,7/com.jadedpixel.pos/10.3.1) - Build 1"
|
464
|
+
sniffer = BrowserSniffer.new(user_agent)
|
465
|
+
|
466
|
+
assert_equal ({
|
467
|
+
name: 'Shopify POS',
|
468
|
+
version: '3.12.1',
|
469
|
+
}), sniffer.browser_info
|
470
|
+
|
471
|
+
assert_equal ({
|
472
|
+
type: :tablet,
|
473
|
+
model: '4,7',
|
474
|
+
}), sniffer.device_info
|
475
|
+
|
476
|
+
assert_equal ({
|
477
|
+
type: :ios,
|
478
|
+
name: 'iOS',
|
479
|
+
version: '10.3.1',
|
480
|
+
}), sniffer.os_info
|
481
|
+
end
|
482
|
+
|
409
483
|
it "Shopify POS with okhttp user agent can be parsed" do
|
410
484
|
user_agent = "okhttp/3.6.0"
|
411
485
|
sniffer = BrowserSniffer.new(user_agent)
|
@@ -486,7 +560,8 @@ describe "Shopify agents" do
|
|
486
560
|
|
487
561
|
assert_equal ({
|
488
562
|
name: 'Shopify Mobile',
|
489
|
-
version: '6.0.0
|
563
|
+
version: '6.0.0',
|
564
|
+
debug_mode: 'debug',
|
490
565
|
build: '1',
|
491
566
|
sdk_version: '25',
|
492
567
|
}), sniffer.browser_info
|
@@ -509,7 +584,8 @@ describe "Shopify agents" do
|
|
509
584
|
|
510
585
|
assert_equal ({
|
511
586
|
name: 'Shopify Mobile',
|
512
|
-
version: '6.0.0
|
587
|
+
version: '6.0.0',
|
588
|
+
debug_mode: 'debug-push',
|
513
589
|
build: '1',
|
514
590
|
sdk_version: '25',
|
515
591
|
}), sniffer.browser_info
|
@@ -603,4 +679,37 @@ describe "Shopify agents" do
|
|
603
679
|
name: 'iOS',
|
604
680
|
}), sniffer.os_info
|
605
681
|
end
|
682
|
+
|
683
|
+
INCOMPATIBLE_USER_AGENTS = [
|
684
|
+
"Mozilla/5.0 (iPhone; CPU iPhone OS 12_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko)"\
|
685
|
+
" GSA/87.0.279142407 Mobile/15E148 Safari/605.1",
|
686
|
+
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/605.1.15 (KHTML, like Gecko)"\
|
687
|
+
" Version/12.1.2 Safari/605.1.15",
|
688
|
+
"Mozilla/5.0 (Linux; U; Android 7.0; en-US; SM-G935F Build/NRD90M) AppleWebKit/534.30 (KHTML, like Gecko) "\
|
689
|
+
"Version/4.0 UCBrowser/11.3.8.976 U3/0.8.0 Mobile Safari/534.30",
|
690
|
+
]
|
691
|
+
|
692
|
+
INCOMPATIBLE_USER_AGENTS.each do |user_agent|
|
693
|
+
it "user agent #{user_agent} is correctly marked as incompatible" do
|
694
|
+
sniffer = BrowserSniffer.new(user_agent)
|
695
|
+
|
696
|
+
refute sniffer.same_site_none_compatible?
|
697
|
+
end
|
698
|
+
end
|
699
|
+
|
700
|
+
COMPATIBLE_USER_AGENTS = [
|
701
|
+
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.117"\
|
702
|
+
" Safari/537.36",
|
703
|
+
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:72.0) Gecko/20100101 Firefox/72.0",
|
704
|
+
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.4"\
|
705
|
+
" Safari/605.1.15",
|
706
|
+
]
|
707
|
+
|
708
|
+
COMPATIBLE_USER_AGENTS.each do |user_agent|
|
709
|
+
it "user agent #{user_agent} is correctly marked as compatible" do
|
710
|
+
sniffer = BrowserSniffer.new(user_agent)
|
711
|
+
|
712
|
+
assert sniffer.same_site_none_compatible?
|
713
|
+
end
|
714
|
+
end
|
606
715
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: browser_sniffer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shopify
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-10-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -79,7 +79,8 @@ homepage: https://github.com/Shopify/browser_sniffer
|
|
79
79
|
licenses:
|
80
80
|
- GPLv2
|
81
81
|
- MIT
|
82
|
-
metadata:
|
82
|
+
metadata:
|
83
|
+
allowed_push_host: https://rubygems.org
|
83
84
|
post_install_message:
|
84
85
|
rdoc_options: []
|
85
86
|
require_paths:
|
@@ -95,8 +96,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
95
96
|
- !ruby/object:Gem::Version
|
96
97
|
version: '0'
|
97
98
|
requirements: []
|
98
|
-
|
99
|
-
rubygems_version: 2.7.6
|
99
|
+
rubygems_version: 3.2.20
|
100
100
|
signing_key:
|
101
101
|
specification_version: 4
|
102
102
|
summary: Parses user agent strings and boils it all down to a few simple classifications.
|