webdrivers 2.3.2 → 4.7.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 (49) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +204 -56
  3. data/LICENSE.txt +2 -2
  4. data/README.md +253 -17
  5. data/lib/webdrivers/Rakefile +6 -0
  6. data/lib/webdrivers/chrome_finder.rb +127 -0
  7. data/lib/webdrivers/chromedriver.rb +131 -23
  8. data/lib/webdrivers/common.rb +145 -70
  9. data/lib/webdrivers/edge_finder.rb +99 -0
  10. data/lib/webdrivers/edgedriver.rb +87 -17
  11. data/lib/webdrivers/geckodriver.rb +46 -25
  12. data/lib/webdrivers/iedriver.rb +51 -18
  13. data/lib/webdrivers/logger.rb +111 -0
  14. data/lib/webdrivers/network.rb +63 -0
  15. data/lib/webdrivers/railtie.rb +15 -0
  16. data/lib/webdrivers/system.rb +197 -0
  17. data/lib/webdrivers/tasks/chromedriver.rake +44 -0
  18. data/lib/webdrivers/tasks/edgedriver.rake +44 -0
  19. data/lib/webdrivers/tasks/geckodriver.rake +44 -0
  20. data/lib/webdrivers/tasks/iedriver.rake +44 -0
  21. data/lib/webdrivers/version.rb +5 -0
  22. data/lib/webdrivers.rb +7 -9
  23. data/spec/spec_helper.rb +18 -2
  24. data/spec/webdrivers/chrome_finder_spec.rb +103 -0
  25. data/spec/webdrivers/chromedriver_spec.rb +276 -0
  26. data/spec/webdrivers/edge_finder_spec.rb +58 -0
  27. data/spec/webdrivers/edgedriver_spec.rb +279 -0
  28. data/spec/webdrivers/geckodriver_spec.rb +211 -0
  29. data/spec/webdrivers/i_edriver_spec.rb +197 -0
  30. data/spec/webdrivers/system_spec.rb +79 -0
  31. data/spec/webdrivers/webdrivers_spec.rb +80 -0
  32. data/spec/webdrivers_proxy_support_spec.rb +53 -0
  33. metadata +157 -43
  34. data/.gitignore +0 -6
  35. data/.travis.yml +0 -3
  36. data/Gemfile +0 -4
  37. data/Rakefile +0 -6
  38. data/bin/IEDriverServer +0 -5
  39. data/bin/MicrosoftWebDriver +0 -5
  40. data/bin/chromedriver +0 -5
  41. data/bin/geckodriver +0 -5
  42. data/bin/phantomjs +0 -5
  43. data/lib/webdrivers/phantomjs.rb +0 -40
  44. data/spec/chromedriver_spec.rb +0 -36
  45. data/spec/edgedriver_spec.rb +0 -24
  46. data/spec/geckodriver_spec.rb +0 -36
  47. data/spec/iedriver_spec.rb +0 -27
  48. data/spec/phantomjs_spec.rb +0 -36
  49. data/webdrivers.gemspec +0 -24
@@ -1,34 +1,104 @@
1
- require 'nokogiri'
1
+ # frozen_string_literal: true
2
2
 
3
- module Webdrivers
4
- class Edgedriver < Common
3
+ require 'shellwords'
4
+ require 'webdrivers/common'
5
+ require 'webdrivers/chromedriver'
6
+ require 'webdrivers/edge_finder'
5
7
 
8
+ module Webdrivers
9
+ class Edgedriver < Chromedriver
6
10
  class << self
11
+ undef :chrome_version
12
+ #
13
+ # Returns currently installed Edge version.
14
+ #
15
+ # @return [Gem::Version]
16
+ def browser_version
17
+ normalize_version EdgeFinder.version
18
+ end
19
+
20
+ #
21
+ # Returns url with domain for calls to get this driver.
22
+ #
23
+ # @return [String]
24
+ def base_url
25
+ # 'https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/'
26
+ 'https://msedgedriver.azureedge.net/'
27
+ end
28
+
29
+ private
30
+
31
+ def latest_point_release(version)
32
+ # Microsoft doesn't currently provide LATEST_RELEASE_X.Y.Z - only use X
33
+ # but require the driver version be >= the passed in version
34
+ str = Network.get(URI.join(base_url, "LATEST_RELEASE_#{version.segments[0]}"))
35
+ latest_release = normalize_version(str.encode('ASCII-8BIT', 'UTF-16'))
36
+ raise VersionError unless latest_release >= version
37
+
38
+ latest_release
39
+ rescue NetworkError, VersionError
40
+ msg = failed_to_find_message(version)
41
+ Webdrivers.logger.debug msg
42
+ raise VersionError, msg
43
+ end
44
+
45
+ def failed_to_find_message(version)
46
+ msg = "Unable to find latest point release version for #{version}."
47
+ msg = begin
48
+ # str = Network.get(URI.join(base_url, 'LATEST_RELEASE'))
49
+ # Microsoft doesn't yet/ever support LATEST_RELEASE - Use Canary as latest
50
+ str = Network.get(URI.join(base_url, 'LATEST_CANARY'))
51
+ latest_release = normalize_version(str.encode('ASCII-8BIT', 'UTF-16'))
52
+ if version > latest_release
53
+ "#{msg} You appear to be using a non-production version of Edge."
54
+ else
55
+ msg
56
+ end
57
+ rescue NetworkError
58
+ "#{msg} A network issue is preventing determination of latest msedgedriver release."
59
+ end
60
+
61
+ "#{msg} Please set `Webdrivers::Edgedriver.required_version = <desired driver version>` "\
62
+ "to a known edgedriver version: Can not reach #{base_url}"
63
+ end
64
+
7
65
  def file_name
8
- "MicrosoftWebDriver.exe"
66
+ System.platform == 'win' ? 'msedgedriver.exe' : 'msedgedriver'
9
67
  end
10
68
 
11
- def current_version
12
- # No version information available
69
+ def apple_m1_compatible?(driver_version)
70
+ if System.apple_m1_architecture? && driver_version >= normalize_version('87.0.669.0')
71
+ Webdrivers.logger.debug 'msedgedriver version is Apple M1 compatible.'
72
+ return true
73
+ end
74
+
75
+ Webdrivers.logger.debug 'msedgedriver version is NOT Apple M1 compatible. Required >= 87.0.669.0'
76
+ false
13
77
  end
14
78
 
15
- def newest_version
16
- version = %x(ver)
17
- version[/\d+\.\d+\.\d+/][/[^\.]\d+$/]
79
+ def linux_compatible?(driver_version)
80
+ System.platform == 'linux' && driver_version >= normalize_version('89.0.731.0')
18
81
  end
19
82
 
20
- def download_url(version = nil)
21
- if newest_version.to_i >= 14965
22
- 'https://download.microsoft.com/download/1/4/1/14156DA0-D40F-460A-B14D-1B264CA081A5/MicrosoftWebDriver.exe'
83
+ def driver_filename(driver_version)
84
+ if System.platform == 'win' || System.wsl_v1?
85
+ "win#{System.bitsize}" # 32 or 64-bit
86
+ elsif linux_compatible?(driver_version)
87
+ 'linux64'
88
+ elsif System.platform == 'mac'
89
+ # Determine M1 or Intel architecture
90
+ apple_arch = apple_m1_compatible?(driver_version) ? 'arm' : 'mac'
91
+ "#{apple_arch}64"
23
92
  else
24
- 'https://download.microsoft.com/download/3/2/D/32D3E464-F2EF-490F-841B-05D53C848D15/MicrosoftWebDriver.exe'
93
+ raise 'Failed to determine driver filename to download for your OS.'
25
94
  end
26
95
  end
27
96
 
28
- def base_url
29
- 'http://google.com'
97
+ def direct_url(driver_version)
98
+ "#{base_url}/#{driver_version}/edgedriver_#{driver_filename(driver_version)}.zip"
30
99
  end
31
100
  end
32
-
33
101
  end
34
- end
102
+ end
103
+
104
+ ::Selenium::WebDriver::Edge::Service.driver_path = proc { ::Webdrivers::Edgedriver.update }
@@ -1,42 +1,63 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'nokogiri'
4
+ require 'webdrivers/common'
2
5
 
3
6
  module Webdrivers
4
7
  class Geckodriver < Common
5
-
6
8
  class << self
7
- def file_name
8
- platform == "win" ? "geckodriver.exe" : "geckodriver"
9
- end
10
-
9
+ #
10
+ # Returns current geckodriver version.
11
+ #
12
+ # @return [Gem::Version]
11
13
  def current_version
12
- return nil unless File.exists?(binary_path)
13
- %x(#{binary_path} --version).match(/geckodriver (\d\.\d+\.\d+)/)[1]
14
- end
14
+ Webdrivers.logger.debug 'Checking current version'
15
+ return nil unless exists?
15
16
 
16
- def newest_version
17
- padded = downloads.keys.each_with_object({}) do |version, hash|
18
- matched = version.match(/^(\d+)\.(\d+)\.(\d+)$/)
19
- minor = sprintf '%02d', matched[2]
20
- hash["#{matched[1]}.#{minor}.#{matched[3]}"] = version
21
- end
22
- padded.keys.sort.last
17
+ version = binary_version
18
+ return nil if version.nil?
19
+
20
+ normalize_version version.match(/geckodriver (\d+\.\d+\.\d+)/)[1]
23
21
  end
24
22
 
25
- def downloads
26
- doc = Nokogiri::XML.parse(OpenURI.open_uri(base_url))
27
- items = doc.css(".release-downloads a").collect {|item| item["href"]}
28
- items.reject! {|item| item.include?('archive')}
29
- items.select! {|item| item.include?(platform)}
30
- items.each_with_object({}) do |item, hash|
31
- hash[item[/v(\d+\.\d+\.\d+)/, 1]] = "https://github.com#{item}"
32
- end
23
+ #
24
+ # Returns latest available geckodriver version.
25
+ #
26
+ # @return [Gem::Version]
27
+ def latest_version
28
+ @latest_version ||= with_cache(file_name) { normalize_version(Network.get_url("#{base_url}/latest")[/[^v]*$/]) }
33
29
  end
34
30
 
31
+ #
32
+ # Returns url with domain for calls to get this driver.
33
+ #
34
+ # @return [String]
35
35
  def base_url
36
36
  'https://github.com/mozilla/geckodriver/releases'
37
37
  end
38
38
 
39
- end
39
+ private
40
40
 
41
+ def file_name
42
+ System.platform == 'win' ? 'geckodriver.exe' : 'geckodriver'
43
+ end
44
+
45
+ def direct_url(version)
46
+ "#{base_url}/download/v#{version}/geckodriver-v#{version}-#{platform_ext}"
47
+ end
48
+
49
+ def platform_ext
50
+ case System.platform
51
+ when 'linux'
52
+ "linux#{System.bitsize}.tar.gz"
53
+ when 'mac'
54
+ 'macos.tar.gz'
55
+ when 'win'
56
+ "win#{System.bitsize}.zip"
57
+ end
58
+ end
59
+ end
41
60
  end
42
- end
61
+ end
62
+
63
+ ::Selenium::WebDriver::Firefox::Service.driver_path = proc { ::Webdrivers::Geckodriver.update }
@@ -1,35 +1,68 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'nokogiri'
4
+ require 'rubygems/version'
5
+ require 'webdrivers/common'
2
6
 
3
7
  module Webdrivers
4
- class IEDriver < Common
5
-
8
+ class IEdriver < Common
6
9
  class << self
7
- def file_name
8
- "IEDriverServer.exe"
10
+ #
11
+ # Returns current IEDriverServer.exe version.
12
+ #
13
+ # @return [Gem::Version]
14
+ def current_version
15
+ Webdrivers.logger.debug 'Checking current version'
16
+ return nil unless exists?
17
+
18
+ version = binary_version
19
+ return nil if version.nil?
20
+
21
+ normalize_version version.match(/IEDriverServer.exe (\d\.\d+\.\d+)/)[1]
9
22
  end
10
23
 
11
- def current_version
12
- return nil unless File.exists?(binary_path)
13
- %x(#{binary_path} --version).strip.match(/IEDriverServer.exe (\d\.\d+\.\d*\.\d*)/)[1]
24
+ #
25
+ # Returns latest available IEDriverServer.exe version.
26
+ #
27
+ # @return [Gem::Version]
28
+ def latest_version
29
+ @latest_version ||= with_cache(file_name) { downloads.keys.max }
14
30
  end
15
31
 
16
- def newest_version
17
- downloads.keys.sort.last
32
+ #
33
+ # Returns url with domain for calls to get this driver.
34
+ #
35
+ # @return [String]
36
+ def base_url
37
+ 'https://api.github.com/repos/seleniumhq/selenium/releases'
38
+ end
39
+
40
+ private
41
+
42
+ def file_name
43
+ 'IEDriverServer.exe'
44
+ end
45
+
46
+ def direct_url(version)
47
+ downloads[version]
18
48
  end
19
49
 
20
50
  def downloads
21
- doc = Nokogiri::XML.parse(OpenURI.open_uri(base_url))
22
- items = doc.css("Key").collect(&:text)
23
- items.select! { |item| item.include?('IEDriverServer_Win32') }
24
- items.each_with_object({}) do |item, hash|
25
- hash[item[/^[^\/]+/]] = "#{base_url}#{item}"
51
+ ds = download_manifest.each_with_object({}) do |item, hash|
52
+ version = normalize_version item['name'][/\.?([^_]+)\.zip/, 1]
53
+ hash[version] = item['browser_download_url']
26
54
  end
55
+ Webdrivers.logger.debug "Versions now located on downloads site: #{ds.keys}"
56
+ ds
27
57
  end
28
58
 
29
- def base_url
30
- 'http://selenium-release.storage.googleapis.com/'
59
+ def download_manifest
60
+ json = Network.get(base_url)
61
+ all_assets = JSON.parse(json).map { |release| release['assets'] }.flatten
62
+ all_assets.select { |asset| asset['name'].include?('IEDriverServer_Win32') }
31
63
  end
32
64
  end
33
-
34
65
  end
35
- end
66
+ end
67
+
68
+ ::Selenium::WebDriver::IE::Service.driver_path = proc { ::Webdrivers::IEdriver.update }
@@ -0,0 +1,111 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'forwardable'
4
+ require 'logger'
5
+
6
+ # Code adapted from Selenium Implementation
7
+ # https://github.com/SeleniumHQ/selenium/blob/master/rb/lib/selenium/webdriver/common/logger.rb
8
+
9
+ module Webdrivers
10
+ #
11
+ # @example Enable full logging
12
+ # Webdrivers.logger.level = :debug
13
+ #
14
+ # @example Log to file
15
+ # Webdrivers.logger.output = 'webdrivers.log'
16
+ #
17
+ # @example Use logger manually
18
+ # Webdrivers.logger.info('This is info message')
19
+ # Webdrivers.logger.warn('This is warning message')
20
+ #
21
+ class Logger
22
+ extend Forwardable
23
+ include ::Logger::Severity
24
+
25
+ def_delegators :@logger, :debug, :debug?,
26
+ :info, :info?,
27
+ :warn, :warn?,
28
+ :error, :error?,
29
+ :fatal, :fatal?,
30
+ :level
31
+
32
+ def initialize
33
+ @logger = create_logger($stdout)
34
+ end
35
+
36
+ def output=(io)
37
+ # `Logger#reopen` was added in Ruby 2.3
38
+ if @logger.respond_to?(:reopen)
39
+ @logger.reopen(io)
40
+ else
41
+ @logger = create_logger(io)
42
+ end
43
+ end
44
+
45
+ #
46
+ # For Ruby < 2.3 compatibility
47
+ # Based on https://github.com/ruby/ruby/blob/ruby_2_3/lib/logger.rb#L250
48
+ #
49
+
50
+ def level=(severity)
51
+ if severity.is_a?(Integer)
52
+ @logger.level = severity
53
+ else
54
+ case severity.to_s.downcase
55
+ when 'debug'
56
+ @logger.level = DEBUG
57
+ when 'info'
58
+ @logger.level = INFO
59
+ when 'warn'
60
+ @logger.level = WARN
61
+ when 'error'
62
+ @logger.level = ERROR
63
+ when 'fatal'
64
+ @logger.level = FATAL
65
+ when 'unknown'
66
+ @logger.level = UNKNOWN
67
+ else
68
+ raise ArgumentError, "invalid log level: #{severity}"
69
+ end
70
+ end
71
+ end
72
+
73
+ #
74
+ # Returns IO object used by logger internally.
75
+ #
76
+ # Normally, we would have never needed it, but we want to
77
+ # use it as IO object for all child processes to ensure their
78
+ # output is redirected there.
79
+ #
80
+ # It is only used in debug level, in other cases output is suppressed.
81
+ #
82
+ # @api private
83
+ #
84
+ def io
85
+ @logger.instance_variable_get(:@logdev).instance_variable_get(:@dev)
86
+ end
87
+
88
+ #
89
+ # Marks code as deprecated with replacement.
90
+ #
91
+ # @param [String] old
92
+ # @param [String] new
93
+ #
94
+ def deprecate(old, new)
95
+ warn "[DEPRECATION] #{old} is deprecated. Use #{new} instead."
96
+ end
97
+
98
+ private
99
+
100
+ def create_logger(output)
101
+ logger = ::Logger.new(output)
102
+ logger.progname = 'Webdrivers'
103
+ logger.level = ($DEBUG ? DEBUG : WARN)
104
+ logger.formatter = proc do |severity, time, progname, msg|
105
+ "#{time.strftime('%F %T')} #{severity} #{progname} #{msg}\n"
106
+ end
107
+
108
+ logger
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'net/http'
4
+
5
+ module Webdrivers
6
+ #
7
+ # @api private
8
+ #
9
+ class Network
10
+ class << self
11
+ def get(url, limit = 10)
12
+ Webdrivers.logger.debug "Making network call to #{url}"
13
+
14
+ response = get_response(url, limit)
15
+ case response
16
+ when Net::HTTPSuccess
17
+ response.body
18
+ else
19
+ raise NetworkError, "#{response.class::EXCEPTION_TYPE}: #{response.code} \"#{response.message}\" with #{url}"
20
+ end
21
+ end
22
+
23
+ def get_url(url, limit = 10)
24
+ Webdrivers.logger.debug "Making network call to #{url}"
25
+
26
+ get_response(url, limit).uri.to_s
27
+ end
28
+
29
+ def get_response(url, limit = 10)
30
+ raise ConnectionError, 'Too many HTTP redirects' if limit.zero?
31
+
32
+ begin
33
+ response = http.get_response(URI(url))
34
+ rescue SocketError
35
+ raise ConnectionError, "Can not reach #{url}"
36
+ end
37
+
38
+ Webdrivers.logger.debug "Get response: #{response.inspect}"
39
+
40
+ if response.is_a?(Net::HTTPRedirection)
41
+ location = response['location']
42
+ Webdrivers.logger.debug "Redirected to #{location}"
43
+ get_response(location, limit - 1)
44
+ else
45
+ response
46
+ end
47
+ end
48
+
49
+ def http
50
+ if using_proxy
51
+ Net::HTTP.Proxy(Webdrivers.proxy_addr, Webdrivers.proxy_port,
52
+ Webdrivers.proxy_user, Webdrivers.proxy_pass)
53
+ else
54
+ Net::HTTP
55
+ end
56
+ end
57
+
58
+ def using_proxy
59
+ Webdrivers.proxy_addr && Webdrivers.proxy_port
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'webdrivers'
4
+ require 'rails'
5
+
6
+ module Webdrivers
7
+ class Railtie < Rails::Railtie
8
+ railtie_name :webdrivers
9
+
10
+ rake_tasks do
11
+ path = File.expand_path(__dir__)
12
+ Dir.glob("#{path}/tasks/*.rake").each { |f| load f }
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,197 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rubygems/package'
4
+ require 'zip'
5
+ require 'English'
6
+
7
+ # validate zip entry sizes to avoid zip bombs
8
+ # see https://github.com/rubyzip/rubyzip#size-validation
9
+ # and https://github.com/rubyzip/rubyzip/pull/403 for further details
10
+ # this will be the default in rubyzip 2.0+
11
+ Zip.validate_entry_sizes = true
12
+
13
+ module Webdrivers
14
+ #
15
+ # @api private
16
+ #
17
+ class System
18
+ class << self
19
+ def delete(file)
20
+ max_attempts = 3
21
+ attempts_made = 0
22
+ delay = 0.5
23
+
24
+ begin
25
+ attempts_made += 1
26
+ if File.exist? file
27
+ Webdrivers.logger.debug "Deleting #{file}"
28
+ File.delete file
29
+ end
30
+ rescue Errno::EACCES # Solves an intermittent file locking issue on Windows
31
+ sleep(delay)
32
+ retry if File.exist?(file) && attempts_made <= max_attempts
33
+ raise
34
+ end
35
+ end
36
+
37
+ def install_dir
38
+ Webdrivers.install_dir
39
+ end
40
+
41
+ def cache_version(file_name, version)
42
+ FileUtils.mkdir_p(install_dir) unless File.exist?(install_dir)
43
+
44
+ File.open("#{install_dir}/#{file_name.gsub('.exe', '')}.version", 'w+') do |file|
45
+ file.print(version)
46
+ end
47
+ end
48
+
49
+ def cached_version(file_name)
50
+ File.open("#{install_dir}/#{file_name.gsub('.exe', '')}.version", 'r', &:read)
51
+ end
52
+
53
+ def valid_cache?(file_name)
54
+ file = "#{install_dir}/#{file_name.gsub('.exe', '')}.version"
55
+ return false unless File.exist?(file)
56
+
57
+ Time.now - File.mtime(file) < Webdrivers.cache_time
58
+ end
59
+
60
+ def download(url, target)
61
+ FileUtils.mkdir_p(install_dir) unless File.exist?(install_dir)
62
+
63
+ download_file(url, target)
64
+
65
+ FileUtils.chmod 'ugo+rx', target
66
+ Webdrivers.logger.debug "Completed download and processing of #{target}"
67
+ target
68
+ end
69
+
70
+ def download_file(url, target)
71
+ file_name = File.basename(url)
72
+ Dir.chdir(install_dir) do
73
+ tempfile = Tempfile.open(['', file_name], binmode: true) do |file|
74
+ file.print Network.get(url)
75
+ file
76
+ end
77
+
78
+ raise "Could not download #{url}" unless File.exist?(tempfile.to_path)
79
+
80
+ Webdrivers.logger.debug "Successfully downloaded #{tempfile.to_path}"
81
+
82
+ decompress_file(tempfile, file_name, target)
83
+ tempfile.close!
84
+ end
85
+ end
86
+
87
+ def exists?(file)
88
+ result = File.exist? file
89
+ Webdrivers.logger.debug "#{file} is#{' not' unless result} already downloaded"
90
+ result
91
+ end
92
+
93
+ def decompress_file(tempfile, file_name, target)
94
+ tempfile = tempfile.to_path
95
+ case tempfile
96
+ when /tar\.gz$/
97
+ untargz_file(tempfile, File.basename(target))
98
+ when /tar\.bz2$/
99
+ untarbz2_file(tempfile)
100
+ when /\.zip$/
101
+ unzip_file(tempfile, File.basename(target))
102
+ else
103
+ Webdrivers.logger.debug 'No Decompression needed'
104
+ FileUtils.cp(tempfile, File.join(Dir.pwd, file_name))
105
+ end
106
+ raise "Could not decompress #{file_name} to get #{target}" unless File.exist?(File.basename(target))
107
+ end
108
+
109
+ def untarbz2_file(filename)
110
+ Webdrivers.logger.debug "Decompressing #{filename}"
111
+
112
+ call("tar xjf #{filename}").gsub('.tar.bz2', '')
113
+ end
114
+
115
+ def untargz_file(source, target)
116
+ Webdrivers.logger.debug "Decompressing #{source}"
117
+
118
+ tar_extract = Gem::Package::TarReader.new(Zlib::GzipReader.open(source))
119
+
120
+ File.open(target, 'w+b') do |ucf|
121
+ tar_extract.each { |entry| ucf << entry.read }
122
+ File.basename ucf
123
+ end
124
+ end
125
+
126
+ def unzip_file(filename, driver_name)
127
+ Webdrivers.logger.debug "Decompressing #{filename}"
128
+
129
+ Zip::File.open(filename) do |zip_file|
130
+ driver = zip_file.get_entry(driver_name)
131
+ f_path = File.join(Dir.pwd, driver.name)
132
+ delete(f_path)
133
+ FileUtils.mkdir_p(File.dirname(f_path)) unless File.exist?(File.dirname(f_path))
134
+ zip_file.extract(driver, f_path)
135
+ end
136
+ driver_name
137
+ end
138
+
139
+ def platform
140
+ if Selenium::WebDriver::Platform.linux?
141
+ 'linux'
142
+ elsif Selenium::WebDriver::Platform.mac?
143
+ 'mac'
144
+ elsif Selenium::WebDriver::Platform.windows?
145
+ 'win'
146
+ else
147
+ raise NotImplementedError, 'Your OS is not supported by webdrivers gem.'
148
+ end
149
+ end
150
+
151
+ def apple_m1_architecture?
152
+ if platform == 'mac' && RUBY_PLATFORM.include?('arm64-darwin')
153
+ Webdrivers.logger.debug 'Apple architecture: M1 (arm64-darwin)'
154
+ return true
155
+ end
156
+
157
+ Webdrivers.logger.debug 'Apple architecture: Intel (mac64)'
158
+ false
159
+ end
160
+
161
+ # @return [TrueClass, FalseClass]
162
+ def wsl_v1?
163
+ platform == 'linux' && File.open('/proc/version').read.include?('Microsoft')
164
+ end
165
+
166
+ # @param [String] path
167
+ # @return [String]
168
+ def to_win32_path(path)
169
+ return path if /[a-z]:\\/iu.match?(path)
170
+
171
+ call("wslpath -w '#{path}'").chomp
172
+ end
173
+
174
+ # @param [String] path
175
+ # @return [String]
176
+ def to_wsl_path(path)
177
+ call("wslpath -u '#{path}'").chomp
178
+ end
179
+
180
+ def bitsize
181
+ Selenium::WebDriver::Platform.bitsize
182
+ end
183
+
184
+ def call(process, arg = nil)
185
+ cmd = arg ? [process, arg] : process # Windows provides powershell command (process) only, no args.
186
+ Webdrivers.logger.debug "making System call: #{cmd}"
187
+ p = IO.popen(cmd)
188
+ out = p.read
189
+ p.close
190
+ raise "Failed to make system call: #{cmd}" unless $CHILD_STATUS.success?
191
+
192
+ Webdrivers.logger.debug "System call returned: #{out}"
193
+ out
194
+ end
195
+ end
196
+ end
197
+ end