Class: Ferrum::Browser::WebSocket

Inherits:
Object
  • Object
show all
Defined in:
lib/ferrum/browser/web_socket.rb

Constant Summary collapse

WEBSOCKET_BUG_SLEEP =
0.01
SKIP_LOGGING_SCREENSHOTS =
!ENV["FERRUM_LOGGING_SCREENSHOTS"]

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(url, max_receive_size, logger) ⇒ WebSocket

Returns a new instance of WebSocket.



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/ferrum/browser/web_socket.rb', line 15

def initialize(url, max_receive_size, logger)
  @url      = url
  @logger   = logger
  uri       = URI.parse(@url)
  @sock     = TCPSocket.new(uri.host, uri.port)
  max_receive_size ||= ::WebSocket::Driver::MAX_LENGTH
  @driver   = ::WebSocket::Driver.client(self, max_length: max_receive_size)
  @messages = Queue.new

  if SKIP_LOGGING_SCREENSHOTS
    @screenshot_commands = Concurrent::Hash.new
  end

  @driver.on(:open,    &method(:on_open))
  @driver.on(:message, &method(:on_message))
  @driver.on(:close,   &method(:on_close))

  @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

    begin
      while data = @sock.readpartial(512)
        @driver.parse(data)
      end
    rescue EOFError, Errno::ECONNRESET, Errno::EPIPE
      @messages.close
    end
  end

  @driver.start
end

Instance Attribute Details

#messagesObject (readonly)

Returns the value of attribute messages.



13
14
15
# File 'lib/ferrum/browser/web_socket.rb', line 13

def messages
  @messages
end

#urlObject (readonly)

Returns the value of attribute url.



13
14
15
# File 'lib/ferrum/browser/web_socket.rb', line 13

def url
  @url
end

Instance Method Details

#closeObject



89
90
91
# File 'lib/ferrum/browser/web_socket.rb', line 89

def close
  @driver.close
end

#on_close(_event) ⇒ Object



68
69
70
71
# File 'lib/ferrum/browser/web_socket.rb', line 68

def on_close(_event)
  @messages.close
  @thread.kill
end

#on_message(event) ⇒ Object



55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/ferrum/browser/web_socket.rb', line 55

def on_message(event)
  data = JSON.parse(event.data)
  @messages.push(data)

  output = event.data
  if SKIP_LOGGING_SCREENSHOTS && @screenshot_commands[data["id"]]
    @screenshot_commands.delete(data["id"])
    output.sub!(/{"data":"(.*)"}/, %("Set FERRUM_LOGGING_SCREENSHOTS=true to see screenshots in Base64"))
  end

  @logger&.puts("    ◀ #{Ferrum.elapsed_time} #{output}\n")
end

#on_open(_event) ⇒ Object



50
51
52
53
# File 'lib/ferrum/browser/web_socket.rb', line 50

def on_open(_event)
  # https://github.com/faye/websocket-driver-ruby/issues/46
  sleep(WEBSOCKET_BUG_SLEEP)
end

#send_message(data) ⇒ Object



73
74
75
76
77
78
79
80
81
# File 'lib/ferrum/browser/web_socket.rb', line 73

def send_message(data)
  if SKIP_LOGGING_SCREENSHOTS
    @screenshot_commands[data[:id]] = true
  end

  json = data.to_json
  @driver.text(json)
  @logger&.puts("\n\n▶ #{Ferrum.elapsed_time} #{json}")
end

#write(data) ⇒ Object



83
84
85
86
87
# File 'lib/ferrum/browser/web_socket.rb', line 83

def write(data)
  @sock.write(data)
rescue EOFError, Errno::ECONNRESET, Errno::EPIPE
  @messages.close
end