selenium-webdriver 2.45.0 → 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.
Files changed (172) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGES +795 -3
  3. data/Gemfile +2 -0
  4. data/{COPYING → LICENSE} +1 -3
  5. data/README.md +13 -9
  6. data/lib/selenium/server.rb +93 -71
  7. data/lib/selenium/webdriver/atoms/getAttribute.js +7 -0
  8. data/lib/selenium/webdriver/atoms/isDisplayed.js +102 -0
  9. data/lib/selenium/webdriver/atoms.rb +37 -0
  10. data/lib/selenium/webdriver/chrome/bridge.rb +47 -99
  11. data/lib/selenium/webdriver/chrome/driver.rb +127 -0
  12. data/lib/selenium/webdriver/chrome/options.rb +190 -0
  13. data/lib/selenium/webdriver/chrome/profile.rb +40 -20
  14. data/lib/selenium/webdriver/chrome/service.rb +46 -62
  15. data/lib/selenium/webdriver/chrome.rb +34 -6
  16. data/lib/selenium/webdriver/common/action_builder.rb +69 -56
  17. data/lib/selenium/webdriver/common/alert.rb +25 -8
  18. data/lib/selenium/webdriver/common/bridge_helper.rb +35 -20
  19. data/lib/selenium/webdriver/common/driver.rb +90 -63
  20. data/lib/selenium/webdriver/common/driver_extensions/downloads_files.rb +45 -0
  21. data/lib/selenium/webdriver/common/driver_extensions/has_addons.rb +50 -0
  22. data/lib/selenium/webdriver/common/driver_extensions/has_debugger.rb +42 -0
  23. data/lib/selenium/webdriver/common/driver_extensions/has_location.rb +26 -11
  24. data/lib/selenium/webdriver/common/driver_extensions/has_network_conditions.rb +51 -0
  25. data/lib/selenium/webdriver/common/driver_extensions/has_network_connection.rb +58 -0
  26. data/lib/selenium/webdriver/common/driver_extensions/has_permissions.rb +51 -0
  27. data/lib/selenium/webdriver/common/driver_extensions/has_remote_status.rb +23 -6
  28. data/lib/selenium/webdriver/common/driver_extensions/has_session_id.rb +19 -2
  29. data/lib/selenium/webdriver/common/driver_extensions/has_touch_screen.rb +24 -7
  30. data/lib/selenium/webdriver/common/driver_extensions/has_web_storage.rb +19 -3
  31. data/lib/selenium/webdriver/common/driver_extensions/rotatable.rb +23 -7
  32. data/lib/selenium/webdriver/common/driver_extensions/takes_screenshot.rb +26 -5
  33. data/lib/selenium/webdriver/common/driver_extensions/uploads_files.rb +20 -6
  34. data/lib/selenium/webdriver/common/element.rb +79 -37
  35. data/lib/selenium/webdriver/common/error.rb +282 -106
  36. data/lib/selenium/webdriver/common/file_reaper.rb +23 -12
  37. data/lib/selenium/webdriver/common/html5/local_storage.rb +29 -12
  38. data/lib/selenium/webdriver/common/html5/session_storage.rb +29 -12
  39. data/lib/selenium/webdriver/common/html5/shared_web_storage.rb +29 -18
  40. data/lib/selenium/webdriver/common/interactions/input_device.rb +54 -0
  41. data/lib/selenium/webdriver/common/interactions/interaction.rb +53 -0
  42. data/lib/selenium/webdriver/common/interactions/interactions.rb +43 -0
  43. data/lib/selenium/webdriver/common/interactions/key_actions.rb +145 -0
  44. data/lib/selenium/webdriver/common/interactions/key_input.rb +66 -0
  45. data/lib/selenium/webdriver/common/interactions/none_input.rb +36 -0
  46. data/lib/selenium/webdriver/common/interactions/pointer_actions.rb +363 -0
  47. data/lib/selenium/webdriver/common/interactions/pointer_input.rb +139 -0
  48. data/lib/selenium/webdriver/common/keyboard.rb +27 -12
  49. data/lib/selenium/webdriver/common/keys.rb +118 -81
  50. data/lib/selenium/webdriver/common/log_entry.rb +27 -8
  51. data/lib/selenium/webdriver/common/logger.rb +115 -0
  52. data/lib/selenium/webdriver/common/logs.rb +24 -7
  53. data/lib/selenium/webdriver/common/manager.rb +177 -0
  54. data/lib/selenium/webdriver/common/mouse.rb +29 -12
  55. data/lib/selenium/webdriver/common/navigation.rb +21 -4
  56. data/lib/selenium/webdriver/common/options.rb +43 -126
  57. data/lib/selenium/webdriver/common/platform.rb +101 -97
  58. data/lib/selenium/webdriver/common/port_prober.rb +24 -17
  59. data/lib/selenium/webdriver/common/profile_helper.rb +27 -11
  60. data/lib/selenium/webdriver/common/proxy.rb +86 -73
  61. data/lib/selenium/webdriver/common/search_context.rb +49 -33
  62. data/lib/selenium/webdriver/common/service.rb +219 -0
  63. data/lib/selenium/webdriver/common/socket_lock.rb +82 -0
  64. data/lib/selenium/webdriver/common/socket_poller.rb +47 -26
  65. data/lib/selenium/webdriver/common/target_locator.rb +35 -14
  66. data/lib/selenium/webdriver/common/timeouts.rb +23 -6
  67. data/lib/selenium/webdriver/common/touch_action_builder.rb +25 -11
  68. data/lib/selenium/webdriver/common/touch_screen.rb +42 -24
  69. data/lib/selenium/webdriver/common/w3c_action_builder.rb +212 -0
  70. data/lib/selenium/webdriver/common/w3c_manager.rb +45 -0
  71. data/lib/selenium/webdriver/common/wait.rb +34 -14
  72. data/lib/selenium/webdriver/common/window.rb +75 -16
  73. data/lib/selenium/webdriver/common/zipper.rb +26 -11
  74. data/lib/selenium/webdriver/common.rb +40 -7
  75. data/lib/selenium/webdriver/edge/bridge.rb +76 -0
  76. data/lib/selenium/webdriver/edge/driver.rb +66 -0
  77. data/lib/selenium/webdriver/edge/options.rb +80 -0
  78. data/lib/selenium/webdriver/edge/service.rb +52 -0
  79. data/lib/selenium/webdriver/edge.rb +44 -0
  80. data/lib/selenium/webdriver/firefox/binary.rb +70 -48
  81. data/lib/selenium/webdriver/firefox/driver.rb +50 -0
  82. data/lib/selenium/webdriver/firefox/extension/prefs.json +14 -13
  83. data/lib/selenium/webdriver/firefox/extension/webdriver.xpi +0 -0
  84. data/lib/selenium/webdriver/firefox/extension.rb +50 -19
  85. data/lib/selenium/webdriver/firefox/launcher.rb +33 -28
  86. data/lib/selenium/webdriver/firefox/legacy/driver.rb +83 -0
  87. data/lib/selenium/webdriver/firefox/marionette/bridge.rb +49 -0
  88. data/lib/selenium/webdriver/firefox/marionette/driver.rb +90 -0
  89. data/lib/selenium/webdriver/firefox/options.rb +162 -0
  90. data/lib/selenium/webdriver/firefox/profile.rb +66 -48
  91. data/lib/selenium/webdriver/firefox/profiles_ini.rb +28 -16
  92. data/lib/selenium/webdriver/firefox/service.rb +52 -0
  93. data/lib/selenium/webdriver/firefox/util.rb +19 -2
  94. data/lib/selenium/webdriver/firefox.rb +46 -10
  95. data/lib/selenium/webdriver/ie/driver.rb +85 -0
  96. data/lib/selenium/webdriver/ie/options.rb +138 -0
  97. data/lib/selenium/webdriver/ie/service.rb +54 -0
  98. data/lib/selenium/webdriver/ie.rb +32 -10
  99. data/lib/selenium/webdriver/remote/bridge.rb +117 -572
  100. data/lib/selenium/webdriver/remote/capabilities.rb +116 -99
  101. data/lib/selenium/webdriver/remote/driver.rb +51 -0
  102. data/lib/selenium/webdriver/remote/http/common.rb +54 -23
  103. data/lib/selenium/webdriver/remote/http/curb.rb +30 -12
  104. data/lib/selenium/webdriver/remote/http/default.rb +85 -42
  105. data/lib/selenium/webdriver/remote/http/persistent.rb +29 -7
  106. data/lib/selenium/webdriver/remote/oss/bridge.rb +594 -0
  107. data/lib/selenium/webdriver/remote/oss/commands.rb +223 -0
  108. data/lib/selenium/webdriver/remote/response.rb +68 -30
  109. data/lib/selenium/webdriver/remote/server_error.rb +22 -5
  110. data/lib/selenium/webdriver/remote/w3c/bridge.rb +605 -0
  111. data/lib/selenium/webdriver/remote/w3c/capabilities.rb +310 -0
  112. data/lib/selenium/webdriver/remote/w3c/commands.rb +157 -0
  113. data/lib/selenium/webdriver/remote.rb +27 -13
  114. data/lib/selenium/webdriver/safari/bridge.rb +38 -107
  115. data/lib/selenium/webdriver/safari/driver.rb +68 -0
  116. data/lib/selenium/webdriver/safari/options.rb +56 -75
  117. data/lib/selenium/webdriver/safari/service.rb +38 -0
  118. data/lib/selenium/webdriver/safari.rb +49 -31
  119. data/lib/selenium/webdriver/support/abstract_event_listener.rb +40 -6
  120. data/lib/selenium/webdriver/support/block_event_listener.rb +24 -7
  121. data/lib/selenium/webdriver/support/color.rb +82 -46
  122. data/lib/selenium/webdriver/support/escaper.rb +43 -0
  123. data/lib/selenium/webdriver/support/event_firing_bridge.rb +56 -39
  124. data/lib/selenium/webdriver/support/select.rb +66 -89
  125. data/lib/selenium/webdriver/support.rb +20 -0
  126. data/lib/selenium/webdriver/version.rb +24 -0
  127. data/lib/selenium/webdriver.rb +55 -25
  128. data/lib/selenium-webdriver.rb +19 -0
  129. data/selenium-webdriver.gemspec +42 -29
  130. metadata +331 -260
  131. data/Gemfile.lock +0 -48
  132. data/lib/selenium/client/base.rb +0 -132
  133. data/lib/selenium/client/driver.rb +0 -10
  134. data/lib/selenium/client/errors.rb +0 -9
  135. data/lib/selenium/client/extensions.rb +0 -118
  136. data/lib/selenium/client/idiomatic.rb +0 -488
  137. data/lib/selenium/client/javascript_expression_builder.rb +0 -116
  138. data/lib/selenium/client/javascript_frameworks/jquery.rb +0 -13
  139. data/lib/selenium/client/javascript_frameworks/prototype.rb +0 -13
  140. data/lib/selenium/client/legacy_driver.rb +0 -1720
  141. data/lib/selenium/client/protocol.rb +0 -104
  142. data/lib/selenium/client/selenium_helper.rb +0 -34
  143. data/lib/selenium/client.rb +0 -38
  144. data/lib/selenium/rake/server_task.rb +0 -157
  145. data/lib/selenium/webdriver/android/bridge.rb +0 -49
  146. data/lib/selenium/webdriver/android.rb +0 -9
  147. data/lib/selenium/webdriver/common/core_ext/base64.rb +0 -9
  148. data/lib/selenium/webdriver/common/core_ext/dir.rb +0 -42
  149. data/lib/selenium/webdriver/common/core_ext/string.rb +0 -5
  150. data/lib/selenium/webdriver/common/driver_extensions/has_browser_connection.rb +0 -17
  151. data/lib/selenium/webdriver/common/driver_extensions/has_input_devices.rb +0 -39
  152. data/lib/selenium/webdriver/common/html5/location.rb +0 -0
  153. data/lib/selenium/webdriver/common/json_helper.rb +0 -34
  154. data/lib/selenium/webdriver/firefox/bridge.rb +0 -70
  155. data/lib/selenium/webdriver/firefox/socket_lock.rb +0 -61
  156. data/lib/selenium/webdriver/ie/bridge.rb +0 -69
  157. data/lib/selenium/webdriver/ie/server.rb +0 -90
  158. data/lib/selenium/webdriver/iphone/bridge.rb +0 -45
  159. data/lib/selenium/webdriver/iphone.rb +0 -9
  160. data/lib/selenium/webdriver/opera/bridge.rb +0 -112
  161. data/lib/selenium/webdriver/opera/service.rb +0 -49
  162. data/lib/selenium/webdriver/opera.rb +0 -24
  163. data/lib/selenium/webdriver/phantomjs/bridge.rb +0 -59
  164. data/lib/selenium/webdriver/phantomjs/service.rb +0 -90
  165. data/lib/selenium/webdriver/phantomjs.rb +0 -22
  166. data/lib/selenium/webdriver/remote/commands.rb +0 -192
  167. data/lib/selenium/webdriver/safari/browser.rb +0 -20
  168. data/lib/selenium/webdriver/safari/extensions.rb +0 -170
  169. data/lib/selenium/webdriver/safari/resources/SafariDriver.safariextz +0 -0
  170. data/lib/selenium/webdriver/safari/resources/client.js +0 -6903
  171. data/lib/selenium/webdriver/safari/server.rb +0 -145
  172. data/lib/selenium-client.rb +0 -2
@@ -1,119 +1,67 @@
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
+
1
20
  module Selenium
2
21
  module WebDriver
3
22
  module Chrome
4
-
5
- # @api private
6
- class Bridge < Remote::Bridge
7
-
8
- def initialize(opts = {})
9
- http_client = opts.delete(:http_client)
10
-
11
- if opts.has_key?(:url)
12
- url = opts.delete(:url)
13
- else
14
- @service = Service.default_service(*extract_service_args(opts))
15
- @service.start
16
-
17
- url = @service.uri
18
- end
19
-
20
- caps = create_capabilities(opts)
21
-
22
- remote_opts = {
23
- :url => url,
24
- :desired_capabilities => caps
25
- }
26
-
27
- remote_opts.merge!(:http_client => http_client) if http_client
28
-
29
- super(remote_opts)
23
+ module Bridge
24
+
25
+ COMMANDS = {
26
+ get_network_conditions: [:get, 'session/:session_id/chromium/network_conditions'],
27
+ set_network_conditions: [:post, 'session/:session_id/chromium/network_conditions'],
28
+ send_command: [:post, 'session/:session_id/goog/cdp/execute'],
29
+ get_available_log_types: [:get, 'session/:session_id/se/log/types'],
30
+ get_log: [:post, 'session/:session_id/se/log']
31
+ }.freeze
32
+
33
+ def commands(command)
34
+ COMMANDS[command] || super
30
35
  end
31
36
 
32
- def browser
33
- :chrome
37
+ def network_conditions
38
+ execute :get_network_conditions
34
39
  end
35
40
 
36
- def driver_extensions
37
- [
38
- DriverExtensions::TakesScreenshot,
39
- DriverExtensions::HasInputDevices
40
- ]
41
+ def send_command(command_params)
42
+ execute :send_command, {}, command_params
41
43
  end
42
44
 
43
- def capabilities
44
- @capabilities ||= Remote::Capabilities.chrome
45
+ def network_conditions=(conditions)
46
+ execute :set_network_conditions, {}, {network_conditions: conditions}
45
47
  end
46
48
 
47
- def quit
48
- super
49
- ensure
50
- @service.stop if @service
49
+ def available_log_types
50
+ types = execute :get_available_log_types
51
+ Array(types).map(&:to_sym)
51
52
  end
52
53
 
53
- private
54
+ def log(type)
55
+ data = execute :get_log, {}, {type: type.to_s}
54
56
 
55
- def create_capabilities(opts)
56
- caps = opts.delete(:desired_capabilities) { Remote::Capabilities.chrome }
57
- args = opts.delete(:args) || opts.delete(:switches)
58
- native_events = opts.delete(:native_events)
59
- verbose = opts.delete(:verbose)
60
- profile = opts.delete(:profile)
61
- detach = opts.delete(:detach)
62
- proxy = opts.delete(:proxy)
63
- no_website_testing_defaults = opts.delete(:no_website_testing_defaults)
64
- prefs = opts.delete(:prefs)
65
-
66
- unless opts.empty?
67
- raise ArgumentError, "unknown option#{'s' if opts.size != 1}: #{opts.inspect}"
68
- end
69
-
70
- chrome_options = caps['chromeOptions'] || {}
71
-
72
- if args
73
- unless args.kind_of? Array
74
- raise ArgumentError, ":args must be an Array of Strings"
57
+ Array(data).map do |l|
58
+ begin
59
+ LogEntry.new l.fetch('level', 'UNKNOWN'), l.fetch('timestamp'), l.fetch('message')
60
+ rescue KeyError
61
+ next
75
62
  end
76
-
77
- chrome_options['args'] = args.map { |e| e.to_s }
78
63
  end
79
-
80
- if profile
81
- data = profile.as_json
82
-
83
- chrome_options.merge! 'profile' => data['zip'],
84
- 'extensions' => data['extensions']
85
- end
86
-
87
-
88
- chrome_options['binary'] = Chrome.path if Chrome.path
89
- chrome_options['nativeEvents'] = true if native_events
90
- chrome_options['verbose'] = true if verbose
91
- chrome_options['detach'] = detach.nil? || !!detach
92
- chrome_options['noWebsiteTestingDefaults'] = true if no_website_testing_defaults
93
- chrome_options['prefs'] = prefs if prefs
94
-
95
- caps['chromeOptions'] = chrome_options
96
- caps['proxy'] = proxy if proxy
97
-
98
- # legacy options - for chromedriver < 17.0.963.0
99
- caps["chrome.switches"] = chrome_options['args'] if chrome_options.member?('args')
100
- %w[binary detach extensions nativeEvents noWebsiteTestingDefaults prefs profile verbose].each do |key|
101
- caps["chrome.#{key}"] = chrome_options[key] if chrome_options.member?(key)
102
- end
103
-
104
- caps
105
64
  end
106
-
107
- def extract_service_args(opts)
108
- args = []
109
-
110
- if opts.has_key?(:service_log_path)
111
- args << "--log-path=#{opts.delete(:service_log_path)}"
112
- end
113
-
114
- args
115
- end
116
-
117
65
  end # Bridge
118
66
  end # Chrome
119
67
  end # WebDriver
@@ -0,0 +1,127 @@
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 Chrome
23
+
24
+ #
25
+ # Driver implementation for Chrome.
26
+ # @api private
27
+ #
28
+
29
+ class Driver < WebDriver::Driver
30
+ include DriverExtensions::HasNetworkConditions
31
+ include DriverExtensions::HasTouchScreen
32
+ include DriverExtensions::HasWebStorage
33
+ include DriverExtensions::HasLocation
34
+ include DriverExtensions::TakesScreenshot
35
+ include DriverExtensions::DownloadsFiles
36
+
37
+ def initialize(opts = {})
38
+ opts[:desired_capabilities] = create_capabilities(opts)
39
+
40
+ opts[:url] ||= service_url(opts)
41
+
42
+ listener = opts.delete(:listener)
43
+ @bridge = Remote::Bridge.handshake(**opts)
44
+ @bridge.extend Bridge
45
+
46
+ super(@bridge, listener: listener)
47
+ end
48
+
49
+ def browser
50
+ :chrome
51
+ end
52
+
53
+ def quit
54
+ super
55
+ ensure
56
+ @service&.stop
57
+ end
58
+
59
+ def execute_cdp(cmd, **params)
60
+ @bridge.send_command(cmd: cmd, params: params)
61
+ end
62
+
63
+ private
64
+
65
+ def create_capabilities(opts)
66
+ caps = opts.delete(:desired_capabilities) { Remote::Capabilities.chrome }
67
+ options = opts.delete(:options) { Options.new }
68
+
69
+ args = opts.delete(:args) || opts.delete(:switches)
70
+ if args
71
+ WebDriver.logger.deprecate ':args or :switches', 'Selenium::WebDriver::Chrome::Options#add_argument'
72
+ raise ArgumentError, ':args must be an Array of Strings' unless args.is_a? Array
73
+
74
+ args.each { |arg| options.add_argument(arg.to_s) }
75
+ end
76
+
77
+ profile = opts.delete(:profile)
78
+ if profile
79
+ WebDriver.logger.deprecate 'Selenium::WebDriver::Chrome::Driver#new with `:profile` parameter',
80
+ 'Selenium::WebDriver::Chrome::Options#profile or Options#add_option'
81
+
82
+ profile = profile.as_json
83
+
84
+ if options.args.none?(&/user-data-dir/.method(:match?))
85
+ options.add_argument("--user-data-dir=#{profile['directory']}")
86
+ end
87
+
88
+ if profile['extensions']
89
+ WebDriver.logger.deprecate 'Selenium::WebDriver::Chrome::Profile#extensions',
90
+ 'Selenium::WebDriver::Chrome::Options#add_extension'
91
+ profile['extensions'].each do |extension|
92
+ options.add_encoded_extension(extension)
93
+ end
94
+ end
95
+ end
96
+
97
+ if opts.key?(:detach)
98
+ WebDriver.logger.deprecate 'Selenium::WebDriver::Chrome::Driver#new with `:detach` parameter',
99
+ 'Selenium::WebDriver::Chrome::Options#new or Options#add_option'
100
+ options.add_option(:detach, opts.delete(:detach))
101
+ end
102
+
103
+ prefs = opts.delete(:prefs)
104
+ if prefs
105
+ WebDriver.logger.deprecate ':prefs', 'Selenium::WebDriver::Chrome::Options#add_preference'
106
+ prefs.each do |key, value|
107
+ options.add_preference(key, value)
108
+ end
109
+ end
110
+
111
+ options = options.as_json
112
+ caps.merge!(options) unless options[Options::KEY].empty?
113
+
114
+ if opts.key?(:proxy) || opts.key?('proxy')
115
+ WebDriver.logger.deprecate 'Selenium::WebDriver::Chrome::Driver#new with `:proxy` parameter',
116
+ 'Selenium::WebDriver::Chrome::Capabilities#proxy='
117
+
118
+ caps[:proxy] = opts.delete(:proxy) if opts.key?(:proxy)
119
+ caps[:proxy] ||= opts.delete('proxy') if opts.key?('proxy')
120
+ end
121
+
122
+ caps
123
+ end
124
+ end # Driver
125
+ end # Chrome
126
+ end # WebDriver
127
+ end # Selenium
@@ -0,0 +1,190 @@
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 Chrome
23
+ class Options < WebDriver::Common::Options
24
+ attr_reader :args, :prefs, :options, :emulation, :extensions, :encoded_extensions
25
+ attr_accessor :binary, :profile, :detach
26
+
27
+ KEY = 'goog:chromeOptions'
28
+
29
+ #
30
+ # Create a new Options instance.
31
+ #
32
+ # @example
33
+ # options = Selenium::WebDriver::Chrome::Options.new(args: ['start-maximized', 'user-data-dir=/tmp/temp_profile'])
34
+ # driver = Selenium::WebDriver.for(:chrome, options: options)
35
+ #
36
+ # @param [Hash] opts the pre-defined options to create the Chrome::Options with
37
+ # @option opts [Array<String>] :args List of command-line arguments to use when starting Chrome
38
+ # @option opts [String] :binary Path to the Chrome executable to use
39
+ # @option opts [Hash] :prefs A hash with each entry consisting of the name of the preference and its value
40
+ # @option opts [Array<String>] :extensions A list of paths to (.crx) Chrome extensions to install on startup
41
+ # @option opts [Hash] :options A hash for raw options
42
+ # @option opts [Hash] :emulation A hash for raw emulation options
43
+ #
44
+
45
+ def initialize(**opts)
46
+ @args = Set.new(opts.delete(:args) || [])
47
+ @binary = opts.delete(:binary) || Chrome.path
48
+ @prefs = opts.delete(:prefs) || {}
49
+ @extensions = opts.delete(:extensions) || []
50
+ @options = opts.delete(:options) || {}
51
+ @emulation = opts.delete(:emulation) || {}
52
+ @detach = opts.delete(:detach)
53
+ @profile = opts.delete(:profile)
54
+ @encoded_extensions = []
55
+ end
56
+
57
+ #
58
+ # Add an extension by local path.
59
+ #
60
+ # @example
61
+ # options = Selenium::WebDriver::Chrome::Options.new
62
+ # options.add_extension('/path/to/extension.crx')
63
+ #
64
+ # @param [String] path The local path to the .crx file
65
+ #
66
+
67
+ def add_extension(path)
68
+ raise Error::WebDriverError, "could not find extension at #{path.inspect}" unless File.file?(path)
69
+ raise Error::WebDriverError, "file was not an extension #{path.inspect}" unless File.extname(path) == '.crx'
70
+
71
+ @extensions << path
72
+ end
73
+
74
+ #
75
+ # Add an extension by Base64-encoded string.
76
+ #
77
+ # @example
78
+ # options = Selenium::WebDriver::Chrome::Options.new
79
+ # options.add_encoded_extension(encoded_string)
80
+ #
81
+ # @param [String] encoded The Base64-encoded string of the .crx file
82
+ #
83
+
84
+ def add_encoded_extension(encoded)
85
+ @encoded_extensions << encoded
86
+ end
87
+
88
+ #
89
+ # Add a command-line argument to use when starting Chrome.
90
+ #
91
+ # @example Start Chrome maximized
92
+ # options = Selenium::WebDriver::Chrome::Options.new
93
+ # options.add_argument('start-maximized')
94
+ #
95
+ # @param [String] arg The command-line argument to add
96
+ #
97
+
98
+ def add_argument(arg)
99
+ @args << arg
100
+ end
101
+
102
+ #
103
+ # Add a new option not yet handled by bindings.
104
+ #
105
+ # @example Leave Chrome open when chromedriver is killed
106
+ # options = Selenium::WebDriver::Chrome::Options.new
107
+ # options.add_option(:detach, true)
108
+ #
109
+ # @param [String, Symbol] name Name of the option
110
+ # @param [Boolean, String, Integer] value Value of the option
111
+ #
112
+
113
+ def add_option(name, value)
114
+ @options[name] = value
115
+ end
116
+
117
+ #
118
+ # Add a preference that is only applied to the user profile in use.
119
+ #
120
+ # @example Set the default homepage
121
+ # options = Selenium::WebDriver::Chrome::Options.new
122
+ # options.add_preference('homepage', 'http://www.seleniumhq.com/')
123
+ #
124
+ # @param [String] name Key of the preference
125
+ # @param [Boolean, String, Integer] value Value of the preference
126
+ #
127
+
128
+ def add_preference(name, value)
129
+ prefs[name] = value
130
+ end
131
+
132
+ #
133
+ # Run Chrome in headless mode.
134
+ #
135
+ # @example Enable headless mode
136
+ # options = Selenium::WebDriver::Chrome::Options.new
137
+ # options.headless!
138
+ #
139
+
140
+ def headless!
141
+ add_argument '--headless'
142
+ end
143
+
144
+ #
145
+ # Add an emulation device name
146
+ #
147
+ # @example Start Chrome in mobile emulation mode by device name
148
+ # options = Selenium::WebDriver::Chrome::Options.new
149
+ # options.add_emulation(device_name: 'iPhone 6')
150
+ #
151
+ # @example Start Chrome in mobile emulation mode by device metrics
152
+ # options = Selenium::WebDriver::Chrome::Options.new
153
+ # options.add_emulation(device_metrics: {width: 400, height: 800, pixelRatio: 1, touch: true})
154
+ #
155
+ # @param [String] device_name Name of the device or a hash containing width, height, pixelRatio, touch
156
+ # @param [Hash] device_metrics Hash containing width, height, pixelRatio, touch
157
+ # @param [String] user_agent Full user agent
158
+ #
159
+
160
+ def add_emulation(device_name: nil, device_metrics: nil, user_agent: nil)
161
+ @emulation[:deviceName] = device_name if device_name
162
+ @emulation[:deviceMetrics] = device_metrics if device_metrics
163
+ @emulation[:userAgent] = user_agent if user_agent
164
+ end
165
+
166
+ #
167
+ # @api private
168
+ #
169
+
170
+ def as_json(*)
171
+ extensions = @extensions.map do |crx_path|
172
+ File.open(crx_path, 'rb') { |crx_file| Base64.strict_encode64 crx_file.read }
173
+ end
174
+ extensions.concat(@encoded_extensions)
175
+ add_argument("--user-data-dir=#{@profile[:directory]}") if @profile
176
+
177
+ opts = @options
178
+ opts[:binary] = @binary if @binary
179
+ opts[:args] = @args.to_a if @args.any?
180
+ opts[:extensions] = extensions if extensions.any?
181
+ opts[:mobileEmulation] = @emulation unless @emulation.empty?
182
+ opts[:prefs] = @prefs unless @prefs.empty?
183
+ opts[:detach] = @detach if !@detach.nil? && @detach != false
184
+
185
+ {KEY => generate_as_json(opts)}
186
+ end
187
+ end # Options
188
+ end # Chrome
189
+ end # WebDriver
190
+ end # Selenium
@@ -1,7 +1,25 @@
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
+
1
20
  module Selenium
2
21
  module WebDriver
3
22
  module Chrome
4
-
5
23
  #
6
24
  # @private
7
25
  #
@@ -9,16 +27,16 @@ module Selenium
9
27
  class Profile
10
28
  include ProfileHelper
11
29
 
30
+ attr_reader :directory
31
+
12
32
  def initialize(model = nil)
13
- @model = verify_model(model)
33
+ @model = verify_model(model)
14
34
  @extensions = []
15
35
  @encoded_extensions = []
16
36
  end
17
37
 
18
38
  def add_extension(path)
19
- unless File.file?(path)
20
- raise Error::WebDriverError, "could not find extension at #{path.inspect}"
21
- end
39
+ raise Error::WebDriverError, "could not find extension at #{path.inspect}" unless File.file?(path)
22
40
 
23
41
  @extensions << path
24
42
  end
@@ -30,36 +48,38 @@ module Selenium
30
48
  #
31
49
  # Set a preference in the profile.
32
50
  #
33
- # See http://codesearch.google.com/codesearch#OAMlx_jo-ck/src/chrome/common/pref_names.cc&exact_package=chromium
51
+ # See https://src.chromium.org/svn/trunk/src/chrome/common/pref_names.cc
34
52
  #
35
53
 
36
54
  def []=(key, value)
37
- parts = key.split(".")
38
- parts[0..-2].inject(prefs) { |pr, k| pr[k] ||= {} }[parts.last] = value
55
+ parts = key.split('.')
56
+ parts[0..-2].inject(prefs) { |a, e| a[e] ||= {} }[parts.last] = value
39
57
  end
40
58
 
41
59
  def [](key)
42
- parts = key.split(".")
43
- parts.inject(prefs) { |pr, k| pr.fetch(k) }
60
+ parts = key.split('.')
61
+ parts.inject(prefs) { |a, e| a.fetch(e) }
44
62
  end
45
63
 
46
64
  def layout_on_disk
47
- dir = @model ? create_tmp_copy(@model) : Dir.mktmpdir("webdriver-chrome-profile")
48
- FileReaper << dir
65
+ @directory = @model ? create_tmp_copy(@model) : Dir.mktmpdir('webdriver-chrome-profile')
66
+ FileReaper << @directory
49
67
 
50
- write_prefs_to dir
68
+ write_prefs_to @directory
51
69
 
52
- dir
70
+ @directory
53
71
  end
54
72
 
55
- def as_json(opts = nil)
73
+ def as_json(*)
56
74
  extensions = @extensions.map do |crx_path|
57
- File.open(crx_path, "rb") { |crx_file| Base64.strict_encode64 crx_file.read }
75
+ File.open(crx_path, 'rb') { |crx_file| Base64.strict_encode64 crx_file.read }
58
76
  end
59
77
 
60
78
  extensions.concat(@encoded_extensions)
61
79
 
62
- super.merge('extensions' => extensions)
80
+ opts = {'directory' => directory || layout_on_disk}
81
+ opts['extensions'] = extensions if extensions.any?
82
+ opts
63
83
  end
64
84
 
65
85
  private
@@ -68,7 +88,7 @@ module Selenium
68
88
  prefs_file = prefs_file_for(dir)
69
89
 
70
90
  FileUtils.mkdir_p File.dirname(prefs_file)
71
- File.open(prefs_file, "w") { |file| file << WebDriver.json_dump(prefs) }
91
+ File.open(prefs_file, 'w') { |file| file << JSON.generate(prefs) }
72
92
  end
73
93
 
74
94
  def prefs
@@ -77,14 +97,14 @@ module Selenium
77
97
 
78
98
  def read_model_prefs
79
99
  return {} unless @model
80
- WebDriver.json_load File.read(prefs_file_for(@model))
100
+
101
+ JSON.parse File.read(prefs_file_for(@model))
81
102
  end
82
103
 
83
104
  def prefs_file_for(dir)
84
105
  File.join dir, 'Default', 'Preferences'
85
106
  end
86
107
  end # Profile
87
-
88
108
  end # Chrome
89
109
  end # WebDriver
90
110
  end # Selenium