selenium-webdriver 3.142.7 → 4.0.3
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 +5 -5
- data/CHANGES +350 -5
- data/Gemfile +3 -1
- data/LICENSE +1 -1
- data/NOTICE +2 -0
- data/README.md +4 -5
- data/lib/selenium/server.rb +69 -63
- data/lib/selenium/webdriver/atoms/findElements.js +122 -0
- data/lib/selenium/webdriver/atoms/getAttribute.js +100 -7
- data/lib/selenium/webdriver/atoms/isDisplayed.js +76 -78
- data/lib/selenium/webdriver/atoms/mutationListener.js +55 -0
- data/lib/selenium/webdriver/chrome/driver.rb +26 -83
- data/lib/selenium/webdriver/chrome/{bridge.rb → features.rb} +50 -12
- data/lib/selenium/webdriver/chrome/options.rb +129 -58
- data/lib/selenium/webdriver/chrome/profile.rb +6 -3
- data/lib/selenium/webdriver/chrome/service.rb +8 -15
- data/lib/selenium/webdriver/chrome.rb +10 -9
- data/lib/selenium/webdriver/common/action_builder.rb +97 -249
- data/lib/selenium/webdriver/common/driver.rb +112 -23
- data/lib/selenium/webdriver/common/driver_extensions/full_page_screenshot.rb +43 -0
- data/lib/selenium/webdriver/common/driver_extensions/has_apple_permissions.rb +51 -0
- data/lib/selenium/webdriver/common/driver_extensions/has_authentication.rb +89 -0
- data/lib/selenium/webdriver/common/driver_extensions/has_casting.rb +77 -0
- data/lib/selenium/webdriver/common/driver_extensions/{has_touch_screen.rb → has_cdp.rb} +10 -8
- data/lib/selenium/webdriver/common/driver_extensions/has_context.rb +45 -0
- data/lib/selenium/webdriver/{firefox/util.rb → common/driver_extensions/has_devtools.rb} +16 -19
- data/lib/selenium/webdriver/common/driver_extensions/has_launching.rb +38 -0
- data/lib/selenium/webdriver/common/driver_extensions/has_location.rb +5 -8
- data/lib/selenium/webdriver/common/driver_extensions/has_log_events.rb +144 -0
- data/lib/selenium/webdriver/common/driver_extensions/has_logs.rb +30 -0
- data/lib/selenium/webdriver/common/driver_extensions/has_network_conditions.rb +17 -0
- data/lib/selenium/webdriver/common/driver_extensions/has_network_connection.rb +6 -27
- data/lib/selenium/webdriver/common/driver_extensions/has_network_interception.rb +136 -0
- data/lib/selenium/webdriver/common/driver_extensions/has_permissions.rb +11 -11
- data/lib/selenium/webdriver/common/driver_extensions/has_pinned_scripts.rb +77 -0
- data/lib/selenium/webdriver/common/driver_extensions/has_remote_status.rb +1 -0
- data/lib/selenium/webdriver/common/driver_extensions/{rotatable.rb → prints_page.rb} +18 -20
- data/lib/selenium/webdriver/common/element.rb +82 -22
- data/lib/selenium/webdriver/common/error.rb +32 -196
- data/lib/selenium/webdriver/common/interactions/interaction.rb +4 -1
- data/lib/selenium/webdriver/common/interactions/key_actions.rb +5 -5
- data/lib/selenium/webdriver/common/interactions/pointer_actions.rb +13 -13
- data/lib/selenium/webdriver/common/log_entry.rb +2 -2
- data/lib/selenium/webdriver/common/logger.rb +50 -15
- data/lib/selenium/webdriver/common/manager.rb +15 -15
- data/lib/selenium/webdriver/common/options.rb +154 -23
- data/lib/selenium/webdriver/common/platform.rb +6 -1
- data/lib/selenium/webdriver/common/port_prober.rb +4 -6
- data/lib/selenium/webdriver/common/profile_helper.rb +11 -9
- data/lib/selenium/webdriver/common/proxy.rb +6 -3
- data/lib/selenium/webdriver/common/search_context.rb +7 -3
- data/lib/selenium/webdriver/common/service.rb +17 -125
- data/lib/selenium/webdriver/common/service_manager.rb +151 -0
- data/lib/selenium/webdriver/common/shadow_root.rb +87 -0
- data/lib/selenium/webdriver/common/socket_lock.rb +2 -2
- data/lib/selenium/webdriver/common/socket_poller.rb +2 -2
- data/lib/selenium/webdriver/common/takes_screenshot.rb +66 -0
- data/lib/selenium/webdriver/common/target_locator.rb +32 -4
- data/lib/selenium/webdriver/common/timeouts.rb +31 -4
- data/lib/selenium/webdriver/common/wait.rb +1 -1
- data/lib/selenium/webdriver/common/window.rb +0 -4
- data/lib/selenium/webdriver/common/zipper.rb +1 -9
- data/lib/selenium/webdriver/common.rb +23 -17
- data/lib/selenium/webdriver/devtools/console_event.rb +38 -0
- data/lib/selenium/webdriver/devtools/exception_event.rb +36 -0
- data/lib/selenium/webdriver/devtools/mutation_event.rb +37 -0
- data/lib/selenium/webdriver/devtools/pinned_script.rb +59 -0
- data/lib/selenium/webdriver/devtools/request.rb +67 -0
- data/lib/selenium/webdriver/devtools/response.rb +66 -0
- data/lib/selenium/webdriver/devtools.rb +182 -0
- data/lib/selenium/webdriver/edge/driver.rb +7 -29
- data/lib/selenium/webdriver/edge/features.rb +44 -0
- data/lib/selenium/webdriver/edge/options.rb +11 -48
- data/lib/selenium/webdriver/{common/w3c_manager.rb → edge/profile.rb} +7 -19
- data/lib/selenium/webdriver/edge/service.rb +10 -26
- data/lib/selenium/webdriver/edge.rb +11 -14
- data/lib/selenium/webdriver/firefox/driver.rb +31 -19
- data/lib/selenium/webdriver/firefox/extension.rb +8 -0
- data/lib/selenium/webdriver/firefox/features.rb +66 -0
- data/lib/selenium/webdriver/firefox/options.rb +70 -49
- data/lib/selenium/webdriver/firefox/profile.rb +21 -71
- data/lib/selenium/webdriver/firefox/service.rb +5 -9
- data/lib/selenium/webdriver/firefox.rb +22 -20
- data/lib/selenium/webdriver/ie/driver.rb +1 -47
- data/lib/selenium/webdriver/ie/options.rb +13 -44
- data/lib/selenium/webdriver/ie/service.rb +13 -15
- data/lib/selenium/webdriver/ie.rb +8 -7
- data/lib/selenium/webdriver/remote/bridge.rb +558 -86
- data/lib/selenium/webdriver/remote/capabilities.rb +159 -123
- data/lib/selenium/webdriver/remote/commands.rb +163 -0
- data/lib/selenium/webdriver/remote/driver.rb +22 -12
- data/lib/selenium/webdriver/remote/http/common.rb +0 -5
- data/lib/selenium/webdriver/remote/http/default.rb +17 -20
- data/lib/selenium/webdriver/remote/http/persistent.rb +11 -6
- data/lib/selenium/webdriver/remote/response.rb +16 -47
- data/lib/selenium/webdriver/remote.rb +15 -13
- data/lib/selenium/webdriver/safari/driver.rb +3 -31
- data/lib/selenium/webdriver/safari/{bridge.rb → features.rb} +3 -3
- data/lib/selenium/webdriver/safari/options.rb +10 -29
- data/lib/selenium/webdriver/safari/service.rb +4 -8
- data/lib/selenium/webdriver/safari.rb +17 -9
- data/lib/selenium/webdriver/support/block_event_listener.rb +1 -1
- data/lib/selenium/webdriver/support/cdp/domain.rb.erb +63 -0
- data/lib/selenium/webdriver/support/cdp_client_generator.rb +108 -0
- data/lib/selenium/webdriver/support/color.rb +2 -2
- data/lib/selenium/webdriver/support/event_firing_bridge.rb +4 -4
- data/lib/selenium/webdriver/support/guards/guard.rb +89 -0
- data/lib/selenium/webdriver/{firefox/marionette/bridge.rb → support/guards/guard_condition.rb} +22 -19
- data/lib/selenium/webdriver/support/guards.rb +95 -0
- data/lib/selenium/webdriver/support/relative_locator.rb +51 -0
- data/lib/selenium/webdriver/support/select.rb +3 -3
- data/lib/selenium/webdriver/support.rb +1 -0
- data/lib/selenium/webdriver/version.rb +1 -1
- data/lib/selenium/webdriver.rb +12 -12
- data/selenium-webdriver.gemspec +28 -12
- metadata +128 -69
- data/lib/selenium/webdriver/common/bridge_helper.rb +0 -82
- data/lib/selenium/webdriver/common/driver_extensions/takes_screenshot.rb +0 -64
- data/lib/selenium/webdriver/common/keyboard.rb +0 -70
- data/lib/selenium/webdriver/common/mouse.rb +0 -89
- data/lib/selenium/webdriver/common/touch_action_builder.rb +0 -78
- data/lib/selenium/webdriver/common/touch_screen.rb +0 -123
- data/lib/selenium/webdriver/common/w3c_action_builder.rb +0 -212
- data/lib/selenium/webdriver/edge/bridge.rb +0 -76
- data/lib/selenium/webdriver/firefox/binary.rb +0 -187
- data/lib/selenium/webdriver/firefox/extension/prefs.json +0 -69
- data/lib/selenium/webdriver/firefox/extension/webdriver.xpi +0 -0
- data/lib/selenium/webdriver/firefox/launcher.rb +0 -111
- data/lib/selenium/webdriver/firefox/legacy/driver.rb +0 -83
- data/lib/selenium/webdriver/firefox/marionette/driver.rb +0 -90
- data/lib/selenium/webdriver/firefox/native/linux/amd64/x_ignore_nofocus.so +0 -0
- data/lib/selenium/webdriver/firefox/native/linux/x86/x_ignore_nofocus.so +0 -0
- data/lib/selenium/webdriver/remote/oss/bridge.rb +0 -594
- data/lib/selenium/webdriver/remote/oss/commands.rb +0 -223
- data/lib/selenium/webdriver/remote/w3c/bridge.rb +0 -605
- data/lib/selenium/webdriver/remote/w3c/capabilities.rb +0 -310
- data/lib/selenium/webdriver/remote/w3c/commands.rb +0 -157
|
@@ -20,30 +20,42 @@
|
|
|
20
20
|
module Selenium
|
|
21
21
|
module WebDriver
|
|
22
22
|
module Firefox
|
|
23
|
-
module Driver
|
|
24
|
-
class << self
|
|
25
|
-
|
|
26
|
-
#
|
|
27
|
-
# Instantiates correct Firefox driver implementation
|
|
28
|
-
# @return [Marionette::Driver, Legacy::Driver]
|
|
29
|
-
#
|
|
30
|
-
|
|
31
|
-
def new(**opts)
|
|
32
|
-
if marionette?(opts)
|
|
33
|
-
Firefox::Marionette::Driver.new(opts)
|
|
34
|
-
else
|
|
35
|
-
Firefox::Legacy::Driver.new(opts)
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
23
|
|
|
39
|
-
|
|
24
|
+
#
|
|
25
|
+
# Driver implementation for Firefox using GeckoDriver.
|
|
26
|
+
# @api private
|
|
27
|
+
#
|
|
28
|
+
|
|
29
|
+
class Driver < WebDriver::Driver
|
|
30
|
+
EXTENSIONS = [DriverExtensions::HasAddons,
|
|
31
|
+
DriverExtensions::FullPageScreenshot,
|
|
32
|
+
DriverExtensions::HasContext,
|
|
33
|
+
DriverExtensions::HasDevTools,
|
|
34
|
+
DriverExtensions::HasLogEvents,
|
|
35
|
+
DriverExtensions::HasNetworkInterception,
|
|
36
|
+
DriverExtensions::HasWebStorage,
|
|
37
|
+
DriverExtensions::PrintsPage].freeze
|
|
38
|
+
|
|
39
|
+
def browser
|
|
40
|
+
:firefox
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
private
|
|
40
44
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
45
|
+
def devtools_url
|
|
46
|
+
if capabilities['moz:debuggerAddress'].nil?
|
|
47
|
+
raise(Error::WebDriverError, "DevTools is not supported by this version of Firefox; use v85 or higher")
|
|
44
48
|
end
|
|
49
|
+
|
|
50
|
+
uri = URI("http://#{capabilities['moz:debuggerAddress']}")
|
|
51
|
+
response = Net::HTTP.get(uri.hostname, '/json/version', uri.port)
|
|
52
|
+
|
|
53
|
+
JSON.parse(response)['webSocketDebuggerUrl']
|
|
45
54
|
end
|
|
46
55
|
|
|
56
|
+
def devtools_version
|
|
57
|
+
Firefox::DEVTOOLS_VERSION
|
|
58
|
+
end
|
|
47
59
|
end # Driver
|
|
48
60
|
end # Firefox
|
|
49
61
|
end # WebDriver
|
|
@@ -87,6 +87,14 @@ module Selenium
|
|
|
87
87
|
return unless File.exist?(manifest_path)
|
|
88
88
|
|
|
89
89
|
manifest = JSON.parse(File.read(manifest_path))
|
|
90
|
+
applications_gecko_id(manifest) || name_and_version(manifest)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def applications_gecko_id(manifest)
|
|
94
|
+
manifest.dig('applications', 'gecko', 'id')&.strip
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def name_and_version(manifest)
|
|
90
98
|
[manifest['name'].delete(' '), manifest['version']].join('@')
|
|
91
99
|
end
|
|
92
100
|
end # Extension
|
|
@@ -0,0 +1,66 @@
|
|
|
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
|
+
module Features
|
|
24
|
+
|
|
25
|
+
FIREFOX_COMMANDS = {
|
|
26
|
+
get_context: [:get, 'session/:session_id/moz/context'],
|
|
27
|
+
set_context: [:post, 'session/:session_id/moz/context'],
|
|
28
|
+
install_addon: [:post, 'session/:session_id/moz/addon/install'],
|
|
29
|
+
uninstall_addon: [:post, 'session/:session_id/moz/addon/uninstall'],
|
|
30
|
+
full_page_screenshot: [:get, 'session/:session_id/moz/screenshot/full']
|
|
31
|
+
}.freeze
|
|
32
|
+
|
|
33
|
+
def commands(command)
|
|
34
|
+
FIREFOX_COMMANDS[command] || self.class::COMMANDS[command]
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
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
|
|
42
|
+
|
|
43
|
+
payload = {path: path}
|
|
44
|
+
payload[:temporary] = temporary unless temporary.nil?
|
|
45
|
+
execute :install_addon, {}, payload
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def uninstall_addon(id)
|
|
49
|
+
execute :uninstall_addon, {}, {id: id}
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def full_screenshot
|
|
53
|
+
execute :full_page_screenshot
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def context=(context)
|
|
57
|
+
execute :set_context, {}, {context: context}
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def context
|
|
61
|
+
execute :get_context
|
|
62
|
+
end
|
|
63
|
+
end # Bridge
|
|
64
|
+
end # Firefox
|
|
65
|
+
end # WebDriver
|
|
66
|
+
end # Selenium
|
|
@@ -20,12 +20,25 @@
|
|
|
20
20
|
module Selenium
|
|
21
21
|
module WebDriver
|
|
22
22
|
module Firefox
|
|
23
|
-
class Options < WebDriver::
|
|
24
|
-
|
|
25
|
-
attr_accessor :binary, :log_level
|
|
23
|
+
class Options < WebDriver::Options
|
|
24
|
+
attr_accessor :debugger_address
|
|
26
25
|
|
|
27
26
|
KEY = 'moz:firefoxOptions'
|
|
28
27
|
|
|
28
|
+
# see: https://firefox-source-docs.mozilla.org/testing/geckodriver/Capabilities.html
|
|
29
|
+
CAPABILITIES = {binary: 'binary',
|
|
30
|
+
args: 'args',
|
|
31
|
+
log: 'log',
|
|
32
|
+
prefs: 'prefs',
|
|
33
|
+
android_package: 'androidPackage',
|
|
34
|
+
android_activity: 'androidActivity',
|
|
35
|
+
android_device_serial: 'androidDeviceSerial',
|
|
36
|
+
android_intent_arguments: 'androidIntentArguments'}.freeze
|
|
37
|
+
BROWSER = 'firefox'
|
|
38
|
+
|
|
39
|
+
# NOTE: special handling of 'profile' to validate when set instead of when used
|
|
40
|
+
attr_reader :profile
|
|
41
|
+
|
|
29
42
|
#
|
|
30
43
|
# Create a new Options instance, only for W3C-capable versions of Firefox.
|
|
31
44
|
#
|
|
@@ -42,13 +55,16 @@ module Selenium
|
|
|
42
55
|
# @option opts [Hash] :options A hash for raw options
|
|
43
56
|
#
|
|
44
57
|
|
|
45
|
-
def initialize(**opts)
|
|
46
|
-
@
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
@
|
|
51
|
-
@options
|
|
58
|
+
def initialize(log_level: nil, **opts)
|
|
59
|
+
@debugger_address = opts.delete(:debugger_address)
|
|
60
|
+
|
|
61
|
+
super(**opts)
|
|
62
|
+
|
|
63
|
+
@options[:args] ||= []
|
|
64
|
+
@options[:prefs] ||= {}
|
|
65
|
+
@options[:log] ||= {level: log_level} if log_level
|
|
66
|
+
|
|
67
|
+
process_profile(@options.delete(:profile))
|
|
52
68
|
end
|
|
53
69
|
|
|
54
70
|
#
|
|
@@ -62,22 +78,7 @@ module Selenium
|
|
|
62
78
|
#
|
|
63
79
|
|
|
64
80
|
def add_argument(arg)
|
|
65
|
-
@args << arg
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
#
|
|
69
|
-
# Add a new option not yet handled by these bindings.
|
|
70
|
-
#
|
|
71
|
-
# @example
|
|
72
|
-
# options = Selenium::WebDriver::Firefox::Options.new
|
|
73
|
-
# options.add_option(:foo, 'bar')
|
|
74
|
-
#
|
|
75
|
-
# @param [String, Symbol] name Name of the option
|
|
76
|
-
# @param [Boolean, String, Integer] value Value of the option
|
|
77
|
-
#
|
|
78
|
-
|
|
79
|
-
def add_option(name, value)
|
|
80
|
-
@options[name] = value
|
|
81
|
+
@options[:args] << arg
|
|
81
82
|
end
|
|
82
83
|
|
|
83
84
|
#
|
|
@@ -92,7 +93,7 @@ module Selenium
|
|
|
92
93
|
#
|
|
93
94
|
|
|
94
95
|
def add_preference(name, value)
|
|
95
|
-
prefs[name] = value
|
|
96
|
+
@options[:prefs][name] = value
|
|
96
97
|
end
|
|
97
98
|
|
|
98
99
|
#
|
|
@@ -123,38 +124,58 @@ module Selenium
|
|
|
123
124
|
#
|
|
124
125
|
|
|
125
126
|
def profile=(profile)
|
|
126
|
-
|
|
127
|
+
process_profile(profile)
|
|
127
128
|
end
|
|
128
129
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
130
|
+
def log_level
|
|
131
|
+
@options.dig(:log, :level)
|
|
132
|
+
end
|
|
132
133
|
|
|
133
|
-
def
|
|
134
|
-
|
|
134
|
+
def log_level=(level)
|
|
135
|
+
@options[:log] = {level: level}
|
|
136
|
+
end
|
|
135
137
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
138
|
+
#
|
|
139
|
+
# Enables mobile browser use on Android.
|
|
140
|
+
#
|
|
141
|
+
# @see https://developer.mozilla.org/en-US/docs/Web/WebDriver/Capabilities/firefoxOptions#android
|
|
142
|
+
#
|
|
143
|
+
# @param [String] package The package name of the Chrome or WebView app.
|
|
144
|
+
# @param [String] serial_number The serial number of the device on which to launch the application.
|
|
145
|
+
# If not specified and multiple devices are attached, an error will be returned.
|
|
146
|
+
# @param [String] activity The fully qualified class name of the activity to be launched.
|
|
147
|
+
# @param [Array] intent_arguments Arguments to launch the intent with.
|
|
148
|
+
#
|
|
141
149
|
|
|
142
|
-
|
|
150
|
+
def enable_android(package: 'org.mozilla.firefox', serial_number: nil, activity: nil, intent_arguments: nil)
|
|
151
|
+
@options[:android_package] = package
|
|
152
|
+
@options[:android_activity] = activity unless activity.nil?
|
|
153
|
+
@options[:android_device_serial] = serial_number unless serial_number.nil?
|
|
154
|
+
@options[:android_intent_arguments] = intent_arguments unless intent_arguments.nil?
|
|
143
155
|
end
|
|
144
156
|
|
|
145
157
|
private
|
|
146
158
|
|
|
159
|
+
def process_browser_options(browser_options)
|
|
160
|
+
browser_options['moz:debuggerAddress'] = true if @debugger_address
|
|
161
|
+
options = browser_options[KEY]
|
|
162
|
+
options['binary'] ||= Firefox.path if Firefox.path
|
|
163
|
+
options['profile'] = @profile if @profile
|
|
164
|
+
end
|
|
165
|
+
|
|
147
166
|
def process_profile(profile)
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
167
|
+
@profile = case profile
|
|
168
|
+
when nil
|
|
169
|
+
nil
|
|
170
|
+
when Profile
|
|
171
|
+
profile
|
|
172
|
+
else
|
|
173
|
+
Profile.from_name(profile)
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def camelize?(key)
|
|
178
|
+
key != "prefs"
|
|
158
179
|
end
|
|
159
180
|
end # Options
|
|
160
181
|
end # Firefox
|
|
@@ -23,18 +23,18 @@ module Selenium
|
|
|
23
23
|
class Profile
|
|
24
24
|
include ProfileHelper
|
|
25
25
|
|
|
26
|
-
VALID_PREFERENCE_TYPES
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
26
|
+
VALID_PREFERENCE_TYPES = [TrueClass, FalseClass, Integer, Float, String].freeze
|
|
27
|
+
|
|
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
|
|
34
34
|
}.freeze
|
|
35
35
|
|
|
36
36
|
attr_reader :name, :log_file
|
|
37
|
-
attr_writer :secure_ssl, :
|
|
37
|
+
attr_writer :secure_ssl, :load_no_focus_lib
|
|
38
38
|
|
|
39
39
|
class << self
|
|
40
40
|
def ini
|
|
@@ -48,10 +48,8 @@ module Selenium
|
|
|
48
48
|
raise Error::WebDriverError, "unable to find profile named: #{name.inspect}"
|
|
49
49
|
end
|
|
50
50
|
|
|
51
|
-
def
|
|
52
|
-
|
|
53
|
-
File.read(File.expand_path("#{WebDriver.root}/selenium/webdriver/firefox/extension/prefs.json"))
|
|
54
|
-
).freeze
|
|
51
|
+
def decoded(json)
|
|
52
|
+
JSON.parse(json)
|
|
55
53
|
end
|
|
56
54
|
end
|
|
57
55
|
|
|
@@ -70,25 +68,7 @@ module Selenium
|
|
|
70
68
|
def initialize(model = nil)
|
|
71
69
|
@model = verify_model(model)
|
|
72
70
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
if model_prefs.empty?
|
|
76
|
-
@native_events = DEFAULT_ENABLE_NATIVE_EVENTS
|
|
77
|
-
@secure_ssl = DEFAULT_SECURE_SSL
|
|
78
|
-
@untrusted_issuer = DEFAULT_ASSUME_UNTRUSTED_ISSUER
|
|
79
|
-
@load_no_focus_lib = DEFAULT_LOAD_NO_FOCUS_LIB
|
|
80
|
-
|
|
81
|
-
@additional_prefs = {}
|
|
82
|
-
else
|
|
83
|
-
# TODO: clean this up
|
|
84
|
-
@native_events = model_prefs.delete(WEBDRIVER_PREFS[:native_events]) == 'true'
|
|
85
|
-
@secure_ssl = model_prefs.delete(WEBDRIVER_PREFS[:untrusted_certs]) != 'true'
|
|
86
|
-
@untrusted_issuer = model_prefs.delete(WEBDRIVER_PREFS[:untrusted_issuer]) == 'true'
|
|
87
|
-
# not stored in profile atm, so will always be false.
|
|
88
|
-
@load_no_focus_lib = model_prefs.delete(WEBDRIVER_PREFS[:load_no_focus_lib]) == 'true'
|
|
89
|
-
@additional_prefs = model_prefs
|
|
90
|
-
end
|
|
91
|
-
|
|
71
|
+
@additional_prefs = read_model_prefs
|
|
92
72
|
@extensions = {}
|
|
93
73
|
end
|
|
94
74
|
|
|
@@ -116,7 +96,7 @@ module Selenium
|
|
|
116
96
|
raise TypeError, "expected one of #{VALID_PREFERENCE_TYPES.inspect}, got #{value.inspect}:#{value.class}"
|
|
117
97
|
end
|
|
118
98
|
|
|
119
|
-
if value.is_a?(String) &&
|
|
99
|
+
if value.is_a?(String) && stringified?(value)
|
|
120
100
|
raise ArgumentError, "preference values must be plain strings: #{key.inspect} => #{value.inspect}"
|
|
121
101
|
end
|
|
122
102
|
|
|
@@ -132,12 +112,6 @@ module Selenium
|
|
|
132
112
|
self[WEBDRIVER_PREFS[:log_file]] = file
|
|
133
113
|
end
|
|
134
114
|
|
|
135
|
-
def add_webdriver_extension
|
|
136
|
-
return if @extensions.key?(:webdriver)
|
|
137
|
-
|
|
138
|
-
add_extension(WEBDRIVER_EXTENSION_PATH, :webdriver)
|
|
139
|
-
end
|
|
140
|
-
|
|
141
115
|
#
|
|
142
116
|
# Add the extension (directory, .zip or .xpi) at the given path to the profile.
|
|
143
117
|
#
|
|
@@ -146,26 +120,6 @@ module Selenium
|
|
|
146
120
|
@extensions[name] = Extension.new(path)
|
|
147
121
|
end
|
|
148
122
|
|
|
149
|
-
def native_events?
|
|
150
|
-
@native_events == true
|
|
151
|
-
end
|
|
152
|
-
|
|
153
|
-
def load_no_focus_lib?
|
|
154
|
-
@load_no_focus_lib == true
|
|
155
|
-
end
|
|
156
|
-
|
|
157
|
-
def secure_ssl?
|
|
158
|
-
@secure_ssl == true
|
|
159
|
-
end
|
|
160
|
-
|
|
161
|
-
def assume_untrusted_certificate_issuer?
|
|
162
|
-
@untrusted_issuer == true
|
|
163
|
-
end
|
|
164
|
-
|
|
165
|
-
def assume_untrusted_certificate_issuer=(bool)
|
|
166
|
-
@untrusted_issuer = bool
|
|
167
|
-
end
|
|
168
|
-
|
|
169
123
|
def proxy=(proxy)
|
|
170
124
|
raise TypeError, "expected #{Proxy.name}, got #{proxy.inspect}:#{proxy.class}" unless proxy.is_a? Proxy
|
|
171
125
|
|
|
@@ -189,9 +143,7 @@ module Selenium
|
|
|
189
143
|
end
|
|
190
144
|
end
|
|
191
145
|
|
|
192
|
-
|
|
193
|
-
Zipper.zip(layout_on_disk)
|
|
194
|
-
end
|
|
146
|
+
alias_method :as_json, :encoded
|
|
195
147
|
|
|
196
148
|
private
|
|
197
149
|
|
|
@@ -236,17 +188,11 @@ module Selenium
|
|
|
236
188
|
def update_user_prefs_in(directory)
|
|
237
189
|
path = File.join(directory, 'user.js')
|
|
238
190
|
prefs = read_user_prefs(path)
|
|
239
|
-
|
|
240
|
-
prefs.merge!
|
|
241
|
-
prefs.merge! @additional_prefs
|
|
242
|
-
prefs.merge! self.class.default_preferences.fetch 'frozen'
|
|
243
|
-
|
|
244
|
-
prefs[WEBDRIVER_PREFS[:untrusted_certs]] = !secure_ssl?
|
|
245
|
-
prefs[WEBDRIVER_PREFS[:native_events]] = native_events?
|
|
246
|
-
prefs[WEBDRIVER_PREFS[:untrusted_issuer]] = assume_untrusted_certificate_issuer?
|
|
191
|
+
prefs.merge! self.class::DEFAULT_PREFERENCES
|
|
192
|
+
prefs.merge!(@additional_prefs)
|
|
247
193
|
|
|
248
194
|
# If the user sets the home page, we should also start up there
|
|
249
|
-
prefs['startup.homepage_welcome_url']
|
|
195
|
+
prefs['startup.homepage_welcome_url'] ||= prefs['browser.startup.homepage']
|
|
250
196
|
|
|
251
197
|
write_prefs prefs, path
|
|
252
198
|
end
|
|
@@ -275,6 +221,10 @@ module Selenium
|
|
|
275
221
|
end
|
|
276
222
|
end
|
|
277
223
|
end
|
|
224
|
+
|
|
225
|
+
def stringified?(str)
|
|
226
|
+
/^".*"$/.match?(str)
|
|
227
|
+
end
|
|
278
228
|
end # Profile
|
|
279
229
|
end # Firefox
|
|
280
230
|
end # WebDriver
|
|
@@ -20,23 +20,19 @@
|
|
|
20
20
|
module Selenium
|
|
21
21
|
module WebDriver
|
|
22
22
|
module Firefox
|
|
23
|
-
#
|
|
24
|
-
# @api private
|
|
25
|
-
#
|
|
26
|
-
|
|
27
23
|
class Service < WebDriver::Service
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
24
|
+
DEFAULT_PORT = 4444
|
|
25
|
+
EXECUTABLE = 'geckodriver'
|
|
26
|
+
MISSING_TEXT = <<~ERROR
|
|
31
27
|
Unable to find Mozilla geckodriver. Please download the server from
|
|
32
28
|
https://github.com/mozilla/geckodriver/releases and place it somewhere on your PATH.
|
|
33
29
|
More info at https://developer.mozilla.org/en-US/docs/Mozilla/QA/Marionette/WebDriver.
|
|
34
30
|
ERROR
|
|
35
|
-
|
|
31
|
+
SHUTDOWN_SUPPORTED = false
|
|
36
32
|
|
|
37
33
|
private
|
|
38
34
|
|
|
39
|
-
#
|
|
35
|
+
# NOTE: This processing is deprecated
|
|
40
36
|
def extract_service_args(driver_opts)
|
|
41
37
|
driver_args = super
|
|
42
38
|
driver_opts = driver_opts.dup
|
|
@@ -21,46 +21,48 @@ require 'timeout'
|
|
|
21
21
|
require 'socket'
|
|
22
22
|
require 'rexml/document'
|
|
23
23
|
|
|
24
|
-
require 'selenium/webdriver/firefox/driver'
|
|
25
|
-
|
|
26
|
-
require 'selenium/webdriver/firefox/util'
|
|
27
|
-
require 'selenium/webdriver/firefox/extension'
|
|
28
|
-
require 'selenium/webdriver/firefox/binary'
|
|
29
|
-
require 'selenium/webdriver/firefox/profiles_ini'
|
|
30
|
-
require 'selenium/webdriver/firefox/profile'
|
|
31
|
-
require 'selenium/webdriver/firefox/launcher'
|
|
32
|
-
require 'selenium/webdriver/firefox/legacy/driver'
|
|
33
|
-
|
|
34
|
-
require 'selenium/webdriver/firefox/marionette/bridge'
|
|
35
|
-
require 'selenium/webdriver/firefox/marionette/driver'
|
|
36
|
-
require 'selenium/webdriver/firefox/options'
|
|
37
|
-
|
|
38
24
|
module Selenium
|
|
39
25
|
module WebDriver
|
|
40
26
|
module Firefox
|
|
27
|
+
autoload :Extension, 'selenium/webdriver/firefox/extension'
|
|
28
|
+
autoload :ProfilesIni, 'selenium/webdriver/firefox/profiles_ini'
|
|
29
|
+
autoload :Profile, 'selenium/webdriver/firefox/profile'
|
|
30
|
+
autoload :Features, 'selenium/webdriver/firefox/features'
|
|
31
|
+
autoload :Driver, 'selenium/webdriver/firefox/driver'
|
|
32
|
+
autoload :Options, 'selenium/webdriver/firefox/options'
|
|
33
|
+
autoload :Service, 'selenium/webdriver/firefox/service'
|
|
34
|
+
|
|
41
35
|
DEFAULT_PORT = 7055
|
|
42
|
-
DEFAULT_ENABLE_NATIVE_EVENTS = Platform.os == :windows
|
|
43
36
|
DEFAULT_SECURE_SSL = false
|
|
44
37
|
DEFAULT_ASSUME_UNTRUSTED_ISSUER = true
|
|
45
38
|
DEFAULT_LOAD_NO_FOCUS_LIB = false
|
|
46
39
|
|
|
40
|
+
# Mozilla Automation Team asked to only support 85
|
|
41
|
+
# until WebDriver Bidi is available.
|
|
42
|
+
DEVTOOLS_VERSION = 85
|
|
43
|
+
|
|
47
44
|
def self.driver_path=(path)
|
|
48
45
|
WebDriver.logger.deprecate 'Selenium::WebDriver::Firefox#driver_path=',
|
|
49
|
-
'Selenium::WebDriver::Firefox::Service#driver_path='
|
|
46
|
+
'Selenium::WebDriver::Firefox::Service#driver_path=',
|
|
47
|
+
id: :driver_path
|
|
50
48
|
Selenium::WebDriver::Firefox::Service.driver_path = path
|
|
51
49
|
end
|
|
52
50
|
|
|
53
51
|
def self.driver_path
|
|
54
52
|
WebDriver.logger.deprecate 'Selenium::WebDriver::Firefox#driver_path',
|
|
55
|
-
'Selenium::WebDriver::Firefox::Service#driver_path'
|
|
53
|
+
'Selenium::WebDriver::Firefox::Service#driver_path',
|
|
54
|
+
id: :driver_path
|
|
56
55
|
Selenium::WebDriver::Firefox::Service.driver_path
|
|
57
56
|
end
|
|
58
57
|
|
|
59
58
|
def self.path=(path)
|
|
60
|
-
|
|
59
|
+
Platform.assert_executable path
|
|
60
|
+
@path = path
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def self.path
|
|
64
|
+
@path ||= nil
|
|
61
65
|
end
|
|
62
66
|
end # Firefox
|
|
63
67
|
end # WebDriver
|
|
64
68
|
end # Selenium
|
|
65
|
-
|
|
66
|
-
require 'selenium/webdriver/firefox/service'
|
|
@@ -28,57 +28,11 @@ module Selenium
|
|
|
28
28
|
#
|
|
29
29
|
|
|
30
30
|
class Driver < WebDriver::Driver
|
|
31
|
-
|
|
32
|
-
include DriverExtensions::TakesScreenshot
|
|
33
|
-
|
|
34
|
-
def initialize(opts = {})
|
|
35
|
-
opts[:desired_capabilities] = create_capabilities(opts)
|
|
36
|
-
|
|
37
|
-
opts[:url] ||= service_url(opts)
|
|
38
|
-
|
|
39
|
-
listener = opts.delete(:listener)
|
|
40
|
-
@bridge = Remote::Bridge.handshake(**opts)
|
|
41
|
-
super(@bridge, listener: listener)
|
|
42
|
-
end
|
|
31
|
+
EXTENSIONS = [DriverExtensions::HasWebStorage].freeze
|
|
43
32
|
|
|
44
33
|
def browser
|
|
45
34
|
:internet_explorer
|
|
46
35
|
end
|
|
47
|
-
|
|
48
|
-
def quit
|
|
49
|
-
super
|
|
50
|
-
ensure
|
|
51
|
-
@service&.stop
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
private
|
|
55
|
-
|
|
56
|
-
def create_capabilities(opts)
|
|
57
|
-
caps = opts.delete(:desired_capabilities) { Remote::Capabilities.internet_explorer }
|
|
58
|
-
options = opts.delete(:options) { Options.new }
|
|
59
|
-
|
|
60
|
-
if opts.delete(:introduce_flakiness_by_ignoring_security_domains)
|
|
61
|
-
WebDriver.logger.deprecate ':introduce_flakiness_by_ignoring_security_domains',
|
|
62
|
-
'Selenium::WebDriver::IE::Options#ignore_protected_mode_settings='
|
|
63
|
-
options.ignore_protected_mode_settings = true
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
native_events = opts.delete(:native_events)
|
|
67
|
-
unless native_events.nil?
|
|
68
|
-
WebDriver.logger.deprecate ':native_events', 'Selenium::WebDriver::IE::Options#native_events='
|
|
69
|
-
options.native_events = native_events
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
# Backward compatibility with older IEDriverServer versions
|
|
73
|
-
caps[:ignore_protected_mode_settings] = options.ignore_protected_mode_settings
|
|
74
|
-
caps[:native_events] = options.native_events
|
|
75
|
-
|
|
76
|
-
options = options.as_json
|
|
77
|
-
caps.merge!(options) unless options.empty?
|
|
78
|
-
|
|
79
|
-
caps
|
|
80
|
-
end
|
|
81
|
-
|
|
82
36
|
end # Driver
|
|
83
37
|
end # IE
|
|
84
38
|
end # WebDriver
|