class Selenium::WebDriver::ServiceManager

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

@api private

Constants

SOCKET_LOCK_TIMEOUT
START_TIMEOUT
STOP_TIMEOUT

Public Class Methods

new(config) click to toggle source

End users should use a class method for the desired driver, rather than using this directly.

@api private

# File lib/selenium/webdriver/common/service_manager.rb, line 39
def initialize(config)
  @executable_path = config.executable_path
  @host = Platform.localhost
  @port = config.port
  @extra_args = config.extra_args
  @shutdown_supported = config.shutdown_supported

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

Public Instance Methods

start() click to toggle source
# File lib/selenium/webdriver/common/service_manager.rb, line 49
def start
  raise "already started: #{uri.inspect} #{@executable_path.inspect}" if process_running?

  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_manager.rb, line 61
def stop
  return unless @shutdown_supported
  return if process_exited?

  stop_server
  @process.poll_for_exit STOP_TIMEOUT
rescue ChildProcess::TimeoutError
  nil # noop
ensure
  stop_process
end
uri() click to toggle source
# File lib/selenium/webdriver/common/service_manager.rb, line 73
def uri
  @uri ||= URI.parse("http://#{@host}:#{@port}")
end

Private Instance Methods

build_process(*command) click to toggle source
# File lib/selenium/webdriver/common/service_manager.rb, line 79
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_manager.rb, line 141
def cannot_connect_error_text
  "unable to connect to #{@executable_path} #{@host}:#{@port}"
end
connect_to_server() { |http| ... } click to toggle source
# File lib/selenium/webdriver/common/service_manager.rb, line 92
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_manager.rb, line 134
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_manager.rb, line 101
def find_free_port
  @port = PortProber.above(@port)
end
process_exited?() click to toggle source
# File lib/selenium/webdriver/common/service_manager.rb, line 130
def process_exited?
  @process.nil? || @process.exited?
end
process_running?() click to toggle source
# File lib/selenium/webdriver/common/service_manager.rb, line 126
def process_running?
  defined?(@process) && @process&.alive?
end
socket_lock() click to toggle source
# File lib/selenium/webdriver/common/service_manager.rb, line 145
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_manager.rb, line 105
def start_process
  @process = build_process(@executable_path, "--port=#{@port}", *@extra_args)
  # NOTE: this is a bug only in Windows 7
  @process.leader = true unless Platform.windows?
  @process.start
end
stop_process() click to toggle source
# File lib/selenium/webdriver/common/service_manager.rb, line 112
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_manager.rb, line 119
def stop_server
  connect_to_server do |http|
    headers = WebDriver::Remote::Http::Common::DEFAULT_HEADERS.dup
    http.get('/shutdown', headers)
  end
end