puppeteer-ruby 0.0.22 → 0.28.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.circleci/config.yml +32 -22
- data/.github/ISSUE_TEMPLATE/bug_report.md +17 -0
- data/.github/workflows/docs.yml +2 -2
- data/.github/workflows/reviewdog.yml +1 -1
- data/.rubocop.yml +37 -0
- data/CHANGELOG.md +81 -0
- data/Dockerfile +1 -1
- data/README.md +15 -0
- data/lib/puppeteer.rb +3 -0
- data/lib/puppeteer/browser.rb +19 -28
- data/lib/puppeteer/browser_context.rb +48 -49
- data/lib/puppeteer/browser_runner.rb +0 -1
- data/lib/puppeteer/cdp_session.rb +11 -7
- data/lib/puppeteer/concurrent_ruby_utils.rb +6 -3
- data/lib/puppeteer/connection.rb +30 -11
- data/lib/puppeteer/define_async_method.rb +15 -6
- data/lib/puppeteer/dom_world.rb +2 -2
- data/lib/puppeteer/event_callbackable.rb +4 -0
- data/lib/puppeteer/events.rb +184 -0
- data/lib/puppeteer/exception_details.rb +38 -0
- data/lib/puppeteer/frame_manager.rb +20 -16
- data/lib/puppeteer/geolocation.rb +24 -0
- data/lib/puppeteer/launcher/chrome.rb +4 -1
- data/lib/puppeteer/lifecycle_watcher.rb +6 -6
- data/lib/puppeteer/network_manager.rb +6 -6
- data/lib/puppeteer/page.rb +131 -138
- data/lib/puppeteer/page/screenshot_options.rb +2 -2
- data/lib/puppeteer/page/screenshot_task_queue.rb +13 -0
- data/lib/puppeteer/target.rb +4 -6
- data/lib/puppeteer/version.rb +1 -1
- data/puppeteer-ruby.gemspec +6 -4
- metadata +44 -10
@@ -9,7 +9,7 @@ class Puppeteer::CDPSession
|
|
9
9
|
# @param {string} targetType
|
10
10
|
# @param {string} sessionId
|
11
11
|
def initialize(connection, target_type, session_id)
|
12
|
-
@callbacks =
|
12
|
+
@callbacks = Concurrent::Hash.new
|
13
13
|
@connection = connection
|
14
14
|
@target_type = target_type
|
15
15
|
@session_id = session_id
|
@@ -31,10 +31,14 @@ class Puppeteer::CDPSession
|
|
31
31
|
if !@connection
|
32
32
|
raise Error.new("Protocol error (#{method}): Session closed. Most likely the #{@target_type} has been closed.")
|
33
33
|
end
|
34
|
-
|
34
|
+
|
35
35
|
promise = resolvable_future
|
36
|
-
|
37
|
-
@
|
36
|
+
|
37
|
+
@connection.generate_id do |id|
|
38
|
+
@callbacks[id] = Puppeteer::Connection::MessageCallback.new(method: method, promise: promise)
|
39
|
+
@connection.raw_send(id: id, message: { sessionId: @session_id, method: method, params: params })
|
40
|
+
end
|
41
|
+
|
38
42
|
promise
|
39
43
|
end
|
40
44
|
|
@@ -44,10 +48,10 @@ class Puppeteer::CDPSession
|
|
44
48
|
if callback = @callbacks.delete(message['id'])
|
45
49
|
callback_with_message(callback, message)
|
46
50
|
else
|
47
|
-
raise Error.new("unknown id: #{id}")
|
51
|
+
raise Error.new("unknown id: #{message['id']}")
|
48
52
|
end
|
49
53
|
else
|
50
|
-
emit_event
|
54
|
+
emit_event(message['method'], message['params'])
|
51
55
|
end
|
52
56
|
end
|
53
57
|
|
@@ -79,7 +83,7 @@ class Puppeteer::CDPSession
|
|
79
83
|
end
|
80
84
|
@callbacks.clear
|
81
85
|
@connection = nil
|
82
|
-
emit_event
|
86
|
+
emit_event(CDPSessionEmittedEvents::Disconnected)
|
83
87
|
end
|
84
88
|
|
85
89
|
# @param event_name [String]
|
@@ -39,9 +39,12 @@ module Puppeteer::ConcurrentRubyUtils
|
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
42
|
-
def future(&block)
|
43
|
-
Concurrent::Promises.future do
|
44
|
-
block.call
|
42
|
+
def future(*args, &block)
|
43
|
+
Concurrent::Promises.future(*args) do |*block_args|
|
44
|
+
block.call(*block_args)
|
45
|
+
rescue Puppeteer::TimeoutError
|
46
|
+
# suppress error logging
|
47
|
+
raise
|
45
48
|
rescue => err
|
46
49
|
Logger.new($stderr).warn(err)
|
47
50
|
raise err
|
data/lib/puppeteer/connection.rb
CHANGED
@@ -39,7 +39,7 @@ class Puppeteer::Connection
|
|
39
39
|
def initialize(url, transport, delay = 0)
|
40
40
|
@url = url
|
41
41
|
@last_id = 0
|
42
|
-
@callbacks =
|
42
|
+
@callbacks = Concurrent::Hash.new
|
43
43
|
@delay = delay
|
44
44
|
|
45
45
|
@transport = transport
|
@@ -52,7 +52,7 @@ class Puppeteer::Connection
|
|
52
52
|
handle_close
|
53
53
|
end
|
54
54
|
|
55
|
-
@sessions =
|
55
|
+
@sessions = Concurrent::Hash.new
|
56
56
|
@closed = false
|
57
57
|
end
|
58
58
|
|
@@ -92,22 +92,41 @@ class Puppeteer::Connection
|
|
92
92
|
end
|
93
93
|
|
94
94
|
def async_send_message(method, params = {})
|
95
|
-
id = raw_send(message: { method: method, params: params })
|
96
95
|
promise = resolvable_future
|
97
|
-
|
96
|
+
|
97
|
+
generate_id do |id|
|
98
|
+
@callbacks[id] = MessageCallback.new(method: method, promise: promise)
|
99
|
+
raw_send(id: id, message: { method: method, params: params })
|
100
|
+
end
|
101
|
+
|
98
102
|
promise
|
99
103
|
end
|
100
104
|
|
101
|
-
private
|
102
|
-
|
105
|
+
# package private. not intended to use externally.
|
106
|
+
#
|
107
|
+
# ```usage
|
108
|
+
# connection.generate_id do |generated_id|
|
109
|
+
# # play with generated_id
|
110
|
+
# end
|
111
|
+
# ````
|
112
|
+
#
|
113
|
+
def generate_id(&block)
|
114
|
+
block.call(@last_id += 1)
|
103
115
|
end
|
104
116
|
|
105
|
-
|
106
|
-
|
117
|
+
# package private. not intended to use externally.
|
118
|
+
def raw_send(id:, message:)
|
119
|
+
# In original puppeteer (JS) implementation,
|
120
|
+
# id is generated here using #generate_id and the id argument is not passed to #raw_send.
|
121
|
+
#
|
122
|
+
# However with concurrent-ruby, '#handle_message' is sometimes called
|
123
|
+
# just soon after @transport.send_text and **before returning the id.**
|
124
|
+
#
|
125
|
+
# So we have to know the message id in advance before send_text.
|
126
|
+
#
|
107
127
|
payload = JSON.fast_generate(message.compact.merge(id: id))
|
108
128
|
@transport.send_text(payload)
|
109
129
|
request_debug_printer.handle_payload(payload)
|
110
|
-
id
|
111
130
|
end
|
112
131
|
|
113
132
|
# Just for effective debugging :)
|
@@ -211,7 +230,7 @@ class Puppeteer::Connection
|
|
211
230
|
end
|
212
231
|
end
|
213
232
|
else
|
214
|
-
emit_event
|
233
|
+
emit_event(message['method'], message['params'])
|
215
234
|
end
|
216
235
|
end
|
217
236
|
|
@@ -233,7 +252,7 @@ class Puppeteer::Connection
|
|
233
252
|
session.handle_closed
|
234
253
|
end
|
235
254
|
@sessions.clear
|
236
|
-
emit_event
|
255
|
+
emit_event(ConnectionEmittedEvents::Disconnected)
|
237
256
|
end
|
238
257
|
|
239
258
|
def on_close(&block)
|
@@ -10,12 +10,21 @@ module Puppeteer::DefineAsyncMethod
|
|
10
10
|
end
|
11
11
|
|
12
12
|
original_method = instance_method(async_method_name[6..-1])
|
13
|
-
define_method(async_method_name) do |*args|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
13
|
+
define_method(async_method_name) do |*args, **kwargs|
|
14
|
+
if kwargs.empty? # for Ruby < 2.7
|
15
|
+
Concurrent::Promises.future do
|
16
|
+
original_method.bind(self).call(*args)
|
17
|
+
rescue => err
|
18
|
+
Logger.new($stderr).warn(err)
|
19
|
+
raise err
|
20
|
+
end
|
21
|
+
else
|
22
|
+
Concurrent::Promises.future do
|
23
|
+
original_method.bind(self).call(*args, **kwargs)
|
24
|
+
rescue => err
|
25
|
+
Logger.new($stderr).warn(err)
|
26
|
+
raise err
|
27
|
+
end
|
19
28
|
end
|
20
29
|
end
|
21
30
|
end
|
data/lib/puppeteer/dom_world.rb
CHANGED
@@ -134,7 +134,7 @@ class Puppeteer::DOMWorld
|
|
134
134
|
|
135
135
|
# @return [String]
|
136
136
|
def content
|
137
|
-
evaluate
|
137
|
+
evaluate(<<-JAVASCRIPT)
|
138
138
|
() => {
|
139
139
|
let retVal = '';
|
140
140
|
if (document.doctype)
|
@@ -151,7 +151,7 @@ class Puppeteer::DOMWorld
|
|
151
151
|
# @param wait_until [String|Array<String>]
|
152
152
|
def set_content(html, timeout: nil, wait_until: nil)
|
153
153
|
option_wait_until = [wait_until || 'load'].flatten
|
154
|
-
option_timeout = @timeout_settings.navigation_timeout
|
154
|
+
option_timeout = timeout || @timeout_settings.navigation_timeout
|
155
155
|
|
156
156
|
# We rely upon the fact that document.open() will reset frame lifecycle with "init"
|
157
157
|
# lifecycle event. @see https://crrev.com/608658
|
@@ -31,6 +31,8 @@ module Puppeteer::EventCallbackable
|
|
31
31
|
(@event_listeners[event_name] ||= EventListeners.new).add(&block)
|
32
32
|
end
|
33
33
|
|
34
|
+
alias_method :on, :add_event_listener
|
35
|
+
|
34
36
|
def remove_event_listener(*id_args)
|
35
37
|
(@event_listeners ||= {}).each do |event_name, listeners|
|
36
38
|
id_args.each do |id|
|
@@ -50,6 +52,8 @@ module Puppeteer::EventCallbackable
|
|
50
52
|
end
|
51
53
|
end
|
52
54
|
|
55
|
+
alias_method :once, :observe_first
|
56
|
+
|
53
57
|
def on_event(event_name, &block)
|
54
58
|
@event_callbackable_handlers ||= {}
|
55
59
|
@event_callbackable_handlers[event_name] = block
|
@@ -0,0 +1,184 @@
|
|
1
|
+
require 'digest/md5'
|
2
|
+
|
3
|
+
module EventsDefinitionUtils
|
4
|
+
refine Kernel do
|
5
|
+
# Symbol is used to prevent external parties listening to these events
|
6
|
+
def Symbol(str)
|
7
|
+
Digest::MD5.hexdigest(str)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
refine Hash do
|
12
|
+
def define_const_into(target_module)
|
13
|
+
each do |key, value|
|
14
|
+
target_module.const_set(key, value)
|
15
|
+
target_module.define_singleton_method(key) { value }
|
16
|
+
end
|
17
|
+
keyset = Set.new(keys)
|
18
|
+
valueset = Set.new(values)
|
19
|
+
target_module.define_singleton_method(:keys) { keyset }
|
20
|
+
target_module.define_singleton_method(:values) { valueset }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
using EventsDefinitionUtils
|
26
|
+
|
27
|
+
# Internal events that the Connection class emits.
|
28
|
+
module ConnectionEmittedEvents ; end
|
29
|
+
|
30
|
+
{
|
31
|
+
Disconnected: Symbol('Connection.Disconnected'),
|
32
|
+
}.define_const_into(ConnectionEmittedEvents)
|
33
|
+
|
34
|
+
# Internal events that the CDPSession class emits.
|
35
|
+
module CDPSessionEmittedEvents ; end
|
36
|
+
|
37
|
+
{
|
38
|
+
Disconnected: Symbol('CDPSession.Disconnected'),
|
39
|
+
}.define_const_into(CDPSessionEmittedEvents)
|
40
|
+
|
41
|
+
# All the events a Browser may emit.
|
42
|
+
module BrowserEmittedEvents ; end
|
43
|
+
|
44
|
+
{
|
45
|
+
# Emitted when Puppeteer gets disconnected from the Chromium instance. This might happen because of one of the following:
|
46
|
+
# - Chromium is closed or crashed
|
47
|
+
# - The Browser#disconnect method was called.
|
48
|
+
Disconnected: 'disconnected',
|
49
|
+
|
50
|
+
# Emitted when the url of a target changes. Contains a {@link Target} instance.
|
51
|
+
TargetChanged: 'targetchanged',
|
52
|
+
|
53
|
+
# Emitted when a target is created, for example when a new page is opened by
|
54
|
+
# window.open or by Browser#newPage
|
55
|
+
# Contains a Target instance.
|
56
|
+
TargetCreated: 'targetcreated',
|
57
|
+
|
58
|
+
# Emitted when a target is destroyed, for example when a page is closed.
|
59
|
+
# Contains a Target instance.
|
60
|
+
TargetDestroyed: 'targetdestroyed',
|
61
|
+
}.define_const_into(BrowserEmittedEvents)
|
62
|
+
|
63
|
+
module BrowserContextEmittedEvents ; end
|
64
|
+
|
65
|
+
{
|
66
|
+
# Emitted when the url of a target inside the browser context changes.
|
67
|
+
# Contains a Target instance.
|
68
|
+
TargetChanged: 'targetchanged',
|
69
|
+
|
70
|
+
# Emitted when a target is created, for example when a new page is opened by
|
71
|
+
# window.open or by BrowserContext#newPage
|
72
|
+
# Contains a Target instance.
|
73
|
+
TargetCreated: 'targetcreated',
|
74
|
+
|
75
|
+
# Emitted when a target is destroyed within the browser context, for example when a page is closed.
|
76
|
+
# Contains a Target instance.
|
77
|
+
TargetDestroyed: 'targetdestroyed',
|
78
|
+
}.define_const_into(BrowserContextEmittedEvents)
|
79
|
+
|
80
|
+
# We use symbols to prevent any external parties listening to these events.
|
81
|
+
# They are internal to Puppeteer.
|
82
|
+
module NetworkManagerEmittedEvents ; end
|
83
|
+
|
84
|
+
{
|
85
|
+
Request: Symbol('NetworkManager.Request'),
|
86
|
+
Response: Symbol('NetworkManager.Response'),
|
87
|
+
RequestFailed: Symbol('NetworkManager.RequestFailed'),
|
88
|
+
RequestFinished: Symbol('NetworkManager.RequestFinished'),
|
89
|
+
}.define_const_into(NetworkManagerEmittedEvents)
|
90
|
+
|
91
|
+
|
92
|
+
# We use symbols to prevent external parties listening to these events.
|
93
|
+
# They are internal to Puppeteer.
|
94
|
+
module FrameManagerEmittedEvents ; end
|
95
|
+
|
96
|
+
{
|
97
|
+
FrameAttached: Symbol('FrameManager.FrameAttached'),
|
98
|
+
FrameNavigated: Symbol('FrameManager.FrameNavigated'),
|
99
|
+
FrameDetached: Symbol('FrameManager.FrameDetached'),
|
100
|
+
LifecycleEvent: Symbol('FrameManager.LifecycleEvent'),
|
101
|
+
FrameNavigatedWithinDocument: Symbol('FrameManager.FrameNavigatedWithinDocument'),
|
102
|
+
ExecutionContextCreated: Symbol('FrameManager.ExecutionContextCreated'),
|
103
|
+
ExecutionContextDestroyed: Symbol('FrameManager.ExecutionContextDestroyed'),
|
104
|
+
}.define_const_into(FrameManagerEmittedEvents)
|
105
|
+
|
106
|
+
# All the events that a page instance may emit.
|
107
|
+
module PageEmittedEvents ; end
|
108
|
+
|
109
|
+
{
|
110
|
+
# Emitted when the page closes.
|
111
|
+
Close: 'close',
|
112
|
+
|
113
|
+
# Emitted when JavaScript within the page calls one of console API methods,
|
114
|
+
# e.g. `console.log` or `console.dir`. Also emitted if the page throws an
|
115
|
+
# error or a warning.
|
116
|
+
Console: 'console',
|
117
|
+
|
118
|
+
# Emitted when a JavaScript dialog appears, such as `alert`, `prompt`,
|
119
|
+
# `confirm` or `beforeunload`. Puppeteer can respond to the dialog via
|
120
|
+
# Dialog#accept or Dialog#dismiss.
|
121
|
+
Dialog: 'dialog',
|
122
|
+
|
123
|
+
# Emitted when the JavaScript
|
124
|
+
# {https://developer.mozilla.org/en-US/docs/Web/Events/DOMContentLoaded DOMContentLoaded} event is dispatched.
|
125
|
+
DOMContentLoaded: 'domcontentloaded',
|
126
|
+
|
127
|
+
# Emitted when the page crashes. Will contain an `Error`.
|
128
|
+
Error: 'error',
|
129
|
+
|
130
|
+
# Emitted when a frame is attached. Will contain a Frame.
|
131
|
+
FrameAttached: 'frameattached',
|
132
|
+
# Emitted when a frame is detached. Will contain a Frame.
|
133
|
+
FrameDetached: 'framedetached',
|
134
|
+
# Emitted when a frame is navigated to a new URL. Will contain a {@link Frame}.
|
135
|
+
FrameNavigated: 'framenavigated',
|
136
|
+
|
137
|
+
# Emitted when the JavaScript
|
138
|
+
# {https://developer.mozilla.org/en-US/docs/Web/Events/load | load} event is dispatched.
|
139
|
+
Load: 'load',
|
140
|
+
|
141
|
+
# Emitted when the JavaScript code makes a call to `console.timeStamp`. For
|
142
|
+
# the list of metrics see {@link Page.metrics | page.metrics}.
|
143
|
+
#
|
144
|
+
# Contains an object with two properties:
|
145
|
+
# - `title`: the title passed to `console.timeStamp`
|
146
|
+
# - `metrics`: objec containing metrics as key/value pairs. The values will be `number`s.
|
147
|
+
Metrics: 'metrics',
|
148
|
+
|
149
|
+
# Emitted when an uncaught exception happens within the page.
|
150
|
+
# Contains an `Error`.
|
151
|
+
PageError: 'pageerror',
|
152
|
+
|
153
|
+
# Emitted when the page opens a new tab or window.
|
154
|
+
# Contains a Page corresponding to the popup window.
|
155
|
+
Popup: 'popup',
|
156
|
+
|
157
|
+
# Emitted when a page issues a request and contains a HTTPRequest.
|
158
|
+
#
|
159
|
+
# The object is readonly. See Page#setRequestInterception for intercepting and mutating requests.
|
160
|
+
Request: 'request',
|
161
|
+
|
162
|
+
# Emitted when a request fails, for example by timing out.
|
163
|
+
#
|
164
|
+
# Contains a HTTPRequest.
|
165
|
+
#
|
166
|
+
# NOTE: HTTP Error responses, such as 404 or 503, are still successful
|
167
|
+
# responses from HTTP standpoint, so request will complete with
|
168
|
+
# `requestfinished` event and not with `requestfailed`.
|
169
|
+
RequestFailed: 'requestfailed',
|
170
|
+
|
171
|
+
# Emitted when a request finishes successfully. Contains a HTTPRequest.
|
172
|
+
RequestFinished: 'requestfinished',
|
173
|
+
|
174
|
+
# Emitted when a response is received. Contains a HTTPResponse.
|
175
|
+
Response: 'response',
|
176
|
+
|
177
|
+
# Emitted when a dedicated
|
178
|
+
# {https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API WebWorker} is spawned by the page.
|
179
|
+
WorkerCreated: 'workercreated',
|
180
|
+
|
181
|
+
# Emitted when a dedicated
|
182
|
+
# {https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API WebWorker} is destroyed by the page.
|
183
|
+
WorkerDestroyed: 'workerdestroyed',
|
184
|
+
}.define_const_into(PageEmittedEvents)
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# Original implementation, helpers.getExceptionMessage
|
2
|
+
class Puppeteer::ExceptionDetails
|
3
|
+
# @param exception_details [Hash]
|
4
|
+
def initialize(exception_details)
|
5
|
+
@exception_details = exception_details
|
6
|
+
end
|
7
|
+
|
8
|
+
def message
|
9
|
+
# "exceptionDetails"=>{"exceptionId"=>1, "text"=>"Uncaught", "lineNumber"=>12, "columnNumber"=>10, "url"=>"http://127.0.0.1:4567/error.html",
|
10
|
+
# "stackTrace"=>{"callFrames"=>[
|
11
|
+
# {"functionName"=>"c", "scriptId"=>"6", "url"=>"http://127.0.0.1:4567/error.html", "lineNumber"=>12, "columnNumber"=>10},
|
12
|
+
# {"functionName"=>"b", "scriptId"=>"6", "url"=>"http://127.0.0.1:4567/error.html", "lineNumber"=>8, "columnNumber"=>4},
|
13
|
+
# {"functionName"=>"a", "scriptId"=>"6", "url"=>"http://127.0.0.1:4567/error.html", "lineNumber"=>4, "columnNumber"=>4},
|
14
|
+
# {"functionName"=>"", "scriptId"=>"6", "url"=>"http://127.0.0.1:4567/error.html", "lineNumber"=>1, "columnNumber"=>0}
|
15
|
+
# ]},
|
16
|
+
# "exception"=>{"type"=>"object", "subtype"=>"error", "className"=>"Error", "description"=>"Error: Fancy error!\n at c (http://127.0.0.1:4567/error.html:13:11)\n at b (http://127.0.0.1:4567/error.html:9:5)\n at a (http://127.0.0.1:4567/error.html:5:5)\n at http://127.0.0.1:4567/error.html:2:1", "objectId"=>"{\"injectedScriptId\":3,\"id\":1}", "preview"=>{"type"=>"object", "subtype"=>"error", "description"=>"Error: Fancy error!\n at c (http://127.0.0.1:4567/error.html:13:11)\n at b (http://127.0.0.1:4567/error.html:9:5)\n at a (http://127.0.0.1:4567/error.html:5:5)\n at http://127.0.0.1:4567/error.html:2:1", "overflow"=>false, "properties"=>[{"name"=>"stack", "type"=>"string", "value"=>"Error: Fancy error!\n at c (http://127.0.0.1:456…:5:5)\n at http://127.0.0.1:4567/error.html:2:1"}, {"name"=>"message", "type"=>"string", "value"=>"Fancy error!"}]}}
|
17
|
+
if @exception_details['exception']
|
18
|
+
return exception_description_or_value(@exception_details['exception'])
|
19
|
+
end
|
20
|
+
|
21
|
+
messages = []
|
22
|
+
messages << @exception_details['text']
|
23
|
+
|
24
|
+
if @exception_details['stackTrace']
|
25
|
+
@exception_details['stackTrace']['callFrames'].each do |call_frame|
|
26
|
+
location = "#{call_frame['url']}:#{call_frame['lineNumber']}:#{call_frame['columnNumber']}"
|
27
|
+
function_name = call_frame['functionName'] || '<anonymous>'
|
28
|
+
messages << "at #{function_name} (#{location})"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
messages.join("\n ")
|
33
|
+
end
|
34
|
+
|
35
|
+
private def exception_description_or_value(exception)
|
36
|
+
exception['description'] || exception['value']
|
37
|
+
end
|
38
|
+
end
|
@@ -27,31 +27,31 @@ class Puppeteer::FrameManager
|
|
27
27
|
# @type {!Set<string>}
|
28
28
|
@isolated_worlds = Set.new
|
29
29
|
|
30
|
-
@client.on_event
|
30
|
+
@client.on_event('Page.frameAttached') do |event|
|
31
31
|
handle_frame_attached(event['frameId'], event['parentFrameId'])
|
32
32
|
end
|
33
|
-
@client.on_event
|
33
|
+
@client.on_event('Page.frameNavigated') do |event|
|
34
34
|
handle_frame_navigated(event['frame'])
|
35
35
|
end
|
36
|
-
@client.on_event
|
36
|
+
@client.on_event('Page.navigatedWithinDocument') do |event|
|
37
37
|
handle_frame_navigated_within_document(event['frameId'], event['url'])
|
38
38
|
end
|
39
|
-
@client.on_event
|
39
|
+
@client.on_event('Page.frameDetached') do |event|
|
40
40
|
handle_frame_detached(event['frameId'])
|
41
41
|
end
|
42
|
-
@client.on_event
|
42
|
+
@client.on_event('Page.frameStoppedLoading') do |event|
|
43
43
|
handle_frame_stopped_loading(event['frameId'])
|
44
44
|
end
|
45
|
-
@client.on_event
|
45
|
+
@client.on_event('Runtime.executionContextCreated') do |event|
|
46
46
|
handle_execution_context_created(event['context'])
|
47
47
|
end
|
48
|
-
@client.on_event
|
48
|
+
@client.on_event('Runtime.executionContextDestroyed') do |event|
|
49
49
|
handle_execution_context_destroyed(event['executionContextId'])
|
50
50
|
end
|
51
|
-
@client.on_event
|
51
|
+
@client.on_event('Runtime.executionContextsCleared') do |event|
|
52
52
|
handle_execution_contexts_cleared
|
53
53
|
end
|
54
|
-
@client.on_event
|
54
|
+
@client.on_event('Page.lifecycleEvent') do |event|
|
55
55
|
handle_lifecycle_event(event)
|
56
56
|
end
|
57
57
|
end
|
@@ -121,6 +121,8 @@ class Puppeteer::FrameManager
|
|
121
121
|
document_navigation_promise,
|
122
122
|
watcher.timeout_or_termination_promise,
|
123
123
|
)
|
124
|
+
rescue Puppeteer::TimeoutError => err
|
125
|
+
raise NavigationError.new(err)
|
124
126
|
ensure
|
125
127
|
watcher.dispose
|
126
128
|
end
|
@@ -143,6 +145,8 @@ class Puppeteer::FrameManager
|
|
143
145
|
watcher.same_document_navigation_promise,
|
144
146
|
watcher.new_document_navigation_promise,
|
145
147
|
)
|
148
|
+
rescue Puppeteer::TimeoutError => err
|
149
|
+
raise NavigationError.new(err)
|
146
150
|
ensure
|
147
151
|
watcher.dispose
|
148
152
|
end
|
@@ -155,7 +159,7 @@ class Puppeteer::FrameManager
|
|
155
159
|
frame = @frames[event['frameId']]
|
156
160
|
return if !frame
|
157
161
|
frame.handle_lifecycle_event(event['loaderId'], event['name'])
|
158
|
-
emit_event
|
162
|
+
emit_event(FrameManagerEmittedEvents::LifecycleEvent, frame)
|
159
163
|
end
|
160
164
|
|
161
165
|
# @param {string} frameId
|
@@ -163,7 +167,7 @@ class Puppeteer::FrameManager
|
|
163
167
|
frame = @frames[frame_id]
|
164
168
|
return if !frame
|
165
169
|
frame.handle_loading_stopped
|
166
|
-
emit_event
|
170
|
+
emit_event(FrameManagerEmittedEvents::LifecycleEvent, frame)
|
167
171
|
end
|
168
172
|
|
169
173
|
# @param frame_tree [Hash]
|
@@ -211,7 +215,7 @@ class Puppeteer::FrameManager
|
|
211
215
|
frame = Puppeteer::Frame.new(self, @client, parent_frame, frame_id)
|
212
216
|
@frames[frame_id] = frame
|
213
217
|
|
214
|
-
emit_event
|
218
|
+
emit_event(FrameManagerEmittedEvents::FrameAttached, frame)
|
215
219
|
end
|
216
220
|
|
217
221
|
# @param frame_payload [Hash]
|
@@ -252,7 +256,7 @@ class Puppeteer::FrameManager
|
|
252
256
|
# Update frame payload.
|
253
257
|
frame.navigated(frame_payload)
|
254
258
|
|
255
|
-
emit_event
|
259
|
+
emit_event(FrameManagerEmittedEvents::FrameNavigated, frame)
|
256
260
|
end
|
257
261
|
|
258
262
|
# @param name [String]
|
@@ -280,8 +284,8 @@ class Puppeteer::FrameManager
|
|
280
284
|
frame = @frames[frame_id]
|
281
285
|
return unless frame
|
282
286
|
frame.navigated_within_document(url)
|
283
|
-
emit_event
|
284
|
-
emit_event
|
287
|
+
emit_event(FrameManagerEmittedEvents::FrameNavigatedWithinDocument, frame)
|
288
|
+
emit_event(FrameManagerEmittedEvents::FrameNavigated, frame)
|
285
289
|
end
|
286
290
|
|
287
291
|
# @param frame_id [String]
|
@@ -349,7 +353,7 @@ class Puppeteer::FrameManager
|
|
349
353
|
end
|
350
354
|
frame.detach
|
351
355
|
@frames.delete(frame.id)
|
352
|
-
emit_event
|
356
|
+
emit_event(FrameManagerEmittedEvents::FrameDetached, frame)
|
353
357
|
end
|
354
358
|
|
355
359
|
private def assert_no_legacy_navigation_options(wait_until:)
|