selenium-webdriver 4.4.0 → 4.8.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 (121) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +86 -1
  3. data/LICENSE +1 -1
  4. data/NOTICE +1 -1
  5. data/bin/linux/selenium-manager +0 -0
  6. data/bin/macos/selenium-manager +0 -0
  7. data/bin/windows/selenium-manager.exe +0 -0
  8. data/lib/selenium/server.rb +20 -16
  9. data/lib/selenium/webdriver/atoms/findElements.js +0 -0
  10. data/lib/selenium/webdriver/atoms/getAttribute.js +0 -0
  11. data/lib/selenium/webdriver/atoms/isDisplayed.js +0 -0
  12. data/lib/selenium/webdriver/atoms/mutationListener.js +0 -0
  13. data/lib/selenium/webdriver/atoms.rb +2 -3
  14. data/lib/selenium/webdriver/bidi/browsing_context.rb +88 -0
  15. data/lib/selenium/webdriver/bidi/browsing_context_info.rb +35 -0
  16. data/lib/selenium/webdriver/bidi/log/base_log_entry.rb +35 -0
  17. data/lib/selenium/webdriver/bidi/log/console_log_entry.rb +35 -0
  18. data/lib/selenium/webdriver/bidi/log/generic_log_entry.rb +33 -0
  19. data/lib/selenium/webdriver/bidi/log/javascript_log_entry.rb +33 -0
  20. data/lib/selenium/webdriver/bidi/log_inspector.rb +140 -0
  21. data/lib/selenium/webdriver/bidi/navigate_result.rb +33 -0
  22. data/lib/selenium/webdriver/bidi/session.rb +13 -0
  23. data/lib/selenium/webdriver/bidi.rb +2 -1
  24. data/lib/selenium/webdriver/chrome/driver.rb +19 -28
  25. data/lib/selenium/webdriver/chrome/features.rb +5 -72
  26. data/lib/selenium/webdriver/chrome/options.rb +3 -237
  27. data/lib/selenium/webdriver/chrome/profile.rb +3 -83
  28. data/lib/selenium/webdriver/chrome/service.rb +4 -19
  29. data/lib/selenium/webdriver/chromium/driver.rb +61 -0
  30. data/lib/selenium/webdriver/chromium/features.rb +103 -0
  31. data/lib/selenium/webdriver/chromium/options.rb +261 -0
  32. data/lib/selenium/webdriver/chromium/profile.rb +113 -0
  33. data/lib/selenium/webdriver/chromium/service.rb +42 -0
  34. data/lib/selenium/webdriver/chromium.rb +32 -0
  35. data/lib/selenium/webdriver/common/action_builder.rb +11 -48
  36. data/lib/selenium/webdriver/common/child_process.rb +124 -0
  37. data/lib/selenium/webdriver/common/driver.rb +34 -25
  38. data/lib/selenium/webdriver/common/driver_extensions/downloads_files.rb +0 -2
  39. data/lib/selenium/webdriver/common/driver_extensions/full_page_screenshot.rb +0 -1
  40. data/lib/selenium/webdriver/common/driver_extensions/has_addons.rb +0 -2
  41. data/lib/selenium/webdriver/common/driver_extensions/has_apple_permissions.rb +0 -2
  42. data/lib/selenium/webdriver/common/driver_extensions/has_authentication.rb +0 -2
  43. data/lib/selenium/webdriver/common/driver_extensions/has_bidi.rb +0 -2
  44. data/lib/selenium/webdriver/common/driver_extensions/has_casting.rb +0 -1
  45. data/lib/selenium/webdriver/common/driver_extensions/has_cdp.rb +0 -2
  46. data/lib/selenium/webdriver/common/driver_extensions/has_context.rb +0 -2
  47. data/lib/selenium/webdriver/common/driver_extensions/has_debugger.rb +0 -2
  48. data/lib/selenium/webdriver/common/driver_extensions/has_devtools.rb +0 -2
  49. data/lib/selenium/webdriver/common/driver_extensions/has_launching.rb +0 -2
  50. data/lib/selenium/webdriver/common/driver_extensions/has_location.rb +1 -2
  51. data/lib/selenium/webdriver/common/driver_extensions/has_log_events.rb +0 -1
  52. data/lib/selenium/webdriver/common/driver_extensions/has_network_conditions.rb +0 -2
  53. data/lib/selenium/webdriver/common/driver_extensions/has_network_interception.rb +0 -2
  54. data/lib/selenium/webdriver/common/driver_extensions/has_permissions.rb +0 -2
  55. data/lib/selenium/webdriver/common/driver_extensions/has_pinned_scripts.rb +0 -2
  56. data/lib/selenium/webdriver/common/element.rb +7 -7
  57. data/lib/selenium/webdriver/common/error.rb +0 -2
  58. data/lib/selenium/webdriver/common/html5/shared_web_storage.rb +2 -2
  59. data/lib/selenium/webdriver/common/interactions/pointer_actions.rb +3 -3
  60. data/lib/selenium/webdriver/common/interactions/pointer_move.rb +2 -2
  61. data/lib/selenium/webdriver/common/interactions/scroll.rb +7 -5
  62. data/lib/selenium/webdriver/common/logger.rb +10 -2
  63. data/lib/selenium/webdriver/common/options.rb +30 -8
  64. data/lib/selenium/webdriver/common/platform.rb +4 -1
  65. data/lib/selenium/webdriver/common/profile_helper.rb +1 -1
  66. data/lib/selenium/webdriver/common/proxy.rb +1 -1
  67. data/lib/selenium/webdriver/common/selenium_manager.rb +89 -0
  68. data/lib/selenium/webdriver/common/service.rb +16 -8
  69. data/lib/selenium/webdriver/common/service_manager.rb +2 -10
  70. data/lib/selenium/webdriver/common/shadow_root.rb +1 -2
  71. data/lib/selenium/webdriver/common/socket_lock.rb +2 -2
  72. data/lib/selenium/webdriver/common/takes_screenshot.rb +2 -3
  73. data/lib/selenium/webdriver/common/target_locator.rb +2 -3
  74. data/lib/selenium/webdriver/common/timeouts.rb +2 -2
  75. data/lib/selenium/webdriver/common/virtual_authenticator/credential.rb +8 -6
  76. data/lib/selenium/webdriver/common/virtual_authenticator/virtual_authenticator.rb +0 -1
  77. data/lib/selenium/webdriver/common/virtual_authenticator/virtual_authenticator_options.rb +16 -16
  78. data/lib/selenium/webdriver/common/websocket_connection.rb +10 -2
  79. data/lib/selenium/webdriver/common.rb +2 -0
  80. data/lib/selenium/webdriver/devtools/console_event.rb +0 -2
  81. data/lib/selenium/webdriver/devtools/exception_event.rb +0 -2
  82. data/lib/selenium/webdriver/devtools/mutation_event.rb +0 -2
  83. data/lib/selenium/webdriver/devtools/network_interceptor.rb +3 -6
  84. data/lib/selenium/webdriver/devtools/pinned_script.rb +0 -2
  85. data/lib/selenium/webdriver/devtools/request.rb +0 -2
  86. data/lib/selenium/webdriver/devtools/response.rb +0 -2
  87. data/lib/selenium/webdriver/devtools.rb +0 -1
  88. data/lib/selenium/webdriver/edge/driver.rb +20 -3
  89. data/lib/selenium/webdriver/edge/features.rb +3 -4
  90. data/lib/selenium/webdriver/edge/options.rb +3 -5
  91. data/lib/selenium/webdriver/edge/profile.rb +2 -2
  92. data/lib/selenium/webdriver/edge/service.rb +2 -2
  93. data/lib/selenium/webdriver/firefox/driver.rb +19 -2
  94. data/lib/selenium/webdriver/firefox/features.rb +5 -2
  95. data/lib/selenium/webdriver/firefox/options.rb +6 -2
  96. data/lib/selenium/webdriver/firefox/profile.rb +6 -6
  97. data/lib/selenium/webdriver/firefox/service.rb +0 -1
  98. data/lib/selenium/webdriver/ie/driver.rb +20 -1
  99. data/lib/selenium/webdriver/ie/service.rb +1 -2
  100. data/lib/selenium/webdriver/remote/bridge.rb +8 -15
  101. data/lib/selenium/webdriver/remote/capabilities.rb +34 -12
  102. data/lib/selenium/webdriver/remote/commands.rb +0 -2
  103. data/lib/selenium/webdriver/remote/driver.rb +13 -13
  104. data/lib/selenium/webdriver/remote/http/curb.rb +0 -2
  105. data/lib/selenium/webdriver/remote/http/default.rb +1 -0
  106. data/lib/selenium/webdriver/remote/response.rb +0 -1
  107. data/lib/selenium/webdriver/safari/driver.rb +20 -1
  108. data/lib/selenium/webdriver/safari/features.rb +0 -2
  109. data/lib/selenium/webdriver/safari/options.rb +5 -1
  110. data/lib/selenium/webdriver/safari.rb +1 -1
  111. data/lib/selenium/webdriver/support/color.rb +15 -15
  112. data/lib/selenium/webdriver/support/guards/guard.rb +0 -2
  113. data/lib/selenium/webdriver/support/guards/guard_condition.rb +0 -2
  114. data/lib/selenium/webdriver/support/relative_locator.rb +0 -1
  115. data/lib/selenium/webdriver/support/select.rb +3 -1
  116. data/lib/selenium/webdriver/version.rb +1 -1
  117. data/lib/selenium/webdriver.rb +3 -4
  118. data/selenium-webdriver.gemspec +8 -9
  119. metadata +29 -73
  120. data/lib/selenium/webdriver/support/cdp/domain.rb.erb +0 -63
  121. data/lib/selenium/webdriver/support/cdp_client_generator.rb +0 -108
@@ -32,6 +32,19 @@ module Selenium
32
32
  Status.new(status['ready'], status['message'])
33
33
  end
34
34
 
35
+ def subscribe(events, browsing_contexts = nil)
36
+ events_list = Array(events)
37
+ browsing_contexts_list = browsing_contexts.nil? ? nil : Array(browsing_contexts)
38
+
39
+ @bidi.send_cmd('session.subscribe', events: events_list, contexts: browsing_contexts_list)
40
+ end
41
+
42
+ def unsubscribe(events, browsing_contexts = nil)
43
+ events_list = Array(events)
44
+ browsing_contexts_list = browsing_contexts.nil? ? nil : Array(browsing_contexts)
45
+
46
+ @bidi.send_cmd('session.unsubscribe', events: events_list, contexts: browsing_contexts_list)
47
+ end
35
48
  end # Session
36
49
  end # BiDi
37
50
  end # WebDriver
@@ -21,6 +21,8 @@ module Selenium
21
21
  module WebDriver
22
22
  class BiDi
23
23
  autoload :Session, 'selenium/webdriver/bidi/session'
24
+ autoload :LogInspector, 'selenium/webdriver/bidi/log_inspector'
25
+ autoload :BrowsingContext, 'selenium/webdriver/bidi/browsing_context'
24
26
 
25
27
  def initialize(url:)
26
28
  @ws = WebSocketConnection.new(url: url)
@@ -49,7 +51,6 @@ module Selenium
49
51
  def error_message(message)
50
52
  "#{message['error']}: #{message['message']}\n#{message['stacktrace']}"
51
53
  end
52
-
53
54
  end # BiDi
54
55
  end # WebDriver
55
56
  end # Selenium
@@ -17,31 +17,24 @@
17
17
  # specific language governing permissions and limitations
18
18
  # under the License.
19
19
 
20
+ require 'selenium/webdriver/chromium/driver'
21
+
20
22
  module Selenium
21
23
  module WebDriver
22
24
  module Chrome
23
-
24
25
  #
25
26
  # Driver implementation for Chrome.
26
27
  # @api private
27
28
  #
28
29
 
29
- class Driver < WebDriver::Driver
30
- EXTENSIONS = [DriverExtensions::HasCDP,
31
- DriverExtensions::HasCasting,
32
- DriverExtensions::HasNetworkConditions,
33
- DriverExtensions::HasNetworkInterception,
34
- DriverExtensions::HasWebStorage,
35
- DriverExtensions::HasLaunching,
36
- DriverExtensions::HasLocation,
37
- DriverExtensions::HasPermissions,
38
- DriverExtensions::DownloadsFiles,
39
- DriverExtensions::HasDevTools,
40
- DriverExtensions::HasAuthentication,
41
- DriverExtensions::HasLogs,
42
- DriverExtensions::HasLogEvents,
43
- DriverExtensions::HasPinnedScripts,
44
- DriverExtensions::PrintsPage].freeze
30
+ class Driver < Chromium::Driver
31
+ def initialize(capabilities: nil, options: nil, service: nil, url: nil, **opts)
32
+ raise ArgumentError, "Can't initialize #{self.class} with :url" if url
33
+
34
+ caps = process_options(options, capabilities)
35
+ url = service_url(service || Service.chrome)
36
+ super(caps: caps, url: url, **opts)
37
+ end
45
38
 
46
39
  def browser
47
40
  :chrome
@@ -49,21 +42,19 @@ module Selenium
49
42
 
50
43
  private
51
44
 
52
- def devtools_url
53
- uri = URI(devtools_address)
54
- response = Net::HTTP.get(uri.hostname, '/json/version', uri.port)
55
-
56
- JSON.parse(response)['webSocketDebuggerUrl']
57
- end
58
-
59
- def devtools_version
60
- Integer(capabilities.browser_version.split('.').first)
61
- end
62
-
63
45
  def devtools_address
64
46
  "http://#{capabilities['goog:chromeOptions']['debuggerAddress']}"
65
47
  end
66
48
 
49
+ def process_options(options, capabilities)
50
+ if options && !options.is_a?(Options)
51
+ raise ArgumentError, ":options must be an instance of #{Options}"
52
+ elsif options.nil? && capabilities.nil?
53
+ options = Options.new
54
+ end
55
+
56
+ super(options, capabilities)
57
+ end
67
58
  end # Driver
68
59
  end # Chrome
69
60
  end # WebDriver
@@ -17,93 +17,26 @@
17
17
  # specific language governing permissions and limitations
18
18
  # under the License.
19
19
 
20
+ require 'selenium/webdriver/chromium/features'
21
+
20
22
  module Selenium
21
23
  module WebDriver
22
24
  module Chrome
23
25
  module Features
26
+ include WebDriver::Chromium::Features
24
27
 
25
28
  CHROME_COMMANDS = {
26
- launch_app: [:post, 'session/:session_id/chromium/launch_app'],
27
29
  get_cast_sinks: [:get, 'session/:session_id/goog/cast/get_sinks'],
28
30
  set_cast_sink_to_use: [:post, 'session/:session_id/goog/cast/set_sink_to_use'],
29
31
  start_cast_tab_mirroring: [:post, 'session/:session_id/goog/cast/start_tab_mirroring'],
30
32
  start_cast_desktop_mirroring: [:post, 'session/:session_id/goog/cast/start_desktop_mirroring'],
31
33
  get_cast_issue_message: [:get, 'session/:session_id/goog/cast/get_issue_message'],
32
34
  stop_casting: [:post, 'session/:session_id/goog/cast/stop_casting'],
33
- get_network_conditions: [:get, 'session/:session_id/chromium/network_conditions'],
34
- set_network_conditions: [:post, 'session/:session_id/chromium/network_conditions'],
35
- delete_network_conditions: [:delete, 'session/:session_id/chromium/network_conditions'],
36
- set_permission: [:post, 'session/:session_id/permissions'],
37
- send_command: [:post, 'session/:session_id/goog/cdp/execute'],
38
- get_available_log_types: [:get, 'session/:session_id/se/log/types'],
39
- get_log: [:post, 'session/:session_id/se/log']
35
+ send_command: [:post, 'session/:session_id/goog/cdp/execute']
40
36
  }.freeze
41
37
 
42
38
  def commands(command)
43
- CHROME_COMMANDS[command] || self.class::COMMANDS[command]
44
- end
45
-
46
- def launch_app(id)
47
- execute :launch_app, {}, {id: id}
48
- end
49
-
50
- def cast_sinks
51
- execute :get_cast_sinks
52
- end
53
-
54
- def cast_sink_to_use=(name)
55
- execute :set_cast_sink_to_use, {}, {sinkName: name}
56
- end
57
-
58
- def cast_issue_message
59
- execute :cast_issue_message
60
- end
61
-
62
- def start_cast_tab_mirroring(name)
63
- execute :start_cast_tab_mirroring, {}, {sinkName: name}
64
- end
65
-
66
- def start_cast_desktop_mirroring(name)
67
- execute :start_cast_desktop_mirroring, {}, {sinkName: name}
68
- end
69
-
70
- def stop_casting(name)
71
- execute :stop_casting, {}, {sinkName: name}
72
- end
73
-
74
- def set_permission(name, value)
75
- execute :set_permission, {}, {descriptor: {name: name}, state: value}
76
- end
77
-
78
- def network_conditions
79
- execute :get_network_conditions
80
- end
81
-
82
- def network_conditions=(conditions)
83
- execute :set_network_conditions, {}, {network_conditions: conditions}
84
- end
85
-
86
- def delete_network_conditions
87
- execute :delete_network_conditions
88
- end
89
-
90
- def send_command(command_params)
91
- execute :send_command, {}, command_params
92
- end
93
-
94
- def available_log_types
95
- types = execute :get_available_log_types
96
- Array(types).map(&:to_sym)
97
- end
98
-
99
- def log(type)
100
- data = execute :get_log, {}, {type: type.to_s}
101
-
102
- Array(data).map do |l|
103
- LogEntry.new l.fetch('level', 'UNKNOWN'), l.fetch('timestamp'), l.fetch('message')
104
- rescue KeyError
105
- next
106
- end
39
+ CHROME_COMMANDS[command] || CHROMIUM_COMMANDS[command] || self.class::COMMANDS[command]
107
40
  end
108
41
  end # Bridge
109
42
  end # Chrome
@@ -17,258 +17,24 @@
17
17
  # specific language governing permissions and limitations
18
18
  # under the License.
19
19
 
20
+ require 'selenium/webdriver/chromium/options'
21
+
20
22
  module Selenium
21
23
  module WebDriver
22
24
  module Chrome
23
- class Options < WebDriver::Options
24
- attr_accessor :profile, :logging_prefs
25
-
25
+ class Options < Chromium::Options
26
26
  KEY = 'goog:chromeOptions'
27
27
  BROWSER = 'chrome'
28
28
 
29
- # see: http://chromedriver.chromium.org/capabilities
30
- CAPABILITIES = {args: 'args',
31
- binary: 'binary',
32
- local_state: 'localState',
33
- prefs: 'prefs',
34
- detach: 'detach',
35
- debugger_address: 'debuggerAddress',
36
- exclude_switches: 'excludeSwitches',
37
- minidump_path: 'minidumpPath',
38
- emulation: 'mobileEmulation',
39
- perf_logging_prefs: 'perfLoggingPrefs',
40
- window_types: 'windowTypes',
41
- android_package: 'androidPackage',
42
- android_activity: 'androidActivity',
43
- android_device_serial: 'androidDeviceSerial',
44
- android_use_running_app: 'androidUseRunningApp'}.freeze
45
-
46
- # NOTE: special handling of 'extensions' to validate when set instead of when used
47
- attr_reader :extensions
48
-
49
- # Create a new Options instance.
50
- #
51
- # @example
52
- # options = Selenium::WebDriver::Chrome::Options.new(args: ['start-maximized', 'user-data-dir=/tmp/temp_profile'])
53
- # driver = Selenium::WebDriver.for(:chrome, capabilities: options)
54
- #
55
- # @param [Profile] profile An instance of a Chrome::Profile Class
56
- # @param [Hash] opts the pre-defined options to create the Chrome::Options with
57
- # @option opts [Array] encoded_extensions List of extensions that do not need to be Base64 encoded
58
- # @option opts [Array<String>] args List of command-line arguments to use when starting Chrome
59
- # @option opts [String] binary Path to the Chrome executable to use
60
- # @option opts [Hash] prefs A hash with each entry consisting of the name of the preference and its value
61
- # @option opts [Array<String>] extensions A list of paths to (.crx) Chrome extensions to install on startup
62
- # @option opts [Hash] options A hash for raw options
63
- # @option opts [Hash] emulation A hash for raw emulation options
64
- # @option opts [Hash] local_state A hash for the Local State file in the user data folder
65
- # @option opts [Boolean] detach whether browser is closed when the driver is sent the quit command
66
- # @option opts [String] debugger_address address of a Chrome debugger server to connect to
67
- # @option opts [Array<String>] exclude_switches command line switches to exclude
68
- # @option opts [String] minidump_path Directory to store Chrome minidumps (linux only)
69
- # @option opts [Hash] perf_logging_prefs A hash for performance logging preferences
70
- # @option opts [Array<String>] window_types A list of window types to appear in the list of window handles
71
- #
72
-
73
- def initialize(profile: nil, **opts)
74
- super(**opts)
75
-
76
- @profile = profile
77
-
78
- @options = {args: [],
79
- prefs: {},
80
- emulation: {},
81
- extensions: [],
82
- local_state: {},
83
- exclude_switches: [],
84
- perf_logging_prefs: {},
85
- window_types: []}.merge(@options)
86
-
87
- @logging_prefs = options.delete(:logging_prefs) || {}
88
- @encoded_extensions = @options.delete(:encoded_extensions) || []
89
- @extensions = []
90
- @options.delete(:extensions).each { |ext| validate_extension(ext) }
91
- end
92
-
93
- #
94
- # Add an extension by local path.
95
- #
96
- # @example
97
- # options = Selenium::WebDriver::Chrome::Options.new
98
- # options.add_extension('/path/to/extension.crx')
99
- #
100
- # @param [String] path The local path to the .crx file
101
- #
102
-
103
- def add_extension(path)
104
- validate_extension(path)
105
- end
106
-
107
- #
108
- # Add an extension by local path.
109
- #
110
- # @example
111
- # extensions = ['/path/to/extension.crx', '/path/to/other.crx']
112
- # options = Selenium::WebDriver::Chrome::Options.new
113
- # options.extensions = extensions
114
- #
115
- # @param [Array<String>] extensions A list of paths to (.crx) Chrome extensions to install on startup
116
- #
117
-
118
- def extensions=(extensions)
119
- extensions.each { |ext| validate_extension(ext) }
120
- end
121
-
122
- #
123
- # Add an extension by Base64-encoded string.
124
- #
125
- # @example
126
- # options = Selenium::WebDriver::Chrome::Options.new
127
- # options.add_encoded_extension(encoded_string)
128
- #
129
- # @param [String] encoded The Base64-encoded string of the .crx file
130
- #
131
-
132
- def add_encoded_extension(encoded)
133
- @encoded_extensions << encoded
134
- end
135
-
136
- #
137
- # Add a command-line argument to use when starting Chrome.
138
- #
139
- # @example Start Chrome maximized
140
- # options = Selenium::WebDriver::Chrome::Options.new
141
- # options.add_argument('start-maximized')
142
- #
143
- # @param [String] arg The command-line argument to add
144
- #
145
-
146
- def add_argument(arg)
147
- @options[:args] << arg
148
- end
149
-
150
- #
151
- # Add a preference that is only applied to the user profile in use.
152
- #
153
- # @example Set the default homepage
154
- # options = Selenium::WebDriver::Chrome::Options.new
155
- # options.add_preference('homepage', 'http://www.seleniumhq.com/')
156
- #
157
- # @param [String] name Key of the preference
158
- # @param [Boolean, String, Integer] value Value of the preference
159
- #
160
-
161
- def add_preference(name, value)
162
- @options[:prefs][name] = value
163
- end
164
-
165
- #
166
- # Run Chrome in headless mode.
167
- #
168
- # @example Enable headless mode
169
- # options = Selenium::WebDriver::Chrome::Options.new
170
- # options.headless!
171
- #
172
-
173
- def headless!
174
- add_argument '--headless'
175
- end
176
-
177
- #
178
- # Add emulation device information
179
- #
180
- # see: http://chromedriver.chromium.org/mobile-emulation
181
- #
182
- # @example Start Chrome in mobile emulation mode by device name
183
- # options = Selenium::WebDriver::Chrome::Options.new
184
- # options.add_emulation(device_name: 'iPhone 6')
185
- #
186
- # @example Start Chrome in mobile emulation mode by device metrics
187
- # options = Selenium::WebDriver::Chrome::Options.new
188
- # options.add_emulation(device_metrics: {width: 400, height: 800, pixelRatio: 1, touch: true})
189
- #
190
- # @param [Hash] opts the pre-defined options for adding mobile emulation values
191
- # @option opts [String] :device_name A valid device name from the Chrome DevTools Emulation panel
192
- # @option opts [Hash] :device_metrics Hash containing width, height, pixelRatio, touch
193
- # @option opts [String] :user_agent Full user agent
194
- #
195
-
196
- def add_emulation(**opts)
197
- @options[:emulation] = opts
198
- end
199
-
200
- #
201
- # Enables mobile browser use on Android.
202
- #
203
- # @see https://chromedriver.chromium.org/getting-started/getting-started---android
204
- #
205
- # @param [String] package The package name of the Chrome or WebView app.
206
- # @param [String] serial_number The device serial number on which to launch the Chrome or WebView app.
207
- # @param [String] use_running_app When true uses an already-running Chrome or WebView app,
208
- # instead of launching the app with a clear data directory.
209
- # @param [String] activity Name of the Activity hosting the WebView (Not available on Chrome Apps).
210
- #
211
-
212
- def enable_android(package: 'com.android.chrome', serial_number: nil, use_running_app: nil, activity: nil)
213
- @options[:android_package] = package
214
- @options[:android_activity] = activity unless activity.nil?
215
- @options[:android_device_serial] = serial_number unless serial_number.nil?
216
- @options[:android_use_running_app] = use_running_app unless use_running_app.nil?
217
- end
218
-
219
29
  private
220
30
 
221
31
  def enable_logging(browser_options)
222
32
  browser_options['goog:loggingPrefs'] = @logging_prefs
223
33
  end
224
34
 
225
- def process_browser_options(browser_options)
226
- enable_logging(browser_options) unless @logging_prefs.empty?
227
-
228
- options = browser_options[self.class::KEY]
229
- options['binary'] ||= binary_path if binary_path
230
-
231
- check_w3c(options[:w3c]) if options.key?(:w3c)
232
-
233
- if @profile
234
- options['args'] ||= []
235
- options['args'] << "--user-data-dir=#{@profile.directory}"
236
- end
237
-
238
- return if (@encoded_extensions + @extensions).empty?
239
-
240
- options['extensions'] = @encoded_extensions + @extensions.map { |ext| encode_extension(ext) }
241
- end
242
-
243
- def check_w3c(w3c)
244
- if w3c
245
- WebDriver.logger.warn("Setting 'w3c: true' is redundant and will no longer be allowed", id: :w3c)
246
- return
247
- end
248
-
249
- raise Error::InvalidArgumentError,
250
- "Setting 'w3c: false' is not allowed.\n" \
251
- "Please update to W3C Syntax: https://www.selenium.dev/blog/2022/legacy-protocol-support/"
252
- end
253
-
254
35
  def binary_path
255
36
  Chrome.path
256
37
  end
257
-
258
- def encode_extension(path)
259
- File.open(path, 'rb') { |crx_file| Base64.strict_encode64 crx_file.read }
260
- end
261
-
262
- def validate_extension(path)
263
- raise Error::WebDriverError, "could not find extension at #{path.inspect}" unless File.file?(path)
264
- raise Error::WebDriverError, "file was not an extension #{path.inspect}" unless File.extname(path) == '.crx'
265
-
266
- @extensions << path
267
- end
268
-
269
- def camelize?(key)
270
- !%w[localState prefs].include?(key)
271
- end
272
38
  end # Options
273
39
  end # Chrome
274
40
  end # WebDriver
@@ -17,6 +17,8 @@
17
17
  # specific language governing permissions and limitations
18
18
  # under the License.
19
19
 
20
+ require 'selenium/webdriver/chromium/profile'
21
+
20
22
  module Selenium
21
23
  module WebDriver
22
24
  module Chrome
@@ -24,89 +26,7 @@ module Selenium
24
26
  # @private
25
27
  #
26
28
 
27
- class Profile
28
- include ProfileHelper
29
-
30
- def initialize(model = nil)
31
- @model = verify_model(model)
32
- @extensions = []
33
- @encoded_extensions = []
34
- @directory = nil
35
- end
36
-
37
- def add_extension(path)
38
- raise Error::WebDriverError, "could not find extension at #{path.inspect}" unless File.file?(path)
39
-
40
- @extensions << path
41
- end
42
-
43
- def add_encoded_extension(encoded)
44
- @encoded_extensions << encoded
45
- end
46
-
47
- def directory
48
- @directory || layout_on_disk
49
- end
50
-
51
- #
52
- # Set a preference in the profile.
53
- #
54
- # See https://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/pref_names.cc
55
- #
56
-
57
- def []=(key, value)
58
- parts = key.split('.')
59
- parts[0..-2].inject(prefs) { |a, e| a[e] ||= {} }[parts.last] = value
60
- end
61
-
62
- def [](key)
63
- parts = key.split('.')
64
- parts.inject(prefs) { |a, e| a.fetch(e) }
65
- end
66
-
67
- def layout_on_disk
68
- @directory = @model ? create_tmp_copy(@model) : Dir.mktmpdir('webdriver-chrome-profile')
69
- FileReaper << @directory
70
-
71
- write_prefs_to @directory
72
-
73
- @directory
74
- end
75
-
76
- def as_json(*)
77
- extensions = @extensions.map do |crx_path|
78
- File.open(crx_path, 'rb') { |crx_file| Base64.strict_encode64 crx_file.read }
79
- end
80
-
81
- extensions.concat(@encoded_extensions)
82
-
83
- opts = {'directory' => directory || layout_on_disk}
84
- opts['extensions'] = extensions if extensions.any?
85
- opts
86
- end
87
-
88
- private
89
-
90
- def write_prefs_to(dir)
91
- prefs_file = prefs_file_for(dir)
92
-
93
- FileUtils.mkdir_p File.dirname(prefs_file)
94
- File.open(prefs_file, 'w') { |file| file << JSON.generate(prefs) }
95
- end
96
-
97
- def prefs
98
- @prefs ||= read_model_prefs
99
- end
100
-
101
- def read_model_prefs
102
- return {} unless @model
103
-
104
- JSON.parse File.read(prefs_file_for(@model))
105
- end
106
-
107
- def prefs_file_for(dir)
108
- File.join dir, 'Default', 'Preferences'
109
- end
29
+ class Profile < Chromium::Profile
110
30
  end # Profile
111
31
  end # Chrome
112
32
  end # WebDriver
@@ -17,35 +17,20 @@
17
17
  # specific language governing permissions and limitations
18
18
  # under the License.
19
19
 
20
+ require 'selenium/webdriver/chromium/service'
21
+
20
22
  module Selenium
21
23
  module WebDriver
22
24
  module Chrome
23
- class Service < WebDriver::Service
25
+ class Service < Chromium::Service
24
26
  DEFAULT_PORT = 9515
25
27
  EXECUTABLE = 'chromedriver'
26
28
  MISSING_TEXT = <<~ERROR
27
29
  Unable to find chromedriver. Please download the server from
28
30
  https://chromedriver.storage.googleapis.com/index.html and place it somewhere on your PATH.
29
- More info at https://github.com/SeleniumHQ/selenium/wiki/ChromeDriver.
31
+ More info at https://www.selenium.dev/documentation/webdriver/getting_started/install_drivers/?language=ruby.
30
32
  ERROR
31
33
  SHUTDOWN_SUPPORTED = true
32
-
33
- private
34
-
35
- # NOTE: This processing is deprecated
36
- def extract_service_args(driver_opts)
37
- driver_args = super
38
- driver_opts = driver_opts.dup
39
- driver_args << "--log-path=#{driver_opts.delete(:log_path)}" if driver_opts.key?(:log_path)
40
- driver_args << "--url-base=#{driver_opts.delete(:url_base)}" if driver_opts.key?(:url_base)
41
- driver_args << "--port-server=#{driver_opts.delete(:port_server)}" if driver_opts.key?(:port_server)
42
- if driver_opts.key?(:whitelisted_ips)
43
- driver_args << "--whitelisted-ips=#{driver_opts.delete(:whitelisted_ips)}"
44
- end
45
- driver_args << "--verbose" if driver_opts.key?(:verbose)
46
- driver_args << "--silent" if driver_opts.key?(:silent)
47
- driver_args
48
- end
49
34
  end # Service
50
35
  end # Chrome
51
36
  end # WebDriver
@@ -0,0 +1,61 @@
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 Chromium
23
+ #
24
+ # Driver implementation for Chrome.
25
+ # @api private
26
+ #
27
+
28
+ class Driver < WebDriver::Driver
29
+ EXTENSIONS = [DriverExtensions::HasCDP,
30
+ DriverExtensions::HasBiDi,
31
+ DriverExtensions::HasCasting,
32
+ DriverExtensions::HasNetworkConditions,
33
+ DriverExtensions::HasNetworkInterception,
34
+ DriverExtensions::HasWebStorage,
35
+ DriverExtensions::HasLaunching,
36
+ DriverExtensions::HasLocation,
37
+ DriverExtensions::HasPermissions,
38
+ DriverExtensions::DownloadsFiles,
39
+ DriverExtensions::HasDevTools,
40
+ DriverExtensions::HasAuthentication,
41
+ DriverExtensions::HasLogs,
42
+ DriverExtensions::HasLogEvents,
43
+ DriverExtensions::HasPinnedScripts,
44
+ DriverExtensions::PrintsPage].freeze
45
+
46
+ protected
47
+
48
+ def devtools_url
49
+ uri = URI(devtools_address)
50
+ response = Net::HTTP.get(uri.hostname, '/json/version', uri.port)
51
+
52
+ JSON.parse(response)['webSocketDebuggerUrl']
53
+ end
54
+
55
+ def devtools_version
56
+ Integer(capabilities.browser_version.split('.').first)
57
+ end
58
+ end # Driver
59
+ end # Chromium
60
+ end # WebDriver
61
+ end # Selenium