class Selenium::WebDriver::Service

Base class implementing default behavior of service object, responsible for starting and stopping driver implementations.

Subclasses must implement the following private methods:

* #start_process
* #stop_server
* #cannot_connect_error_text

@api private

Constants

SOCKET_LOCK_TIMEOUT
START_TIMEOUT
STOP_TIMEOUT

Attributes

executable[R]
missing_text[R]
host[RW]

Public Class Methods

new(executable_path, port, driver_opts) click to toggle source
# File lib/selenium/webdriver/common/service.rb, line 46
def initialize(executable_path, port, driver_opts)
  @executable_path = binary_path(executable_path)
  @host            = Platform.localhost
  @port            = Integer(port)
  @extra_args      = extract_service_args(driver_opts)

  raise Error::WebDriverError, "invalid port: #{@port}" if @port < 1
end

Public Instance Methods

binary_path(path) click to toggle source
# File lib/selenium/webdriver/common/service.rb, line 55
def binary_path(path)
  path = Platform.find_binary(self.class.executable) if path.nil?
  raise Error::WebDriverError, self.class.missing_text unless path
  Platform.assert_executable path
  path
end
start() click to toggle source
# File lib/selenium/webdriver/common/service.rb, line 62
def start
  if process_running?
    raise "already started: #{uri.inspect} #{@executable_path.inspect}"
  end

  Platform.exit_hook { stop } # make sure we don't leave the server running

  socket_lock.locked do
    find_free_port
    start_process
    connect_until_stable
  end
end
stop() click to toggle source
# File lib/selenium/webdriver/common/service.rb, line 76
def stop
  stop_server
  @process.poll_for_exit STOP_TIMEOUT
rescue ChildProcess::TimeoutError
ensure
  stop_process
end
uri() click to toggle source
# File lib/selenium/webdriver/common/service.rb, line 84
def uri
  @uri ||= URI.parse("http://#{@host}:#{@port}")
end

Protected Instance Methods

extract_service_args(driver_opts) click to toggle source
# File lib/selenium/webdriver/common/service.rb, line 155
def extract_service_args(driver_opts)
  driver_opts.key?(:args) ? driver_opts.delete(:args) : []
end

Private Instance Methods

build_process(*command) click to toggle source
# File lib/selenium/webdriver/common/service.rb, line 90
def build_process(*command)
  WebDriver.logger.debug("Executing Process #{command}")
  @process = ChildProcess.build(*command)
  if WebDriver.logger.debug?
    @process.io.stdout = @process.io.stderr = WebDriver.logger.io
  elsif Platform.jruby?
    # Apparently we need to read the output of drivers on JRuby.
    @process.io.stdout = @process.io.stderr = File.new(Platform.null_device, 'w')
  end

  @process
end
cannot_connect_error_text() click to toggle source
# File lib/selenium/webdriver/common/service.rb, line 145
def cannot_connect_error_text
  raise NotImplementedError, 'subclass responsibility'
end
connect_to_server() { |http| ... } click to toggle source
# File lib/selenium/webdriver/common/service.rb, line 103
def connect_to_server
  Net::HTTP.start(@host, @port) do |http|
    http.open_timeout = STOP_TIMEOUT / 2
    http.read_timeout = STOP_TIMEOUT / 2

    yield http
  end
end
connect_until_stable() click to toggle source
# File lib/selenium/webdriver/common/service.rb, line 139
def connect_until_stable
  socket_poller = SocketPoller.new @host, @port, START_TIMEOUT
  return if socket_poller.connected?
  raise Error::WebDriverError, cannot_connect_error_text
end
find_free_port() click to toggle source
# File lib/selenium/webdriver/common/service.rb, line 112
def find_free_port
  @port = PortProber.above(@port)
end
process_exited?() click to toggle source
# File lib/selenium/webdriver/common/service.rb, line 135
def process_exited?
  @process.nil? || @process.exited?
end
process_running?() click to toggle source
# File lib/selenium/webdriver/common/service.rb, line 131
def process_running?
  defined?(@process) && @process && @process.alive?
end
socket_lock() click to toggle source
# File lib/selenium/webdriver/common/service.rb, line 149
def socket_lock
  @socket_lock ||= SocketLock.new(@port - 1, SOCKET_LOCK_TIMEOUT)
end
start_process() click to toggle source
# File lib/selenium/webdriver/common/service.rb, line 116
def start_process
  raise NotImplementedError, 'subclass responsibility'
end
stop_process() click to toggle source
# File lib/selenium/webdriver/common/service.rb, line 120
def stop_process
  return if process_exited?
  @process.stop STOP_TIMEOUT
  @process.io.stdout.close if Platform.jruby? && !WebDriver.logger.debug?
end
stop_server() click to toggle source
# File lib/selenium/webdriver/common/service.rb, line 126
def stop_server
  return if process_exited?
  connect_to_server { |http| http.get('/shutdown') }
end