Class: Selenium::WebDriver::WebSocketConnection
- Inherits:
-
Object
- Object
- Selenium::WebDriver::WebSocketConnection
- Defined in:
- lib/selenium/webdriver/common/websocket_connection.rb
Constant Summary collapse
- CONNECTION_ERRORS =
[ Errno::ECONNRESET, # connection is aborted (browser process was killed) Errno::EPIPE, # broken pipe (browser process was killed) Errno::EBADF, # file descriptor already closed (double-close or GC) IOError, # Ruby socket read/write after close EOFError # socket reached EOF after remote closed cleanly ].freeze
- RESPONSE_WAIT_TIMEOUT =
30- RESPONSE_WAIT_INTERVAL =
0.1
- MAX_LOG_MESSAGE_SIZE =
9999
Instance Method Summary collapse
- #add_callback(event, &block) ⇒ Object
- #callbacks ⇒ Object
- #close ⇒ Object
-
#initialize(url:) ⇒ WebSocketConnection
constructor
A new instance of WebSocketConnection.
- #remove_callback(event, id) ⇒ Object
- #send_cmd(**payload) ⇒ Object
Constructor Details
#initialize(url:) ⇒ WebSocketConnection
Returns a new instance of WebSocketConnection.
38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
# File 'lib/selenium/webdriver/common/websocket_connection.rb', line 38 def initialize(url:) @callback_threads = ThreadGroup.new @callbacks_mtx = Mutex.new = Mutex.new @closing_mtx = Mutex.new @closing = false @session_id = nil @url = url process_handshake @socket_thread = attach_socket_listener end |
Instance Method Details
#add_callback(event, &block) ⇒ Object
80 81 82 83 84 85 |
# File 'lib/selenium/webdriver/common/websocket_connection.rb', line 80 def add_callback(event, &block) @callbacks_mtx.synchronize do callbacks[event] << block block.object_id end end |
#callbacks ⇒ Object
76 77 78 |
# File 'lib/selenium/webdriver/common/websocket_connection.rb', line 76 def callbacks @callbacks ||= Hash.new { |callbacks, event| callbacks[event] = [] } end |
#close ⇒ Object
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
# File 'lib/selenium/webdriver/common/websocket_connection.rb', line 53 def close @closing_mtx.synchronize do return if @closing @closing = true end begin socket.close rescue *CONNECTION_ERRORS => e WebDriver.logger.debug "WebSocket listener closed: #{e.class}: #{e.message}", id: :ws # already closed end # Let threads unwind instead of calling exit @socket_thread&.join(0.5) @callback_threads.list.each do |thread| thread.join(0.5) rescue StandardError => e WebDriver.logger.debug "Failed to join thread during close: #{e.class}: #{e.message}", id: :ws end end |
#remove_callback(event, id) ⇒ Object
87 88 89 90 91 92 93 94 95 96 97 |
# File 'lib/selenium/webdriver/common/websocket_connection.rb', line 87 def remove_callback(event, id) @callbacks_mtx.synchronize do return if @closing callbacks_for_event = callbacks[event] return if callbacks_for_event.reject! { |cb| cb.object_id == id } ids = callbacks_for_event.map(&:object_id) raise Error::WebDriverError, "Callback with ID #{id} does not exist for event #{event}: #{ids}" end end |
#send_cmd(**payload) ⇒ Object
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/selenium/webdriver/common/websocket_connection.rb', line 99 def send_cmd(**payload) id = next_id data = payload.merge(id: id) WebDriver.logger.debug "WebSocket -> #{data}"[...MAX_LOG_MESSAGE_SIZE], id: :ws data = JSON.generate(data) out_frame = WebSocket::Frame::Outgoing::Client.new(version: ws.version, data: data, type: 'text') begin socket.write(out_frame.to_s) rescue *CONNECTION_ERRORS => e raise e, "WebSocket is closed (#{e.class}: #{e.message})" end wait.until { .synchronize { .delete(id) } } end |