selenium-webdriver 4.47.0 → 4.49.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGES +18 -0
- data/bin/linux-arm64/selenium-manager +0 -0
- data/bin/{linux → linux-x86_64}/selenium-manager +0 -0
- data/bin/macos/selenium-manager +0 -0
- data/bin/selenium-manager-THIRD-PARTY-NOTICES.txt +343 -129
- data/bin/selenium-manager.cdx.json +947 -868
- data/bin/windows/selenium-manager.exe +0 -0
- data/lib/selenium/webdriver/bidi/error.rb +4 -0
- data/lib/selenium/webdriver/bidi/protocol/browsing_context.rb +20 -3
- data/lib/selenium/webdriver/bidi/protocol/emulation.rb +272 -6
- data/lib/selenium/webdriver/bidi/serialization/record.rb +38 -41
- data/lib/selenium/webdriver/bidi/serialization/union.rb +11 -7
- data/lib/selenium/webdriver/bidi/serialization.rb +2 -14
- data/lib/selenium/webdriver/bidi/support/bidi_generate.rb +21 -12
- data/lib/selenium/webdriver/common/selenium_manager.rb +6 -2
- data/lib/selenium/webdriver/common/websocket_connection.rb +64 -26
- data/lib/selenium/webdriver/version.rb +1 -1
- metadata +4 -3
|
@@ -77,16 +77,20 @@ module Selenium
|
|
|
77
77
|
elsif Platform.mac?
|
|
78
78
|
"#{directory}/macos/selenium-manager"
|
|
79
79
|
elsif Platform.linux?
|
|
80
|
-
"#{directory}/
|
|
80
|
+
"#{directory}/#{linux_directory}/selenium-manager"
|
|
81
81
|
elsif Platform.unix?
|
|
82
82
|
WebDriver.logger.warn('Selenium Manager binary may not be compatible with Unix',
|
|
83
83
|
id: %i[selenium_manager unix_binary])
|
|
84
|
-
"#{directory}/
|
|
84
|
+
"#{directory}/#{linux_directory}/selenium-manager"
|
|
85
85
|
else
|
|
86
86
|
raise Error::WebDriverError, "unsupported platform: #{Platform.os}"
|
|
87
87
|
end
|
|
88
88
|
end
|
|
89
89
|
|
|
90
|
+
def linux_directory
|
|
91
|
+
RbConfig::CONFIG['host_cpu'].to_s.downcase == 'aarch64' ? 'linux-arm64' : 'linux-x86_64'
|
|
92
|
+
end
|
|
93
|
+
|
|
90
94
|
def execute_command(*command)
|
|
91
95
|
WebDriver.logger.debug("Executing Process #{command}", id: :selenium_manager)
|
|
92
96
|
|
|
@@ -21,6 +21,7 @@ require 'websocket'
|
|
|
21
21
|
|
|
22
22
|
module Selenium
|
|
23
23
|
module WebDriver
|
|
24
|
+
# @api private
|
|
24
25
|
class WebSocketConnection
|
|
25
26
|
CONNECTION_ERRORS = [
|
|
26
27
|
Errno::ECONNRESET, # connection is aborted (browser process was killed)
|
|
@@ -35,6 +36,15 @@ module Selenium
|
|
|
35
36
|
|
|
36
37
|
MAX_LOG_MESSAGE_SIZE = 9999
|
|
37
38
|
|
|
39
|
+
# websocket-ruby defaults to a 20MB limit and silently drops larger
|
|
40
|
+
# frames, which can stall the listener. CDP payloads (e.g. large data:
|
|
41
|
+
# URLs) can exceed that, so raise the ceiling for our connections.
|
|
42
|
+
# The gem only exposes the limit as process-global state, so it is
|
|
43
|
+
# raised (never lowered) and not restored on close - concurrent
|
|
44
|
+
# connections share the value. Other bindings rely on their own
|
|
45
|
+
# websocket clients' limits; this constant only affects websocket-ruby.
|
|
46
|
+
MAX_FRAME_SIZE = 100 * 1024 * 1024 # 100MB
|
|
47
|
+
|
|
38
48
|
def initialize(url:)
|
|
39
49
|
@callback_threads = ThreadGroup.new
|
|
40
50
|
|
|
@@ -46,26 +56,19 @@ module Selenium
|
|
|
46
56
|
@session_id = nil
|
|
47
57
|
@url = url
|
|
48
58
|
|
|
59
|
+
apply_frame_size_limit
|
|
49
60
|
process_handshake
|
|
50
61
|
@socket_thread = attach_socket_listener
|
|
51
62
|
end
|
|
52
63
|
|
|
64
|
+
# Idempotent: the listener may already have initiated shutdown (see
|
|
65
|
+
# #frame_dropped?), so always close the socket and join threads rather
|
|
66
|
+
# than short-circuiting on @closing.
|
|
53
67
|
def close
|
|
54
|
-
|
|
55
|
-
return if @closing
|
|
56
|
-
|
|
57
|
-
@closing = true
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
begin
|
|
61
|
-
socket.close
|
|
62
|
-
rescue *CONNECTION_ERRORS => e
|
|
63
|
-
WebDriver.logger.debug "WebSocket listener closed: #{e.class}: #{e.message}", id: :ws
|
|
64
|
-
# already closed
|
|
65
|
-
end
|
|
68
|
+
close_socket
|
|
66
69
|
|
|
67
70
|
# Let threads unwind instead of calling exit
|
|
68
|
-
@socket_thread&.join(0.5)
|
|
71
|
+
@socket_thread&.join(0.5) unless @socket_thread == Thread.current
|
|
69
72
|
@callback_threads.list.each do |thread|
|
|
70
73
|
thread.join(0.5)
|
|
71
74
|
rescue StandardError => e
|
|
@@ -97,6 +100,9 @@ module Selenium
|
|
|
97
100
|
end
|
|
98
101
|
|
|
99
102
|
def send_cmd(**payload)
|
|
103
|
+
# IOError to match what writing to an already-closed socket raises
|
|
104
|
+
raise IOError, 'WebSocket connection is closed' if @closing
|
|
105
|
+
|
|
100
106
|
id = next_id
|
|
101
107
|
data = payload.merge(id: id)
|
|
102
108
|
WebDriver.logger.debug "WebSocket -> #{data}"[...MAX_LOG_MESSAGE_SIZE], id: :ws
|
|
@@ -109,7 +115,11 @@ module Selenium
|
|
|
109
115
|
raise e, "WebSocket is closed (#{e.class}: #{e.message})"
|
|
110
116
|
end
|
|
111
117
|
|
|
112
|
-
wait.until
|
|
118
|
+
wait.until do
|
|
119
|
+
raise IOError, 'WebSocket connection closed while waiting for a response' if @closing
|
|
120
|
+
|
|
121
|
+
@messages_mtx.synchronize { messages.delete(id) }
|
|
122
|
+
end
|
|
113
123
|
end
|
|
114
124
|
|
|
115
125
|
private
|
|
@@ -132,22 +142,51 @@ module Selenium
|
|
|
132
142
|
|
|
133
143
|
incoming_frame << socket.readpartial(1024)
|
|
134
144
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
message = process_frame(frame)
|
|
139
|
-
next unless message['method']
|
|
140
|
-
|
|
141
|
-
@messages_mtx.synchronize { callbacks[message['method']].dup }.each do |callback|
|
|
142
|
-
@callback_threads.add(callback_thread(message['params'], &callback))
|
|
143
|
-
end
|
|
144
|
-
end
|
|
145
|
+
process_incoming_frames
|
|
146
|
+
break if frame_dropped?
|
|
145
147
|
end
|
|
146
148
|
rescue *CONNECTION_ERRORS, WebSocket::Error => e
|
|
147
149
|
WebDriver.logger.debug "WebSocket listener closed: #{e.class}: #{e.message}", id: :ws
|
|
148
150
|
end
|
|
149
151
|
end
|
|
150
152
|
|
|
153
|
+
def close_socket
|
|
154
|
+
@closing_mtx.synchronize { @closing = true }
|
|
155
|
+
socket.close
|
|
156
|
+
rescue *CONNECTION_ERRORS => e
|
|
157
|
+
WebDriver.logger.debug "WebSocket socket closed: #{e.class}: #{e.message}", id: :ws
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def process_incoming_frames
|
|
161
|
+
while (frame = incoming_frame.next)
|
|
162
|
+
break if @closing
|
|
163
|
+
|
|
164
|
+
message = process_frame(frame)
|
|
165
|
+
next unless message['method']
|
|
166
|
+
|
|
167
|
+
@messages_mtx.synchronize { callbacks[message['method']].dup }.each do |callback|
|
|
168
|
+
@callback_threads.add(callback_thread(message['params'], &callback))
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
# True when the buffered frame could not be decoded (e.g. exceeds MAX_FRAME_SIZE).
|
|
174
|
+
# websocket-ruby swallows the error and keeps returning nil, so surface it and close
|
|
175
|
+
# the connection here instead of leaving a dead listener on an open socket.
|
|
176
|
+
def frame_dropped?
|
|
177
|
+
return false unless incoming_frame.error?
|
|
178
|
+
|
|
179
|
+
WebDriver.logger.error("WebSocket frame dropped (#{incoming_frame.error}); if payloads can legitimately " \
|
|
180
|
+
"exceed #{WebSocket.max_frame_size} bytes, set WebSocket.max_frame_size " \
|
|
181
|
+
'to a higher value', id: :ws)
|
|
182
|
+
close_socket
|
|
183
|
+
true
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def apply_frame_size_limit
|
|
187
|
+
WebSocket.max_frame_size = MAX_FRAME_SIZE if WebSocket.max_frame_size < MAX_FRAME_SIZE
|
|
188
|
+
end
|
|
189
|
+
|
|
151
190
|
def incoming_frame
|
|
152
191
|
@incoming_frame ||= WebSocket::Frame::Incoming::Client.new(version: ws.version)
|
|
153
192
|
end
|
|
@@ -204,8 +243,7 @@ module Selenium
|
|
|
204
243
|
end
|
|
205
244
|
|
|
206
245
|
def next_id
|
|
207
|
-
@id
|
|
208
|
-
@id += 1
|
|
246
|
+
@id = (@id || 0) + 1
|
|
209
247
|
end
|
|
210
248
|
end # BiDi
|
|
211
249
|
end # WebDriver
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: selenium-webdriver
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 4.
|
|
4
|
+
version: 4.49.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Alex Rodionov
|
|
@@ -10,7 +10,7 @@ authors:
|
|
|
10
10
|
autorequire:
|
|
11
11
|
bindir: bin
|
|
12
12
|
cert_chain: []
|
|
13
|
-
date: 2026-
|
|
13
|
+
date: 2026-09-09 00:00:00.000000000 Z
|
|
14
14
|
dependencies:
|
|
15
15
|
- !ruby/object:Gem::Dependency
|
|
16
16
|
name: base64
|
|
@@ -271,7 +271,8 @@ files:
|
|
|
271
271
|
- LICENSE
|
|
272
272
|
- NOTICE
|
|
273
273
|
- README.md
|
|
274
|
-
- bin/linux/selenium-manager
|
|
274
|
+
- bin/linux-arm64/selenium-manager
|
|
275
|
+
- bin/linux-x86_64/selenium-manager
|
|
275
276
|
- bin/macos/selenium-manager
|
|
276
277
|
- bin/selenium-manager-THIRD-PARTY-NOTICES.txt
|
|
277
278
|
- bin/selenium-manager.cdx.json
|