puppeteer-ruby 0.0.22 → 0.28.1
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/.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
@@ -0,0 +1,24 @@
|
|
1
|
+
class Puppeteer::Geolocation
|
2
|
+
# @param latitude [Fixnum]
|
3
|
+
# @param longitude [Fixnum]
|
4
|
+
# @param accuracy [Fixnum]
|
5
|
+
def initialize(latitude:, longitude:, accuracy: 0)
|
6
|
+
unless (-180..180).include?(longitude)
|
7
|
+
raise ArgumentError.new("Invalid longitude \"#{longitude}\": precondition -180 <= LONGITUDE <= 180 failed.")
|
8
|
+
end
|
9
|
+
unless (-90..90).include?(latitude)
|
10
|
+
raise ArgumentError.new("Invalid latitude \"#{latitude}\": precondition -90 <= LATITUDE <= 90 failed.")
|
11
|
+
end
|
12
|
+
if accuracy < 0
|
13
|
+
raise ArgumentError.new("Invalid accuracy \"#{longitude}\": precondition 0 <= ACCURACY failed.")
|
14
|
+
end
|
15
|
+
|
16
|
+
@latitude = latitude
|
17
|
+
@longitude = longitude
|
18
|
+
@accuracy = accuracy
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_h
|
22
|
+
{ latitude: @latitude, longitude: @longitude, accuracy: @accuracy }
|
23
|
+
end
|
24
|
+
end
|
@@ -92,7 +92,7 @@ module Puppeteer::Launcher
|
|
92
92
|
'--disable-default-apps',
|
93
93
|
'--disable-dev-shm-usage',
|
94
94
|
'--disable-extensions',
|
95
|
-
'--disable-features=
|
95
|
+
'--disable-features=Translate',
|
96
96
|
'--disable-hang-monitor',
|
97
97
|
'--disable-ipc-flooding-protection',
|
98
98
|
'--disable-popup-blocking',
|
@@ -105,6 +105,9 @@ module Puppeteer::Launcher
|
|
105
105
|
'--enable-automation',
|
106
106
|
'--password-store=basic',
|
107
107
|
'--use-mock-keychain',
|
108
|
+
# TODO(sadym): remove '--enable-blink-features=IdleDetection'
|
109
|
+
# once IdleDetection is turned on by default.
|
110
|
+
'--enable-blink-features=IdleDetection',
|
108
111
|
]
|
109
112
|
|
110
113
|
if chrome_arg_options.user_data_dir
|
@@ -69,17 +69,17 @@ class Puppeteer::LifecycleWatcher
|
|
69
69
|
@timeout = timeout
|
70
70
|
|
71
71
|
@listener_ids = {}
|
72
|
-
@listener_ids['client'] = @frame_manager.client.add_event_listener(
|
72
|
+
@listener_ids['client'] = @frame_manager.client.add_event_listener(CDPSessionEmittedEvents::Disconnected) do
|
73
73
|
terminate(TerminatedError.new('Navigation failed because browser has disconnected!'))
|
74
74
|
end
|
75
75
|
@listener_ids['frame_manager'] = [
|
76
|
-
@frame_manager.add_event_listener(
|
76
|
+
@frame_manager.add_event_listener(FrameManagerEmittedEvents::LifecycleEvent) do |_|
|
77
77
|
check_lifecycle_complete
|
78
78
|
end,
|
79
|
-
@frame_manager.add_event_listener(
|
80
|
-
@frame_manager.add_event_listener(
|
79
|
+
@frame_manager.add_event_listener(FrameManagerEmittedEvents::FrameNavigatedWithinDocument, &method(:navigated_within_document)),
|
80
|
+
@frame_manager.add_event_listener(FrameManagerEmittedEvents::FrameDetached, &method(:handle_frame_detached)),
|
81
81
|
]
|
82
|
-
@listener_ids['network_manager'] = @frame_manager.network_manager.add_event_listener(
|
82
|
+
@listener_ids['network_manager'] = @frame_manager.network_manager.add_event_listener(NetworkManagerEmittedEvents::Request, &method(:handle_request))
|
83
83
|
|
84
84
|
@same_document_navigation_promise = resolvable_future
|
85
85
|
@lifecycle_promise = resolvable_future
|
@@ -128,7 +128,7 @@ class Puppeteer::LifecycleWatcher
|
|
128
128
|
@termination_promise.value!
|
129
129
|
end
|
130
130
|
rescue Timeout::Error
|
131
|
-
raise Puppeteer::
|
131
|
+
raise Puppeteer::TimeoutError.new("Navigation timeout of #{@timeout}ms exceeded")
|
132
132
|
end
|
133
133
|
else
|
134
134
|
@termination_promise
|
@@ -212,7 +212,7 @@ class Puppeteer::NetworkManager
|
|
212
212
|
frame = if_present(event['frameId']) { |frame_id| @frame_manager.frame(frame_id) }
|
213
213
|
request = Puppeteer::Request.new(@client, frame, interception_id, @user_request_interception_enabled, event, redirect_chain)
|
214
214
|
@request_id_to_request[event['requestId']] = request
|
215
|
-
emit_event
|
215
|
+
emit_event(NetworkManagerEmittedEvents::Request, request)
|
216
216
|
end
|
217
217
|
|
218
218
|
private def handle_request_served_from_cache(event)
|
@@ -230,8 +230,8 @@ class Puppeteer::NetworkManager
|
|
230
230
|
response.internal.body_loaded_promise.reject(Puppeteer::Response::Redirected.new)
|
231
231
|
@request_id_to_request.delete(request.internal.request_id)
|
232
232
|
@attempted_authentications.delete(request.internal.interception_id)
|
233
|
-
emit_event
|
234
|
-
emit_event
|
233
|
+
emit_event(NetworkManagerEmittedEvents::Response, response)
|
234
|
+
emit_event(NetworkManagerEmittedEvents::RequestFinished, request)
|
235
235
|
end
|
236
236
|
|
237
237
|
# @param event [Hash]
|
@@ -242,7 +242,7 @@ class Puppeteer::NetworkManager
|
|
242
242
|
|
243
243
|
response = Puppeteer::Response.new(@client, request, event['response'])
|
244
244
|
request.internal.response = response
|
245
|
-
emit_event
|
245
|
+
emit_event(NetworkManagerEmittedEvents::Response, response)
|
246
246
|
end
|
247
247
|
|
248
248
|
private def handle_loading_finished(event)
|
@@ -260,7 +260,7 @@ class Puppeteer::NetworkManager
|
|
260
260
|
|
261
261
|
@request_id_to_request.delete(request.internal.request_id)
|
262
262
|
@attempted_authentications.delete(request.internal.interception_id)
|
263
|
-
emit_event
|
263
|
+
emit_event(NetworkManagerEmittedEvents::RequestFinished, request)
|
264
264
|
end
|
265
265
|
|
266
266
|
private def handle_loading_failed(event)
|
@@ -275,6 +275,6 @@ class Puppeteer::NetworkManager
|
|
275
275
|
end
|
276
276
|
@request_id_to_request.delete(request.internal.request_id)
|
277
277
|
@attempted_authentications.delete(request.internal.interception_id)
|
278
|
-
emit_event
|
278
|
+
emit_event(NetworkManagerEmittedEvents::RequestFailed, request)
|
279
279
|
end
|
280
280
|
end
|
data/lib/puppeteer/page.rb
CHANGED
@@ -3,6 +3,7 @@ require "stringio"
|
|
3
3
|
|
4
4
|
require_relative './page/pdf_options'
|
5
5
|
require_relative './page/screenshot_options'
|
6
|
+
require_relative './page/screenshot_task_queue'
|
6
7
|
|
7
8
|
class Puppeteer::Page
|
8
9
|
include Puppeteer::EventCallbackable
|
@@ -13,10 +14,9 @@ class Puppeteer::Page
|
|
13
14
|
# @param {!Puppeteer.Target} target
|
14
15
|
# @param {boolean} ignoreHTTPSErrors
|
15
16
|
# @param {?Puppeteer.Viewport} defaultViewport
|
16
|
-
# @param {!Puppeteer.TaskQueue} screenshotTaskQueue
|
17
17
|
# @return {!Promise<!Page>}
|
18
|
-
def self.create(client, target, ignore_https_errors, default_viewport
|
19
|
-
page = Puppeteer::Page.new(client, target, ignore_https_errors
|
18
|
+
def self.create(client, target, ignore_https_errors, default_viewport)
|
19
|
+
page = Puppeteer::Page.new(client, target, ignore_https_errors)
|
20
20
|
page.init
|
21
21
|
if default_viewport
|
22
22
|
page.viewport = default_viewport
|
@@ -27,8 +27,7 @@ class Puppeteer::Page
|
|
27
27
|
# @param {!Puppeteer.CDPSession} client
|
28
28
|
# @param {!Puppeteer.Target} target
|
29
29
|
# @param {boolean} ignoreHTTPSErrors
|
30
|
-
|
31
|
-
def initialize(client, target, ignore_https_errors, screenshot_task_queue)
|
30
|
+
def initialize(client, target, ignore_https_errors)
|
32
31
|
@closed = false
|
33
32
|
@client = client
|
34
33
|
@target = target
|
@@ -43,10 +42,10 @@ class Puppeteer::Page
|
|
43
42
|
@page_bindings = {}
|
44
43
|
# @coverage = Coverage.new(client)
|
45
44
|
@javascript_enabled = true
|
46
|
-
@screenshot_task_queue =
|
45
|
+
@screenshot_task_queue = ScreenshotTaskQueue.new
|
47
46
|
|
48
47
|
@workers = {}
|
49
|
-
@client.on_event
|
48
|
+
@client.on_event('Target.attachedToTarget') do |event|
|
50
49
|
if event['targetInfo']['type'] != 'worker'
|
51
50
|
# If we don't detach from service workers, they will never die.
|
52
51
|
await @client.send_message('Target.detachFromTarget', sessionId: event['sessionId'])
|
@@ -56,65 +55,69 @@ class Puppeteer::Page
|
|
56
55
|
session = Puppeteer::Connection.from_session(@client).session(event['sessionId']) # rubocop:disable Lint/UselessAssignment
|
57
56
|
# const worker = new Worker(session, event.targetInfo.url, this._addConsoleMessage.bind(this), this._handleException.bind(this));
|
58
57
|
# this._workers.set(event.sessionId, worker);
|
59
|
-
# this.emit(
|
58
|
+
# this.emit(PageEmittedEvents::WorkerCreated, worker);
|
60
59
|
end
|
61
|
-
@client.on_event
|
60
|
+
@client.on_event('Target.detachedFromTarget') do |event|
|
62
61
|
session_id = event['sessionId']
|
63
62
|
worker = @workers[session_id]
|
64
63
|
next unless worker
|
65
64
|
|
66
|
-
emit_event(
|
65
|
+
emit_event(PageEmittedEvents::WorkerDestroyed, worker)
|
67
66
|
@workers.delete(session_id)
|
68
67
|
end
|
69
68
|
|
70
|
-
@frame_manager.on_event
|
71
|
-
emit_event
|
69
|
+
@frame_manager.on_event(FrameManagerEmittedEvents::FrameAttached) do |event|
|
70
|
+
emit_event(PageEmittedEvents::FrameAttached, event)
|
72
71
|
end
|
73
|
-
@frame_manager.on_event
|
74
|
-
emit_event
|
72
|
+
@frame_manager.on_event(FrameManagerEmittedEvents::FrameDetached) do |event|
|
73
|
+
emit_event(PageEmittedEvents::FrameDetached, event)
|
75
74
|
end
|
76
|
-
@frame_manager.on_event
|
77
|
-
emit_event
|
75
|
+
@frame_manager.on_event(FrameManagerEmittedEvents::FrameNavigated) do |event|
|
76
|
+
emit_event(PageEmittedEvents::FrameNavigated, event)
|
78
77
|
end
|
79
78
|
|
80
79
|
network_manager = @frame_manager.network_manager
|
81
|
-
network_manager.on_event
|
82
|
-
emit_event
|
80
|
+
network_manager.on_event(NetworkManagerEmittedEvents::Request) do |event|
|
81
|
+
emit_event(PageEmittedEvents::Request, event)
|
83
82
|
end
|
84
|
-
network_manager.on_event
|
85
|
-
emit_event
|
83
|
+
network_manager.on_event(NetworkManagerEmittedEvents::Response) do |event|
|
84
|
+
emit_event(PageEmittedEvents::Response, event)
|
86
85
|
end
|
87
|
-
network_manager.on_event
|
88
|
-
emit_event
|
86
|
+
network_manager.on_event(NetworkManagerEmittedEvents::RequestFailed) do |event|
|
87
|
+
emit_event(PageEmittedEvents::RequestFailed, event)
|
89
88
|
end
|
90
|
-
network_manager.on_event
|
91
|
-
emit_event
|
89
|
+
network_manager.on_event(NetworkManagerEmittedEvents::RequestFinished) do |event|
|
90
|
+
emit_event(PageEmittedEvents::RequestFinished, event)
|
92
91
|
end
|
93
92
|
@file_chooser_interception_is_disabled = false
|
94
93
|
@file_chooser_interceptors = Set.new
|
95
94
|
|
96
|
-
@client.on_event
|
97
|
-
emit_event
|
95
|
+
@client.on_event('Page.domContentEventFired') do |event|
|
96
|
+
emit_event(PageEmittedEvents::DOMContentLoaded)
|
98
97
|
end
|
99
|
-
@client.on_event
|
100
|
-
emit_event
|
98
|
+
@client.on_event('Page.loadEventFired') do |event|
|
99
|
+
emit_event(PageEmittedEvents::Load)
|
101
100
|
end
|
102
101
|
# client.on('Runtime.consoleAPICalled', event => this._onConsoleAPI(event));
|
103
102
|
# client.on('Runtime.bindingCalled', event => this._onBindingCalled(event));
|
104
|
-
@client.on_event
|
103
|
+
@client.on_event('Page.javascriptDialogOpening') do |event|
|
105
104
|
handle_dialog_opening(event)
|
106
105
|
end
|
107
|
-
|
108
|
-
|
106
|
+
@client.on_event('Runtime.exceptionThrown') do |exception|
|
107
|
+
handle_exception(exception['exceptionDetails'])
|
108
|
+
end
|
109
|
+
@client.on_event('Inspector.targetCrashed') do |event|
|
110
|
+
handle_target_crashed
|
111
|
+
end
|
109
112
|
# client.on('Performance.metrics', event => this._emitMetrics(event));
|
110
|
-
@client.on_event
|
113
|
+
@client.on_event('Log.entryAdded') do |event|
|
111
114
|
handle_log_entry_added(event)
|
112
115
|
end
|
113
|
-
@client.on_event
|
116
|
+
@client.on_event('Page.fileChooserOpened') do |event|
|
114
117
|
handle_file_chooser(event)
|
115
118
|
end
|
116
119
|
@target.is_closed_promise.then do
|
117
|
-
emit_event
|
120
|
+
emit_event(PageEmittedEvents::Close)
|
118
121
|
@closed = true
|
119
122
|
end
|
120
123
|
end
|
@@ -128,43 +131,22 @@ class Puppeteer::Page
|
|
128
131
|
)
|
129
132
|
end
|
130
133
|
|
131
|
-
EVENT_MAPPINGS = {
|
132
|
-
close: 'Events.Page.Close',
|
133
|
-
# console: 'Events.Page.Console',
|
134
|
-
dialog: 'Events.Page.Dialog',
|
135
|
-
domcontentloaded: 'Events.Page.DOMContentLoaded',
|
136
|
-
# error:
|
137
|
-
frameattached: 'Events.Page.FrameAttached',
|
138
|
-
framedetached: 'Events.Page.FrameDetached',
|
139
|
-
framenavigated: 'Events.Page.FrameNavigated',
|
140
|
-
load: 'Events.Page.Load',
|
141
|
-
# metrics: 'Events.Page.Metrics',
|
142
|
-
# pageerror: 'Events.Page.PageError',
|
143
|
-
popup: 'Events.Page.Popup',
|
144
|
-
request: 'Events.Page.Request',
|
145
|
-
requestfailed: 'Events.Page.RequestFailed',
|
146
|
-
requestfinished: 'Events.Page.RequestFinished',
|
147
|
-
response: 'Events.Page.Response',
|
148
|
-
# workercreated: 'Events.Page.WorkerCreated',
|
149
|
-
# workerdestroyed: 'Events.Page.WorkerDestroyed',
|
150
|
-
}
|
151
|
-
|
152
134
|
# @param event_name [Symbol]
|
153
135
|
def on(event_name, &block)
|
154
|
-
unless
|
155
|
-
raise ArgumentError.new("Unknown event name: #{event_name}. Known events are #{
|
136
|
+
unless PageEmittedEvents.values.include?(event_name.to_s)
|
137
|
+
raise ArgumentError.new("Unknown event name: #{event_name}. Known events are #{PageEmittedEvents.values.to_a.join(", ")}")
|
156
138
|
end
|
157
139
|
|
158
|
-
|
140
|
+
super(event_name.to_s, &block)
|
159
141
|
end
|
160
142
|
|
161
143
|
# @param event_name [Symbol]
|
162
144
|
def once(event_name, &block)
|
163
|
-
unless
|
164
|
-
raise ArgumentError.new("Unknown event name: #{event_name}. Known events are #{
|
145
|
+
unless PageEmittedEvents.values.include?(event_name.to_s)
|
146
|
+
raise ArgumentError.new("Unknown event name: #{event_name}. Known events are #{PageEmittedEvents.values.to_a.join(", ")}")
|
165
147
|
end
|
166
148
|
|
167
|
-
|
149
|
+
super(event_name.to_s, &block)
|
168
150
|
end
|
169
151
|
|
170
152
|
def handle_file_chooser(event)
|
@@ -211,19 +193,10 @@ class Puppeteer::Page
|
|
211
193
|
|
212
194
|
define_async_method :async_wait_for_file_chooser
|
213
195
|
|
214
|
-
#
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
# const { longitude, latitude, accuracy = 0} = options;
|
219
|
-
# if (longitude < -180 || longitude > 180)
|
220
|
-
# throw new Error(`Invalid longitude "${longitude}": precondition -180 <= LONGITUDE <= 180 failed.`);
|
221
|
-
# if (latitude < -90 || latitude > 90)
|
222
|
-
# throw new Error(`Invalid latitude "${latitude}": precondition -90 <= LATITUDE <= 90 failed.`);
|
223
|
-
# if (accuracy < 0)
|
224
|
-
# throw new Error(`Invalid accuracy "${accuracy}": precondition 0 <= ACCURACY failed.`);
|
225
|
-
# await this._client.send('Emulation.setGeolocationOverride', {longitude, latitude, accuracy});
|
226
|
-
# }
|
196
|
+
# @param [Puppeteer::Geolocation]
|
197
|
+
def geolocation=(geolocation)
|
198
|
+
@client.send_message('Emulation.setGeolocationOverride', geolocation.to_h)
|
199
|
+
end
|
227
200
|
|
228
201
|
attr_reader :javascript_enabled, :target
|
229
202
|
|
@@ -238,7 +211,7 @@ class Puppeteer::Page
|
|
238
211
|
class TargetCrashedError < StandardError; end
|
239
212
|
|
240
213
|
private def handle_target_crashed
|
241
|
-
emit_event
|
214
|
+
emit_event(PageEmittedEvents::Error, TargetCrashedError.new('Page crashed!'))
|
242
215
|
end
|
243
216
|
|
244
217
|
private def handle_log_entry_added(event)
|
@@ -259,7 +232,7 @@ class Puppeteer::Page
|
|
259
232
|
url: url,
|
260
233
|
line_number: line_number,
|
261
234
|
)
|
262
|
-
emit_event(
|
235
|
+
emit_event(PageEmittedEvents::Console,
|
263
236
|
Puppeteer::ConsoleMessage.new(level, text, [], console_message_location))
|
264
237
|
end
|
265
238
|
end
|
@@ -367,47 +340,34 @@ class Puppeteer::Page
|
|
367
340
|
|
368
341
|
define_async_method :async_Sx
|
369
342
|
|
370
|
-
#
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
# async cookies(...urls) {
|
375
|
-
# return (await this._client.send('Network.getCookies', {
|
376
|
-
# urls: urls.length ? urls : [this.url()]
|
377
|
-
# })).cookies;
|
378
|
-
# }
|
343
|
+
# @return [Array<Hash>]
|
344
|
+
def cookies(*urls)
|
345
|
+
@client.send_message('Network.getCookies', urls: (urls.empty? ? [url] : urls))['cookies']
|
346
|
+
end
|
379
347
|
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
# item.url = pageURL;
|
389
|
-
# await this._client.send('Network.deleteCookies', item);
|
390
|
-
# }
|
391
|
-
# }
|
348
|
+
def delete_cookie(*cookies)
|
349
|
+
page_url = url
|
350
|
+
starts_with_http = page_url.start_with?("http")
|
351
|
+
cookies.each do |cookie|
|
352
|
+
item = (starts_with_http ? { url: page_url } : {}).merge(cookie)
|
353
|
+
@client.send_message("Network.deleteCookies", item)
|
354
|
+
end
|
355
|
+
end
|
392
356
|
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
# await this.deleteCookie(...items);
|
408
|
-
# if (items.length)
|
409
|
-
# await this._client.send('Network.setCookies', { cookies: items });
|
410
|
-
# }
|
357
|
+
def set_cookie(*cookies)
|
358
|
+
page_url = url
|
359
|
+
starts_with_http = page_url.start_with?("http")
|
360
|
+
items = cookies.map do |cookie|
|
361
|
+
(starts_with_http ? { url: page_url } : {}).merge(cookie).tap do |item|
|
362
|
+
raise ArgumentError.new("Blank page can not have cookie \"#{item[:name]}\"") if item[:url] == "about:blank"
|
363
|
+
raise ArgumetnError.new("Data URL page can not have cookie \"#{item[:name]}\"") if item[:url]&.start_with?("data:")
|
364
|
+
end
|
365
|
+
end
|
366
|
+
delete_cookie(*items)
|
367
|
+
unless items.empty?
|
368
|
+
@client.send_message("Network.setCookies", cookies: items)
|
369
|
+
end
|
370
|
+
end
|
411
371
|
|
412
372
|
class ScriptTag
|
413
373
|
# @param {!{content?: string, path?: string, type?: string, url?: string}} options
|
@@ -502,7 +462,7 @@ class Puppeteer::Page
|
|
502
462
|
# * @param {!Protocol.Performance.metricsPayload} event
|
503
463
|
# */
|
504
464
|
# _emitMetrics(event) {
|
505
|
-
# this.emit(
|
465
|
+
# this.emit(PageEmittedEvents::Metrics, {
|
506
466
|
# title: event.title,
|
507
467
|
# metrics: this._buildMetricsObject(event.metrics)
|
508
468
|
# });
|
@@ -521,15 +481,14 @@ class Puppeteer::Page
|
|
521
481
|
# return result;
|
522
482
|
# }
|
523
483
|
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
# }
|
484
|
+
class PageError < StandardError ; end
|
485
|
+
|
486
|
+
private def handle_exception(exception_details)
|
487
|
+
message = Puppeteer::ExceptionDetails.new(exception_details).message
|
488
|
+
err = PageError.new(message)
|
489
|
+
# err.stack = ''; // Don't report clientside error with a node stack attached
|
490
|
+
emit_event(PageEmittedEvents::PageError, err)
|
491
|
+
end
|
533
492
|
|
534
493
|
# /**
|
535
494
|
# * @param {!Protocol.Runtime.consoleAPICalledPayload} event
|
@@ -613,7 +572,7 @@ class Puppeteer::Page
|
|
613
572
|
# * @param {Protocol.Runtime.StackTrace=} stackTrace
|
614
573
|
# */
|
615
574
|
# _addConsoleMessage(type, args, stackTrace) {
|
616
|
-
# if (!this.listenerCount(
|
575
|
+
# if (!this.listenerCount(PageEmittedEvents::Console)) {
|
617
576
|
# args.forEach(arg => arg.dispose());
|
618
577
|
# return;
|
619
578
|
# }
|
@@ -631,7 +590,7 @@ class Puppeteer::Page
|
|
631
590
|
# columnNumber: stackTrace.callFrames[0].columnNumber,
|
632
591
|
# } : {};
|
633
592
|
# const message = new ConsoleMessage(type, textTokens.join(' '), args, location);
|
634
|
-
# this.emit(
|
593
|
+
# this.emit(PageEmittedEvents::Console, message);
|
635
594
|
# }
|
636
595
|
|
637
596
|
private def handle_dialog_opening(event)
|
@@ -643,7 +602,7 @@ class Puppeteer::Page
|
|
643
602
|
type: dialog_type,
|
644
603
|
message: event['message'],
|
645
604
|
default_value: event['defaultPrompt'])
|
646
|
-
emit_event(
|
605
|
+
emit_event(PageEmittedEvents::Dialog, dialog)
|
647
606
|
end
|
648
607
|
|
649
608
|
# @return [String]
|
@@ -726,7 +685,7 @@ class Puppeteer::Page
|
|
726
685
|
|
727
686
|
private def session_close_promise
|
728
687
|
@disconnect_promise ||= resolvable_future do |future|
|
729
|
-
@client.observe_first(
|
688
|
+
@client.observe_first(CDPSessionEmittedEvents::Disconnected) do
|
730
689
|
future.reject(Puppeteer::CDPSession::Error.new('Target Closed'))
|
731
690
|
end
|
732
691
|
end
|
@@ -746,7 +705,7 @@ class Puppeteer::Page
|
|
746
705
|
-> (request) { predicate.call(request) }
|
747
706
|
end
|
748
707
|
|
749
|
-
wait_for_network_manager_event(
|
708
|
+
wait_for_network_manager_event(NetworkManagerEmittedEvents::Request,
|
750
709
|
predicate: request_predicate,
|
751
710
|
timeout: timeout,
|
752
711
|
)
|
@@ -780,7 +739,7 @@ class Puppeteer::Page
|
|
780
739
|
-> (response) { predicate.call(response) }
|
781
740
|
end
|
782
741
|
|
783
|
-
wait_for_network_manager_event(
|
742
|
+
wait_for_network_manager_event(NetworkManagerEmittedEvents::Response,
|
784
743
|
predicate: response_predicate,
|
785
744
|
timeout: timeout,
|
786
745
|
)
|
@@ -870,6 +829,21 @@ class Puppeteer::Page
|
|
870
829
|
end
|
871
830
|
end
|
872
831
|
|
832
|
+
# @param is_user_active [Boolean]
|
833
|
+
# @param is_screen_unlocked [Boolean]
|
834
|
+
def emulate_idle_state(is_user_active: nil, is_screen_unlocked: nil)
|
835
|
+
overrides = {
|
836
|
+
isUserActive: is_user_active,
|
837
|
+
isScreenUnlocked: is_screen_unlocked,
|
838
|
+
}.compact
|
839
|
+
|
840
|
+
if overrides.empty?
|
841
|
+
@client.send_message('Emulation.clearIdleOverride')
|
842
|
+
else
|
843
|
+
@client.send_message('Emulation.setIdleOverride', overrides)
|
844
|
+
end
|
845
|
+
end
|
846
|
+
|
873
847
|
# @param viewport [Viewport]
|
874
848
|
def viewport=(viewport)
|
875
849
|
needs_reload = @emulation_manager.emulate_viewport(viewport)
|
@@ -907,15 +881,28 @@ class Puppeteer::Page
|
|
907
881
|
main_frame.title
|
908
882
|
end
|
909
883
|
|
910
|
-
#
|
911
|
-
#
|
912
|
-
#
|
913
|
-
#
|
914
|
-
|
884
|
+
# @param type [String] "png"|"jpeg"
|
885
|
+
# @param path [String]
|
886
|
+
# @param full_page [Boolean]
|
887
|
+
# @param clip [Hash]
|
888
|
+
# @param quality [Integer]
|
889
|
+
# @param omit_background [Boolean]
|
890
|
+
# @param encoding [String]
|
891
|
+
def screenshot(type: nil, path: nil, full_page: nil, clip: nil, quality: nil, omit_background: nil, encoding: nil)
|
892
|
+
options = {
|
893
|
+
type: type,
|
894
|
+
path: path,
|
895
|
+
full_page: full_page,
|
896
|
+
clip: clip,
|
897
|
+
quality: quality,
|
898
|
+
omit_background: omit_background,
|
899
|
+
encoding: encoding,
|
900
|
+
}.compact
|
915
901
|
screenshot_options = ScreenshotOptions.new(options)
|
916
902
|
|
917
|
-
|
918
|
-
|
903
|
+
@screenshot_task_queue.post_task do
|
904
|
+
screenshot_task(screenshot_options.type, screenshot_options)
|
905
|
+
end
|
919
906
|
end
|
920
907
|
|
921
908
|
# @param {"png"|"jpeg"} format
|
@@ -1043,6 +1030,12 @@ class Puppeteer::Page
|
|
1043
1030
|
else
|
1044
1031
|
@client.connection.send_message('Target.closeTarget', targetId: @target.target_id)
|
1045
1032
|
await @target.is_closed_promise
|
1033
|
+
|
1034
|
+
# @closed sometimes remains false, so wait for @closed = true with 100ms timeout.
|
1035
|
+
25.times do
|
1036
|
+
break if @closed
|
1037
|
+
sleep 0.004
|
1038
|
+
end
|
1046
1039
|
end
|
1047
1040
|
end
|
1048
1041
|
|