selenium_tor 1.7.0 → 2.0.1

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: e0b43f3c595a9b52864114bd23e728e824349b3cd514dbc30cbf3bdaca3e1f09
4
- data.tar.gz: 45a4d53c8881fa99b6530c11d28131195c57d355f1caba27e4ed51181d52b368
3
+ metadata.gz: 3a9593a60ababf45d1e54bf5583d46bb778b4e34c86559189eda2f855436acb8
4
+ data.tar.gz: c8e3250798ac2b5b1be3d61d1971e155bc648d0882f5998cf8fc9f7818157ba0
5
5
  SHA512:
6
- metadata.gz: a8cf7f476a0aaa8d25d79e904c4d485e147f0527bdde799f46e62f0d2b140a83ace68cf5601e5b21c2f47cb5106004cbdde1ed99ce8625444d5e906a0014a3e3
7
- data.tar.gz: 81c8bef22783b315ec3e4c570f601d8dd442478b30c813c069b491b66665443f6fff05827721e7610b266f28877db38c6c85420dfa13e69e4e7e8e84b187d864
6
+ metadata.gz: edc94603c8979106bde423b38e00465c7038168742060c2a3e4880eb870a4910727b14701398a409d305273f3eb7547769ad5610d89d18c806edc76d5e61c706
7
+ data.tar.gz: 3f3157dde56b05f7046df3364a49a8f5d57586828dce22697b9fbe5d3e86d0b866ba60b20124da4635eb7aa4457589b2f4be9daac94139321d5aa16405f015ed
data/.rubocop.yml CHANGED
@@ -34,3 +34,6 @@ Minitest/TestMethodName:
34
34
 
35
35
  Minitest/AssertTruthy:
36
36
  Enabled: false
37
+
38
+ Minitest/RefuteFalse:
39
+ Enabled: false
data/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  ## master (unreleased)
2
2
 
3
+ ## [2.0.0] - 2025-05-31
4
+
5
+ * fix bug loading selenium-webdriver in IRB
6
+
7
+ ## [2.0.0] - 2025-05-31
8
+
9
+ ### New features
10
+
11
+ * SocksPort is now auto selected, 'SocksPort'/:socks_port keys are ignored in Tor::Options :tor_opts hash
12
+ * selenium-manager is disabled (avoids chance of FF being downloaded & used)
13
+ * errors in Tor namespace now subclass Selenium::WebDriver::Error::WebDriverError
14
+ * drop Xvfb/headless gem dependency
15
+ * drop deprecated :system_tor options
16
+
17
+ ### Bug fixes
18
+
19
+ * ControlPort no longer set by default in torrc (security)
20
+
3
21
  ## [1.7.0] - 2025-05-21
4
22
 
5
23
  ### New features
data/README.md CHANGED
@@ -8,7 +8,8 @@ A Selenium extension for Tor Browser.
8
8
  # before_all
9
9
  require 'selenium_tor'
10
10
 
11
- options = Selenium::WebDriver::Tor::Options.new
11
+ options = Selenium::WebDriver::Options.tor
12
+ options.args << '-headless'
12
13
  @driver = Selenium::WebDriver.for :tor, options: options
13
14
  ```
14
15
  When you are done don't forget to quit the driver. Failure to do so may leave orphaned tor processes.
@@ -18,6 +19,9 @@ When you are done don't forget to quit the driver. Failure to do so may leave or
18
19
  ```
19
20
  Once you have a driver instance:
20
21
  ```ruby
22
+ @driver
23
+ # => instance_of Selenium::WebDriver::Tor::Driver
24
+
21
25
  @driver.get 'https://check.torproject.org'
22
26
  @driver.title
23
27
  # => "Congratulations. This browser is configured to use Tor."
@@ -43,11 +47,11 @@ If bundler is not being used to manage dependencies, install the gem by executin
43
47
 
44
48
  [Tor Browser](https://www.torproject.org/download). Tests are conducted with the latest stable ('release') and alpha versions of Tor Browser. Support for older versions is periodically dropped - see the CHANGELOG.
45
49
 
46
- As with Firefox browser, `geckodriver` needs to be installed and in your PATH.
50
+ As with Firefox browser, `geckodriver` needs to be installed and in your PATH. [Selenium Manager](https://www.selenium.dev/documentation/selenium_manager) is disabled for security reasons, so you are responsible for ensuring the correct (latest) version of geckodriver is installed.
47
51
 
48
52
  The gem needs to know the location of the Tor Browser Bundle (TBB). The Tor Browser download package archive must be extracted and the root TBB directory (named "tor-browser") placed somewhere on your system. By default it is assumed to be in the current user's HOME directory. An alternative location can be set via the env var `TOR_BROWSER_ROOT_DIR` - e.g. `export TOR_BROWSER_ROOT_DIR=/home/<user>/Downloads`. The Tor Browser binary location is *automatically set* by reference to this directory, so there is no need to do this:
49
53
  ```ruby
50
- options = Selenium::WebDriver::Tor::Options.new
54
+ options = Selenium::WebDriver::Options.tor
51
55
  options.binary = '/some/path/to/tor_firefox_binary' # UNNECESSARY
52
56
  # => '/some/path/to/tor_firefox_binary'
53
57
  ```
@@ -56,21 +60,6 @@ The location of the TBB is not expected to change during code execution.
56
60
 
57
61
  Tor Selenium is tested on **Linux only** right now.
58
62
 
59
- ### Patching libxul.so
60
-
61
- A configuration option to patch the `libxul.so` packaged with Tor Browser is provided. This has the effect of preventing websites from fingerprinting Selenium-driven Tor Browser via a JS call to `navigator.webdriver`:
62
- ```ruby
63
- @driver_class = Selenium::WebDriver::Tor::Driver
64
- @driver_class.libxul_patched? # is Tor Browser's libxul.so patched?
65
- # => false
66
- @driver_class.patch_libxul # patch libxul.so
67
- @driver_class.libxul_patched?
68
- # => true
69
- @driver_class.unpatch_libxul # revert the patch and restore the libxul.so packaged with Tor Browser
70
- # => 0
71
- ```
72
- The patcher uses the [Bsdiff](https://gitlab.com/matzfan/bsdiff) gem.
73
-
74
63
  ## Usage
75
64
  ```ruby
76
65
  require 'selenium_tor'
@@ -84,21 +73,17 @@ A separate tor process is used for each driver. Failure to call `Driver#quit` af
84
73
 
85
74
  ### Tor options
86
75
 
87
- In addition to the regular Firefox options, a :tor_opts key may be passed to an instance of `Tor::Options` with a hash of tor options. All valid tor options are recognized - see `man tor`. For convenience, "SocksPort" and "ControlPort" options may be set using snake_case symbols - i.e. :socks_port and :control_port. Additionally, a :tor_opts timeout value may be set with the :timeout key. This overrides the default time allowed for the tor process to bootstrap (10 seconds).
76
+ In addition to the regular Firefox options, a `:tor_opts` key may be passed to an instance of `Tor::Options` with a hash of tor options. All valid tor client options are recognized - see `man tor`. Snake case key symbols may be used if these can be coerced to valid camel case key strings - e.g. `:control_port` becomes 'ControlPort'. Additionally, a `:tor_opts` timeout value may be set with the `:timeout` key. This overrides the default time allowed for the tor process to bootstrap (10 seconds).
88
77
 
89
78
  ### Multiple driver instances
90
79
 
91
- Running multiple tor processes requires that each uses different ports for SocksPort (and ControlPort, if used). These must be passed using the `:tor_opts` key. An example using the [Parallel gem](https://rubygems.org/gems/parallel):
80
+ Running multiple tor processes requires that each uses different ports for SocksPort (and ControlPort, if used). From version 2.0 the SocksPort is auto selected, so no configuration is required. An example using the [Parallel gem](https://rubygems.org/gems/parallel):
92
81
  ```ruby
93
82
  require 'parallel'
94
83
 
95
- @socks_port = 9150
96
- @control_port = 9151
97
-
98
84
  def driver
99
- @socks_port += 2
100
- @control_port += 2
101
- options = Selenium::WebDriver::Tor::Options.new tor_opts: { socks_port: @socks_port, control_port: @control_port }
85
+ options = Selenium::WebDriver::Options.tor # no needs to pass SocksPort in :tor_opts from version 2.0
86
+ options.args << '-headless'
102
87
  Selenium::WebDriver.for :tor, options: options
103
88
  end
104
89
 
@@ -155,24 +140,34 @@ Tor::TBB_EXTENSIONS_DIR # path to the 'extensions' directory in the above
155
140
  Tor::TBB_VERSION # the version installed, e.g. "13.0.1", note: driver.capabilities.browser_version returns the Firefox version Tor Browser is based on
156
141
  # => instance_of String
157
142
  ```
143
+ ### Patching libxul.so
158
144
 
159
- ## Known issues
145
+ A configuration option to patch the `libxul.so` packaged with Tor Browser is provided. This has the effect of preventing websites from fingerprinting Selenium-driven Tor Browser via a JS call to `navigator.webdriver`:
146
+ ```ruby
147
+ @driver_class = Selenium::WebDriver::Tor::Driver
148
+ @driver_class.libxul_patched? # is Tor Browser's libxul.so patched?
149
+ # => false
150
+ @driver_class.patch_libxul # patch libxul.so
151
+ @driver_class.libxul_patched?
152
+ # => true
153
+ @driver_class.unpatch_libxul # revert the patch and restore the libxul.so packaged with Tor Browser
154
+ # => 0
155
+ ```
156
+ The patcher uses the [Bsdiff](https://gitlab.com/matzfan/bsdiff) gem.
160
157
 
161
- Known issues are recorded [here](https://gitlab.com/matzfan/selenium-tor/-/issues).
158
+ ### Exceptions
162
159
 
163
- ### Fingerprinting
160
+ Tor-specific webdriver functionality raises `Tor::Error` or a subclass. `Tor::Error` itself subclasses `WebDriver::Error::WebDriverError`
164
161
 
165
- The gem uses Xvfb to allow Tor Browser to be manipulated headlessly. Xvfb in turn uses `llvmpipe` software acceleration which may lead to issues with WebGL fingerprinting - see [issue #7](https://gitlab.com/matzfan/selenium-tor/-/issues/7). If this is a problem we recommend using [VirtualGL](https://www.virtualgl.org) to force Xvfb to use your hardware driver instead. This is done by prepending your executable code with the command `vglrun`. For an example take a look at the `test_fingerprintjs_with_virtualgl.rb` test. VirtualGL can be installed from a [package repo](https://virtualgl.org/Downloads/YUM).
162
+ ## Known issues
163
+
164
+ Known issues are recorded [here](https://gitlab.com/matzfan/selenium-tor/-/issues).
166
165
 
167
166
  ## Testing
168
167
 
169
168
  ~~After checking out the repo, run `bin/setup` to install dependencies.~~
170
169
 
171
- Tests dependencies are `Xvfb` if you want to run headless tests and `VirtualGL` (see Fingerprinting above). The latter can be skipped by setting ENV var `CI` to `true`.
172
-
173
- Tests are run in the display set by the `DISPLAY` env var, usually :0 by default. To run headless tests, set it to another value:
174
-
175
- $ DISPLAY=:99 bundle exec rake
170
+ $ bundle exec rake
176
171
 
177
172
  If you find driver instantiation failing with port bind failure error messages ( these include "Address already in use. Is Tor already running?") check you have no other tor processes running with conflicting ports. With timeout errors, you may also want to check the Tor network is actually up, it isn't always..
178
173
 
data/lib/selenium_tor.rb CHANGED
@@ -1,4 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ ENV['SE_OFFLINE'] = 'true' # we don't want selenium-manager getting & using firefox in error
4
+ ENV['SE_AVOID_STATS'] = 'true' # no telemetry thanks!
5
+
3
6
  require 'selenium-webdriver'
7
+ load $LOADED_FEATURES.last # force load to ensure env vars are applied
8
+
4
9
  require_relative 'driver'
data/lib/tor/driver.rb CHANGED
@@ -18,12 +18,20 @@ module Selenium
18
18
  class Driver < DelegateClass(DriverDelegate)
19
19
  extend LibxulPatchable
20
20
 
21
- TORRC_PATH_PREF = 'extensions.torlauncher.torrc_path'
22
- TORRC = 'torrc'
23
- BROWSER_SECURITY_LEVEL_PREF = 'browser.security_level.security_slider'
24
- DOMAIN_ISOLATOR = 'TorDomainIsolator' # ES6 module
25
- NEW_CIRCUIT = 'newCircuitForDomain' # js function
26
- TB_SEC_LEVELS = { 'standard' => 4, 'safer' => 2, 'safest' => 1 }.freeze
21
+ TORRC = 'torrc'
22
+
23
+ PREF_BROWSER_SECURITY_LEVEL = 'browser.security_level.security_slider'
24
+ PREF_TORRC_PATH = 'extensions.torlauncher.torrc_path'
25
+ PREF_SOCKS_PORT = 'network.proxy.socks_port'
26
+
27
+ DOMAIN_ISOLATOR = 'TorDomainIsolator' # ES6 module
28
+ NEW_CIRCUIT = 'newCircuitForDomain' # js function
29
+
30
+ TB_SEC_LEVELS = { 'standard' => 4, 'safer' => 2, 'safest' => 1 }.freeze
31
+
32
+ LOCALHOST_PORT_REGEXP = /127\.0\.0\.1:(\d+)/
33
+
34
+ attr_reader :tor_process
27
35
 
28
36
  def initialize(options: nil, **)
29
37
  @data_dir = Dir.mktmpdir
@@ -31,7 +39,8 @@ module Selenium
31
39
  add_torrc_path_to_options
32
40
  @instance = DriverDelegate.new(options: @options, **)
33
41
  install_extensions @instance
34
- create_tor_process_and_start_tor @options.tor_opts
42
+ pid = create_tor_process_and_start_tor(@options.tor_opts)
43
+ @instance.pref[PREF_SOCKS_PORT] = socks_port(pid)
35
44
  super(@instance)
36
45
  end
37
46
 
@@ -46,13 +55,13 @@ module Selenium
46
55
  end
47
56
 
48
57
  def security_level
49
- pref[BROWSER_SECURITY_LEVEL_PREF]
58
+ pref[PREF_BROWSER_SECURITY_LEVEL]
50
59
  end
51
60
 
52
61
  def security_level=(int)
53
62
  raise(ArgumentError, "Valid security levels are: #{TB_SEC_LEVELS.values}") unless TB_SEC_LEVELS.value?(int)
54
63
 
55
- pref[BROWSER_SECURITY_LEVEL_PREF] = int
64
+ pref[PREF_BROWSER_SECURITY_LEVEL] = int
56
65
  end
57
66
 
58
67
  def new_circuit_for_site
@@ -64,7 +73,7 @@ module Selenium
64
73
  private
65
74
 
66
75
  def add_torrc_path_to_options
67
- @options.prefs[TORRC_PATH_PREF] = File.join(@data_dir, TORRC)
76
+ @options.prefs[PREF_TORRC_PATH] = File.join(@data_dir, TORRC)
68
77
  end
69
78
 
70
79
  def install_extensions(instance)
@@ -73,20 +82,25 @@ module Selenium
73
82
 
74
83
  def create_tor_process_and_start_tor(opts)
75
84
  timeout = opts.delete :timeout
76
- @tor_process = tor_process(opts)
85
+ @tor_process = create_tor_process(opts)
77
86
  @tor_process.start_tor(timeout: timeout)
78
87
  rescue Tor::TorProcess::TorProcessError => e
79
88
  instance_variable_get(:@instance)&.quit # avoids hanging firefox.real process
80
89
  raise Error::WebDriverError, e
81
90
  end
82
91
 
83
- def tor_process(opts)
92
+ def create_tor_process(opts)
84
93
  TorProcess.new(@data_dir, opts || {})
85
94
  end
86
95
 
87
96
  def domain
88
97
  URI(current_url).host&.match(/[^\.]+\.\w+$/)
89
98
  end
99
+
100
+ def socks_port(pid)
101
+ str = `netstat -tnlp 2>/dev/null|grep #{pid}/tor` # net-tools dep
102
+ str.match(LOCALHOST_PORT_REGEXP)[1].to_i
103
+ end
90
104
  end
91
105
  end
92
106
  end
data/lib/tor/error.rb ADDED
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal:true
2
+
3
+ require 'selenium-webdriver'
4
+
5
+ # errors
6
+ module Selenium
7
+ module WebDriver
8
+ module Tor
9
+ class Error < WebDriver::Error::WebDriverError; end
10
+
11
+ class TorrcError < Error; end
12
+
13
+ class TorProcessError < Error; end
14
+
15
+ class LibxulPatchableError < Error; end
16
+ end
17
+ end
18
+ end
@@ -1,4 +1,8 @@
1
1
  ---
2
+ 14.5.3:
3
+ unpatched_libxul: 88c9aef61ca0df4c617a8c7c589194bd8ff31d1d7a6360512e1ab1cfc81390a8
4
+ patched_libxul: 18e6f350a2a8983395ffac984aac1a7a431d2acb0c97faa69d6f965199b67e2c
5
+ patch_checksum: b216ba4ad661e79e9cbf648837e1f18282490ee504f5970a2cb1ae7f847dd271
2
6
  14.5.2:
3
7
  unpatched_libxul: 0e4d960cb427df67a25ab50aa934272e7ac7ee3487c709e48d97e2611e2ae930
4
8
  patched_libxul: 20579db140991d77db1a3ffa3e248752dd689bf4156056402cbe1fd6287430c1
@@ -5,6 +5,8 @@ require 'digest'
5
5
  require 'json'
6
6
  require 'open-uri'
7
7
  require 'yaml'
8
+
9
+ require_relative 'error'
8
10
  require_relative 'options' # module needs access to consts therein defined
9
11
 
10
12
  module Selenium
@@ -12,19 +14,17 @@ module Selenium
12
14
  module Tor
13
15
  # methods to patch/unpatch libxul.so
14
16
  module LibxulPatchable
15
- class LibxulPatchableError < StandardError; end
16
-
17
- PATCH_REPO = 'https://gitlab.com/matzfan/keymaster/-/raw/master/patches/tor-browser'
18
- ISSUES_URL = 'https://gitlab.com/matzfan/keymaster/-/issues'
19
- NO_PATCH_MSG = "No patch for #{Tor::TBB_VERSION}, please raise an issue at #{ISSUES_URL}".freeze
20
- UNDEF_REGEXP = /undefined method (`|')\[\]' for nil/
17
+ PATCH_REPO_URL = 'https://gitlab.com/matzfan/keymaster/-/raw/master/patches/tor-browser'
18
+ ISSUES_URL = 'https://gitlab.com/matzfan/keymaster/-/issues'
19
+ NO_PATCH_MSG = "No patch for #{Tor::TBB_VERSION}, please raise an issue at #{ISSUES_URL}".freeze
20
+ UNDEF_REGEXP = /undefined method (`|')\[\]' for nil/
21
21
 
22
22
  def libxul_patched?
23
23
  libxul_checksum = checksum_for Tor::TBB_LIBXUL
24
24
  return true if patched_libxul_checksum_for_version == libxul_checksum
25
25
  return false if unpatched_libxul_checksum_for_version == libxul_checksum
26
26
 
27
- raise LibxulPatchableError, 'Unrecognized libxul.so'
27
+ raise Tor::LibxulPatchableError, 'Unrecognized libxul.so'
28
28
  end
29
29
 
30
30
  def patch_libxul
@@ -36,7 +36,7 @@ module Selenium
36
36
  execute_patch patchfile
37
37
  FileUtils.cp libxul_patched, Tor::TBB_LIBXUL
38
38
  rescue OpenURI::HTTPError
39
- raise LibxulPatchableError, NO_PATCH_MSG
39
+ raise Tor::LibxulPatchableError, NO_PATCH_MSG
40
40
  end
41
41
 
42
42
  def unpatch_libxul
@@ -57,7 +57,7 @@ module Selenium
57
57
 
58
58
  def valid?(patchfile)
59
59
  msg = "Invalid patch for #{Tor::TBB_VERSION}, please raise an issue at #{ISSUES_URL}"
60
- raise LibxulPatchableError, msg unless patch_checksum_for_version == checksum_for(patchfile)
60
+ raise Tor::LibxulPatchableError, msg unless patch_checksum_for_version == checksum_for(patchfile)
61
61
  end
62
62
 
63
63
  def execute_patch(patchfile)
@@ -71,7 +71,7 @@ module Selenium
71
71
  def unpatched_libxul_checksum_for_version
72
72
  libxul_checksums['unpatched_libxul']
73
73
  rescue NoMethodError => e
74
- raise LibxulPatchableError, NO_PATCH_MSG if e.message.match UNDEF_REGEXP
74
+ raise Tor::LibxulPatchableError, NO_PATCH_MSG if e.message.match UNDEF_REGEXP
75
75
 
76
76
  raise e
77
77
  end
@@ -79,7 +79,7 @@ module Selenium
79
79
  def patched_libxul_checksum_for_version
80
80
  libxul_checksums['patched_libxul']
81
81
  rescue NoMethodError => e
82
- raise LibxulPatchableError, NO_PATCH_MSG if e.message.match UNDEF_REGEXP
82
+ raise Tor::LibxulPatchableError, NO_PATCH_MSG if e.message.match UNDEF_REGEXP
83
83
 
84
84
  raise e
85
85
  end
@@ -87,7 +87,7 @@ module Selenium
87
87
  def patch_checksum_for_version
88
88
  libxul_checksums['patch_checksum']
89
89
  rescue NoMethodError => e
90
- raise LibxulPatchableError, NO_PATCH_MSG if e.message.match UNDEF_REGEXP
90
+ raise Tor::LibxulPatchableError, NO_PATCH_MSG if e.message.match UNDEF_REGEXP
91
91
 
92
92
  raise e
93
93
  end
@@ -106,7 +106,7 @@ module Selenium
106
106
  end
107
107
 
108
108
  def patch_url
109
- File.join PATCH_REPO, "#{Tor::TBB_VERSION}.patch"
109
+ File.join PATCH_REPO_URL, "#{Tor::TBB_VERSION}.patch"
110
110
  end
111
111
  end
112
112
  end
data/lib/tor/options.rb CHANGED
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'tor_prefs'
4
- require_relative 'system_tor'
5
4
  require 'selenium-webdriver'
6
5
 
7
6
  module Selenium
@@ -9,25 +8,23 @@ module Selenium
9
8
  module Tor
10
9
  # tor options
11
10
  class Options < Firefox::Options
12
- CAPABILITIES = CAPABILITIES.merge(tor_opts: 'tor_opts')
13
- CAPABILITIES[:system_tor] = 'system_tor' # DEPRECATED 2.0
11
+ CAPABILITIES = CAPABILITIES.merge(tor_opts: 'tor_opts')
14
12
  DEFAULT_TBB_DIR = File.join Dir.home, 'tor-browser'
15
13
 
16
- Tor::TBB_DIR = ENV.fetch('TOR_BROWSER_ROOT_DIR', nil) || DEFAULT_TBB_DIR
17
- Tor::TBB_BROWSER_DIR = File.join Tor::TBB_DIR, 'Browser'
18
- Tor::TBB_LIBXUL = File.join Tor::TBB_BROWSER_DIR, 'libxul.so'
19
- Tor::TBB_BINARY_PATH = File.join Tor::TBB_BROWSER_DIR, 'firefox'
14
+ Tor::TBB_DIR = ENV.fetch('TOR_BROWSER_ROOT_DIR', nil) || DEFAULT_TBB_DIR
15
+ Tor::TBB_BROWSER_DIR = File.join Tor::TBB_DIR, 'Browser'
16
+ Tor::TBB_LIBXUL = File.join Tor::TBB_BROWSER_DIR, 'libxul.so'
17
+ Tor::TBB_BINARY_PATH = File.join Tor::TBB_BROWSER_DIR, 'firefox'
20
18
  Tor::TBB_TOR_BINARY_PATH = File.join Tor::TBB_BROWSER_DIR, *%w[TorBrowser Tor tor]
21
- Tor::TBB_TOR_DATA_DIR = File.join Tor::TBB_BROWSER_DIR, *%w[TorBrowser Data Tor]
22
- Tor::TBB_PROFILE_DIR = File.join Tor::TBB_BROWSER_DIR, *%w[TorBrowser Data Browser profile.default]
23
- Tor::TBB_EXTENSIONS_DIR = File.join Tor::TBB_PROFILE_DIR, 'extensions'
24
- Tor::TBB_VERSION = JSON.parse(File.read(File.join(Tor::TBB_BROWSER_DIR, 'tbb_version.json')))['version']
19
+ Tor::TBB_TOR_DATA_DIR = File.join Tor::TBB_BROWSER_DIR, *%w[TorBrowser Data Tor]
20
+ Tor::TBB_PROFILE_DIR = File.join Tor::TBB_BROWSER_DIR, *%w[TorBrowser Data Browser profile.default]
21
+ Tor::TBB_EXTENSIONS_DIR = File.join Tor::TBB_PROFILE_DIR, 'extensions'
22
+ Tor::TBB_VERSION = JSON.parse(File.read(File.join(Tor::TBB_BROWSER_DIR, 'tbb_version.json')))['version']
25
23
 
26
24
  attr_reader :tor_opts
27
25
 
28
26
  def initialize(log_level: nil, **opts)
29
- opts[:tor_opts] = opts.delete(:system_tor).opts if opts[:system_tor] # DEPRECATED 2.0
30
- @tor_opts = opts[:tor_opts] ? opts.delete(:tor_opts) : {} # must be deleted before call to super
27
+ @tor_opts = opts[:tor_opts] ? opts.delete(:tor_opts) : {}
31
28
  do_start_tor_browser_script_stuff # stuff the start-tor-browser script in TBB does
32
29
  super(log_level: log_level, **tor_options(opts.delete(:prefs)).merge(opts))
33
30
  end
@@ -39,10 +36,10 @@ module Selenium
39
36
  end
40
37
 
41
38
  def do_start_tor_browser_script_stuff
42
- ENV['SESSION_MANAGER'] = nil
43
- ENV['XAUTHORITY'] = File.join(Dir.home, '.Xauthority') unless ENV.fetch('XAUTHORITY', nil)
44
- FileUtils.rm_rf File.join(Tor::TBB_BROWSER_DIR, *%w[TorBrowser Data fontconfig])
39
+ ENV['SESSION_MANAGER'] = nil
45
40
  ENV['GSETTINGS_BACKEND'] = 'memory'
41
+ ENV['XAUTHORITY'] = File.join(Dir.home, '.Xauthority') unless ENV.fetch('XAUTHORITY', nil)
42
+ FileUtils.rm_rf File.join(Tor::TBB_BROWSER_DIR, *%w[TorBrowser Data fontconfig])
46
43
  end
47
44
  end
48
45
  end
data/lib/tor/tor_prefs.rb CHANGED
@@ -18,7 +18,7 @@ module Selenium
18
18
  OTHER_PREFS = {
19
19
  'intl.language_notification.shown' => true, # affects font fingerprint (viewport size)
20
20
  'remote.active-protocols' => 1, # BiDi only >= 4.32 https://github.com/SeleniumHQ/selenium/pull/15224/files
21
- 'extensions.torlauncher.start_tor' => false
21
+ 'extensions.torlauncher.start_tor' => false # no settings Connection pane
22
22
  }.freeze
23
23
 
24
24
  TOR_PREFS = FIRST_CONNECTION_PREFS.merge OTHER_PREFS
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'timeout'
4
+ require_relative 'error'
4
5
  require_relative 'torrc'
5
6
 
6
7
  module Selenium
@@ -8,12 +9,10 @@ module Selenium
8
9
  module Tor
9
10
  # Respresentation of a tor process
10
11
  class TorProcess
11
- class TorProcessError < StandardError; end
12
-
13
12
  BOOTSTRAP_SUCCESS_REGEX = /Bootstrapped 100% \(done\): Done$/
14
- BOOTSTRAP_FAIL_REGEX = /^[A-Z][a-z]{2} \d{2} \d{2}:\d{2}:\d{2}\.\d{3} \[err\] .*/
13
+ BOOTSTRAP_FAIL_REGEX = /^[A-Z][a-z]{2} \d{2} \d{2}:\d{2}:\d{2}\.\d{3} \[err\] .*/
15
14
 
16
- DIR_MSG = 'data_dir must exist and be a dir'
15
+ DIR_MSG = 'data_dir must exist and be a dir'
17
16
  DATA_FILES = %w[cached-certs cached-microdesc-consensus cached-microdescs.new].freeze
18
17
 
19
18
  class << self
@@ -36,6 +35,7 @@ module Selenium
36
35
  pid = Process.spawn tor_command, out: io, err: :out
37
36
  io.close
38
37
  parse_tor_bootstrap_errors_with_timeout(r, timeout: timeout)
38
+ # tor process now bootstrapped
39
39
  read_from_data_files
40
40
  @pid = pid
41
41
  rescue Timeout::Error
@@ -88,7 +88,7 @@ module Selenium
88
88
  break '' if line.match BOOTSTRAP_SUCCESS_REGEX
89
89
  end
90
90
  end
91
- raise(TorProcessError, "Tor failed to start with errors:\n\n#{errors}") unless errors.empty?
91
+ raise(Tor::TorProcessError, "Tor failed to start with errors:\n\n#{errors}") unless errors.empty?
92
92
  end
93
93
 
94
94
  def read_from_data_files
@@ -101,7 +101,7 @@ module Selenium
101
101
 
102
102
  def timeout_with(pid, timeout)
103
103
  Process.kill 'KILL', pid if pid
104
- raise Error::TimeoutError, "Tor not bootstrapped after #{timeout} seconds"
104
+ raise WebDriver::Error::TimeoutError, "Tor not bootstrapped after #{timeout} seconds" # regular s-w error
105
105
  end
106
106
  end
107
107
  end
data/lib/tor/torrc.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'error'
3
4
  require_relative 'options'
4
5
 
5
6
  module Selenium
@@ -7,9 +8,7 @@ module Selenium
7
8
  module Tor
8
9
  # Respresentation of a torrc file
9
10
  class Torrc
10
- class TorrcError < StandardError; end
11
-
12
- DEFAULT_PORTS = { 'SocksPort' => 9150, 'ControlPort' => 9151 }.freeze
11
+ FIXED_CONFIG_KEYS = %w[DataDirectory GeoIPFile GeoIPv6File SocksPort].freeze
13
12
  INVALID_OPTION_REGEX = %r{\[warn\] Failed to parse/validate config: (.*).$}
14
13
 
15
14
  attr_reader :path
@@ -29,20 +28,26 @@ module Selenium
29
28
  raise ArgumentError, 'Torrc#write_to_config takes a hash as argument' unless hash.is_a? Hash
30
29
 
31
30
  validate_torrc_options hash
32
- @torrc_file.write hash_to_config_string(config.merge(hash))
31
+ @torrc_file.write hash_to_config_string(config.merge(hash).merge(fixed_config))
33
32
  @torrc_file.rewind
34
33
  end
35
34
 
36
35
  private
37
36
 
38
37
  def write_default_config
39
- write_to_config DEFAULT_PORTS.merge(default_config)
38
+ write_to_config fixed_config
39
+ end
40
+
41
+ def fixed_config
42
+ @fixed_config ||= FIXED_CONFIG_KEYS.zip([@data_dir, geoip_file, geoip6_file, 'auto']).to_h
43
+ end
44
+
45
+ def geoip_file
46
+ File.join(TBB_TOR_DATA_DIR, 'geoip')
40
47
  end
41
48
 
42
- def default_config
43
- { 'DataDirectory' => @data_dir,
44
- 'GeoIPFile' => File.join(TBB_TOR_DATA_DIR, 'geoip'),
45
- 'GeoIPv6File' => File.join(TBB_TOR_DATA_DIR, 'geoip6') }
49
+ def geoip6_file
50
+ File.join(TBB_TOR_DATA_DIR, 'geoip6')
46
51
  end
47
52
 
48
53
  def validate_torrc_options(hash)
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.7.0'
6
+ VERSION = '2.0.1'
7
7
  end
8
8
  end
9
9
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: selenium_tor
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.7.0
4
+ version: 2.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - MatzFan
@@ -202,11 +202,11 @@ files:
202
202
  - lib/selenium_tor.rb
203
203
  - lib/service.rb
204
204
  - lib/tor/driver.rb
205
+ - lib/tor/error.rb
205
206
  - lib/tor/libxul_checksums.yml
206
207
  - lib/tor/libxul_patchable.rb
207
208
  - lib/tor/options.rb
208
209
  - lib/tor/profile.rb
209
- - lib/tor/system_tor.rb
210
210
  - lib/tor/tor_prefs.rb
211
211
  - lib/tor/tor_process.rb
212
212
  - lib/tor/torrc.rb
@@ -1,17 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Selenium
4
- module WebDriver
5
- module Tor
6
- # DEPRECATED
7
- class SystemTor
8
- attr_reader :opts
9
-
10
- def initialize(opts = {})
11
- warn '[DEPRECATION] `SystemTor` options are deprecated in `selenium_tor` 2.0. Use `tor_opts` instead.'
12
- @opts = opts
13
- end
14
- end
15
- end
16
- end
17
- end