puppeteer-ruby 0.40.4 → 0.40.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +15 -1
- data/README.md +7 -0
- data/docs/api_coverage.md +4 -4
- data/lib/puppeteer/browser_runner.rb +1 -1
- data/lib/puppeteer/connection.rb +1 -0
- data/lib/puppeteer/element_handle/box_model.rb +3 -2
- data/lib/puppeteer/element_handle.rb +51 -7
- data/lib/puppeteer/events.rb +1 -0
- data/lib/puppeteer/frame_manager.rb +3 -1
- data/lib/puppeteer/http_request.rb +90 -34
- data/lib/puppeteer/js_handle.rb +1 -0
- data/lib/puppeteer/launcher/chrome.rb +1 -1
- data/lib/puppeteer/lifecycle_watcher.rb +11 -0
- data/lib/puppeteer/network_event_manager.rb +4 -0
- data/lib/puppeteer/network_manager.rb +9 -0
- data/lib/puppeteer/page.rb +15 -3
- data/lib/puppeteer/version.rb +1 -1
- data/puppeteer-ruby.gemspec +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 674e5731f3d469805214a3ddb7e56ae83aaaa6850db3ccddd02002cffe4e1ca4
|
4
|
+
data.tar.gz: 47f5ad6e1a7b30c394ce950991c067c9b2dd42c144ec561eaa3dbbc9efb9b77a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b4f53e004dbbba48ebfaa5a1197d5bfdf9d2364a6bd84edf94d378b4b193661f0dc43de51fd61e009d91d5ca1eff7afb62e824fc23ce6bfc6dfa2b36aeda0457
|
7
|
+
data.tar.gz: 537e1dc87b4fa9d7644035e1a7a590ec32d64275ee7166940a9e6454b94997b873b1e06c1f2f8ad25c33f39caed4eb05601de46808f09748e13f9db15868c750
|
data/CHANGELOG.md
CHANGED
@@ -1,7 +1,21 @@
|
|
1
|
-
### main [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.40.
|
1
|
+
### main [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.40.7...main)]
|
2
2
|
|
3
3
|
- xxx
|
4
4
|
|
5
|
+
### 0.40.7 [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.40.6...0.40.7)]
|
6
|
+
|
7
|
+
- Port Puppeteer v13.6-v13.7 features.
|
8
|
+
|
9
|
+
### 0.40.6 [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.40.5...0.40.6)]
|
10
|
+
|
11
|
+
- Port Puppeteer v13.1-v13.5 features mainly for request interception.
|
12
|
+
|
13
|
+
### 0.40.5 [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.40.4...0.40.5)]
|
14
|
+
|
15
|
+
Bugfix:
|
16
|
+
|
17
|
+
- Port Puppeteer v13.1-v13.5 bugfixes mainly for OOPIFs.
|
18
|
+
|
5
19
|
### 0.40.4 [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.40.3...0.40.4)]
|
6
20
|
|
7
21
|
Bugfix:
|
data/README.md
CHANGED
@@ -229,6 +229,13 @@ end
|
|
229
229
|
|
230
230
|
https://yusukeiwaki.github.io/puppeteer-ruby-docs/
|
231
231
|
|
232
|
+
## Limitations
|
233
|
+
|
234
|
+
### Not compatible with Firefox >= v97.0
|
235
|
+
|
236
|
+
:sos: Help and contribution wanted! :sos:
|
237
|
+
https://github.com/YusukeIwaki/puppeteer-ruby/issues/220
|
238
|
+
|
232
239
|
## Contributing
|
233
240
|
|
234
241
|
Bug reports and pull requests are welcome on GitHub at https://github.com/YusukeIwaki/puppeteer-ruby.
|
data/docs/api_coverage.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# API coverages
|
2
|
-
- Puppeteer version: v13.5.
|
3
|
-
- puppeteer-ruby version: 0.40.
|
2
|
+
- Puppeteer version: v13.5.2
|
3
|
+
- puppeteer-ruby version: 0.40.7
|
4
4
|
|
5
5
|
## Puppeteer
|
6
6
|
|
@@ -310,8 +310,8 @@
|
|
310
310
|
* frame
|
311
311
|
* headers
|
312
312
|
* initiator
|
313
|
-
*
|
314
|
-
*
|
313
|
+
* interceptResolutionState => `#intercept_resolution_state`
|
314
|
+
* isInterceptResolutionHandled => `#intercept_resolution_handled?`
|
315
315
|
* isNavigationRequest => `#navigation_request?`
|
316
316
|
* method
|
317
317
|
* postData => `#post_data`
|
data/lib/puppeteer/connection.rb
CHANGED
@@ -2,12 +2,13 @@ class Puppeteer::ElementHandle < Puppeteer::JSHandle
|
|
2
2
|
class BoxModel
|
3
3
|
QUAD_ATTRIBUTE_NAMES = %i(content padding border margin)
|
4
4
|
# @param result [Hash]
|
5
|
-
|
5
|
+
# @param offset [Point]
|
6
|
+
def initialize(result_model, offset:)
|
6
7
|
QUAD_ATTRIBUTE_NAMES.each do |attr_name|
|
7
8
|
quad = result_model[attr_name.to_s]
|
8
9
|
instance_variable_set(
|
9
10
|
:"@#{attr_name}",
|
10
|
-
quad.each_slice(2).map { |x, y| Point.new(x: x, y: y) },
|
11
|
+
quad.each_slice(2).map { |x, y| Point.new(x: x, y: y) + offset },
|
11
12
|
)
|
12
13
|
end
|
13
14
|
@width = result_model['width']
|
@@ -11,10 +11,12 @@ class Puppeteer::ElementHandle < Puppeteer::JSHandle
|
|
11
11
|
# @param context [Puppeteer::ExecutionContext]
|
12
12
|
# @param client [Puppeteer::CDPSession]
|
13
13
|
# @param remote_object [Puppeteer::RemoteObject]
|
14
|
+
# @param frame [Puppeteer::Frame]
|
14
15
|
# @param page [Puppeteer::Page]
|
15
16
|
# @param frame_manager [Puppeteer::FrameManager]
|
16
|
-
def initialize(context:, client:, remote_object:, page:, frame_manager:)
|
17
|
+
def initialize(context:, client:, remote_object:, frame:, page:, frame_manager:)
|
17
18
|
super(context: context, client: client, remote_object: remote_object)
|
19
|
+
@frame = frame
|
18
20
|
@page = page
|
19
21
|
@frame_manager = frame_manager
|
20
22
|
@disposed = false
|
@@ -134,6 +136,37 @@ class Puppeteer::ElementHandle < Puppeteer::JSHandle
|
|
134
136
|
end
|
135
137
|
end
|
136
138
|
|
139
|
+
class ElementNotClickableError < StandardError
|
140
|
+
def initialize
|
141
|
+
super("Node is either not clickable or not an HTMLElement")
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
# @param quad [Array<Array<Point>>]]
|
146
|
+
# @param offset [Point]
|
147
|
+
private def apply_offsets_to_quad(quad, offset)
|
148
|
+
quad.map { |part| part + offset }
|
149
|
+
end
|
150
|
+
|
151
|
+
# @param frame [Puppeteer::Frame]
|
152
|
+
# @return [Point]
|
153
|
+
private def oopif_offsets(frame)
|
154
|
+
offset = Point.new(x: 0, y: 0)
|
155
|
+
while frame.parent_frame
|
156
|
+
parent = frame.parent_frame
|
157
|
+
unless frame.oop_frame?
|
158
|
+
frame = parent
|
159
|
+
next
|
160
|
+
end
|
161
|
+
backend_node_id = parent._client.send_message('DOM.getFrameOwner', frameId: frame.id)['backendNodeId']
|
162
|
+
result = parent._client.send_message('DOM.getBoxModel', backendNodeId: backend_node_id)
|
163
|
+
break unless result
|
164
|
+
offset = BoxModel.new(result['model'], offset: offset).content.first
|
165
|
+
frame = parent
|
166
|
+
end
|
167
|
+
offset
|
168
|
+
end
|
169
|
+
|
137
170
|
def clickable_point(offset = nil)
|
138
171
|
offset_param = Offset.from(offset)
|
139
172
|
|
@@ -150,12 +183,22 @@ class Puppeteer::ElementHandle < Puppeteer::JSHandle
|
|
150
183
|
end
|
151
184
|
|
152
185
|
# Filter out quads that have too small area to click into.
|
153
|
-
layout_metrics = @client.send_message('Page.getLayoutMetrics')
|
154
|
-
|
155
|
-
|
186
|
+
layout_metrics = @page.client.send_message('Page.getLayoutMetrics')
|
187
|
+
|
188
|
+
if result.empty? || result["quads"].empty?
|
189
|
+
raise ElementNotClickableError.new
|
190
|
+
end
|
191
|
+
|
192
|
+
# Filter out quads that have too small area to click into.
|
193
|
+
# Fallback to `layoutViewport` in case of using Firefox.
|
194
|
+
layout_viewport = layout_metrics["cssLayoutViewport"] || layout_metrics["layoutViewport"]
|
195
|
+
client_width = layout_viewport["clientWidth"]
|
196
|
+
client_height = layout_viewport["clientHeight"]
|
156
197
|
|
198
|
+
oopif_offset = oopif_offsets(@frame)
|
157
199
|
quads = result["quads"].
|
158
200
|
map { |quad| from_protocol_quad(quad) }.
|
201
|
+
map { |quad| apply_offsets_to_quad(quad, oopif_offset) }.
|
159
202
|
map { |quad| intersect_quad_with_viewport(quad, client_width, client_height) }.
|
160
203
|
select { |quad| compute_quad_area(quad) > 1 }
|
161
204
|
if quads.empty?
|
@@ -357,13 +400,14 @@ class Puppeteer::ElementHandle < Puppeteer::JSHandle
|
|
357
400
|
# @return [BoundingBox|nil]
|
358
401
|
def bounding_box
|
359
402
|
if_present(box_model) do |result_model|
|
403
|
+
offset = oopif_offsets(@frame)
|
360
404
|
quads = result_model.border
|
361
405
|
|
362
406
|
x = quads.map(&:x).min
|
363
407
|
y = quads.map(&:y).min
|
364
408
|
BoundingBox.new(
|
365
|
-
x: x,
|
366
|
-
y: y,
|
409
|
+
x: x + offset.x,
|
410
|
+
y: y + offset.y,
|
367
411
|
width: quads.map(&:x).max - x,
|
368
412
|
height: quads.map(&:y).max - y,
|
369
413
|
)
|
@@ -373,7 +417,7 @@ class Puppeteer::ElementHandle < Puppeteer::JSHandle
|
|
373
417
|
# @return [BoxModel|nil]
|
374
418
|
def box_model
|
375
419
|
if_present(@remote_object.box_model(@client)) do |result|
|
376
|
-
BoxModel.new(result['model'])
|
420
|
+
BoxModel.new(result['model'], offset: oopif_offsets(@frame))
|
377
421
|
end
|
378
422
|
end
|
379
423
|
|
data/lib/puppeteer/events.rb
CHANGED
@@ -96,6 +96,7 @@ module FrameManagerEmittedEvents ; end
|
|
96
96
|
FrameAttached: EventsDefinitionUtils.symbol('FrameManager.FrameAttached'),
|
97
97
|
FrameNavigated: EventsDefinitionUtils.symbol('FrameManager.FrameNavigated'),
|
98
98
|
FrameDetached: EventsDefinitionUtils.symbol('FrameManager.FrameDetached'),
|
99
|
+
FrameSwapped: EventsDefinitionUtils.symbol('FrameManager.FrameSwapped'),
|
99
100
|
LifecycleEvent: EventsDefinitionUtils.symbol('FrameManager.LifecycleEvent'),
|
100
101
|
FrameNavigatedWithinDocument: EventsDefinitionUtils.symbol('FrameManager.FrameNavigatedWithinDocument'),
|
101
102
|
ExecutionContextCreated: EventsDefinitionUtils.symbol('FrameManager.ExecutionContextCreated'),
|
@@ -178,7 +178,7 @@ class Puppeteer::FrameManager
|
|
178
178
|
frame = @frames[event['targetInfo']['targetId']]
|
179
179
|
session = Puppeteer::Connection.from_session(@client).session(event['sessionId'])
|
180
180
|
|
181
|
-
frame
|
181
|
+
frame&.send(:update_client, session)
|
182
182
|
setup_listeners(session)
|
183
183
|
async_init(session)
|
184
184
|
end
|
@@ -353,6 +353,8 @@ class Puppeteer::FrameManager
|
|
353
353
|
if frame
|
354
354
|
remove_frame_recursively(frame)
|
355
355
|
end
|
356
|
+
elsif reason == 'swap'
|
357
|
+
emit_event(FrameManagerEmittedEvents::FrameSwapped, frame)
|
356
358
|
end
|
357
359
|
end
|
358
360
|
|
@@ -2,6 +2,8 @@ class Puppeteer::HTTPRequest
|
|
2
2
|
include Puppeteer::DebugPrint
|
3
3
|
include Puppeteer::IfPresent
|
4
4
|
|
5
|
+
DEFAULT_INTERCEPT_RESOLUTION_PRIORITY = 0
|
6
|
+
|
5
7
|
# defines some methods used only in NetworkManager, Response
|
6
8
|
class InternalAccessor
|
7
9
|
def initialize(request)
|
@@ -38,6 +40,43 @@ class Puppeteer::HTTPRequest
|
|
38
40
|
end
|
39
41
|
end
|
40
42
|
|
43
|
+
class InterceptResolutionState
|
44
|
+
def self.abort(priority: nil)
|
45
|
+
new(action: 'abort', priority: priority)
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.respond(priority: nil)
|
49
|
+
new(action: 'respond', priority: priority)
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.continue(priority: nil)
|
53
|
+
new(action: 'continue', priority: priority)
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.disabled(priority: nil)
|
57
|
+
new(action: 'disabled', priority: priority)
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.none(priority: nil)
|
61
|
+
new(action: 'none', priority: priority)
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.already_handled(priority: nil)
|
65
|
+
new(action: 'already-handled', priority: priority)
|
66
|
+
end
|
67
|
+
|
68
|
+
private def initialize(action:, priority:)
|
69
|
+
@action = action
|
70
|
+
@priority = priority
|
71
|
+
end
|
72
|
+
|
73
|
+
def priority_unspecified?
|
74
|
+
@priority.nil?
|
75
|
+
end
|
76
|
+
|
77
|
+
attr_reader :action, :priority
|
78
|
+
end
|
79
|
+
|
41
80
|
# @param client [Puppeteer::CDPSession]
|
42
81
|
# @param frame [Puppeteer::Frame]
|
43
82
|
# @param interception_id [string|nil]
|
@@ -57,9 +96,8 @@ class Puppeteer::HTTPRequest
|
|
57
96
|
@frame = frame
|
58
97
|
@redirect_chain = redirect_chain
|
59
98
|
@continue_request_overrides = {}
|
60
|
-
@
|
61
|
-
@
|
62
|
-
@intercept_actions = []
|
99
|
+
@intercept_resolution_state = InterceptResolutionState.none
|
100
|
+
@intercept_handlers = []
|
63
101
|
@initiator = event['initiator']
|
64
102
|
|
65
103
|
@headers = {}
|
@@ -115,19 +153,29 @@ class Puppeteer::HTTPRequest
|
|
115
153
|
@abort_error_reason
|
116
154
|
end
|
117
155
|
|
118
|
-
# @returns An
|
119
|
-
#
|
120
|
-
#
|
121
|
-
|
156
|
+
# @returns An InterceptResolutionState object describing the current resolution
|
157
|
+
# action and priority.
|
158
|
+
#
|
159
|
+
# InterceptResolutionState contains:
|
160
|
+
# action: InterceptResolutionAction
|
161
|
+
# priority?: number
|
162
|
+
#
|
163
|
+
# InterceptResolutionAction is one of: `abort`, `respond`, `continue`,
|
164
|
+
# `disabled`, `none`, or `alreay-handled`
|
165
|
+
def intercept_resolution_state
|
122
166
|
if !@allow_interception
|
123
|
-
|
167
|
+
InterceptResolutionState.disabled
|
124
168
|
elsif @interception_handled
|
125
|
-
|
169
|
+
InterceptResolutionState.already_handled
|
126
170
|
else
|
127
|
-
|
171
|
+
@intercept_resolution_state.dup
|
128
172
|
end
|
129
173
|
end
|
130
174
|
|
175
|
+
def intercept_resolution_handled?
|
176
|
+
@interception_handled
|
177
|
+
end
|
178
|
+
|
131
179
|
# Adds an async request handler to the processing queue.
|
132
180
|
# Deferred handlers are not guaranteed to execute in any particular order,
|
133
181
|
# but they are guarnateed to resolve before the request interception
|
@@ -135,19 +183,19 @@ class Puppeteer::HTTPRequest
|
|
135
183
|
#
|
136
184
|
# @param pending_handler [Proc]
|
137
185
|
def enqueue_intercept_action(pending_handler)
|
138
|
-
@
|
186
|
+
@intercept_handlers << pending_handler
|
139
187
|
end
|
140
188
|
|
141
189
|
# Awaits pending interception handlers and then decides how to fulfill
|
142
190
|
# the request interception.
|
143
191
|
def finalize_interceptions
|
144
|
-
@
|
145
|
-
case
|
146
|
-
when
|
192
|
+
@intercept_handlers.each(&:call)
|
193
|
+
case intercept_resolution_state.action
|
194
|
+
when 'abort'
|
147
195
|
abort_impl(**@abort_error_reason)
|
148
|
-
when
|
196
|
+
when 'respond'
|
149
197
|
respond_impl(**@response_for_request)
|
150
|
-
when
|
198
|
+
when 'continue'
|
151
199
|
continue_impl(@continue_request_overrides)
|
152
200
|
end
|
153
201
|
end
|
@@ -169,8 +217,14 @@ class Puppeteer::HTTPRequest
|
|
169
217
|
private def headers_to_array(headers)
|
170
218
|
return nil unless headers
|
171
219
|
|
172
|
-
headers.
|
173
|
-
|
220
|
+
headers.flat_map do |key, value|
|
221
|
+
if value.is_a?(Enumerable)
|
222
|
+
value.map do |v|
|
223
|
+
{ name: key, value: v.to_s }
|
224
|
+
end
|
225
|
+
else
|
226
|
+
{ name: key, value: value.to_s }
|
227
|
+
end
|
174
228
|
end
|
175
229
|
end
|
176
230
|
|
@@ -220,17 +274,16 @@ class Puppeteer::HTTPRequest
|
|
220
274
|
end
|
221
275
|
|
222
276
|
@continue_request_overrides = overrides
|
223
|
-
if @
|
224
|
-
@
|
225
|
-
@current_priority = priority
|
277
|
+
if @intercept_resolution_state.priority_unspecified? || priority > @intercept_resolution_state.priority
|
278
|
+
@intercept_resolution_state = InterceptResolutionState.continue(priority: priority)
|
226
279
|
return
|
227
280
|
end
|
228
281
|
|
229
|
-
if priority == @
|
230
|
-
if @
|
282
|
+
if priority == @intercept_resolution_state.priority
|
283
|
+
if @intercept_resolution_state.action == :abort || @intercept_resolution_state.action == :respond
|
231
284
|
return
|
232
285
|
end
|
233
|
-
@
|
286
|
+
@intercept_resolution_state = InterceptResolutionState.continue(priority: priority)
|
234
287
|
end
|
235
288
|
end
|
236
289
|
|
@@ -284,17 +337,16 @@ class Puppeteer::HTTPRequest
|
|
284
337
|
body: body,
|
285
338
|
}
|
286
339
|
|
287
|
-
if @
|
288
|
-
@
|
289
|
-
@current_priority = priority
|
340
|
+
if @intercept_resolution_state.priority_unspecified? || priority > @intercept_resolution_state.priority
|
341
|
+
@intercept_resolution_state = InterceptResolutionState.respond(priority: priority)
|
290
342
|
return
|
291
343
|
end
|
292
344
|
|
293
|
-
if priority == @
|
294
|
-
if @
|
345
|
+
if priority == @intercept_resolution_state.priority
|
346
|
+
if @intercept_resolution_state.action == :abort
|
295
347
|
return
|
296
348
|
end
|
297
|
-
@
|
349
|
+
@intercept_resolution_state = InterceptResolutionState.respond(priority: priority)
|
298
350
|
end
|
299
351
|
end
|
300
352
|
|
@@ -303,7 +355,12 @@ class Puppeteer::HTTPRequest
|
|
303
355
|
|
304
356
|
mock_response_headers = {}
|
305
357
|
headers&.each do |key, value|
|
306
|
-
mock_response_headers[key.downcase] =
|
358
|
+
mock_response_headers[key.downcase] =
|
359
|
+
if value.is_a?(Enumerable)
|
360
|
+
value.map(&:to_s)
|
361
|
+
else
|
362
|
+
value.to_s
|
363
|
+
end
|
307
364
|
end
|
308
365
|
if content_type
|
309
366
|
mock_response_headers['content-type'] = content_type
|
@@ -360,9 +417,8 @@ class Puppeteer::HTTPRequest
|
|
360
417
|
end
|
361
418
|
@abort_error_reason = error_reason
|
362
419
|
|
363
|
-
if @
|
364
|
-
@
|
365
|
-
@current_priority = priority
|
420
|
+
if @intercept_resolution_state.priority_unspecified? || priority > @intercept_resolution_state.priority
|
421
|
+
@intercept_resolution_state = InterceptResolutionState.abort(priority: priority)
|
366
422
|
end
|
367
423
|
end
|
368
424
|
|
data/lib/puppeteer/js_handle.rb
CHANGED
@@ -122,7 +122,7 @@ module Puppeteer::Launcher
|
|
122
122
|
'--disable-default-apps',
|
123
123
|
'--disable-dev-shm-usage',
|
124
124
|
'--disable-extensions',
|
125
|
-
'--disable-features=Translate',
|
125
|
+
'--disable-features=Translate,BackForwardCache',
|
126
126
|
'--disable-hang-monitor',
|
127
127
|
'--disable-ipc-flooding-protection',
|
128
128
|
'--disable-popup-blocking',
|
@@ -77,6 +77,7 @@ class Puppeteer::LifecycleWatcher
|
|
77
77
|
check_lifecycle_complete
|
78
78
|
end,
|
79
79
|
@frame_manager.add_event_listener(FrameManagerEmittedEvents::FrameNavigatedWithinDocument, &method(:navigated_within_document)),
|
80
|
+
@frame_manager.add_event_listener(FrameManagerEmittedEvents::FrameSwapped, &method(:handle_frame_swapped)),
|
80
81
|
@frame_manager.add_event_listener(FrameManagerEmittedEvents::FrameDetached, &method(:handle_frame_detached)),
|
81
82
|
]
|
82
83
|
@listener_ids['network_manager'] = @frame_manager.network_manager.add_event_listener(NetworkManagerEmittedEvents::Request, &method(:handle_request))
|
@@ -142,11 +143,21 @@ class Puppeteer::LifecycleWatcher
|
|
142
143
|
check_lifecycle_complete
|
143
144
|
end
|
144
145
|
|
146
|
+
private def handle_frame_swapped(frame)
|
147
|
+
return if frame != @frame
|
148
|
+
@swapped = true
|
149
|
+
check_lifecycle_complete
|
150
|
+
end
|
151
|
+
|
145
152
|
private def check_lifecycle_complete
|
146
153
|
# We expect navigation to commit.
|
147
154
|
return unless @expected_lifecycle.completed?(@frame)
|
148
155
|
@lifecycle_promise.fulfill(true) if @lifecycle_promise.pending?
|
149
156
|
if @frame.loader_id == @initial_loader_id && !@has_same_document_navigation
|
157
|
+
if @swapped
|
158
|
+
@swapped = false
|
159
|
+
@new_document_navigation_promise.fulfill(true)
|
160
|
+
end
|
150
161
|
return
|
151
162
|
end
|
152
163
|
if @has_same_document_navigation && @same_document_navigation_promise.pending?
|
@@ -119,4 +119,8 @@ class Puppeteer::NetworkEventManager
|
|
119
119
|
def get_queued_event_group(network_request_id)
|
120
120
|
@queued_event_group_map[network_request_id]
|
121
121
|
end
|
122
|
+
|
123
|
+
def forget_queued_event_group(network_request_id)
|
124
|
+
@queued_event_group_map.delete(network_request_id)
|
125
|
+
end
|
122
126
|
end
|
@@ -217,6 +217,7 @@ class Puppeteer::NetworkManager
|
|
217
217
|
# CDP may have sent a Fetch.requestPaused event already. Check for it.
|
218
218
|
if_present(@network_event_manager.get_request_paused(network_request_id)) do |request_paused_event|
|
219
219
|
fetch_request_id = request_paused_event['requestId']
|
220
|
+
patch_request_event_headers(event, request_paused_event)
|
220
221
|
handle_request(event, fetch_request_id)
|
221
222
|
@network_event_manager.forget_request_paused(network_request_id)
|
222
223
|
end
|
@@ -277,12 +278,19 @@ class Puppeteer::NetworkManager
|
|
277
278
|
end
|
278
279
|
|
279
280
|
if request_will_be_sent_event
|
281
|
+
patch_request_event_headers(request_will_be_sent_event, event)
|
280
282
|
handle_request(request_will_be_sent_event, fetch_request_id)
|
281
283
|
else
|
282
284
|
@network_event_manager.store_request_paused(network_request_id, event)
|
283
285
|
end
|
284
286
|
end
|
285
287
|
|
288
|
+
private def patch_request_event_headers(request_will_be_sent_event, request_paused_event)
|
289
|
+
request_will_be_sent_event['request']['headers'].merge!(
|
290
|
+
# includes extra headers, like: Accept, Origin
|
291
|
+
request_paused_event['request']['headers'])
|
292
|
+
end
|
293
|
+
|
286
294
|
private def handle_request(event, fetch_request_id)
|
287
295
|
redirect_chain = []
|
288
296
|
if event['redirectResponse']
|
@@ -387,6 +395,7 @@ class Puppeteer::NetworkManager
|
|
387
395
|
# We may have skipped response and loading events because we didn't have
|
388
396
|
# this ExtraInfo event yet. If so, emit those events now.
|
389
397
|
if_present(@network_event_manager.get_queued_event_group(event['requestId'])) do |queued_events|
|
398
|
+
@network_event_manager.forget_queued_event_group(event['requestId'])
|
390
399
|
emit_response_event(queued_events.response_received_event, event)
|
391
400
|
if_present(queued_events.loading_finished_event) do |loading_finished_event|
|
392
401
|
emit_loading_finished(loading_finished_event)
|
data/lib/puppeteer/page.rb
CHANGED
@@ -227,7 +227,7 @@ class Puppeteer::Page
|
|
227
227
|
@client.send_message('Emulation.setGeolocationOverride', geolocation.to_h)
|
228
228
|
end
|
229
229
|
|
230
|
-
attr_reader :javascript_enabled, :target
|
230
|
+
attr_reader :javascript_enabled, :target, :client
|
231
231
|
alias_method :javascript_enabled?, :javascript_enabled
|
232
232
|
|
233
233
|
def browser
|
@@ -389,7 +389,18 @@ class Puppeteer::Page
|
|
389
389
|
@client.send_message('Network.getCookies', urls: (urls.empty? ? [url] : urls))['cookies']
|
390
390
|
end
|
391
391
|
|
392
|
+
# check if each cookie element has required fields ('name' and 'value')
|
393
|
+
private def assert_cookie_params(cookies, requires:)
|
394
|
+
return if cookies.all? do |cookie|
|
395
|
+
requires.all? { |field_name| cookie[field_name] || cookie[field_name.to_s] }
|
396
|
+
end
|
397
|
+
|
398
|
+
raise ArgumentError.new("Each coookie must have #{requires.join(" and ")} attribute.")
|
399
|
+
end
|
400
|
+
|
392
401
|
def delete_cookie(*cookies)
|
402
|
+
assert_cookie_params(cookies, requires: %i(name))
|
403
|
+
|
393
404
|
page_url = url
|
394
405
|
starts_with_http = page_url.start_with?("http")
|
395
406
|
cookies.each do |cookie|
|
@@ -399,12 +410,14 @@ class Puppeteer::Page
|
|
399
410
|
end
|
400
411
|
|
401
412
|
def set_cookie(*cookies)
|
413
|
+
assert_cookie_params(cookies, requires: %i(name value))
|
414
|
+
|
402
415
|
page_url = url
|
403
416
|
starts_with_http = page_url.start_with?("http")
|
404
417
|
items = cookies.map do |cookie|
|
405
418
|
(starts_with_http ? { url: page_url } : {}).merge(cookie).tap do |item|
|
406
419
|
raise ArgumentError.new("Blank page can not have cookie \"#{item[:name]}\"") if item[:url] == "about:blank"
|
407
|
-
raise
|
420
|
+
raise ArgumentError.new("Data URL page can not have cookie \"#{item[:name]}\"") if item[:url]&.start_with?("data:")
|
408
421
|
end
|
409
422
|
end
|
410
423
|
delete_cookie(*items)
|
@@ -508,7 +521,6 @@ class Puppeteer::Page
|
|
508
521
|
end
|
509
522
|
|
510
523
|
private def handle_console_api(event)
|
511
|
-
puts "~~~~~~~~~~~~~~#{event}"
|
512
524
|
if event['executionContextId'] == 0
|
513
525
|
# DevTools protocol stores the last 1000 console messages. These
|
514
526
|
# messages are always reported even for removed execution contexts. In
|
data/lib/puppeteer/version.rb
CHANGED
data/puppeteer-ruby.gemspec
CHANGED
@@ -32,7 +32,7 @@ Gem::Specification.new do |spec|
|
|
32
32
|
spec.add_development_dependency 'rollbar'
|
33
33
|
spec.add_development_dependency 'rspec', '~> 3.11.0'
|
34
34
|
spec.add_development_dependency 'rspec_junit_formatter' # for CircleCI.
|
35
|
-
spec.add_development_dependency 'rubocop', '~> 1.
|
35
|
+
spec.add_development_dependency 'rubocop', '~> 1.29.0'
|
36
36
|
spec.add_development_dependency 'rubocop-rspec'
|
37
37
|
spec.add_development_dependency 'sinatra'
|
38
38
|
spec.add_development_dependency 'webrick'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: puppeteer-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.40.
|
4
|
+
version: 0.40.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- YusukeIwaki
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-05-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: concurrent-ruby
|
@@ -170,14 +170,14 @@ dependencies:
|
|
170
170
|
requirements:
|
171
171
|
- - "~>"
|
172
172
|
- !ruby/object:Gem::Version
|
173
|
-
version: 1.
|
173
|
+
version: 1.29.0
|
174
174
|
type: :development
|
175
175
|
prerelease: false
|
176
176
|
version_requirements: !ruby/object:Gem::Requirement
|
177
177
|
requirements:
|
178
178
|
- - "~>"
|
179
179
|
- !ruby/object:Gem::Version
|
180
|
-
version: 1.
|
180
|
+
version: 1.29.0
|
181
181
|
- !ruby/object:Gem::Dependency
|
182
182
|
name: rubocop-rspec
|
183
183
|
requirement: !ruby/object:Gem::Requirement
|