selenium-webdriver 2.53.3 → 3.142.7
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 +7 -0
- data/CHANGES +665 -8
- data/Gemfile +2 -0
- data/LICENSE +1 -1
- data/README.md +2 -3
- data/lib/selenium/server.rb +76 -73
- data/lib/selenium/webdriver/atoms/getAttribute.js +7 -0
- data/lib/selenium/webdriver/atoms/isDisplayed.js +102 -0
- data/lib/selenium/webdriver/{phantomjs.rb → atoms.rb} +10 -14
- data/lib/selenium/webdriver/chrome/bridge.rb +30 -101
- data/lib/selenium/webdriver/chrome/driver.rb +127 -0
- data/lib/selenium/webdriver/chrome/options.rb +190 -0
- data/lib/selenium/webdriver/chrome/profile.rb +21 -20
- data/lib/selenium/webdriver/chrome/service.rb +26 -93
- data/lib/selenium/webdriver/chrome.rb +15 -6
- data/lib/selenium/webdriver/common/action_builder.rb +52 -58
- data/lib/selenium/webdriver/common/alert.rb +7 -15
- data/lib/selenium/webdriver/common/bridge_helper.rb +18 -22
- data/lib/selenium/webdriver/common/driver.rb +72 -72
- data/lib/selenium/webdriver/common/driver_extensions/downloads_files.rb +45 -0
- data/lib/selenium/webdriver/common/driver_extensions/has_addons.rb +50 -0
- data/lib/selenium/webdriver/common/driver_extensions/{has_input_devices.rb → has_debugger.rb} +11 -27
- data/lib/selenium/webdriver/common/driver_extensions/has_location.rb +6 -10
- data/lib/selenium/webdriver/common/driver_extensions/has_network_conditions.rb +51 -0
- data/lib/selenium/webdriver/common/driver_extensions/has_network_connection.rb +7 -8
- data/lib/selenium/webdriver/common/driver_extensions/has_permissions.rb +51 -0
- data/lib/selenium/webdriver/common/driver_extensions/has_remote_status.rb +2 -4
- data/lib/selenium/webdriver/common/driver_extensions/has_session_id.rb +2 -4
- data/lib/selenium/webdriver/common/driver_extensions/has_touch_screen.rb +3 -5
- data/lib/selenium/webdriver/common/driver_extensions/has_web_storage.rb +2 -5
- data/lib/selenium/webdriver/common/driver_extensions/rotatable.rb +6 -9
- data/lib/selenium/webdriver/common/driver_extensions/takes_screenshot.rb +9 -7
- data/lib/selenium/webdriver/common/driver_extensions/uploads_files.rb +3 -8
- data/lib/selenium/webdriver/common/element.rb +59 -39
- data/lib/selenium/webdriver/common/error.rb +259 -104
- data/lib/selenium/webdriver/common/file_reaper.rb +6 -14
- data/lib/selenium/webdriver/common/html5/local_storage.rb +8 -10
- data/lib/selenium/webdriver/common/html5/session_storage.rb +8 -10
- data/lib/selenium/webdriver/common/html5/shared_web_storage.rb +8 -16
- data/lib/selenium/webdriver/common/interactions/input_device.rb +54 -0
- data/lib/selenium/webdriver/common/interactions/interaction.rb +53 -0
- data/lib/selenium/webdriver/{safari/browser.rb → common/interactions/interactions.rb} +17 -14
- data/lib/selenium/webdriver/common/interactions/key_actions.rb +145 -0
- data/lib/selenium/webdriver/common/interactions/key_input.rb +66 -0
- data/lib/selenium/webdriver/{android.rb → common/interactions/none_input.rb} +14 -6
- data/lib/selenium/webdriver/common/interactions/pointer_actions.rb +363 -0
- data/lib/selenium/webdriver/common/interactions/pointer_input.rb +139 -0
- data/lib/selenium/webdriver/common/keyboard.rb +10 -14
- data/lib/selenium/webdriver/common/keys.rb +102 -82
- data/lib/selenium/webdriver/common/log_entry.rb +7 -8
- data/lib/selenium/webdriver/common/logger.rb +115 -0
- data/lib/selenium/webdriver/common/logs.rb +4 -6
- data/lib/selenium/webdriver/common/manager.rb +177 -0
- data/lib/selenium/webdriver/common/mouse.rb +12 -14
- data/lib/selenium/webdriver/common/navigation.rb +4 -6
- data/lib/selenium/webdriver/common/options.rb +26 -127
- data/lib/selenium/webdriver/common/platform.rb +75 -101
- data/lib/selenium/webdriver/common/port_prober.rb +7 -19
- data/lib/selenium/webdriver/common/profile_helper.rb +8 -11
- data/lib/selenium/webdriver/common/proxy.rb +68 -74
- data/lib/selenium/webdriver/common/search_context.rb +28 -37
- data/lib/selenium/webdriver/common/service.rb +219 -0
- data/lib/selenium/webdriver/common/socket_lock.rb +15 -16
- data/lib/selenium/webdriver/common/socket_poller.rb +30 -28
- data/lib/selenium/webdriver/common/target_locator.rb +16 -18
- data/lib/selenium/webdriver/common/timeouts.rb +6 -8
- data/lib/selenium/webdriver/common/touch_action_builder.rb +5 -10
- data/lib/selenium/webdriver/common/touch_screen.rb +22 -23
- data/lib/selenium/webdriver/common/w3c_action_builder.rb +212 -0
- data/lib/selenium/webdriver/common/w3c_manager.rb +45 -0
- data/lib/selenium/webdriver/common/wait.rb +17 -16
- data/lib/selenium/webdriver/common/window.rb +50 -17
- data/lib/selenium/webdriver/common/zipper.rb +9 -13
- data/lib/selenium/webdriver/common.rb +21 -7
- data/lib/selenium/webdriver/edge/bridge.rb +34 -63
- data/lib/selenium/webdriver/edge/driver.rb +66 -0
- data/lib/selenium/webdriver/edge/options.rb +80 -0
- data/lib/selenium/webdriver/edge/service.rb +23 -95
- data/lib/selenium/webdriver/edge.rb +13 -13
- data/lib/selenium/webdriver/firefox/binary.rb +45 -60
- data/lib/selenium/webdriver/firefox/driver.rb +50 -0
- data/lib/selenium/webdriver/firefox/extension/prefs.json +3 -12
- data/lib/selenium/webdriver/firefox/extension/webdriver.xpi +0 -0
- data/lib/selenium/webdriver/firefox/extension.rb +20 -10
- data/lib/selenium/webdriver/firefox/launcher.rb +16 -22
- data/lib/selenium/webdriver/firefox/legacy/driver.rb +83 -0
- data/lib/selenium/webdriver/firefox/marionette/bridge.rb +49 -0
- data/lib/selenium/webdriver/firefox/marionette/driver.rb +90 -0
- data/lib/selenium/webdriver/firefox/options.rb +162 -0
- data/lib/selenium/webdriver/firefox/profile.rb +47 -48
- data/lib/selenium/webdriver/firefox/profiles_ini.rb +11 -18
- data/lib/selenium/webdriver/firefox/service.rb +24 -95
- data/lib/selenium/webdriver/firefox/util.rb +2 -4
- data/lib/selenium/webdriver/firefox.rb +27 -12
- data/lib/selenium/webdriver/ie/driver.rb +85 -0
- data/lib/selenium/webdriver/ie/options.rb +138 -0
- data/lib/selenium/webdriver/ie/service.rb +54 -0
- data/lib/selenium/webdriver/ie.rb +12 -10
- data/lib/selenium/webdriver/remote/bridge.rb +100 -564
- data/lib/selenium/webdriver/remote/capabilities.rb +98 -100
- data/lib/selenium/webdriver/remote/driver.rb +51 -0
- data/lib/selenium/webdriver/remote/http/common.rb +34 -22
- data/lib/selenium/webdriver/remote/http/curb.rb +13 -14
- data/lib/selenium/webdriver/remote/http/default.rb +62 -43
- data/lib/selenium/webdriver/remote/http/persistent.rb +12 -9
- data/lib/selenium/webdriver/remote/oss/bridge.rb +594 -0
- data/lib/selenium/webdriver/remote/oss/commands.rb +223 -0
- data/lib/selenium/webdriver/remote/response.rb +48 -28
- data/lib/selenium/webdriver/remote/server_error.rb +3 -5
- data/lib/selenium/webdriver/remote/w3c/bridge.rb +605 -0
- data/lib/selenium/webdriver/remote/w3c/capabilities.rb +310 -0
- data/lib/selenium/webdriver/remote/w3c/commands.rb +157 -0
- data/lib/selenium/webdriver/remote.rb +10 -16
- data/lib/selenium/webdriver/safari/bridge.rb +17 -101
- data/lib/selenium/webdriver/{firefox/w3c_bridge.rb → safari/driver.rb} +27 -25
- data/lib/selenium/webdriver/safari/options.rb +29 -31
- data/lib/selenium/webdriver/safari/service.rb +38 -0
- data/lib/selenium/webdriver/safari.rb +27 -27
- data/lib/selenium/webdriver/support/abstract_event_listener.rb +19 -4
- data/lib/selenium/webdriver/support/block_event_listener.rb +3 -5
- data/lib/selenium/webdriver/support/color.rb +60 -43
- data/lib/selenium/webdriver/support/escaper.rb +43 -0
- data/lib/selenium/webdriver/support/event_firing_bridge.rb +39 -41
- data/lib/selenium/webdriver/support/select.rb +45 -97
- data/lib/selenium/webdriver/support.rb +3 -2
- data/lib/selenium/webdriver/{iphone.rb → version.rb} +3 -7
- data/lib/selenium/webdriver.rb +36 -23
- data/lib/selenium-webdriver.rb +2 -2
- data/selenium-webdriver.gemspec +42 -29
- metadata +331 -262
- data/lib/selenium/client/base.rb +0 -151
- data/lib/selenium/client/driver.rb +0 -29
- data/lib/selenium/client/errors.rb +0 -28
- data/lib/selenium/client/extensions.rb +0 -132
- data/lib/selenium/client/idiomatic.rb +0 -507
- data/lib/selenium/client/javascript_expression_builder.rb +0 -135
- data/lib/selenium/client/javascript_frameworks/jquery.rb +0 -32
- data/lib/selenium/client/javascript_frameworks/prototype.rb +0 -32
- data/lib/selenium/client/legacy_driver.rb +0 -1722
- data/lib/selenium/client/protocol.rb +0 -123
- data/lib/selenium/client/selenium_helper.rb +0 -49
- data/lib/selenium/client.rb +0 -57
- data/lib/selenium/rake/server_task.rb +0 -176
- data/lib/selenium/webdriver/android/bridge.rb +0 -68
- data/lib/selenium/webdriver/common/core_ext/base64.rb +0 -28
- data/lib/selenium/webdriver/common/core_ext/dir.rb +0 -61
- data/lib/selenium/webdriver/common/html5/location.rb +0 -19
- data/lib/selenium/webdriver/common/w3c_error.rb +0 -194
- data/lib/selenium/webdriver/edge/legacy_support.rb +0 -117
- data/lib/selenium/webdriver/firefox/bridge.rb +0 -89
- data/lib/selenium/webdriver/ie/bridge.rb +0 -88
- data/lib/selenium/webdriver/ie/server.rb +0 -133
- data/lib/selenium/webdriver/iphone/bridge.rb +0 -64
- data/lib/selenium/webdriver/phantomjs/bridge.rb +0 -78
- data/lib/selenium/webdriver/phantomjs/service.rb +0 -130
- data/lib/selenium/webdriver/remote/commands.rb +0 -211
- data/lib/selenium/webdriver/remote/w3c_bridge.rb +0 -668
- data/lib/selenium/webdriver/remote/w3c_capabilities.rb +0 -236
- data/lib/selenium/webdriver/remote/w3c_commands.rb +0 -132
- data/lib/selenium/webdriver/safari/resources/client.js +0 -7255
- data/lib/selenium/webdriver/safari/server.rb +0 -187
- data/lib/selenium-client.rb +0 -21
|
@@ -0,0 +1,83 @@
|
|
|
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 Legacy
|
|
24
|
+
|
|
25
|
+
#
|
|
26
|
+
# Driver implementation for Firefox using legacy extension.
|
|
27
|
+
# @api private
|
|
28
|
+
#
|
|
29
|
+
|
|
30
|
+
class Driver < WebDriver::Driver
|
|
31
|
+
include DriverExtensions::TakesScreenshot
|
|
32
|
+
|
|
33
|
+
def initialize(opts = {}) # rubocop:disable Metrics/AbcSize
|
|
34
|
+
WebDriver.logger.deprecate 'Selenium support for legacy Firefox', 'Firefox via marionette'
|
|
35
|
+
|
|
36
|
+
opts[:desired_capabilities] ||= Remote::Capabilities.firefox_legacy
|
|
37
|
+
|
|
38
|
+
if opts.key? :proxy
|
|
39
|
+
WebDriver.logger.deprecate ':proxy', "Selenium::WebDriver::Remote::Capabilities.firefox(proxy: #{opts[:proxy]})"
|
|
40
|
+
opts[:desired_capabilities].proxy = opts.delete(:proxy)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
unless opts.key?(:url)
|
|
44
|
+
port = opts.delete(:port) || DEFAULT_PORT
|
|
45
|
+
profile = opts.delete(:profile)
|
|
46
|
+
|
|
47
|
+
Binary.path = opts[:desired_capabilities][:firefox_binary] if opts[:desired_capabilities][:firefox_binary]
|
|
48
|
+
@launcher = Launcher.new Binary.new, port, profile
|
|
49
|
+
@launcher.launch
|
|
50
|
+
opts[:url] = @launcher.url
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
listener = opts.delete(:listener)
|
|
54
|
+
WebDriver.logger.info 'Skipping handshake as we know it is OSS.'
|
|
55
|
+
desired_capabilities = opts.delete(:desired_capabilities)
|
|
56
|
+
bridge = Remote::Bridge.new(opts)
|
|
57
|
+
capabilities = bridge.create_session(desired_capabilities)
|
|
58
|
+
@bridge = Remote::OSS::Bridge.new(capabilities, bridge.session_id, opts)
|
|
59
|
+
|
|
60
|
+
begin
|
|
61
|
+
super(@bridge, listener: listener)
|
|
62
|
+
rescue
|
|
63
|
+
@launcher&.quit
|
|
64
|
+
raise
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def browser
|
|
69
|
+
:firefox
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def quit
|
|
73
|
+
super
|
|
74
|
+
nil
|
|
75
|
+
ensure
|
|
76
|
+
@launcher.quit
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
end # Driver
|
|
80
|
+
end # Legacy
|
|
81
|
+
end # Firefox
|
|
82
|
+
end # WebDriver
|
|
83
|
+
end # Selenium
|
|
@@ -0,0 +1,49 @@
|
|
|
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 Marionette
|
|
24
|
+
module Bridge
|
|
25
|
+
|
|
26
|
+
COMMANDS = {
|
|
27
|
+
install_addon: [:post, 'session/:session_id/moz/addon/install'],
|
|
28
|
+
uninstall_addon: [:post, 'session/:session_id/moz/addon/uninstall']
|
|
29
|
+
}.freeze
|
|
30
|
+
|
|
31
|
+
def commands(command)
|
|
32
|
+
COMMANDS[command] || super
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def install_addon(path, temporary)
|
|
36
|
+
payload = {path: path}
|
|
37
|
+
payload[:temporary] = temporary unless temporary.nil?
|
|
38
|
+
execute :install_addon, {}, payload
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def uninstall_addon(id)
|
|
42
|
+
execute :uninstall_addon, {}, {id: id}
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
end # Bridge
|
|
46
|
+
end # Marionette
|
|
47
|
+
end # Firefox
|
|
48
|
+
end # WebDriver
|
|
49
|
+
end # Selenium
|
|
@@ -0,0 +1,90 @@
|
|
|
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 Marionette
|
|
24
|
+
|
|
25
|
+
#
|
|
26
|
+
# Driver implementation for Firefox using GeckoDriver.
|
|
27
|
+
# @api private
|
|
28
|
+
#
|
|
29
|
+
|
|
30
|
+
class Driver < WebDriver::Driver
|
|
31
|
+
include DriverExtensions::HasAddons
|
|
32
|
+
include DriverExtensions::HasWebStorage
|
|
33
|
+
include DriverExtensions::TakesScreenshot
|
|
34
|
+
|
|
35
|
+
def initialize(opts = {})
|
|
36
|
+
opts[:desired_capabilities] = create_capabilities(opts)
|
|
37
|
+
|
|
38
|
+
opts[:url] ||= service_url(opts)
|
|
39
|
+
|
|
40
|
+
listener = opts.delete(:listener)
|
|
41
|
+
WebDriver.logger.info 'Skipping handshake as we know it is W3C.'
|
|
42
|
+
desired_capabilities = opts.delete(:desired_capabilities)
|
|
43
|
+
bridge = Remote::Bridge.new(opts)
|
|
44
|
+
capabilities = bridge.create_session(desired_capabilities)
|
|
45
|
+
@bridge = Remote::W3C::Bridge.new(capabilities, bridge.session_id, **opts)
|
|
46
|
+
@bridge.extend Marionette::Bridge
|
|
47
|
+
|
|
48
|
+
super(@bridge, listener: listener)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def browser
|
|
52
|
+
:firefox
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def quit
|
|
56
|
+
super
|
|
57
|
+
ensure
|
|
58
|
+
@service&.stop
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
private
|
|
62
|
+
|
|
63
|
+
def create_capabilities(opts)
|
|
64
|
+
caps = opts.delete(:desired_capabilities) { Remote::Capabilities.firefox }
|
|
65
|
+
options = opts.delete(:options) { Options.new }
|
|
66
|
+
|
|
67
|
+
firefox_options = opts.delete(:firefox_options)
|
|
68
|
+
if firefox_options
|
|
69
|
+
WebDriver.logger.deprecate ':firefox_options', 'Selenium::WebDriver::Firefox::Options'
|
|
70
|
+
firefox_options.each do |key, value|
|
|
71
|
+
options.add_option(key, value)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
profile = opts.delete(:profile)
|
|
76
|
+
if profile
|
|
77
|
+
WebDriver.logger.deprecate ':profile', 'Selenium::WebDriver::Firefox::Options#profile='
|
|
78
|
+
options.profile = profile
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
options = options.as_json
|
|
82
|
+
caps.merge!(options) unless options.empty?
|
|
83
|
+
|
|
84
|
+
caps
|
|
85
|
+
end
|
|
86
|
+
end # Driver
|
|
87
|
+
end # Marionette
|
|
88
|
+
end # Firefox
|
|
89
|
+
end # WebDriver
|
|
90
|
+
end # Selenium
|
|
@@ -0,0 +1,162 @@
|
|
|
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
|
+
class Options < WebDriver::Common::Options
|
|
24
|
+
attr_reader :args, :prefs, :options, :profile
|
|
25
|
+
attr_accessor :binary, :log_level
|
|
26
|
+
|
|
27
|
+
KEY = 'moz:firefoxOptions'
|
|
28
|
+
|
|
29
|
+
#
|
|
30
|
+
# Create a new Options instance, only for W3C-capable versions of Firefox.
|
|
31
|
+
#
|
|
32
|
+
# @example
|
|
33
|
+
# options = Selenium::WebDriver::Firefox::Options.new(args: ['--host=127.0.0.1'])
|
|
34
|
+
# driver = Selenium::WebDriver.for :firefox, options: options
|
|
35
|
+
#
|
|
36
|
+
# @param [Hash] opts the pre-defined options to create the Firefox::Options with
|
|
37
|
+
# @option opts [String] :binary Path to the Firefox executable to use
|
|
38
|
+
# @option opts [Array<String>] :args List of command-line arguments to use when starting geckodriver
|
|
39
|
+
# @option opts [Profile, String] :profile Encoded profile string or Profile instance
|
|
40
|
+
# @option opts [String, Symbol] :log_level Log level for geckodriver
|
|
41
|
+
# @option opts [Hash] :prefs A hash with each entry consisting of the key of the preference and its value
|
|
42
|
+
# @option opts [Hash] :options A hash for raw options
|
|
43
|
+
#
|
|
44
|
+
|
|
45
|
+
def initialize(**opts)
|
|
46
|
+
@args = Set.new(opts.delete(:args) || [])
|
|
47
|
+
@binary = opts.delete(:binary)
|
|
48
|
+
@profile = process_profile(opts.delete(:profile))
|
|
49
|
+
@log_level = opts.delete(:log_level)
|
|
50
|
+
@prefs = opts.delete(:prefs) || {}
|
|
51
|
+
@options = opts.delete(:options) || {}
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
#
|
|
55
|
+
# Add a command-line argument to use when starting Firefox.
|
|
56
|
+
#
|
|
57
|
+
# @example Start geckodriver on a specific host
|
|
58
|
+
# options = Selenium::WebDriver::Firefox::Options.new
|
|
59
|
+
# options.add_argument('--host=127.0.0.1')
|
|
60
|
+
#
|
|
61
|
+
# @param [String] arg The command-line argument to add
|
|
62
|
+
#
|
|
63
|
+
|
|
64
|
+
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
|
+
end
|
|
82
|
+
|
|
83
|
+
#
|
|
84
|
+
# Add a preference that is only applied to the user profile in use.
|
|
85
|
+
#
|
|
86
|
+
# @example Set the default homepage
|
|
87
|
+
# options = Selenium::WebDriver::Firefox::Options.new
|
|
88
|
+
# options.add_preference('browser.startup.homepage', 'http://www.seleniumhq.com/')
|
|
89
|
+
#
|
|
90
|
+
# @param [String] name Key of the preference
|
|
91
|
+
# @param [Boolean, String, Integer] value Value of the preference
|
|
92
|
+
#
|
|
93
|
+
|
|
94
|
+
def add_preference(name, value)
|
|
95
|
+
prefs[name] = value
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
#
|
|
99
|
+
# Run Firefox in headless mode.
|
|
100
|
+
#
|
|
101
|
+
# @example Enable headless mode
|
|
102
|
+
# options = Selenium::WebDriver::Firefox::Options.new
|
|
103
|
+
# options.headless!
|
|
104
|
+
#
|
|
105
|
+
|
|
106
|
+
def headless!
|
|
107
|
+
add_argument '-headless'
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
#
|
|
111
|
+
# Sets Firefox profile.
|
|
112
|
+
#
|
|
113
|
+
# @example Set the custom profile
|
|
114
|
+
# profile = Selenium::WebDriver::Firefox::Profile.new
|
|
115
|
+
# options = Selenium::WebDriver::Firefox::Options.new
|
|
116
|
+
# options.profile = profile
|
|
117
|
+
#
|
|
118
|
+
# @example Use existing profile
|
|
119
|
+
# options = Selenium::WebDriver::Firefox::Options.new
|
|
120
|
+
# options.profile = 'myprofile'
|
|
121
|
+
#
|
|
122
|
+
# @param [Profile, String] profile Profile to be used
|
|
123
|
+
#
|
|
124
|
+
|
|
125
|
+
def profile=(profile)
|
|
126
|
+
@profile = process_profile(profile)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
#
|
|
130
|
+
# @api private
|
|
131
|
+
#
|
|
132
|
+
|
|
133
|
+
def as_json(*)
|
|
134
|
+
opts = @options
|
|
135
|
+
|
|
136
|
+
opts[:profile] = @profile.encoded if @profile
|
|
137
|
+
opts[:args] = @args.to_a if @args.any?
|
|
138
|
+
opts[:binary] = @binary if @binary
|
|
139
|
+
opts[:prefs] = @prefs unless @prefs.empty?
|
|
140
|
+
opts[:log] = {level: @log_level} if @log_level
|
|
141
|
+
|
|
142
|
+
{KEY => generate_as_json(opts)}
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
private
|
|
146
|
+
|
|
147
|
+
def process_profile(profile)
|
|
148
|
+
return unless profile
|
|
149
|
+
|
|
150
|
+
case profile
|
|
151
|
+
when Profile
|
|
152
|
+
profile
|
|
153
|
+
when String
|
|
154
|
+
Profile.from_name(profile)
|
|
155
|
+
else
|
|
156
|
+
raise Error::WebDriverError, "don't know how to handle profile: #{profile.inspect}"
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
end # Options
|
|
160
|
+
end # Firefox
|
|
161
|
+
end # WebDriver
|
|
162
|
+
end # Selenium
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
3
|
# Licensed to the Software Freedom Conservancy (SFC) under one
|
|
4
4
|
# or more contributor license agreements. See the NOTICE file
|
|
5
5
|
# distributed with this work for additional information
|
|
@@ -23,15 +23,15 @@ module Selenium
|
|
|
23
23
|
class Profile
|
|
24
24
|
include ProfileHelper
|
|
25
25
|
|
|
26
|
-
VALID_PREFERENCE_TYPES = [TrueClass, FalseClass, Integer, Float, String]
|
|
26
|
+
VALID_PREFERENCE_TYPES = [TrueClass, FalseClass, Integer, Float, String].freeze
|
|
27
27
|
WEBDRIVER_EXTENSION_PATH = File.expand_path("#{WebDriver.root}/selenium/webdriver/firefox/extension/webdriver.xpi")
|
|
28
28
|
WEBDRIVER_PREFS = {
|
|
29
|
-
:
|
|
30
|
-
:
|
|
31
|
-
:
|
|
32
|
-
:
|
|
33
|
-
:
|
|
34
|
-
}
|
|
29
|
+
native_events: 'webdriver_enable_native_events',
|
|
30
|
+
untrusted_certs: 'webdriver_accept_untrusted_certs',
|
|
31
|
+
untrusted_issuer: 'webdriver_assume_untrusted_issuer',
|
|
32
|
+
port: 'webdriver_firefox_port',
|
|
33
|
+
log_file: 'webdriver.log.file'
|
|
34
|
+
}.freeze
|
|
35
35
|
|
|
36
36
|
attr_reader :name, :log_file
|
|
37
37
|
attr_writer :secure_ssl, :native_events, :load_no_focus_lib
|
|
@@ -42,7 +42,10 @@ module Selenium
|
|
|
42
42
|
end
|
|
43
43
|
|
|
44
44
|
def from_name(name)
|
|
45
|
-
ini[name]
|
|
45
|
+
profile = ini[name]
|
|
46
|
+
return profile if profile
|
|
47
|
+
|
|
48
|
+
raise Error::WebDriverError, "unable to find profile named: #{name.inspect}"
|
|
46
49
|
end
|
|
47
50
|
|
|
48
51
|
def default_preferences
|
|
@@ -78,18 +81,19 @@ module Selenium
|
|
|
78
81
|
@additional_prefs = {}
|
|
79
82
|
else
|
|
80
83
|
# TODO: clean this up
|
|
81
|
-
@native_events = model_prefs.delete(WEBDRIVER_PREFS[:native_events]) ==
|
|
82
|
-
@secure_ssl = model_prefs.delete(WEBDRIVER_PREFS[:untrusted_certs]) !=
|
|
83
|
-
@untrusted_issuer = model_prefs.delete(WEBDRIVER_PREFS[:untrusted_issuer]) ==
|
|
84
|
-
|
|
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'
|
|
85
89
|
@additional_prefs = model_prefs
|
|
86
90
|
end
|
|
87
91
|
|
|
88
|
-
@extensions
|
|
92
|
+
@extensions = {}
|
|
89
93
|
end
|
|
90
94
|
|
|
91
95
|
def layout_on_disk
|
|
92
|
-
profile_dir = @model ? create_tmp_copy(@model) : Dir.mktmpdir(
|
|
96
|
+
profile_dir = @model ? create_tmp_copy(@model) : Dir.mktmpdir('webdriver-profile')
|
|
93
97
|
FileReaper << profile_dir
|
|
94
98
|
|
|
95
99
|
install_extensions(profile_dir)
|
|
@@ -100,7 +104,6 @@ module Selenium
|
|
|
100
104
|
profile_dir
|
|
101
105
|
end
|
|
102
106
|
|
|
103
|
-
|
|
104
107
|
#
|
|
105
108
|
# Set a preference for this particular profile.
|
|
106
109
|
#
|
|
@@ -109,11 +112,11 @@ module Selenium
|
|
|
109
112
|
#
|
|
110
113
|
|
|
111
114
|
def []=(key, value)
|
|
112
|
-
unless VALID_PREFERENCE_TYPES.any? { |e| value.
|
|
115
|
+
unless VALID_PREFERENCE_TYPES.any? { |e| value.is_a? e }
|
|
113
116
|
raise TypeError, "expected one of #{VALID_PREFERENCE_TYPES.inspect}, got #{value.inspect}:#{value.class}"
|
|
114
117
|
end
|
|
115
118
|
|
|
116
|
-
if value.
|
|
119
|
+
if value.is_a?(String) && Util.stringified?(value)
|
|
117
120
|
raise ArgumentError, "preference values must be plain strings: #{key.inspect} => #{value.inspect}"
|
|
118
121
|
end
|
|
119
122
|
|
|
@@ -130,9 +133,9 @@ module Selenium
|
|
|
130
133
|
end
|
|
131
134
|
|
|
132
135
|
def add_webdriver_extension
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
+
return if @extensions.key?(:webdriver)
|
|
137
|
+
|
|
138
|
+
add_extension(WEBDRIVER_EXTENSION_PATH, :webdriver)
|
|
136
139
|
end
|
|
137
140
|
|
|
138
141
|
#
|
|
@@ -164,24 +167,18 @@ module Selenium
|
|
|
164
167
|
end
|
|
165
168
|
|
|
166
169
|
def proxy=(proxy)
|
|
167
|
-
unless proxy.
|
|
168
|
-
raise TypeError, "expected #{Proxy.name}, got #{proxy.inspect}:#{proxy.class}"
|
|
169
|
-
end
|
|
170
|
+
raise TypeError, "expected #{Proxy.name}, got #{proxy.inspect}:#{proxy.class}" unless proxy.is_a? Proxy
|
|
170
171
|
|
|
171
172
|
case proxy.type
|
|
172
173
|
when :manual
|
|
173
174
|
self['network.proxy.type'] = 1
|
|
174
175
|
|
|
175
|
-
set_manual_proxy_preference
|
|
176
|
-
set_manual_proxy_preference
|
|
177
|
-
set_manual_proxy_preference
|
|
178
|
-
set_manual_proxy_preference
|
|
176
|
+
set_manual_proxy_preference 'ftp', proxy.ftp
|
|
177
|
+
set_manual_proxy_preference 'http', proxy.http
|
|
178
|
+
set_manual_proxy_preference 'ssl', proxy.ssl
|
|
179
|
+
set_manual_proxy_preference 'socks', proxy.socks
|
|
179
180
|
|
|
180
|
-
|
|
181
|
-
self["network.proxy.no_proxies_on"] = proxy.no_proxy
|
|
182
|
-
else
|
|
183
|
-
self["network.proxy.no_proxies_on"] = ""
|
|
184
|
-
end
|
|
181
|
+
self['network.proxy.no_proxies_on'] = proxy.no_proxy || ''
|
|
185
182
|
when :pac
|
|
186
183
|
self['network.proxy.type'] = 2
|
|
187
184
|
self['network.proxy.autoconfig_url'] = proxy.pac
|
|
@@ -190,8 +187,10 @@ module Selenium
|
|
|
190
187
|
else
|
|
191
188
|
raise ArgumentError, "unsupported proxy type #{proxy.type}"
|
|
192
189
|
end
|
|
190
|
+
end
|
|
193
191
|
|
|
194
|
-
|
|
192
|
+
def encoded
|
|
193
|
+
Zipper.zip(layout_on_disk)
|
|
195
194
|
end
|
|
196
195
|
|
|
197
196
|
private
|
|
@@ -199,17 +198,17 @@ module Selenium
|
|
|
199
198
|
def set_manual_proxy_preference(key, value)
|
|
200
199
|
return unless value
|
|
201
200
|
|
|
202
|
-
host, port = value.to_s.split(
|
|
201
|
+
host, port = value.to_s.split(':', 2)
|
|
203
202
|
|
|
204
203
|
self["network.proxy.#{key}"] = host
|
|
205
204
|
self["network.proxy.#{key}_port"] = Integer(port) if port
|
|
206
205
|
end
|
|
207
206
|
|
|
208
207
|
def install_extensions(directory)
|
|
209
|
-
destination = File.join(directory,
|
|
208
|
+
destination = File.join(directory, 'extensions')
|
|
210
209
|
|
|
211
210
|
@extensions.each do |name, extension|
|
|
212
|
-
|
|
211
|
+
WebDriver.logger.debug({extenstion: name}.inspect)
|
|
213
212
|
extension.write_to(destination)
|
|
214
213
|
end
|
|
215
214
|
end
|
|
@@ -221,7 +220,7 @@ module Selenium
|
|
|
221
220
|
end
|
|
222
221
|
|
|
223
222
|
def delete_extensions_cache(directory)
|
|
224
|
-
FileUtils.rm_f File.join(directory,
|
|
223
|
+
FileUtils.rm_f File.join(directory, 'extensions.cache')
|
|
225
224
|
end
|
|
226
225
|
|
|
227
226
|
def delete_lock_files(directory)
|
|
@@ -247,7 +246,7 @@ module Selenium
|
|
|
247
246
|
prefs[WEBDRIVER_PREFS[:untrusted_issuer]] = assume_untrusted_certificate_issuer?
|
|
248
247
|
|
|
249
248
|
# If the user sets the home page, we should also start up there
|
|
250
|
-
prefs[
|
|
249
|
+
prefs['startup.homepage_welcome_url'] = prefs['browser.startup.homepage']
|
|
251
250
|
|
|
252
251
|
write_prefs prefs, path
|
|
253
252
|
end
|
|
@@ -257,25 +256,25 @@ module Selenium
|
|
|
257
256
|
return prefs unless File.exist?(path)
|
|
258
257
|
|
|
259
258
|
File.read(path).split("\n").each do |line|
|
|
260
|
-
|
|
261
|
-
key, value = $1.strip, $2.strip
|
|
259
|
+
next unless line =~ /user_pref\("([^"]+)"\s*,\s*(.+?)\);/
|
|
262
260
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
261
|
+
key = Regexp.last_match(1).strip
|
|
262
|
+
value = Regexp.last_match(2).strip
|
|
263
|
+
|
|
264
|
+
# wrap the value in an array to make it a valid JSON string.
|
|
265
|
+
prefs[key] = JSON.parse("[#{value}]").first
|
|
266
266
|
end
|
|
267
267
|
|
|
268
268
|
prefs
|
|
269
269
|
end
|
|
270
270
|
|
|
271
271
|
def write_prefs(prefs, path)
|
|
272
|
-
File.open(path,
|
|
272
|
+
File.open(path, 'w') do |file|
|
|
273
273
|
prefs.each do |key, value|
|
|
274
274
|
file.puts %{user_pref("#{key}", #{value.to_json});}
|
|
275
275
|
end
|
|
276
|
-
|
|
276
|
+
end
|
|
277
277
|
end
|
|
278
|
-
|
|
279
278
|
end # Profile
|
|
280
279
|
end # Firefox
|
|
281
280
|
end # WebDriver
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
3
|
# Licensed to the Software Freedom Conservancy (SFC) under one
|
|
4
4
|
# or more contributor license agreements. See the NOTICE file
|
|
5
5
|
# distributed with this work for additional information
|
|
@@ -20,12 +20,10 @@
|
|
|
20
20
|
module Selenium
|
|
21
21
|
module WebDriver
|
|
22
22
|
module Firefox
|
|
23
|
-
|
|
24
23
|
# @api private
|
|
25
24
|
class ProfilesIni
|
|
26
|
-
|
|
27
25
|
def initialize
|
|
28
|
-
@ini_path = File.join(Util.app_data_path,
|
|
26
|
+
@ini_path = File.join(Util.app_data_path, 'profiles.ini')
|
|
29
27
|
@profile_paths = {}
|
|
30
28
|
|
|
31
29
|
parse if File.exist?(@ini_path)
|
|
@@ -52,29 +50,24 @@ module Selenium
|
|
|
52
50
|
string.split("\n").each do |line|
|
|
53
51
|
case line
|
|
54
52
|
when /^\[Profile/
|
|
55
|
-
|
|
56
|
-
@profile_paths[name] = p
|
|
57
|
-
name, path = nil
|
|
58
|
-
end
|
|
53
|
+
name, path = nil if path_for(name, is_relative, path)
|
|
59
54
|
when /^Name=(.+)$/
|
|
60
|
-
name =
|
|
55
|
+
name = Regexp.last_match(1).strip
|
|
61
56
|
when /^IsRelative=(.+)$/
|
|
62
|
-
is_relative =
|
|
57
|
+
is_relative = Regexp.last_match(1).strip == '1'
|
|
63
58
|
when /^Path=(.+)$/
|
|
64
|
-
path =
|
|
59
|
+
path = Regexp.last_match(1).strip
|
|
60
|
+
p = path_for(name, is_relative, path)
|
|
61
|
+
@profile_paths[name] = p if p
|
|
65
62
|
end
|
|
66
63
|
end
|
|
67
|
-
|
|
68
|
-
if p = path_for(name, is_relative, path)
|
|
69
|
-
@profile_paths[name] = p
|
|
70
|
-
end
|
|
71
64
|
end
|
|
72
65
|
|
|
73
66
|
def path_for(name, is_relative, path)
|
|
74
67
|
return unless [name, path].any?
|
|
75
|
-
path = is_relative ? File.join(Util.app_data_path, path) : path
|
|
76
|
-
end
|
|
77
68
|
|
|
69
|
+
is_relative ? File.join(Util.app_data_path, path) : path
|
|
70
|
+
end
|
|
78
71
|
end # ProfilesIni
|
|
79
72
|
end # Firefox
|
|
80
73
|
end # WebDriver
|