selenium-webdriver 4.1.0 → 4.9.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.
Files changed (157) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +234 -1
  3. data/Gemfile +2 -0
  4. data/LICENSE +1 -1
  5. data/NOTICE +1 -1
  6. data/README.md +1 -1
  7. data/bin/linux/selenium-manager +0 -0
  8. data/bin/macos/selenium-manager +0 -0
  9. data/bin/windows/selenium-manager.exe +0 -0
  10. data/lib/selenium/server.rb +36 -27
  11. data/lib/selenium/webdriver/atoms/findElements.js +0 -0
  12. data/lib/selenium/webdriver/atoms/getAttribute.js +0 -0
  13. data/lib/selenium/webdriver/atoms/isDisplayed.js +0 -0
  14. data/lib/selenium/webdriver/atoms/mutationListener.js +0 -0
  15. data/lib/selenium/webdriver/atoms.rb +2 -3
  16. data/lib/selenium/webdriver/bidi/browsing_context.rb +88 -0
  17. data/lib/selenium/webdriver/bidi/browsing_context_info.rb +35 -0
  18. data/lib/selenium/webdriver/bidi/log/base_log_entry.rb +35 -0
  19. data/lib/selenium/webdriver/bidi/log/console_log_entry.rb +35 -0
  20. data/lib/selenium/webdriver/bidi/log/filter_by.rb +40 -0
  21. data/lib/selenium/webdriver/bidi/log/generic_log_entry.rb +33 -0
  22. data/lib/selenium/webdriver/bidi/log/javascript_log_entry.rb +33 -0
  23. data/lib/selenium/webdriver/bidi/log_inspector.rb +143 -0
  24. data/lib/selenium/webdriver/bidi/navigate_result.rb +33 -0
  25. data/lib/selenium/webdriver/bidi/session.rb +51 -0
  26. data/lib/selenium/webdriver/bidi.rb +56 -0
  27. data/lib/selenium/webdriver/chrome/driver.rb +9 -29
  28. data/lib/selenium/webdriver/chrome/features.rb +6 -68
  29. data/lib/selenium/webdriver/chrome/options.rb +3 -223
  30. data/lib/selenium/webdriver/chrome/profile.rb +3 -83
  31. data/lib/selenium/webdriver/chrome/service.rb +3 -23
  32. data/lib/selenium/webdriver/chrome.rb +0 -14
  33. data/lib/selenium/webdriver/chromium/driver.rb +61 -0
  34. data/lib/selenium/webdriver/chromium/features.rb +103 -0
  35. data/lib/selenium/webdriver/chromium/options.rb +261 -0
  36. data/lib/selenium/webdriver/chromium/profile.rb +113 -0
  37. data/lib/selenium/webdriver/chromium/service.rb +42 -0
  38. data/lib/selenium/webdriver/chromium.rb +32 -0
  39. data/lib/selenium/webdriver/common/action_builder.rb +64 -22
  40. data/lib/selenium/webdriver/common/child_process.rb +124 -0
  41. data/lib/selenium/webdriver/common/driver.rb +36 -74
  42. data/lib/selenium/webdriver/common/driver_extensions/downloads_files.rb +0 -2
  43. data/lib/selenium/webdriver/common/driver_extensions/full_page_screenshot.rb +0 -1
  44. data/lib/selenium/webdriver/common/driver_extensions/has_addons.rb +0 -2
  45. data/lib/selenium/webdriver/common/driver_extensions/has_apple_permissions.rb +0 -2
  46. data/lib/selenium/webdriver/common/driver_extensions/has_authentication.rb +0 -2
  47. data/lib/selenium/webdriver/common/driver_extensions/{has_remote_status.rb → has_bidi.rb} +10 -5
  48. data/lib/selenium/webdriver/common/driver_extensions/has_casting.rb +10 -1
  49. data/lib/selenium/webdriver/common/driver_extensions/has_cdp.rb +0 -2
  50. data/lib/selenium/webdriver/common/driver_extensions/has_context.rb +1 -4
  51. data/lib/selenium/webdriver/common/driver_extensions/has_debugger.rb +0 -2
  52. data/lib/selenium/webdriver/common/driver_extensions/has_devtools.rb +0 -2
  53. data/lib/selenium/webdriver/common/driver_extensions/has_launching.rb +0 -2
  54. data/lib/selenium/webdriver/common/driver_extensions/has_location.rb +1 -2
  55. data/lib/selenium/webdriver/common/driver_extensions/has_log_events.rb +1 -2
  56. data/lib/selenium/webdriver/common/driver_extensions/has_network_conditions.rb +0 -2
  57. data/lib/selenium/webdriver/common/driver_extensions/has_network_interception.rb +2 -69
  58. data/lib/selenium/webdriver/common/driver_extensions/has_permissions.rb +0 -2
  59. data/lib/selenium/webdriver/common/driver_extensions/has_pinned_scripts.rb +1 -3
  60. data/lib/selenium/webdriver/common/driver_finder.rb +44 -0
  61. data/lib/selenium/webdriver/common/element.rb +8 -8
  62. data/lib/selenium/webdriver/common/error.rb +1 -3
  63. data/lib/selenium/webdriver/common/html5/shared_web_storage.rb +2 -2
  64. data/lib/selenium/webdriver/common/interactions/input_device.rb +10 -4
  65. data/lib/selenium/webdriver/common/interactions/interaction.rb +12 -25
  66. data/lib/selenium/webdriver/common/interactions/interactions.rb +24 -4
  67. data/lib/selenium/webdriver/common/interactions/key_actions.rb +5 -1
  68. data/lib/selenium/webdriver/common/interactions/key_input.rb +11 -27
  69. data/lib/selenium/webdriver/common/interactions/none_input.rb +10 -8
  70. data/lib/selenium/webdriver/common/interactions/pause.rb +49 -0
  71. data/lib/selenium/webdriver/common/interactions/pointer_actions.rb +59 -70
  72. data/lib/selenium/webdriver/common/interactions/pointer_cancel.rb +45 -0
  73. data/lib/selenium/webdriver/common/interactions/pointer_event_properties.rb +63 -0
  74. data/lib/selenium/webdriver/common/interactions/pointer_input.rb +15 -84
  75. data/lib/selenium/webdriver/common/interactions/pointer_move.rb +60 -0
  76. data/lib/selenium/webdriver/common/interactions/pointer_press.rb +85 -0
  77. data/lib/selenium/webdriver/common/interactions/scroll.rb +59 -0
  78. data/lib/selenium/webdriver/common/interactions/scroll_origin.rb +48 -0
  79. data/lib/selenium/webdriver/common/interactions/typing_interaction.rb +54 -0
  80. data/lib/selenium/webdriver/common/interactions/wheel_actions.rb +113 -0
  81. data/lib/selenium/webdriver/common/interactions/wheel_input.rb +42 -0
  82. data/lib/selenium/webdriver/common/keys.rb +1 -0
  83. data/lib/selenium/webdriver/common/local_driver.rb +55 -0
  84. data/lib/selenium/webdriver/common/logger.rb +76 -24
  85. data/lib/selenium/webdriver/common/manager.rb +0 -27
  86. data/lib/selenium/webdriver/common/options.rb +32 -17
  87. data/lib/selenium/webdriver/common/platform.rb +8 -5
  88. data/lib/selenium/webdriver/common/port_prober.rb +1 -1
  89. data/lib/selenium/webdriver/common/profile_helper.rb +1 -1
  90. data/lib/selenium/webdriver/common/proxy.rb +1 -1
  91. data/lib/selenium/webdriver/common/search_context.rb +0 -6
  92. data/lib/selenium/webdriver/common/selenium_manager.rb +108 -0
  93. data/lib/selenium/webdriver/common/service.rb +20 -23
  94. data/lib/selenium/webdriver/common/service_manager.rb +8 -15
  95. data/lib/selenium/webdriver/common/shadow_root.rb +2 -3
  96. data/lib/selenium/webdriver/common/socket_lock.rb +3 -3
  97. data/lib/selenium/webdriver/common/socket_poller.rb +2 -2
  98. data/lib/selenium/webdriver/common/takes_screenshot.rb +2 -3
  99. data/lib/selenium/webdriver/common/target_locator.rb +2 -3
  100. data/lib/selenium/webdriver/common/timeouts.rb +2 -2
  101. data/lib/selenium/webdriver/common/virtual_authenticator/credential.rb +85 -0
  102. data/lib/selenium/webdriver/common/virtual_authenticator/virtual_authenticator.rb +72 -0
  103. data/lib/selenium/webdriver/common/virtual_authenticator/virtual_authenticator_options.rb +62 -0
  104. data/lib/selenium/webdriver/common/websocket_connection.rb +164 -0
  105. data/lib/selenium/webdriver/common/window.rb +6 -6
  106. data/lib/selenium/webdriver/common/zipper.rb +1 -1
  107. data/lib/selenium/webdriver/common.rb +21 -3
  108. data/lib/selenium/webdriver/devtools/console_event.rb +0 -2
  109. data/lib/selenium/webdriver/devtools/exception_event.rb +0 -2
  110. data/lib/selenium/webdriver/devtools/mutation_event.rb +0 -2
  111. data/lib/selenium/webdriver/devtools/network_interceptor.rb +173 -0
  112. data/lib/selenium/webdriver/devtools/pinned_script.rb +0 -2
  113. data/lib/selenium/webdriver/devtools/request.rb +1 -3
  114. data/lib/selenium/webdriver/devtools/response.rb +1 -3
  115. data/lib/selenium/webdriver/devtools.rb +17 -114
  116. data/lib/selenium/webdriver/edge/driver.rb +9 -3
  117. data/lib/selenium/webdriver/edge/features.rb +4 -4
  118. data/lib/selenium/webdriver/edge/options.rb +3 -5
  119. data/lib/selenium/webdriver/edge/profile.rb +2 -2
  120. data/lib/selenium/webdriver/edge/service.rb +2 -6
  121. data/lib/selenium/webdriver/firefox/driver.rb +9 -2
  122. data/lib/selenium/webdriver/firefox/features.rb +6 -6
  123. data/lib/selenium/webdriver/firefox/options.rb +9 -3
  124. data/lib/selenium/webdriver/firefox/profile.rb +8 -12
  125. data/lib/selenium/webdriver/firefox/service.rb +0 -6
  126. data/lib/selenium/webdriver/firefox/util.rb +46 -0
  127. data/lib/selenium/webdriver/firefox.rb +1 -14
  128. data/lib/selenium/webdriver/ie/driver.rb +7 -1
  129. data/lib/selenium/webdriver/ie/service.rb +1 -7
  130. data/lib/selenium/webdriver/ie.rb +0 -14
  131. data/lib/selenium/webdriver/remote/{commands.rb → bridge/commands.rb} +15 -8
  132. data/lib/selenium/webdriver/remote/bridge.rb +65 -35
  133. data/lib/selenium/webdriver/remote/capabilities.rb +34 -12
  134. data/lib/selenium/webdriver/remote/driver.rb +19 -14
  135. data/lib/selenium/webdriver/remote/http/common.rb +3 -3
  136. data/lib/selenium/webdriver/remote/http/curb.rb +1 -3
  137. data/lib/selenium/webdriver/remote/http/default.rb +7 -12
  138. data/lib/selenium/webdriver/remote/response.rb +2 -3
  139. data/lib/selenium/webdriver/remote.rb +0 -1
  140. data/lib/selenium/webdriver/safari/driver.rb +7 -1
  141. data/lib/selenium/webdriver/safari/features.rb +0 -2
  142. data/lib/selenium/webdriver/safari/options.rb +5 -1
  143. data/lib/selenium/webdriver/safari/service.rb +0 -4
  144. data/lib/selenium/webdriver/safari.rb +1 -15
  145. data/lib/selenium/webdriver/support/color.rb +22 -22
  146. data/lib/selenium/webdriver/support/guards/guard.rb +0 -2
  147. data/lib/selenium/webdriver/support/guards/guard_condition.rb +1 -3
  148. data/lib/selenium/webdriver/support/guards.rb +1 -1
  149. data/lib/selenium/webdriver/support/relative_locator.rb +0 -1
  150. data/lib/selenium/webdriver/support/select.rb +3 -1
  151. data/lib/selenium/webdriver/version.rb +1 -1
  152. data/lib/selenium/webdriver.rb +5 -4
  153. data/selenium-webdriver.gemspec +13 -12
  154. metadata +70 -73
  155. data/lib/selenium/webdriver/remote/http/persistent.rb +0 -65
  156. data/lib/selenium/webdriver/support/cdp/domain.rb.erb +0 -63
  157. data/lib/selenium/webdriver/support/cdp_client_generator.rb +0 -108
@@ -20,59 +20,49 @@
20
20
  module Selenium
21
21
  module WebDriver
22
22
  class DevTools
23
- RESPONSE_WAIT_TIMEOUT = 30
24
- RESPONSE_WAIT_INTERVAL = 0.1
25
-
26
23
  autoload :ConsoleEvent, 'selenium/webdriver/devtools/console_event'
27
24
  autoload :ExceptionEvent, 'selenium/webdriver/devtools/exception_event'
28
25
  autoload :MutationEvent, 'selenium/webdriver/devtools/mutation_event'
26
+ autoload :NetworkInterceptor, 'selenium/webdriver/devtools/network_interceptor'
29
27
  autoload :PinnedScript, 'selenium/webdriver/devtools/pinned_script'
30
28
  autoload :Request, 'selenium/webdriver/devtools/request'
31
29
  autoload :Response, 'selenium/webdriver/devtools/response'
32
30
 
33
31
  def initialize(url:)
34
- @callback_threads = ThreadGroup.new
35
-
36
- @messages = []
32
+ @ws = WebSocketConnection.new(url: url)
37
33
  @session_id = nil
38
- @url = url
39
-
40
- process_handshake
41
- @socket_thread = attach_socket_listener
42
34
  start_session
43
35
  end
44
36
 
45
37
  def close
46
- @callback_threads.list.each(&:exit)
47
- @socket_thread.exit
48
- socket.close
38
+ @ws.close
49
39
  end
50
40
 
51
41
  def callbacks
52
- @callbacks ||= Hash.new { |callbacks, event| callbacks[event] = [] }
42
+ @ws.callbacks
53
43
  end
54
44
 
55
45
  def send_cmd(method, **params)
56
- id = next_id
57
- data = {id: id, method: method, params: params.reject { |_, v| v.nil? }}
46
+ data = {method: method, params: params.compact}
58
47
  data[:sessionId] = @session_id if @session_id
59
- data = JSON.generate(data)
60
- WebDriver.logger.debug "DevTools -> #{data}"
61
-
62
- out_frame = WebSocket::Frame::Outgoing::Client.new(version: ws.version, data: data, type: 'text')
63
- socket.write(out_frame.to_s)
64
-
65
- message = wait.until do
66
- @messages.find { |m| m['id'] == id }
67
- end
68
-
48
+ message = @ws.send_cmd(**data)
69
49
  raise Error::WebDriverError, error_message(message['error']) if message['error']
70
50
 
71
51
  message
72
52
  end
73
53
 
74
54
  def method_missing(method, *_args)
75
- desired_class = "Selenium::DevTools::V#{Selenium::DevTools.version}::#{method.capitalize}"
55
+ namespace = "Selenium::DevTools::V#{Selenium::DevTools.version}"
56
+ methods_to_classes = "#{namespace}::METHODS_TO_CLASSES"
57
+
58
+ desired_class = if Object.const_defined?(methods_to_classes)
59
+ # selenium-devtools 0.113 and newer
60
+ "#{namespace}::#{Object.const_get(methods_to_classes)[method]}"
61
+ else
62
+ # selenium-devtools 0.112 and older
63
+ "#{namespace}::#{method.capitalize}"
64
+ end
65
+
76
66
  return unless Object.const_defined?(desired_class)
77
67
 
78
68
  self.class.class_eval do
@@ -91,32 +81,6 @@ module Selenium
91
81
 
92
82
  private
93
83
 
94
- def process_handshake
95
- socket.print(ws.to_s)
96
- ws << socket.readpartial(1024)
97
- end
98
-
99
- def attach_socket_listener
100
- Thread.new do
101
- Thread.current.abort_on_exception = true
102
- Thread.current.report_on_exception = false
103
-
104
- until socket.eof?
105
- incoming_frame << socket.readpartial(1024)
106
-
107
- while (frame = incoming_frame.next)
108
- message = process_frame(frame)
109
- next unless message['method']
110
-
111
- params = message['params']
112
- callbacks[message['method']].each do |callback|
113
- @callback_threads.add(callback_thread(params, &callback))
114
- end
115
- end
116
- end
117
- end
118
- end
119
-
120
84
  def start_session
121
85
  targets = target.get_targets.dig('result', 'targetInfos')
122
86
  page_target = targets.find { |target| target['type'] == 'page' }
@@ -124,70 +88,9 @@ module Selenium
124
88
  @session_id = session.dig('result', 'sessionId')
125
89
  end
126
90
 
127
- def incoming_frame
128
- @incoming_frame ||= WebSocket::Frame::Incoming::Client.new(version: ws.version)
129
- end
130
-
131
- def process_frame(frame)
132
- message = frame.to_s
133
-
134
- # Firefox will periodically fail on unparsable empty frame
135
- return {} if message.empty?
136
-
137
- message = JSON.parse(message)
138
- @messages << message
139
- WebDriver.logger.debug "DevTools <- #{message}"
140
-
141
- message
142
- end
143
-
144
- def callback_thread(params)
145
- Thread.new do
146
- Thread.current.abort_on_exception = true
147
-
148
- # We might end up blocked forever when we have an error in event.
149
- # For example, if network interception event raises error,
150
- # the browser will keep waiting for the request to be proceeded
151
- # before returning back to the original thread. In this case,
152
- # we should at least print the error.
153
- Thread.current.report_on_exception = true
154
-
155
- yield params
156
- end
157
- end
158
-
159
- def wait
160
- @wait ||= Wait.new(timeout: RESPONSE_WAIT_TIMEOUT, interval: RESPONSE_WAIT_INTERVAL)
161
- end
162
-
163
- def socket
164
- @socket ||= begin
165
- if URI(@url).scheme == 'wss'
166
- socket = TCPSocket.new(ws.host, ws.port)
167
- socket = OpenSSL::SSL::SSLSocket.new(socket, OpenSSL::SSL::SSLContext.new)
168
- socket.sync_close = true
169
- socket.connect
170
-
171
- socket
172
- else
173
- TCPSocket.new(ws.host, ws.port)
174
- end
175
- end
176
- end
177
-
178
- def ws
179
- @ws ||= WebSocket::Handshake::Client.new(url: @url)
180
- end
181
-
182
- def next_id
183
- @id ||= 0
184
- @id += 1
185
- end
186
-
187
91
  def error_message(error)
188
92
  [error['code'], error['message'], error['data']].join(': ')
189
93
  end
190
-
191
94
  end # DevTools
192
95
  end # WebDriver
193
96
  end # Selenium
@@ -17,18 +17,24 @@
17
17
  # specific language governing permissions and limitations
18
18
  # under the License.
19
19
 
20
- require 'selenium/webdriver/chrome/driver'
20
+ require 'selenium/webdriver/chromium/driver'
21
21
 
22
22
  module Selenium
23
23
  module WebDriver
24
24
  module Edge
25
-
26
25
  #
27
26
  # Driver implementation for Microsoft Edge.
28
27
  # @api private
29
28
  #
30
29
 
31
- class Driver < Selenium::WebDriver::Chrome::Driver
30
+ class Driver < Chromium::Driver
31
+ include LocalDriver
32
+
33
+ def initialize(capabilities: nil, options: nil, service: nil, url: nil, **opts)
34
+ caps, url = initialize_local_driver(capabilities, options, service, url)
35
+ super(caps: caps, url: url, **opts)
36
+ end
37
+
32
38
  def browser
33
39
  :edge
34
40
  end
@@ -17,26 +17,26 @@
17
17
  # specific language governing permissions and limitations
18
18
  # under the License.
19
19
 
20
- require 'selenium/webdriver/chrome/features'
20
+ require 'selenium/webdriver/chromium/features'
21
21
 
22
22
  module Selenium
23
23
  module WebDriver
24
24
  module Edge
25
25
  module Features
26
-
27
- include WebDriver::Chrome::Features
26
+ include WebDriver::Chromium::Features
28
27
 
29
28
  EDGE_COMMANDS = {
30
29
  get_cast_sinks: [:get, 'session/:session_id/ms/cast/get_sinks'],
31
30
  set_cast_sink_to_use: [:post, 'session/:session_id/ms/cast/set_sink_to_use'],
32
31
  start_cast_tab_mirroring: [:post, 'session/:session_id/ms/cast/start_tab_mirroring'],
32
+ start_cast_desktop_mirroring: [:post, 'session/:session_id/ms/cast/start_desktop_mirroring'],
33
33
  get_cast_issue_message: [:get, 'session/:session_id/ms/cast/get_issue_message'],
34
34
  stop_casting: [:post, 'session/:session_id/ms/cast/stop_casting'],
35
35
  send_command: [:post, 'session/:session_id/ms/cdp/execute']
36
36
  }.freeze
37
37
 
38
38
  def commands(command)
39
- EDGE_COMMANDS[command] || Chrome::Features::CHROME_COMMANDS[command] || self.class::COMMANDS[command]
39
+ EDGE_COMMANDS[command] || CHROMIUM_COMMANDS[command] || self.class::COMMANDS[command]
40
40
  end
41
41
  end # Bridge
42
42
  end # Edge
@@ -17,23 +17,21 @@
17
17
  # specific language governing permissions and limitations
18
18
  # under the License.
19
19
 
20
- require 'selenium/webdriver/chrome/options'
20
+ require 'selenium/webdriver/chromium/options'
21
21
 
22
22
  module Selenium
23
23
  module WebDriver
24
24
  module Edge
25
- class Options < Selenium::WebDriver::Chrome::Options
25
+ class Options < Chromium::Options
26
26
  KEY = 'ms:edgeOptions'
27
27
  BROWSER = 'MicrosoftEdge'
28
28
 
29
- protected
29
+ private
30
30
 
31
31
  def enable_logging(browser_options)
32
32
  browser_options['ms:loggingPrefs'] = @logging_prefs
33
33
  end
34
34
 
35
- private
36
-
37
35
  def binary_path
38
36
  Edge.path
39
37
  end
@@ -17,7 +17,7 @@
17
17
  # specific language governing permissions and limitations
18
18
  # under the License.
19
19
 
20
- require 'selenium/webdriver/chrome/profile'
20
+ require 'selenium/webdriver/chromium/profile'
21
21
 
22
22
  module Selenium
23
23
  module WebDriver
@@ -26,7 +26,7 @@ module Selenium
26
26
  # @private
27
27
  #
28
28
 
29
- class Profile < Selenium::WebDriver::Chrome::Profile
29
+ class Profile < Chromium::Profile
30
30
  end # Profile
31
31
  end # Edge
32
32
  end # WebDriver
@@ -17,18 +17,14 @@
17
17
  # specific language governing permissions and limitations
18
18
  # under the License.
19
19
 
20
- require 'selenium/webdriver/chrome/service'
20
+ require 'selenium/webdriver/chromium/service'
21
21
 
22
22
  module Selenium
23
23
  module WebDriver
24
24
  module Edge
25
- class Service < Selenium::WebDriver::Chrome::Service
25
+ class Service < Chromium::Service
26
26
  DEFAULT_PORT = 9515
27
27
  EXECUTABLE = 'msedgedriver'
28
- MISSING_TEXT = <<~ERROR
29
- Unable to find msedgedriver. Please download the server from
30
- https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/ and place it somewhere on your PATH.
31
- ERROR
32
28
  SHUTDOWN_SUPPORTED = true
33
29
  end # Service
34
30
  end # Edge
@@ -20,7 +20,6 @@
20
20
  module Selenium
21
21
  module WebDriver
22
22
  module Firefox
23
-
24
23
  #
25
24
  # Driver implementation for Firefox using GeckoDriver.
26
25
  # @api private
@@ -30,12 +29,20 @@ module Selenium
30
29
  EXTENSIONS = [DriverExtensions::HasAddons,
31
30
  DriverExtensions::FullPageScreenshot,
32
31
  DriverExtensions::HasContext,
32
+ DriverExtensions::HasBiDi,
33
33
  DriverExtensions::HasDevTools,
34
34
  DriverExtensions::HasLogEvents,
35
35
  DriverExtensions::HasNetworkInterception,
36
36
  DriverExtensions::HasWebStorage,
37
37
  DriverExtensions::PrintsPage].freeze
38
38
 
39
+ include LocalDriver
40
+
41
+ def initialize(capabilities: nil, options: nil, service: nil, url: nil, **opts)
42
+ caps, url = initialize_local_driver(capabilities, options, service, url)
43
+ super(caps: caps, url: url, **opts)
44
+ end
45
+
39
46
  def browser
40
47
  :firefox
41
48
  end
@@ -44,7 +51,7 @@ module Selenium
44
51
 
45
52
  def devtools_url
46
53
  if capabilities['moz:debuggerAddress'].nil?
47
- raise(Error::WebDriverError, "DevTools is not supported by this version of Firefox; use v85 or higher")
54
+ raise(Error::WebDriverError, 'DevTools is not supported by this version of Firefox; use v85 or higher')
48
55
  end
49
56
 
50
57
  uri = URI("http://#{capabilities['moz:debuggerAddress']}")
@@ -21,7 +21,6 @@ module Selenium
21
21
  module WebDriver
22
22
  module Firefox
23
23
  module Features
24
-
25
24
  FIREFOX_COMMANDS = {
26
25
  get_context: [:get, 'session/:session_id/moz/context'],
27
26
  set_context: [:post, 'session/:session_id/moz/context'],
@@ -35,12 +34,13 @@ module Selenium
35
34
  end
36
35
 
37
36
  def install_addon(path, temporary)
38
- if @file_detector
39
- local_file = @file_detector.call(path)
40
- path = upload(local_file) if local_file
41
- end
37
+ addon = if File.directory?(path)
38
+ Zipper.zip(path)
39
+ else
40
+ File.open(path, 'rb') { |crx_file| Base64.strict_encode64 crx_file.read }
41
+ end
42
42
 
43
- payload = {path: path}
43
+ payload = {addon: addon}
44
44
  payload[:temporary] = temporary unless temporary.nil?
45
45
  execute :install_addon, {}, payload
46
46
  end
@@ -25,11 +25,12 @@ module Selenium
25
25
 
26
26
  KEY = 'moz:firefoxOptions'
27
27
 
28
- # see: https://firefox-source-docs.mozilla.org/testing/geckodriver/Capabilities.html
28
+ # see: https://developer.mozilla.org/en-US/docs/Web/WebDriver/Capabilities/firefoxOptions
29
29
  CAPABILITIES = {binary: 'binary',
30
30
  args: 'args',
31
31
  log: 'log',
32
32
  prefs: 'prefs',
33
+ env: 'env',
33
34
  android_package: 'androidPackage',
34
35
  android_activity: 'androidActivity',
35
36
  android_device_serial: 'androidDeviceSerial',
@@ -56,12 +57,14 @@ module Selenium
56
57
  #
57
58
 
58
59
  def initialize(log_level: nil, **opts)
59
- @debugger_address = opts.delete(:debugger_address)
60
+ @debugger_address = opts.delete(:debugger_address) { true }
61
+ opts[:accept_insecure_certs] = true unless opts.key?(:accept_insecure_certs)
60
62
 
61
63
  super(**opts)
62
64
 
63
65
  @options[:args] ||= []
64
66
  @options[:prefs] ||= {}
67
+ @options[:env] ||= {}
65
68
  @options[:log] ||= {level: log_level} if log_level
66
69
 
67
70
  process_profile(@options.delete(:profile))
@@ -105,6 +108,9 @@ module Selenium
105
108
  #
106
109
 
107
110
  def headless!
111
+ WebDriver.logger.deprecate('`Options#headless!`',
112
+ "`Options#add_argument('-headless')`",
113
+ id: :headless)
108
114
  add_argument '-headless'
109
115
  end
110
116
 
@@ -175,7 +181,7 @@ module Selenium
175
181
  end
176
182
 
177
183
  def camelize?(key)
178
- key != "prefs"
184
+ key != 'prefs'
179
185
  end
180
186
  end # Options
181
187
  end # Firefox
@@ -26,11 +26,11 @@ module Selenium
26
26
  VALID_PREFERENCE_TYPES = [TrueClass, FalseClass, Integer, Float, String].freeze
27
27
 
28
28
  DEFAULT_PREFERENCES = {
29
- "browser.newtabpage.enabled" => false,
30
- "browser.startup.homepage" => "about:blank",
31
- "browser.usedOnWindows10.introURL" => "about:blank",
32
- "network.captive-portal-service.enabled" => false,
33
- "security.csp.enable" => false
29
+ 'browser.newtabpage.enabled' => false,
30
+ 'browser.startup.homepage' => 'about:blank',
31
+ 'browser.usedOnWindows10.introURL' => 'about:blank',
32
+ 'network.captive-portal-service.enabled' => false,
33
+ 'security.csp.enable' => false
34
34
  }.freeze
35
35
 
36
36
  attr_reader :name, :log_file
@@ -96,7 +96,7 @@ module Selenium
96
96
  raise TypeError, "expected one of #{VALID_PREFERENCE_TYPES.inspect}, got #{value.inspect}:#{value.class}"
97
97
  end
98
98
 
99
- if value.is_a?(String) && stringified?(value)
99
+ if value.is_a?(String) && Util.stringified?(value)
100
100
  raise ArgumentError, "preference values must be plain strings: #{key.inspect} => #{value.inspect}"
101
101
  end
102
102
 
@@ -143,7 +143,7 @@ module Selenium
143
143
  end
144
144
  end
145
145
 
146
- alias_method :as_json, :encoded
146
+ alias as_json encoded
147
147
 
148
148
  private
149
149
 
@@ -160,7 +160,7 @@ module Selenium
160
160
  destination = File.join(directory, 'extensions')
161
161
 
162
162
  @extensions.each do |name, extension|
163
- WebDriver.logger.debug({extenstion: name}.inspect)
163
+ WebDriver.logger.debug({extension: name}.inspect, id: :firefox_profile)
164
164
  extension.write_to(destination)
165
165
  end
166
166
  end
@@ -221,10 +221,6 @@ module Selenium
221
221
  end
222
222
  end
223
223
  end
224
-
225
- def stringified?(str)
226
- /^".*"$/.match?(str)
227
- end
228
224
  end # Profile
229
225
  end # Firefox
230
226
  end # WebDriver
@@ -23,16 +23,10 @@ module Selenium
23
23
  class Service < WebDriver::Service
24
24
  DEFAULT_PORT = 4444
25
25
  EXECUTABLE = 'geckodriver'
26
- MISSING_TEXT = <<~ERROR
27
- Unable to find Mozilla geckodriver. Please download the server from
28
- https://github.com/mozilla/geckodriver/releases and place it somewhere on your PATH.
29
- More info at https://developer.mozilla.org/en-US/docs/Mozilla/QA/Marionette/WebDriver.
30
- ERROR
31
26
  SHUTDOWN_SUPPORTED = false
32
27
 
33
28
  private
34
29
 
35
- # NOTE: This processing is deprecated
36
30
  def extract_service_args(driver_opts)
37
31
  driver_args = super
38
32
  driver_opts = driver_opts.dup
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Licensed to the Software Freedom Conservancy (SFC) under one
4
+ # or more contributor license agreements. See the NOTICE file
5
+ # distributed with this work for additional information
6
+ # regarding copyright ownership. The SFC licenses this file
7
+ # to you under the Apache License, Version 2.0 (the
8
+ # "License"); you may not use this file except in compliance
9
+ # with the License. You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing,
14
+ # software distributed under the License is distributed on an
15
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16
+ # KIND, either express or implied. See the License for the
17
+ # specific language governing permissions and limitations
18
+ # under the License.
19
+
20
+ module Selenium
21
+ module WebDriver
22
+ module Firefox
23
+ # @api private
24
+ module Util
25
+ module_function
26
+
27
+ def app_data_path
28
+ case Platform.os
29
+ when :windows
30
+ "#{ENV.fetch('APPDATA')}\\Mozilla\\Firefox"
31
+ when :macosx
32
+ "#{Platform.home}/Library/Application Support/Firefox"
33
+ when :unix, :linux
34
+ "#{Platform.home}/.mozilla/firefox"
35
+ else
36
+ raise "Unknown os: #{Platform.os}"
37
+ end
38
+ end
39
+
40
+ def stringified?(str)
41
+ str =~ /^".*"$/
42
+ end
43
+ end # Util
44
+ end # Firefox
45
+ end # WebDriver
46
+ end # Selenium
@@ -24,6 +24,7 @@ require 'rexml/document'
24
24
  module Selenium
25
25
  module WebDriver
26
26
  module Firefox
27
+ autoload :Util, 'selenium/webdriver/firefox/util'
27
28
  autoload :Extension, 'selenium/webdriver/firefox/extension'
28
29
  autoload :ProfilesIni, 'selenium/webdriver/firefox/profiles_ini'
29
30
  autoload :Profile, 'selenium/webdriver/firefox/profile'
@@ -41,20 +42,6 @@ module Selenium
41
42
  # until WebDriver Bidi is available.
42
43
  DEVTOOLS_VERSION = 85
43
44
 
44
- def self.driver_path=(path)
45
- WebDriver.logger.deprecate 'Selenium::WebDriver::Firefox#driver_path=',
46
- 'Selenium::WebDriver::Firefox::Service#driver_path=',
47
- id: :driver_path
48
- Selenium::WebDriver::Firefox::Service.driver_path = path
49
- end
50
-
51
- def self.driver_path
52
- WebDriver.logger.deprecate 'Selenium::WebDriver::Firefox#driver_path',
53
- 'Selenium::WebDriver::Firefox::Service#driver_path',
54
- id: :driver_path
55
- Selenium::WebDriver::Firefox::Service.driver_path
56
- end
57
-
58
45
  def self.path=(path)
59
46
  Platform.assert_executable path
60
47
  @path = path
@@ -20,7 +20,6 @@
20
20
  module Selenium
21
21
  module WebDriver
22
22
  module IE
23
-
24
23
  #
25
24
  # Driver implementation for Internet Explorer supporting
26
25
  # both OSS and W3C dialects of JSON wire protocol.
@@ -30,6 +29,13 @@ module Selenium
30
29
  class Driver < WebDriver::Driver
31
30
  EXTENSIONS = [DriverExtensions::HasWebStorage].freeze
32
31
 
32
+ include LocalDriver
33
+
34
+ def initialize(capabilities: nil, options: nil, service: nil, url: nil, **opts)
35
+ caps, url = initialize_local_driver(capabilities, options, service, url)
36
+ super(caps: caps, url: url, **opts)
37
+ end
38
+
33
39
  def browser
34
40
  :internet_explorer
35
41
  end
@@ -23,16 +23,10 @@ module Selenium
23
23
  class Service < WebDriver::Service
24
24
  DEFAULT_PORT = 5555
25
25
  EXECUTABLE = 'IEDriverServer'
26
- MISSING_TEXT = <<~ERROR
27
- Unable to find IEDriverServer. Please download the server from
28
- https://www.selenium.dev/downloads/ and place it somewhere on your PATH.
29
- More info at https://github.com/SeleniumHQ/selenium/wiki/InternetExplorerDriver.
30
- ERROR
31
26
  SHUTDOWN_SUPPORTED = true
32
27
 
33
28
  private
34
29
 
35
- # NOTE: This processing is deprecated
36
30
  def extract_service_args(driver_opts)
37
31
  driver_args = super
38
32
  driver_opts = driver_opts.dup
@@ -43,7 +37,7 @@ module Selenium
43
37
  end
44
38
  driver_args << "--host=#{driver_opts[:host]}" if driver_opts.key?(:host)
45
39
  driver_args << "--extract_path=#{driver_opts[:extract_path]}" if driver_opts.key?(:extract_path)
46
- driver_args << "--silent" if driver_opts[:silent] == true
40
+ driver_args << '--silent' if driver_opts[:silent] == true
47
41
  driver_args
48
42
  end
49
43
  end # Server
@@ -23,20 +23,6 @@ module Selenium
23
23
  autoload :Driver, 'selenium/webdriver/ie/driver'
24
24
  autoload :Options, 'selenium/webdriver/ie/options'
25
25
  autoload :Service, 'selenium/webdriver/ie/service'
26
-
27
- def self.driver_path=(path)
28
- WebDriver.logger.deprecate 'Selenium::WebDriver::IE#driver_path=',
29
- 'Selenium::WebDriver::IE::Service#driver_path=',
30
- id: :driver_path
31
- Selenium::WebDriver::IE::Service.driver_path = path
32
- end
33
-
34
- def self.driver_path
35
- WebDriver.logger.deprecate 'Selenium::WebDriver::IE#driver_path',
36
- 'Selenium::WebDriver::IE::Service#driver_path',
37
- id: :driver_path
38
- Selenium::WebDriver::IE::Service.driver_path
39
- end
40
26
  end # IE
41
27
  end # WebDriver
42
28
  end # Selenium