selenium_tor 1.0.0 → 1.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cd34aa798531de8ada12d53163c343733610aa6115141d58aeaa3b4875c40cd6
4
- data.tar.gz: f989c3ca02651ba825beefde17a4f2ac007ae25bb7c09e29ca080eee24cd3d03
3
+ metadata.gz: 99d3e4260b0873513c67db620d3057d61078b4c1cbae7b5c8c7b3e4cfdbbfbec
4
+ data.tar.gz: bb02cb9d07024a4798723185f4103246dac9b4c008e3f20abec5f710426a26a6
5
5
  SHA512:
6
- metadata.gz: 1a71cffb60fc1e7f58d4a8cb4ffc9b0b42abfca1f5c541332b0febf50b78440fb5adfacb76f18e7289184bd7fb185582c4b338f6c2cde8177847b0db4e9a8ba7
7
- data.tar.gz: 3c9291018aede2ef805bf96110ff3742b4e2791634801be4ac607ad27e4d318ddafe931950946499a8547883c48ca750d6af9a409674b91e40cf9cce41e418b5
6
+ metadata.gz: 654db110ca016a71d04b6def25d4befb86efc27cd2c0cce1ed7874834921d309262bc537b6b23bf8b77603b4d29960c88a10d83c8508ce6398b1d44a13577df1
7
+ data.tar.gz: 7d7369f8055ca42c229079d8732ab49d8d1467af49d35c547528dd792f1208101abcd123a6f05873b9fee4b704863a364708fc9148850f798635b9f3f6b3b8da
data/.rubocop.yml CHANGED
@@ -27,3 +27,7 @@ Style/RegexpLiteral:
27
27
 
28
28
  Minitest/TestMethodName:
29
29
  Enabled: true
30
+
31
+ Minitest/TestFileName:
32
+ Exclude:
33
+ - test/features/fingerprinting/vglrun_test_fingerprintjs.rb
data/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  ## master (unreleased)
2
2
 
3
+ ## [1.1.0] - 2024-07-28
4
+
5
+ ### Bug fixes
6
+
7
+ * [#9](https://gitlab.com/matzfan/selenium-tor/-/issues/9)
8
+
9
+ ### New features
10
+
11
+ * deprecate SystemTor options IFO tor_opts
12
+
3
13
  ## [1.0.0] - 2024-07-15
4
14
 
5
15
  ### New features
data/README.md CHANGED
@@ -44,40 +44,36 @@ options = Selenium::WebDriver::Tor::Options.new
44
44
  @driver.title # => Congratulations. This browser is configured to use Tor.
45
45
  @driver.quit
46
46
  ```
47
- By default Tor Broswer will use the bundled `tor` process, in which case the driver will not be instantiated until a connection to the Tor network is made. If the network is inaccessible for any reason a `TorNetworkError` will result.
47
+ If the network is inaccessible for any reason a `TorNetworkError` will result.
48
48
 
49
- ### Multiple instances using the system tor
49
+ ### Multiple driver instances
50
50
 
51
- The following options require `tor` to be installed. Tor is available via various package managers e.g. `sudo apt install tor`.
52
-
53
- If a `SystemTor` object is passed to options, the system `tor` will be used instead of the `tor` included in the Tor Browser Bundle (TBB).
54
- ```ruby
55
- system_tor = Selenium::WebDriver::Tor::SystemTor.new # writes a driver-specific torrc file
56
- options = Selenium::WebDriver::Tor::Options.new system_tor: system_tor
57
- @driver = Selenium::WebDriver.for :tor, options: options # new tor process started when :system_tor option passed to driver
58
- @driver.get 'https://example.com'
59
- @driver.quit # stops the new system tor process and deletes torrc file
60
- ```
61
- Multiple instances may be instantiated, in which case `SystemTor` options for :socks_port (default 9150) and :control_port (default 9151) must be set for each so they do not conflict. For example:
51
+ Running multiple `tor` processes requires that each uses different ports for SocksPort and ControlPort. These and other valid tor options can be passed using the `:tor_opts` key. Recognized options are snake_case equivalents of the camel case options reconized by tor. For a list see `man tor`. An example using the [Parallel gem](https://rubygems.org/gems/parallel):
62
52
  ```ruby
63
- def new_driver(socks_p, control_p)
64
- system_tor = Selenium::WebDriver::Tor::SystemTor.new(socks_port: socks_p, control_port: control_p)
65
- options = Selenium::WebDriver::Tor::Options.new system_tor: system_tor
66
- Selenium::WebDriver.for :tor, options: options
67
- end
53
+ require 'parallel'
68
54
 
69
55
  socks_port = 9150
70
56
  control_port = 9151
71
57
 
72
- driver1 = new_driver(socks_port, control_port)
73
- socks_port += 2
74
- control_port += 2
75
- driver2 = new_driver(socks_port, control_port)
58
+ def driver(socks_p, control_p)
59
+ options = Selenium::WebDriver::Tor::Options.new tor_opts: { socks_port: socks_p, control_port: control_p }
60
+ Selenium::WebDriver.for :tor, options: options # new tor process started with tor_opts
61
+ end
62
+
63
+ driver1 = driver(socks_port, control_port)
64
+ driver2 = driver(socks_port += 2, control_port += 2)
76
65
 
77
- driver1.quit
78
- driver2.quit
79
- ```
66
+ title = 'Congratulations. This browser is configured to use Tor.'
80
67
 
68
+ Parallel.all?([driver1, driver2], in_threads: 2) do |driver|
69
+ driver.get 'https://check.torproject.org'
70
+ driver.title == title
71
+ end
72
+ # => true
73
+
74
+ driver1&.quit
75
+ driver2&.quit
76
+ ```
81
77
  The `Selenium::WebDriver::Tor` namespace is used for `Driver`, `Options`, `Profile` and all tor-specific classes. Otherwise Selenium's `Selenium::WebDriver::Firefox` namespace is used.
82
78
 
83
79
  Remote functionality is not tested, but may be if a suitable Tor Browser Docker container becomes available.
@@ -0,0 +1,7 @@
1
+ DO NOT MODIFY THE CONTENTS OF THIS DIRECTORY
2
+
3
+ Any adjustment to bundled fonts will result in an altered fingerprint. Font
4
+ fingerprinting is more than just detecting what fonts you have, it also includes
5
+ font fallbacks and characters (unicode code points) and any change in those can
6
+ be measured.
7
+
data/lib/tor/driver.rb CHANGED
@@ -1,58 +1,55 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'open-uri'
4
- require_relative 'driver_not_yet_connected_to_tor_network'
4
+ require_relative '../service'
5
+ require_relative '../options'
6
+ require_relative 'profile'
7
+ require_relative 'tor_process'
5
8
 
6
9
  module Selenium
7
10
  module WebDriver
8
11
  module Tor
12
+ # delegate class so extensions can be added & connection to tor made
13
+ class DriverNotYetConnectedToTorNetwork < Firefox::Driver; end
14
+
9
15
  # tor driver
10
16
  class Driver < DelegateClass(DriverNotYetConnectedToTorNetwork)
11
17
  class TorNetworkError < StandardError; end
12
18
 
13
- CONNECT_BUTTON_ID = 'network-status-tor-connect-button' # visible only until connected
14
- TOR_PREFS_CONNECTION_URL = 'about:preferences#connection'
15
-
16
- attr_reader :system_tor
17
-
18
19
  def initialize(options: nil, **)
19
- instantiate_driver_from_tbb_dir(options: options, **)
20
- setup_system_tor options.system_tor if options&.system_tor
20
+ @data_dir = Dir.mktmpdir
21
+ add_torrc_path_to_options options
22
+ @instance = DriverNotYetConnectedToTorNetwork.new(options: options, **)
21
23
  super(@instance)
22
- install_extensions
23
- wait_for_tor_connection unless system_tor # no need if system tor used
24
+ install_extensions(@instance)
25
+ create_tor_process_and_start_tor options&.tor_opts
26
+ end
27
+
28
+ def browser
29
+ :tor # overides :firefox
24
30
  end
25
31
 
26
32
  def quit
27
- system_tor&.stop_tor
33
+ @tor_process&.stop_tor
34
+ FileUtils.rm_rf @data_dir
28
35
  super
29
36
  end
30
37
 
31
38
  private
32
39
 
33
- def instantiate_driver_from_tbb_dir(...)
34
- cwd = FileUtils.pwd
35
- FileUtils.cd TBB_BROWSER_DIR # crucial - fixes [#2](https://gitlab.com/matzfan/selenium-tor/-/issues/2)
36
- @instance = DriverNotYetConnectedToTorNetwork.new(...)
37
- ensure
38
- FileUtils.cd cwd
39
- end
40
+ def add_torrc_path_to_options(options)
41
+ return unless options
40
42
 
41
- def wait_for_tor_connection
42
- @instance.get TOR_PREFS_CONNECTION_URL
43
- Wait.new(timeout: 10).until { !@instance.find_element(:id, CONNECT_BUTTON_ID).displayed? }
44
- rescue Selenium::WebDriver::Error::TimeoutError => e
45
- @instance.quit # abort initialization
46
- raise TorNetworkError, "Cannot connect to Tor network: #{e.message}"
43
+ options.prefs['extensions.torlauncher.torrc_path'] = File.join(@data_dir, 'torrc')
47
44
  end
48
45
 
49
- def install_extensions
50
- Pathname.new(TBB_EXTENSIONS_DIR).children.each { |xpi_path| @instance.install_addon xpi_path }
46
+ def install_extensions(instance)
47
+ Pathname.new(TBB_EXTENSIONS_DIR).children.each { |xpi_path| instance.install_addon xpi_path }
51
48
  end
52
49
 
53
- def setup_system_tor(system_tor)
54
- @system_tor = system_tor
55
- system_tor.start_tor
50
+ def create_tor_process_and_start_tor(opts)
51
+ @tor_process = TorProcess.new(@data_dir, opts || {})
52
+ @tor_process.start_tor
56
53
  end
57
54
  end
58
55
  end
data/lib/tor/options.rb CHANGED
@@ -9,44 +9,47 @@ module Selenium
9
9
  module Tor
10
10
  # tor options
11
11
  class Options < Firefox::Options
12
- CAPABILITIES = CAPABILITIES.merge(system_tor: 'system_tor')
12
+ CAPABILITIES = CAPABILITIES.merge(tor_opts: 'tor_opts')
13
+ CAPABILITIES[:system_tor] = 'system_tor' # DEPRECATED 2.0
13
14
  DEFAULT_TBB_DIR = File.join Dir.home, 'tor-browser'
14
15
 
15
16
  Tor::TBB_DIR = ENV.fetch('TOR_BROWSER_ROOT_DIR', nil) || DEFAULT_TBB_DIR
16
17
  Tor::TBB_BROWSER_DIR = File.join Tor::TBB_DIR, 'Browser'
17
18
  Tor::TBB_BINARY_PATH = File.join Tor::TBB_BROWSER_DIR, 'firefox'
19
+ Tor::TBB_TOR_BINARY_PATH = File.join Tor::TBB_BROWSER_DIR, *%w[TorBrowser Tor tor]
18
20
  Tor::TBB_PROFILE_DIR = File.join Tor::TBB_BROWSER_DIR, *%w[TorBrowser Data Browser profile.default]
19
21
  Tor::TBB_EXTENSIONS_DIR = File.join Tor::TBB_PROFILE_DIR, 'extensions'
20
22
  Tor::TBB_VERSION = JSON.parse(File.read(File.join(Tor::TBB_BROWSER_DIR, 'tbb_version.json')))['version']
21
23
 
22
- attr_reader :system_tor # read by Driver
24
+ attr_reader :tor_opts
23
25
 
24
26
  def initialize(log_level: nil, **opts)
25
- @system_tor_prefs = {}
26
- system_tor_prefs(opts.delete(:system_tor)) if opts[:system_tor] # must be deleted before call to super
27
+ opts[:tor_opts] = opts.delete(:system_tor).opts if opts[:system_tor] # DEPRECATED 2.0
28
+ @tor_opts = opts[:tor_opts] ? opts.delete(:tor_opts) : {} # must be deleted before call to super
27
29
  super(log_level: log_level, **tor_options(opts.delete(:prefs)).merge(opts))
28
30
  do_start_tor_browser_script_stuff # stuff the start-tor-browser script in TBB does
31
+ copy_fonts # so we don't have to change dir before executing TB binary #2 and #9
29
32
  end
30
33
 
31
34
  private
32
35
 
33
- def system_tor_prefs(system_tor)
34
- @system_tor = system_tor
35
- @system_tor_prefs = system_tor.prefs
36
- end
37
-
38
36
  def tor_options(prefs)
39
- { binary: TBB_BINARY_PATH, prefs: (prefs || {}).merge(TOR_PREFS).merge(@system_tor_prefs) }
37
+ { binary: TBB_BINARY_PATH, prefs: (prefs || {}).merge(TOR_PREFS) }
40
38
  end
41
39
 
42
40
  def do_start_tor_browser_script_stuff
43
41
  ENV['SESSION_MANAGER'] = nil
44
42
  ENV['XAUTHORITY'] = File.join(Dir.home, '.Xauthority') unless ENV.fetch('XAUTHORITY', nil)
45
- ENV['FONTCONFIG_PATH'] = File.join Tor::TBB_BROWSER_DIR, 'fontconfig' # supposed to stop font leaks..
43
+ ENV['FONTCONFIG_PATH'] = File.join TBB_BROWSER_DIR, 'fontconfig'
46
44
  ENV['FONTCONFIG_FILE'] = 'fonts.conf'
47
45
  FileUtils.rm_rf File.join(Tor::TBB_BROWSER_DIR, *%w[TorBrowser Data fontconfig])
48
46
  ENV['GSETTINGS_BACKEND'] = 'memory'
49
- # cd to TBB_BROWSER_DIR now handled in Tor::Driver
47
+ end
48
+
49
+ def copy_fonts
50
+ return unless Dir[File.join('fonts', '*')].size == 1 # README checked into git
51
+
52
+ FileUtils.cp(Dir[File.join(Tor::TBB_BROWSER_DIR, 'fonts', '*')], File.expand_path('fonts'))
50
53
  end
51
54
  end
52
55
  end
@@ -1,82 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'timeout'
4
- require_relative 'torrc'
5
- require_relative '../string_extensions'
6
-
7
3
  module Selenium
8
4
  module WebDriver
9
5
  module Tor
10
- # Respresentation of a system tor process
6
+ # DEPRECATED
11
7
  class SystemTor
12
- include StringExtensions
13
-
14
- class SystemTorError < StandardError; end
15
-
16
- BOOTSTRAP_SUCCESS_REGEX = /Bootstrapped 100% \(done\): Done$/
17
- BOOTSTRAP_FAIL_REGEX = /^[A-Z][a-z]{2} \d{1,2} \d{2}:\d{2}:\d{2}\.\d{3} \[err\] .*/
18
- # BOOTSTRAP_TIMEOUT_REGEX = /^[A-Z][a-z]{2} \d{1,2} \d{2}:\d{2}:\d{2}\.\d{3} \[err\] .*/
19
-
20
- TORRC_PREFS = { 'extensions.torlauncher.start_tor' => false }.freeze
21
- TORRC_PATH_KEY = 'extensions.torlauncher.torrc_path'
22
-
23
- attr_reader :pid, :config
8
+ attr_reader :opts
24
9
 
25
10
  def initialize(opts = {})
26
- raise SystemTorError, 'tor executable not found in PATH' unless tor_executable?
27
- raise ArgumentError, 'SystemTor.new takes an options hash' unless opts.is_a? Hash
28
-
29
- @opts = map_opts_to_torrc_keys opts
30
- @data_dir = Dir.mktmpdir # each tor process needs a separate data directory
31
- @torrc = Torrc.new(@data_dir)
32
- @config ||= setup_config # Hash to store torrc config
33
- end
34
-
35
- def prefs
36
- TORRC_PREFS.merge({ TORRC_PATH_KEY => @torrc.path })
37
- end
38
-
39
- def start_tor
40
- r, io = IO.pipe
41
- pid = Process.spawn "tor -f #{@torrc.path}", out: io, err: :out
42
- io.close
43
- errors = parse_tor_bootstrap_errors r
44
- errors.empty? ? @pid = pid : raise(SystemTorError, "Tor failed to start with errors:\n\n#{errors}")
45
- ensure
46
- r.close
47
- end
48
-
49
- def stop_tor
50
- Process.kill 'KILL', pid if pid
51
- FileUtils.rm_rf @data_dir if @data_dir
52
- @pid = nil
53
- end
54
-
55
- private
56
-
57
- def map_opts_to_torrc_keys(opts)
58
- raise SystemTorError, 'Options hash keys must be snake case' unless opts.keys.map!(&:to_s).all?(&:snake_case?)
59
-
60
- opts.transform_keys { |k| k.to_s.split('_').map(&:capitalize).join }
61
- end
62
-
63
- def setup_config
64
- @torrc.write_to_config @opts
65
- @torrc.config
66
- end
67
-
68
- def tor_executable?
69
- `which tor`
70
- end
71
-
72
- def parse_tor_bootstrap_errors(io)
73
- lines = []
74
- io.each_line do |line|
75
- lines << line
76
- break lines if line.match BOOTSTRAP_FAIL_REGEX
77
- break [] if line.match BOOTSTRAP_SUCCESS_REGEX
78
- # break false if line.match BOOTSTRAP_TIMEOUT_REGEX
79
- end
11
+ warn '[DEPRECATION] `SystemTor` options are deprecated in `selenium_tor` 2.0. Use `tor_opts` instead.'
12
+ @opts = opts
80
13
  end
81
14
  end
82
15
  end
data/lib/tor/tor_prefs.rb CHANGED
@@ -17,7 +17,8 @@ module Selenium
17
17
 
18
18
  OTHER_PREFS = {
19
19
  'intl.language_notification.shown' => true, # affects font fingerprint (viewport size)
20
- 'remote.active-protocols' => 3 # CDP & BiDi future support
20
+ 'remote.active-protocols' => 3, # CDP & BiDi future support
21
+ 'extensions.torlauncher.start_tor' => false
21
22
  }.freeze
22
23
 
23
24
  TOR_PREFS = FIRST_CONNECTION_PREFS.merge OTHER_PREFS
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'timeout'
4
+ require_relative 'torrc'
5
+ require_relative '../string_extensions'
6
+
7
+ module Selenium
8
+ module WebDriver
9
+ module Tor
10
+ # Respresentation of a tor process
11
+ class TorProcess
12
+ include StringExtensions
13
+
14
+ class TorProcessError < StandardError; end
15
+
16
+ BOOTSTRAP_SUCCESS_REGEX = /Bootstrapped 100% \(done\): Done$/
17
+ BOOTSTRAP_FAIL_REGEX = /^[A-Z][a-z]{2} \d{1,2} \d{2}:\d{2}:\d{2}\.\d{3} \[err\] .*/
18
+ # BOOTSTRAP_TIMEOUT_REGEX = /^[A-Z][a-z]{2} \d{1,2} \d{2}:\d{2}:\d{2}\.\d{3} \[err\] .*/
19
+
20
+ attr_reader :pid, :config
21
+
22
+ def initialize(data_dir, opts = {})
23
+ valid_data_dir?(data_dir)
24
+ raise ArgumentError, 'TorProcess.new takes an options hash' unless opts.is_a? Hash
25
+
26
+ @data_dir = data_dir # each tor process needs a separate data directory
27
+ @opts = map_opts_to_torrc_keys opts
28
+ @torrc = Torrc.new(@data_dir)
29
+ @config ||= setup_config # Hash to store torrc config
30
+ end
31
+
32
+ def start_tor
33
+ r, io = IO.pipe
34
+ pid = Process.spawn "#{TBB_TOR_BINARY_PATH} -f #{@torrc.path}", out: io, err: :out
35
+ io.close
36
+ errors = parse_tor_bootstrap_errors r
37
+ errors.empty? ? @pid = pid : raise(TorProcessError, "Tor failed to start with errors:\n\n#{errors}")
38
+ ensure
39
+ r.close
40
+ end
41
+
42
+ def stop_tor
43
+ Process.kill 'KILL', pid if pid
44
+ FileUtils.rm_rf @data_dir if @data_dir
45
+ @pid = nil
46
+ end
47
+
48
+ # private
49
+
50
+ def valid_data_dir?(dir)
51
+ msg = 'data_dir must exist and be a dir'
52
+ raise ArgumentError, msg unless Pathname.new(dir.to_s).directory? && Pathname.new(dir.to_s).empty?
53
+ end
54
+
55
+ def map_opts_to_torrc_keys(opts)
56
+ raise TorProcessError, 'Options keys must be snake case' unless opts.keys.map!(&:to_s).all?(&:snake_case?)
57
+
58
+ opts.transform_keys { |k| k.to_s.split('_').map(&:capitalize).join }
59
+ end
60
+
61
+ def setup_config
62
+ @torrc.write_to_config @opts
63
+ @torrc.config
64
+ end
65
+
66
+ def parse_tor_bootstrap_errors(io)
67
+ lines = []
68
+ io.each_line do |line|
69
+ lines << line
70
+ break lines.join if line.match BOOTSTRAP_FAIL_REGEX
71
+ break '' if line.match BOOTSTRAP_SUCCESS_REGEX
72
+ # break false if line.match BOOTSTRAP_TIMEOUT_REGEX
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
data/lib/tor/torrc.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'options' # for Tor::TBB_TOR_BINARY_PATH
4
+
3
5
  module Selenium
4
6
  module WebDriver
5
7
  module Tor
@@ -41,7 +43,7 @@ module Selenium
41
43
  tmp = Tempfile.new
42
44
  tmp.write hash_to_config_string(hash)
43
45
  tmp.rewind
44
- invalid_opts = parse_invalid_opts `tor -f #{tmp.path} --verify-config`
46
+ invalid_opts = parse_invalid_opts `#{TBB_TOR_BINARY_PATH} -f #{tmp.path} --verify-config`
45
47
  raise TorrcError, "Invalid torrc opts: #{invalid_opts}" unless invalid_opts.empty?
46
48
  ensure
47
49
  tmp.unlink
data/lib/tor/version.rb CHANGED
@@ -3,7 +3,7 @@
3
3
  module Selenium
4
4
  module WebDriver
5
5
  module Tor
6
- VERSION = '1.0.0'
6
+ VERSION = '1.1.0'
7
7
  end
8
8
  end
9
9
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: selenium_tor
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - MatzFan
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-07-15 00:00:00.000000000 Z
11
+ date: 2024-07-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: selenium-webdriver
@@ -39,17 +39,18 @@ files:
39
39
  - LICENSE.txt
40
40
  - README.md
41
41
  - Rakefile
42
+ - fonts/000_README.txt
42
43
  - lib/driver.rb
43
44
  - lib/options.rb
44
45
  - lib/selenium_tor.rb
45
46
  - lib/service.rb
46
47
  - lib/string_extensions.rb
47
48
  - lib/tor/driver.rb
48
- - lib/tor/driver_not_yet_connected_to_tor_network.rb
49
49
  - lib/tor/options.rb
50
50
  - lib/tor/profile.rb
51
51
  - lib/tor/system_tor.rb
52
52
  - lib/tor/tor_prefs.rb
53
+ - lib/tor/tor_process.rb
53
54
  - lib/tor/torrc.rb
54
55
  - lib/tor/version.rb
55
56
  - selenium_tor.gemspec
@@ -77,7 +78,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
77
78
  - !ruby/object:Gem::Version
78
79
  version: '0'
79
80
  requirements: []
80
- rubygems_version: 3.5.15
81
+ rubygems_version: 3.5.16
81
82
  signing_key:
82
83
  specification_version: 4
83
84
  summary: Selenium extension for Tor Browser
@@ -1,18 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative '../service'
4
- require_relative '../options'
5
- require_relative '../tor/profile'
6
-
7
- module Selenium
8
- module WebDriver
9
- module Tor
10
- # subclass - doesn't wait to be connected to tor network
11
- class DriverNotYetConnectedToTorNetwork < Firefox::Driver
12
- def browser
13
- :tor # overides :firefox
14
- end
15
- end
16
- end
17
- end
18
- end