Class: Puppeteer::Connection
Defined Under Namespace
Classes: MessageCallback, ProtocolError, RequestDebugPrinter, ResponseDebugPrinter
Instance Attribute Summary collapse
Class Method Summary
collapse
Instance Method Summary
collapse
#add_event_listener, #emit_event, #observe_first, #off, #on_event, #remove_event_listener
Methods included from DebugPrint
#debug_print, #debug_puts
Constructor Details
#initialize(url, transport, delay = 0, protocol_timeout: nil) ⇒ Connection
Returns a new instance of Connection.
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
|
# File 'lib/puppeteer/connection.rb', line 40
def initialize(url, transport, delay = 0, protocol_timeout: nil)
@url = url
@last_id = 0
@callbacks = {}
@callbacks_mutex = Mutex.new
@delay = delay
@protocol_timeout = protocol_timeout
@reject_emulate_network_conditions_calls = false
@network_message_queue = Async::Queue.new
@network_message_task = nil
@transport = transport
@transport.on_message do |data|
message = JSON.parse(data)
sleep_before_handling_message(message)
if network_event_message?(message)
enqueue_network_message(message)
elsif should_handle_synchronously?(message)
handle_message(message)
else
async_handle_message(message)
end
end
@transport.on_close do |reason, code|
handle_close
end
@sessions = {}
@sessions_mutex = Mutex.new
@closed = false
@manually_attached = Set.new
end
|
Instance Attribute Details
#protocol_timeout ⇒ Object
Returns the value of attribute protocol_timeout.
74
75
76
|
# File 'lib/puppeteer/connection.rb', line 74
def protocol_timeout
@protocol_timeout
end
|
#reject_emulate_network_conditions_calls=(value) ⇒ Object
Sets the attribute reject_emulate_network_conditions_calls
75
76
77
|
# File 'lib/puppeteer/connection.rb', line 75
def reject_emulate_network_conditions_calls=(value)
@reject_emulate_network_conditions_calls = value
end
|
Class Method Details
161
162
163
|
# File 'lib/puppeteer/connection.rb', line 161
def self.from_session(session)
session.connection
end
|
Instance Method Details
#async_send_message(method, params = {}) ⇒ Object
189
190
191
192
193
194
195
196
197
198
199
200
201
|
# File 'lib/puppeteer/connection.rb', line 189
def async_send_message(method, params = {})
ensure_command_allowed!(method)
promise = Async::Promise.new
generate_id do |id|
@callbacks_mutex.synchronize do
@callbacks[id] = MessageCallback.new(method: method, promise: promise)
end
raw_send(id: id, message: { method: method, params: params })
end
promise
end
|
#auto_attached?(target_id) ⇒ Boolean
399
400
401
|
# File 'lib/puppeteer/connection.rb', line 399
def auto_attached?(target_id)
!@manually_attached.include?(target_id)
end
|
#closed? ⇒ Boolean
used only in Browser#connected?
87
88
89
|
# File 'lib/puppeteer/connection.rb', line 87
def closed?
@closed
end
|
#create_session(target_info, auto_attach_emulated: false) ⇒ CDPSession
405
406
407
408
409
410
411
412
413
|
# File 'lib/puppeteer/connection.rb', line 405
def create_session(target_info, auto_attach_emulated: false)
unless auto_attach_emulated
@manually_attached << target_info.target_id
end
result = send_message('Target.attachToTarget', targetId: target_info.target_id, flatten: true)
session_id = result['sessionId']
@manually_attached.delete(target_info.target_id)
@sessions_mutex.synchronize { @sessions[session_id] }.tap { |session| session&.mark_ready }
end
|
#dispose ⇒ void
This method returns an undefined value.
394
395
396
397
|
# File 'lib/puppeteer/connection.rb', line 394
def dispose
handle_close
@transport.close
end
|
#enqueue_network_message(message) ⇒ void
This method returns an undefined value.
148
149
150
151
152
153
154
155
156
157
158
159
|
# File 'lib/puppeteer/connection.rb', line 148
private def enqueue_network_message(message)
if Async::Task.current?
ensure_network_message_task
begin
@network_message_queue.enqueue(message)
rescue Async::Queue::ClosedError
end
else
handle_message(message)
end
end
|
#ensure_command_allowed!(method) ⇒ void
This method returns an undefined value.
77
78
79
80
81
82
83
84
|
# File 'lib/puppeteer/connection.rb', line 77
def ensure_command_allowed!(method)
return unless method == 'Network.emulateNetworkConditions'
return unless @reject_emulate_network_conditions_calls
raise Puppeteer::Error.new(
'Cannot reset network conditions: rule-based emulation is enabled.',
)
end
|
#ensure_network_message_task ⇒ void
This method returns an undefined value.
137
138
139
140
141
142
143
144
145
146
|
# File 'lib/puppeteer/connection.rb', line 137
private def ensure_network_message_task
return if @network_message_task&.alive?
return unless Async::Task.current?
@network_message_task = Async do
while (queued = @network_message_queue.dequeue)
handle_message(queued)
end
end
end
|
#generate_id {|arg0| ... } ⇒ Object
package private. not intended to use externally.
connection.generate_id do |generated_id|
# play with generated_id
end
211
212
213
|
# File 'lib/puppeteer/connection.rb', line 211
def generate_id(&block)
block.call(@last_id += 1)
end
|
#handle_close ⇒ void
This method returns an undefined value.
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
|
# File 'lib/puppeteer/connection.rb', line 359
private def handle_close
return if @closed
@closed = true
@transport.on_message
@transport.on_close
@network_message_queue.close
begin
@network_message_task&.stop
rescue Async::Stop
end
callbacks = @callbacks_mutex.synchronize do
@callbacks.values.tap { @callbacks.clear }
end
callbacks.each do |callback|
callback.reject(
ProtocolError.new(
method: callback.method,
error_message: 'Target Closed.'))
end
sessions = @sessions_mutex.synchronize do
@sessions.values.tap { @sessions.clear }
end
sessions.each(&:handle_closed)
emit_event(ConnectionEmittedEvents::Disconnected)
end
|
#handle_message(message) ⇒ void
This method returns an undefined value.
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
|
# File 'lib/puppeteer/connection.rb', line 295
private def handle_message(message)
if @delay > 0
Puppeteer::AsyncUtils.sleep_seconds(@delay / 1000.0)
end
response_debug_printer.handle_message(message)
case message['method']
when 'Target.attachedToTarget'
session_id = message['params']['sessionId']
parent_session =
if message['sessionId']
@sessions_mutex.synchronize { @sessions[message['sessionId']] }
end
session = Puppeteer::CDPSession.new(
self,
message['params']['targetInfo']['type'],
session_id,
parent_session: parent_session,
)
@sessions_mutex.synchronize { @sessions[session_id] = session }
emit_event('sessionattached', session)
parent_session&.emit_event('sessionattached', session)
when 'Target.detachedFromTarget'
session_id = message['params']['sessionId']
session = @sessions_mutex.synchronize { @sessions[session_id] }
if session
session.handle_closed
@sessions_mutex.synchronize { @sessions.delete(session_id) }
emit_event('sessiondetached', session)
if message['sessionId']
parent_session = @sessions_mutex.synchronize { @sessions[message['sessionId']] }
parent_session&.emit_event('sessiondetached', session)
end
end
end
if message['sessionId']
session_id = message['sessionId']
@sessions_mutex.synchronize { @sessions[session_id] }&.handle_message(message)
elsif message['id']
if callback = @callbacks_mutex.synchronize { @callbacks.delete(message['id']) }
if message['error']
callback.reject(
ProtocolError.new(
method: callback.method,
error_message: message['error']['message'],
error_data: message['error']['data']))
else
callback.resolve(message['result'])
end
else
sessions = @sessions_mutex.synchronize { @sessions.values }
session = sessions.find { |candidate| candidate.callback?(message['id']) }
session&.handle_message(message)
end
else
emit_event(message['method'], message['params'])
end
end
|
#network_event_message?(message) ⇒ Boolean
133
134
135
|
# File 'lib/puppeteer/connection.rb', line 133
private def network_event_message?(message)
message['method']&.start_with?('Network.')
end
|
#on_close {|arg0, arg1| ... } ⇒ void
This method returns an undefined value.
386
387
388
|
# File 'lib/puppeteer/connection.rb', line 386
def on_close(&block)
@on_close = block
end
|
#on_message {|arg0| ... } ⇒ void
This method returns an undefined value.
390
391
392
|
# File 'lib/puppeteer/connection.rb', line 390
def on_message(&block)
@on_message = block
end
|
#raw_send(id:, message:) ⇒ void
This method returns an undefined value.
package private. not intended to use externally.
216
217
218
219
220
221
222
223
224
225
226
227
228
|
# File 'lib/puppeteer/connection.rb', line 216
def raw_send(id:, message:)
payload = JSON.generate(message.compact.merge(id: id))
@transport.send_text(payload)
request_debug_printer.handle_payload(payload)
end
|
#request_debug_printer ⇒ Object
287
288
289
|
# File 'lib/puppeteer/connection.rb', line 287
private def request_debug_printer
@request_debug_printer ||= RequestDebugPrinter.new
end
|
#response_debug_printer ⇒ Object
291
292
293
|
# File 'lib/puppeteer/connection.rb', line 291
private def response_debug_printer
@response_debug_printer ||= ResponseDebugPrinter.new
end
|
#send_message(method, params = {}) ⇒ Object
177
178
179
180
181
182
183
184
185
186
187
|
# File 'lib/puppeteer/connection.rb', line 177
def send_message(method, params = {})
if @protocol_timeout && @protocol_timeout > 0
begin
Puppeteer::AsyncUtils.async_timeout(@protocol_timeout, async_send_message(method, params)).wait
rescue Async::TimeoutError
raise ProtocolError.new(method: method, error_message: "Timeout #{@protocol_timeout}ms exceeded")
end
else
async_send_message(method, params).wait
end
end
|
#session(session_id) ⇒ ?CDPSession
167
168
169
|
# File 'lib/puppeteer/connection.rb', line 167
def session(session_id)
@sessions_mutex.synchronize { @sessions[session_id] }
end
|
#should_handle_synchronously?(message) ⇒ Boolean
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
# File 'lib/puppeteer/connection.rb', line 100
private def should_handle_synchronously?(message)
return true if message['id']
case message['method']
when nil
false
when /^Network\./
false
when /^Page\.frame/
true
when 'Page.lifecycleEvent'
true
when /^Runtime\.executionContext/
true
when 'Target.attachedToTarget', 'Target.detachedFromTarget'
true
when 'Target.targetCreated'
message.dig('params', 'targetInfo', 'type') == 'browser'
else
false
end
end
|
#sleep_before_handling_message(message) ⇒ void
This method returns an undefined value.
91
92
93
94
95
96
97
98
|
# File 'lib/puppeteer/connection.rb', line 91
private def sleep_before_handling_message(message)
return if message['method']&.start_with?('Network.')
Puppeteer::AsyncUtils.sleep_seconds(0.004)
end
|
#url ⇒ String
171
172
173
|
# File 'lib/puppeteer/connection.rb', line 171
def url
@url
end
|