class Ferrum::Browser::Client

Constants

INTERRUPTIONS

Public Class Methods

new(browser, ws_url, id_starts_with: 0) click to toggle source
# File lib/ferrum/browser/client.rb, line 12
def initialize(browser, ws_url, id_starts_with: 0)
  @browser = browser
  @command_id = id_starts_with
  @pendings = Concurrent::Hash.new
  @ws = WebSocket.new(ws_url, @browser.ws_max_receive_size, @browser.logger)
  @subscriber, @interruptor = Subscriber.build(2)

  @thread = Thread.new do
    Thread.current.abort_on_exception = true
    if Thread.current.respond_to?(:report_on_exception=)
      Thread.current.report_on_exception = true
    end

    while message = @ws.messages.pop
      if INTERRUPTIONS.include?(message["method"])
        @interruptor.async.call(message)
      elsif message.key?("method")
        @subscriber.async.call(message)
      else
        @pendings[message["id"]]&.set(message)
      end
    end
  end
end

Public Instance Methods

close() click to toggle source
# File lib/ferrum/browser/client.rb, line 65
def close
  @ws.close
  # Give a thread some time to handle a tail of messages
  @pendings.clear
  @thread.kill unless @thread.join(1)
end
command(method, params = {}) click to toggle source
# File lib/ferrum/browser/client.rb, line 37
def command(method, params = {})
  pending = Concurrent::IVar.new
  message = build_message(method, params)
  @pendings[message[:id]] = pending
  @ws.send_message(message)
  data = pending.value!(@browser.timeout)
  @pendings.delete(message[:id])

  raise DeadBrowserError if data.nil? && @ws.messages.closed?
  raise TimeoutError unless data
  error, response = data.values_at("error", "result")
  raise_browser_error(error) if error
  response
end
on(event, &block) click to toggle source
# File lib/ferrum/browser/client.rb, line 52
def on(event, &block)
  case event
  when *INTERRUPTIONS
    @interruptor.on(event, &block)
  else
    @subscriber.on(event, &block)
  end
end
subscribed?(event) click to toggle source
# File lib/ferrum/browser/client.rb, line 61
def subscribed?(event)
  [@interruptor, @subscriber].any? { |s| s.subscribed?(event) }
end

Private Instance Methods

build_message(method, params) click to toggle source
# File lib/ferrum/browser/client.rb, line 74
def build_message(method, params)
  { method: method, params: params }.merge(id: next_command_id)
end
next_command_id() click to toggle source
# File lib/ferrum/browser/client.rb, line 78
def next_command_id
  @command_id += 1
end
raise_browser_error(error) click to toggle source
# File lib/ferrum/browser/client.rb, line 82
def raise_browser_error(error)
  case error["message"]
  # Node has disappeared while we were trying to get it
  when "No node with given id found",
       "Could not find node with given id"
    raise NodeNotFoundError.new(error)
  # Context is lost, page is reloading
  when "Cannot find context with specified id"
    raise NoExecutionContextError.new(error)
  when "No target with given id found"
    raise NoSuchPageError
  when /Could not compute content quads/
    raise CoordinatesNotFoundError
  else
    raise BrowserError.new(error)
  end
end