selenium-webdriver 2.53.4 → 3.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (122) hide show
  1. data/CHANGES +24 -18
  2. data/README.md +2 -3
  3. data/lib/selenium/server.rb +64 -68
  4. data/lib/selenium/webdriver.rb +5 -9
  5. data/lib/selenium/webdriver/chrome.rb +18 -3
  6. data/lib/selenium/webdriver/chrome/bridge.rb +13 -16
  7. data/lib/selenium/webdriver/chrome/profile.rb +7 -9
  8. data/lib/selenium/webdriver/chrome/service.rb +8 -84
  9. data/lib/selenium/webdriver/common.rb +1 -2
  10. data/lib/selenium/webdriver/common/action_builder.rb +28 -38
  11. data/lib/selenium/webdriver/common/alert.rb +7 -10
  12. data/lib/selenium/webdriver/common/bridge_helper.rb +10 -15
  13. data/lib/selenium/webdriver/common/driver.rb +19 -28
  14. data/lib/selenium/webdriver/common/driver_extensions/has_input_devices.rb +0 -3
  15. data/lib/selenium/webdriver/common/driver_extensions/has_location.rb +4 -6
  16. data/lib/selenium/webdriver/common/driver_extensions/has_network_connection.rb +4 -5
  17. data/lib/selenium/webdriver/common/driver_extensions/has_remote_status.rb +0 -2
  18. data/lib/selenium/webdriver/common/driver_extensions/has_session_id.rb +0 -2
  19. data/lib/selenium/webdriver/common/driver_extensions/has_touch_screen.rb +0 -2
  20. data/lib/selenium/webdriver/common/driver_extensions/has_web_storage.rb +0 -3
  21. data/lib/selenium/webdriver/common/driver_extensions/rotatable.rb +3 -6
  22. data/lib/selenium/webdriver/common/driver_extensions/takes_screenshot.rb +2 -5
  23. data/lib/selenium/webdriver/common/driver_extensions/uploads_files.rb +2 -5
  24. data/lib/selenium/webdriver/common/element.rb +27 -29
  25. data/lib/selenium/webdriver/common/error.rb +17 -20
  26. data/lib/selenium/webdriver/common/file_reaper.rb +3 -9
  27. data/lib/selenium/webdriver/common/html5/local_storage.rb +6 -8
  28. data/lib/selenium/webdriver/common/html5/session_storage.rb +6 -8
  29. data/lib/selenium/webdriver/common/html5/shared_web_storage.rb +6 -15
  30. data/lib/selenium/webdriver/common/keyboard.rb +7 -12
  31. data/lib/selenium/webdriver/common/keys.rb +67 -69
  32. data/lib/selenium/webdriver/common/log_entry.rb +3 -4
  33. data/lib/selenium/webdriver/common/logs.rb +2 -4
  34. data/lib/selenium/webdriver/common/mouse.rb +9 -12
  35. data/lib/selenium/webdriver/common/navigation.rb +2 -4
  36. data/lib/selenium/webdriver/common/options.rb +16 -19
  37. data/lib/selenium/webdriver/common/platform.rb +61 -90
  38. data/lib/selenium/webdriver/common/port_prober.rb +1 -2
  39. data/lib/selenium/webdriver/common/profile_helper.rb +5 -8
  40. data/lib/selenium/webdriver/common/proxy.rb +58 -70
  41. data/lib/selenium/webdriver/common/search_context.rb +15 -19
  42. data/lib/selenium/webdriver/common/service.rb +127 -0
  43. data/lib/selenium/webdriver/common/socket_lock.rb +5 -11
  44. data/lib/selenium/webdriver/common/socket_poller.rb +4 -9
  45. data/lib/selenium/webdriver/common/target_locator.rb +11 -13
  46. data/lib/selenium/webdriver/common/timeouts.rb +4 -6
  47. data/lib/selenium/webdriver/common/touch_action_builder.rb +2 -4
  48. data/lib/selenium/webdriver/common/touch_screen.rb +15 -18
  49. data/lib/selenium/webdriver/common/w3c_error.rb +3 -6
  50. data/lib/selenium/webdriver/common/wait.rb +6 -11
  51. data/lib/selenium/webdriver/common/window.rb +12 -15
  52. data/lib/selenium/webdriver/common/zipper.rb +6 -8
  53. data/lib/selenium/webdriver/edge.rb +18 -3
  54. data/lib/selenium/webdriver/edge/bridge.rb +11 -16
  55. data/lib/selenium/webdriver/edge/legacy_support.rb +38 -39
  56. data/lib/selenium/webdriver/edge/service.rb +8 -82
  57. data/lib/selenium/webdriver/firefox.rb +25 -6
  58. data/lib/selenium/webdriver/firefox/binary.rb +37 -53
  59. data/lib/selenium/webdriver/firefox/bridge.rb +3 -6
  60. data/lib/selenium/webdriver/firefox/extension.rb +4 -6
  61. data/lib/selenium/webdriver/firefox/extension/prefs.json +1 -10
  62. data/lib/selenium/webdriver/firefox/extension/webdriver.xpi +0 -0
  63. data/lib/selenium/webdriver/firefox/launcher.rb +8 -11
  64. data/lib/selenium/webdriver/firefox/profile.rb +40 -42
  65. data/lib/selenium/webdriver/firefox/profiles_ini.rb +8 -15
  66. data/lib/selenium/webdriver/firefox/service.rb +23 -79
  67. data/lib/selenium/webdriver/firefox/util.rb +0 -2
  68. data/lib/selenium/webdriver/firefox/w3c_bridge.rb +2 -4
  69. data/lib/selenium/webdriver/ie.rb +16 -7
  70. data/lib/selenium/webdriver/ie/bridge.rb +16 -23
  71. data/lib/selenium/webdriver/{iphone.rb → ie/service.rb} +26 -4
  72. data/lib/selenium/webdriver/phantomjs.rb +8 -3
  73. data/lib/selenium/webdriver/phantomjs/bridge.rb +9 -11
  74. data/lib/selenium/webdriver/phantomjs/service.rb +17 -81
  75. data/lib/selenium/webdriver/remote.rb +0 -2
  76. data/lib/selenium/webdriver/remote/bridge.rb +193 -191
  77. data/lib/selenium/webdriver/remote/capabilities.rb +60 -90
  78. data/lib/selenium/webdriver/remote/commands.rb +197 -192
  79. data/lib/selenium/webdriver/remote/http/common.rb +15 -13
  80. data/lib/selenium/webdriver/remote/http/curb.rb +5 -9
  81. data/lib/selenium/webdriver/remote/http/default.rb +32 -37
  82. data/lib/selenium/webdriver/remote/http/persistent.rb +4 -6
  83. data/lib/selenium/webdriver/remote/response.rb +13 -21
  84. data/lib/selenium/webdriver/remote/server_error.rb +1 -3
  85. data/lib/selenium/webdriver/remote/w3c_bridge.rb +200 -195
  86. data/lib/selenium/webdriver/remote/w3c_capabilities.rb +38 -46
  87. data/lib/selenium/webdriver/remote/w3c_commands.rb +116 -113
  88. data/lib/selenium/webdriver/safari.rb +23 -7
  89. data/lib/selenium/{client/javascript_frameworks/jquery.rb → webdriver/safari/apple_bridge.rb} +28 -9
  90. data/lib/selenium/webdriver/safari/browser.rb +0 -2
  91. data/lib/selenium/webdriver/safari/{bridge.rb → legacy_bridge.rb} +12 -9
  92. data/lib/selenium/webdriver/safari/options.rb +3 -4
  93. data/lib/selenium/webdriver/safari/resources/client.js +56 -7255
  94. data/lib/selenium/webdriver/safari/server.rb +18 -24
  95. data/lib/selenium/{client/javascript_frameworks/prototype.rb → webdriver/safari/service.rb} +27 -9
  96. data/lib/selenium/webdriver/support.rb +1 -0
  97. data/lib/selenium/webdriver/support/abstract_event_listener.rb +17 -2
  98. data/lib/selenium/webdriver/support/block_event_listener.rb +1 -3
  99. data/lib/selenium/webdriver/support/color.rb +55 -38
  100. data/lib/selenium/webdriver/{android.rb → support/escaper.rb} +19 -4
  101. data/lib/selenium/webdriver/support/event_firing_bridge.rb +36 -38
  102. data/lib/selenium/webdriver/support/select.rb +33 -84
  103. data/selenium-webdriver.gemspec +23 -23
  104. metadata +19 -30
  105. data/lib/selenium-client.rb +0 -21
  106. data/lib/selenium/client.rb +0 -57
  107. data/lib/selenium/client/base.rb +0 -151
  108. data/lib/selenium/client/driver.rb +0 -29
  109. data/lib/selenium/client/errors.rb +0 -28
  110. data/lib/selenium/client/extensions.rb +0 -132
  111. data/lib/selenium/client/idiomatic.rb +0 -507
  112. data/lib/selenium/client/javascript_expression_builder.rb +0 -135
  113. data/lib/selenium/client/legacy_driver.rb +0 -1722
  114. data/lib/selenium/client/protocol.rb +0 -123
  115. data/lib/selenium/client/selenium_helper.rb +0 -49
  116. data/lib/selenium/rake/server_task.rb +0 -176
  117. data/lib/selenium/webdriver/android/bridge.rb +0 -68
  118. data/lib/selenium/webdriver/common/core_ext/base64.rb +0 -28
  119. data/lib/selenium/webdriver/common/core_ext/dir.rb +0 -61
  120. data/lib/selenium/webdriver/common/html5/location.rb +0 -19
  121. data/lib/selenium/webdriver/ie/server.rb +0 -133
  122. data/lib/selenium/webdriver/iphone/bridge.rb +0 -64
@@ -38,7 +38,7 @@ module Selenium
38
38
  port
39
39
  end
40
40
 
41
- IGNORED_ERRORS = [Errno::EADDRNOTAVAIL]
41
+ IGNORED_ERRORS = [Errno::EADDRNOTAVAIL].freeze
42
42
  IGNORED_ERRORS << Errno::EBADF if Platform.cygwin?
43
43
 
44
44
  def self.free?(port)
@@ -55,7 +55,6 @@ module Selenium
55
55
  rescue SocketError, Errno::EADDRINUSE
56
56
  false
57
57
  end
58
-
59
58
  end # PortProber
60
59
  end # WebDriver
61
60
  end # Selenium
@@ -19,7 +19,6 @@
19
19
 
20
20
  module Selenium
21
21
  module WebDriver
22
-
23
22
  #
24
23
  # @api private
25
24
  #
@@ -28,27 +27,26 @@ module Selenium
28
27
  #
29
28
 
30
29
  module ProfileHelper
31
-
32
30
  def self.included(base)
33
31
  base.extend ClassMethods
34
32
  end
35
33
 
36
- def as_json(opts = nil)
34
+ def as_json(*)
37
35
  {'zip' => Zipper.zip(layout_on_disk)}
38
36
  end
39
37
 
40
- def to_json(*args)
38
+ def to_json(*)
41
39
  JSON.generate as_json
42
40
  end
43
41
 
44
42
  private
45
43
 
46
44
  def create_tmp_copy(directory)
47
- tmp_directory = Dir.mktmpdir("webdriver-rb-profilecopy")
45
+ tmp_directory = Dir.mktmpdir('webdriver-rb-profilecopy')
48
46
 
49
47
  # TODO: must be a better way..
50
48
  FileUtils.rm_rf tmp_directory
51
- FileUtils.mkdir_p File.dirname(tmp_directory), :mode => 0700
49
+ FileUtils.mkdir_p File.dirname(tmp_directory), mode: 0700
52
50
  FileUtils.cp_r directory, tmp_directory
53
51
 
54
52
  tmp_directory
@@ -72,7 +70,7 @@ module Selenium
72
70
  tmp_dir = Dir.mktmpdir
73
71
  begin
74
72
  zip_path = File.join(tmp_dir, "webdriver-profile-duplicate-#{json.hash}.zip")
75
- File.open(zip_path, "wb") { |zip_file| zip_file << Base64.decode64(data) }
73
+ File.open(zip_path, 'wb') { |zip_file| zip_file << Base64.decode64(data) }
76
74
 
77
75
  new Zipper.unzip(zip_path)
78
76
  ensure
@@ -80,7 +78,6 @@ module Selenium
80
78
  end
81
79
  end
82
80
  end # ClassMethods
83
-
84
81
  end # ProfileHelper
85
82
  end # WebDriver
86
83
  end # Selenium
@@ -21,45 +21,56 @@ module Selenium
21
21
  module WebDriver
22
22
  class Proxy
23
23
  TYPES = {
24
- :direct => "DIRECT", # Direct connection, no proxy (default on Windows).
25
- :manual => "MANUAL", # Manual proxy settings (e.g., for httpProxy).
26
- :pac => "PAC", # Proxy autoconfiguration from URL.
27
- :auto_detect => "AUTODETECT", # Proxy autodetection (presumably with WPAD).
28
- :system => "SYSTEM" # Use system settings (default on Linux).
29
- }
30
-
31
- attr_reader :type,
32
- :ftp,
33
- :http,
34
- :socks,
35
- :socks_username,
36
- :socks_password,
37
- :no_proxy,
38
- :pac,
39
- :ssl,
40
- :auto_detect
24
+ direct: 'DIRECT', # Direct connection, no proxy (default on Windows).
25
+ manual: 'MANUAL', # Manual proxy settings (e.g., for httpProxy).
26
+ pac: 'PAC', # Proxy autoconfiguration from URL.
27
+ auto_detect: 'AUTODETECT', # Proxy autodetection (presumably with WPAD).
28
+ system: 'SYSTEM' # Use system settings (default on Linux).
29
+ }.freeze
30
+
31
+ ALLOWED = {type: 'proxyType',
32
+ ftp: 'ftpProxy',
33
+ http: 'httpProxy',
34
+ no_proxy: 'noProxy',
35
+ pac: 'proxyAutoconfigUrl',
36
+ ssl: 'sslProxy',
37
+ auto_detect: 'autodetect',
38
+ socks: 'socksProxy',
39
+ socks_username: 'socksUsername',
40
+ socks_password: 'socksPassword'}.freeze
41
+
42
+ ALLOWED.keys.each { |t| attr_reader t }
43
+
44
+ def self.json_create(data)
45
+ data['proxyType'] = data['proxyType'].downcase.to_sym
46
+ return if data['proxyType'] == :unspecified
47
+
48
+ proxy = new
49
+
50
+ ALLOWED.each do |k, v|
51
+ proxy.send("#{k}=", data[v]) if data.key?(v)
52
+ end
53
+
54
+ proxy
55
+ end
41
56
 
42
57
  def initialize(opts = {})
43
- opts = opts.dup
44
-
45
- self.type = opts.delete(:type) if opts.has_key? :type
46
- self.ftp = opts.delete(:ftp) if opts.has_key? :ftp
47
- self.http = opts.delete(:http) if opts.has_key? :http
48
- self.no_proxy = opts.delete(:no_proxy) if opts.has_key? :no_proxy
49
- self.ssl = opts.delete(:ssl) if opts.has_key? :ssl
50
- self.pac = opts.delete(:pac) if opts.has_key? :pac
51
- self.auto_detect = opts.delete(:auto_detect) if opts.has_key? :auto_detect
52
- self.socks = opts.delete(:socks) if opts.has_key? :socks
53
- self.socks_username = opts.delete(:socks_username) if opts.has_key? :socks_username
54
- self.socks_password = opts.delete(:socks_password) if opts.has_key? :socks_password
55
-
56
- unless opts.empty?
57
- raise ArgumentError, "unknown option#{'s' if opts.size != 1}: #{opts.inspect}"
58
+ not_allowed = []
59
+
60
+ opts.each do |k, v|
61
+ if ALLOWED.key?(k)
62
+ send("#{k}=", v)
63
+ else
64
+ not_allowed << k
65
+ end
58
66
  end
67
+
68
+ return if not_allowed.empty?
69
+ raise ArgumentError, "unknown option#{'s' if not_allowed.size != 1}: #{not_allowed.inspect}"
59
70
  end
60
71
 
61
72
  def ==(other)
62
- other.kind_of?(self.class) && as_json == other.as_json
73
+ other.is_a?(self.class) && as_json == other.as_json
63
74
  end
64
75
  alias_method :eql?, :==
65
76
 
@@ -109,7 +120,7 @@ module Selenium
109
120
  end
110
121
 
111
122
  def type=(type)
112
- unless TYPES.has_key? type
123
+ unless TYPES.key? type
113
124
  raise ArgumentError, "invalid proxy type: #{type.inspect}, expected one of #{TYPES.keys.inspect}"
114
125
  end
115
126
 
@@ -120,49 +131,26 @@ module Selenium
120
131
  @type = type
121
132
  end
122
133
 
123
- def as_json(opts = nil)
134
+ def as_json(*)
124
135
  json_result = {
125
- "proxyType" => TYPES[type]
126
- }
127
-
128
- json_result["ftpProxy"] = ftp if ftp
129
- json_result["httpProxy"] = http if http
130
- json_result["noProxy"] = no_proxy if no_proxy
131
- json_result["proxyAutoconfigUrl"] = pac if pac
132
- json_result["sslProxy"] = ssl if ssl
133
- json_result["autodetect"] = auto_detect if auto_detect
134
- json_result["socksProxy"] = socks if socks
135
- json_result["socksUsername"] = socks_username if socks_username
136
- json_result["socksPassword"] = socks_password if socks_password
136
+ 'proxyType' => TYPES[type],
137
+ 'ftpProxy' => ftp,
138
+ 'httpProxy' => http,
139
+ 'noProxy' => no_proxy,
140
+ 'proxyAutoconfigUrl' => pac,
141
+ 'sslProxy' => ssl,
142
+ 'autodetect' => auto_detect,
143
+ 'socksProxy' => socks,
144
+ 'socksUsername' => socks_username,
145
+ 'socksPassword' => socks_password
146
+ }.delete_if { |_k, v| v.nil? }
137
147
 
138
148
  json_result if json_result.length > 1
139
149
  end
140
150
 
141
- def to_json(*args)
151
+ def to_json(*)
142
152
  JSON.generate as_json
143
153
  end
144
-
145
- class << self
146
- def json_create(data)
147
- return if data['proxyType'] == 'UNSPECIFIED'
148
-
149
- proxy = new
150
-
151
- proxy.type = data['proxyType'].downcase.to_sym if data.has_key? 'proxyType'
152
- proxy.ftp = data['ftpProxy'] if data.has_key? 'ftpProxy'
153
- proxy.http = data['httpProxy'] if data.has_key? 'httpProxy'
154
- proxy.no_proxy = data['noProxy'] if data.has_key? 'noProxy'
155
- proxy.pac = data['proxyAutoconfigUrl'] if data.has_key? 'proxyAutoconfigUrl'
156
- proxy.ssl = data['sslProxy'] if data.has_key? 'sslProxy'
157
- proxy.auto_detect = data['autodetect'] if data.has_key? 'autodetect'
158
- proxy.socks = data['socksProxy'] if data.has_key? 'socksProxy'
159
- proxy.socks_username = data['socksUsername'] if data.has_key? 'socksUsername'
160
- proxy.socks_password = data['socksPassword'] if data.has_key? 'socksPassword'
161
-
162
- proxy
163
- end
164
- end # class << self
165
-
166
154
  end # Proxy
167
155
  end # WebDriver
168
156
  end # Selenium
@@ -20,20 +20,19 @@
20
20
  module Selenium
21
21
  module WebDriver
22
22
  module SearchContext
23
-
24
23
  # @api private
25
24
  FINDERS = {
26
- :class => 'class name',
27
- :class_name => 'class name',
28
- :css => 'css selector',
29
- :id => 'id',
30
- :link => 'link text',
31
- :link_text => 'link text',
32
- :name => 'name',
33
- :partial_link_text => 'partial link text',
34
- :tag_name => 'tag name',
35
- :xpath => 'xpath',
36
- }
25
+ class: 'class name',
26
+ class_name: 'class name',
27
+ css: 'css selector',
28
+ id: 'id',
29
+ link: 'link text',
30
+ link_text: 'link text',
31
+ name: 'name',
32
+ partial_link_text: 'partial link text',
33
+ tag_name: 'tag name',
34
+ xpath: 'xpath'
35
+ }.freeze
37
36
 
38
37
  #
39
38
  # Find the first element matching the given arguments.
@@ -54,9 +53,8 @@ module Selenium
54
53
  def find_element(*args)
55
54
  how, what = extract_args(args)
56
55
 
57
- unless by = FINDERS[how.to_sym]
58
- raise ArgumentError, "cannot find element by #{how.inspect}"
59
- end
56
+ by = FINDERS[how.to_sym]
57
+ raise ArgumentError, "cannot find element by #{how.inspect}" unless by
60
58
 
61
59
  bridge.find_element_by by, what.to_s, ref
62
60
  rescue Selenium::WebDriver::Error::TimeOutError
@@ -77,9 +75,8 @@ module Selenium
77
75
  def find_elements(*args)
78
76
  how, what = extract_args(args)
79
77
 
80
- unless by = FINDERS[how.to_sym]
81
- raise ArgumentError, "cannot find elements by #{how.inspect}"
82
- end
78
+ by = FINDERS[how.to_sym]
79
+ raise ArgumentError, "cannot find elements by #{how.inspect}" unless by
83
80
 
84
81
  bridge.find_elements_by by, what.to_s, ref
85
82
  rescue Selenium::WebDriver::Error::TimeOutError
@@ -111,7 +108,6 @@ module Selenium
111
108
  raise ArgumentError, "wrong number of arguments (#{args.size} for 2)"
112
109
  end
113
110
  end
114
-
115
111
  end # SearchContext
116
112
  end # WebDriver
117
113
  end # Selenium
@@ -0,0 +1,127 @@
1
+ # encoding: utf-8
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
+ #
23
+ # Base class implementing default behavior of service object,
24
+ # responsible for starting and stopping driver implementations.
25
+ #
26
+ # Subclasses must implement the following private methods:
27
+ # * #start_process
28
+ # * #stop_server
29
+ # * #cannot_connect_error_text
30
+ #
31
+ # @api private
32
+ #
33
+
34
+ class Service
35
+ START_TIMEOUT = 20
36
+ SOCKET_LOCK_TIMEOUT = 45
37
+ STOP_TIMEOUT = 5
38
+
39
+ attr_accessor :host
40
+
41
+ def initialize(executable_path, port, *extra_args)
42
+ @executable_path = executable_path
43
+ @host = Platform.localhost
44
+ @port = Integer(port)
45
+ @extra_args = extra_args
46
+
47
+ raise Error::WebDriverError, "invalid port: #{@port}" if @port < 1
48
+ end
49
+
50
+ def start
51
+ if process_running?
52
+ raise "already started: #{uri.inspect} #{@executable_path.inspect}"
53
+ end
54
+
55
+ Platform.exit_hook { stop } # make sure we don't leave the server running
56
+
57
+ socket_lock.locked do
58
+ find_free_port
59
+ start_process
60
+ connect_until_stable
61
+ end
62
+ end
63
+
64
+ def stop
65
+ return if process_exited?
66
+ stop_server
67
+ ensure
68
+ stop_process
69
+ end
70
+
71
+ def uri
72
+ @uri ||= URI.parse("http://#{@host}:#{@port}")
73
+ end
74
+
75
+ private
76
+
77
+ def connect_to_server
78
+ Net::HTTP.start(@host, @port) do |http|
79
+ http.open_timeout = STOP_TIMEOUT / 2
80
+ http.read_timeout = STOP_TIMEOUT / 2
81
+
82
+ yield http
83
+ end
84
+ end
85
+
86
+ def find_free_port
87
+ @port = PortProber.above(@port)
88
+ end
89
+
90
+ def start_process
91
+ raise NotImplementedError, 'subclass responsibility'
92
+ end
93
+
94
+ def stop_server
95
+ raise NotImplementedError, 'subclass responsibility'
96
+ end
97
+
98
+ def stop_process
99
+ @process.poll_for_exit STOP_TIMEOUT
100
+ rescue ChildProcess::TimeoutError
101
+ @process.stop STOP_TIMEOUT
102
+ end
103
+
104
+ def process_running?
105
+ @process && @process.alive?
106
+ end
107
+
108
+ def process_exited?
109
+ @process.nil? || @process.exited?
110
+ end
111
+
112
+ def connect_until_stable
113
+ socket_poller = SocketPoller.new @host, @port, START_TIMEOUT
114
+ return if socket_poller.connected?
115
+ raise Error::WebDriverError, cannot_connect_error_text
116
+ end
117
+
118
+ def cannot_connect_error_text
119
+ raise NotImplementedError, 'subclass responsibility'
120
+ end
121
+
122
+ def socket_lock
123
+ @socket_lock ||= SocketLock.new(@port - 1, SOCKET_LOCK_TIMEOUT)
124
+ end
125
+ end # Service
126
+ end # WebDriver
127
+ end # Selenium
@@ -19,13 +19,11 @@
19
19
 
20
20
  module Selenium
21
21
  module WebDriver
22
-
23
22
  #
24
23
  # @api private
25
24
  #
26
25
 
27
26
  class SocketLock
28
-
29
27
  def initialize(port, timeout)
30
28
  @port = port
31
29
  @timeout = timeout
@@ -36,7 +34,7 @@ module Selenium
36
34
  # execution block if the lock could be successfully obtained.
37
35
  #
38
36
 
39
- def locked(&blk)
37
+ def locked
40
38
  lock
41
39
 
42
40
  begin
@@ -51,13 +49,10 @@ module Selenium
51
49
  def lock
52
50
  max_time = Time.now + @timeout
53
51
 
54
- until can_lock? || Time.now >= max_time
55
- sleep 0.1
56
- end
52
+ sleep 0.1 until can_lock? || Time.now >= max_time
57
53
 
58
- unless did_lock?
59
- raise Error::WebDriverError, "unable to bind to locking port #{@port} within #{@timeout} seconds"
60
- end
54
+ return if did_lock?
55
+ raise Error::WebDriverError, "unable to bind to locking port #{@port} within #{@timeout} seconds"
61
56
  end
62
57
 
63
58
  def release
@@ -75,9 +70,8 @@ module Selenium
75
70
  end
76
71
 
77
72
  def did_lock?
78
- !!@server
73
+ !@server.nil?
79
74
  end
80
-
81
75
  end # SocketLock
82
76
  end # WebDriver
83
77
  end # Selenium