Class: Selenium::WebDriver::WebSocketConnection Private
- Inherits:
-
Object
- Object
- Selenium::WebDriver::WebSocketConnection
- Defined in:
- lib/selenium/webdriver/common/websocket_connection.rb
This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.
Constant Summary collapse
- CONNECTION_ERRORS =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
[ 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 =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
30- RESPONSE_WAIT_INTERVAL =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
0.1- MAX_LOG_MESSAGE_SIZE =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
9999- MAX_FRAME_SIZE =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
websocket-ruby defaults to a 20MB limit and silently drops larger frames, which can stall the listener. CDP payloads (e.g. large data: URLs) can exceed that, so raise the ceiling for our connections. The gem only exposes the limit as process-global state, so it is raised (never lowered) and not restored on close - concurrent connections share the value. Other bindings rely on their own websocket clients' limits; this constant only affects websocket-ruby.
100 * 1024 * 1024
Instance Method Summary collapse
- #add_callback(event, &block) ⇒ Object private
- #callbacks ⇒ Object private
-
#close ⇒ Object
private
Idempotent: the listener may already have initiated shutdown (see #frame_dropped?), so always close the socket and join threads rather than short-circuiting on @closing.
-
#initialize(url:) ⇒ WebSocketConnection
constructor
private
100MB.
- #remove_callback(event, id) ⇒ Object private
- #send_cmd(**payload) ⇒ Object private
Constructor Details
#initialize(url:) ⇒ WebSocketConnection
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
100MB
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/selenium/webdriver/common/websocket_connection.rb', line 48 def initialize(url:) @callback_threads = ThreadGroup.new @callbacks_mtx = Mutex.new @messages_mtx = Mutex.new @closing_mtx = Mutex.new @closing = false @session_id = nil @url = url apply_frame_size_limit process_handshake @socket_thread = attach_socket_listener end |
Instance Method Details
#add_callback(event, &block) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
83 84 85 86 87 88 |
# File 'lib/selenium/webdriver/common/websocket_connection.rb', line 83 def add_callback(event, &block) @callbacks_mtx.synchronize do callbacks[event] << block block.object_id end end |
#callbacks ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
79 80 81 |
# File 'lib/selenium/webdriver/common/websocket_connection.rb', line 79 def callbacks @callbacks ||= Hash.new { |callbacks, event| callbacks[event] = [] } end |
#close ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Idempotent: the listener may already have initiated shutdown (see #frame_dropped?), so always close the socket and join threads rather than short-circuiting on @closing.
67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/selenium/webdriver/common/websocket_connection.rb', line 67 def close close_socket # Let threads unwind instead of calling exit @socket_thread&.join(0.5) unless @socket_thread == Thread.current @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.}", id: :ws end end |
#remove_callback(event, id) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
90 91 92 93 94 95 96 97 98 99 100 |
# File 'lib/selenium/webdriver/common/websocket_connection.rb', line 90 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
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 |
# File 'lib/selenium/webdriver/common/websocket_connection.rb', line 102 def send_cmd(**payload) # IOError to match what writing to an already-closed socket raises raise IOError, 'WebSocket connection is closed' if @closing 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.})" end wait.until do raise IOError, 'WebSocket connection closed while waiting for a response' if @closing @messages_mtx.synchronize { .delete(id) } end end |