browser_sniffer 1.1.3 → 1.3.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.
- 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.
|