puppeteer-ruby 0.0.19 → 0.0.25
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/.rubocop.yml +37 -0
- data/README.md +38 -0
- data/lib/puppeteer.rb +10 -2
- data/lib/puppeteer/browser.rb +19 -26
- data/lib/puppeteer/browser_context.rb +48 -49
- data/lib/puppeteer/browser_runner.rb +19 -5
- data/lib/puppeteer/cdp_session.rb +21 -7
- data/lib/puppeteer/concurrent_ruby_utils.rb +18 -5
- data/lib/puppeteer/connection.rb +32 -13
- data/lib/puppeteer/devices.rb +998 -849
- data/lib/puppeteer/dialog.rb +34 -0
- 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.rb +1 -3
- data/lib/puppeteer/frame_manager.rb +20 -16
- data/lib/puppeteer/geolocation.rb +24 -0
- data/lib/puppeteer/keyboard/us_keyboard_layout.rb +2 -2
- data/lib/puppeteer/launcher.rb +0 -1
- data/lib/puppeteer/launcher/browser_options.rb +2 -1
- data/lib/puppeteer/launcher/chrome.rb +4 -8
- data/lib/puppeteer/launcher/firefox.rb +8 -15
- data/lib/puppeteer/lifecycle_watcher.rb +6 -6
- data/lib/puppeteer/network_manager.rb +6 -6
- data/lib/puppeteer/page.rb +106 -141
- data/lib/puppeteer/target.rb +2 -2
- data/lib/puppeteer/version.rb +1 -1
- metadata +6 -2
data/lib/puppeteer/launcher.rb
CHANGED
@@ -28,7 +28,8 @@ module Puppeteer::Launcher
|
|
28
28
|
# @property {number=} slowMo
|
29
29
|
def initialize(options)
|
30
30
|
@ignore_https_errors = options[:ignore_https_errors] || false
|
31
|
-
|
31
|
+
# `default_viewport: nil` must be respected here.
|
32
|
+
@default_viewport = options.key?(:default_viewport) ? options[:default_viewport] : Puppeteer::Viewport.new(width: 800, height: 600)
|
32
33
|
@slow_mo = options[:slow_mo] || 0
|
33
34
|
end
|
34
35
|
|
@@ -12,9 +12,9 @@ module Puppeteer::Launcher
|
|
12
12
|
|
13
13
|
chrome_arguments =
|
14
14
|
if !@launch_options.ignore_default_args
|
15
|
-
default_args.to_a
|
15
|
+
default_args(options).to_a
|
16
16
|
elsif @launch_options.ignore_default_args.is_a?(Enumerable)
|
17
|
-
default_args.reject do |arg|
|
17
|
+
default_args(options).reject do |arg|
|
18
18
|
@launch_options.ignore_default_args.include?(arg)
|
19
19
|
end.to_a
|
20
20
|
else
|
@@ -141,11 +141,7 @@ module Puppeteer::Launcher
|
|
141
141
|
|
142
142
|
# @return [DefaultArgs]
|
143
143
|
def default_args(options = nil)
|
144
|
-
|
145
|
-
@default_args ||= DefaultArgs.new(@chrome_arg_options)
|
146
|
-
else
|
147
|
-
DefaultArgs.new(ChromeArgOptions.new(options))
|
148
|
-
end
|
144
|
+
DefaultArgs.new(ChromeArgOptions.new(options || {}))
|
149
145
|
end
|
150
146
|
|
151
147
|
# @return [Puppeteer::Browser]
|
@@ -206,7 +202,7 @@ module Puppeteer::Launcher
|
|
206
202
|
resolve_executable_path
|
207
203
|
end
|
208
204
|
|
209
|
-
|
205
|
+
def product
|
210
206
|
'chrome'
|
211
207
|
end
|
212
208
|
end
|
@@ -12,9 +12,9 @@ module Puppeteer::Launcher
|
|
12
12
|
|
13
13
|
firefox_arguments =
|
14
14
|
if !@launch_options.ignore_default_args
|
15
|
-
default_args.to_a
|
15
|
+
default_args(options).to_a
|
16
16
|
elsif @launch_options.ignore_default_args.is_a?(Enumerable)
|
17
|
-
default_args.reject do |arg|
|
17
|
+
default_args(options).reject do |arg|
|
18
18
|
@launch_options.ignore_default_args.include?(arg)
|
19
19
|
end.to_a
|
20
20
|
else
|
@@ -127,7 +127,7 @@ module Puppeteer::Launcher
|
|
127
127
|
resolve_executable_path
|
128
128
|
end
|
129
129
|
|
130
|
-
|
130
|
+
def product
|
131
131
|
'firefox'
|
132
132
|
end
|
133
133
|
|
@@ -173,11 +173,7 @@ module Puppeteer::Launcher
|
|
173
173
|
|
174
174
|
# @return [DefaultArgs]
|
175
175
|
def default_args(options = nil)
|
176
|
-
|
177
|
-
@default_args ||= DefaultArgs.new(@chrome_arg_options)
|
178
|
-
else
|
179
|
-
DefaultArgs.new(ChromeArgOptions.new(options))
|
180
|
-
end
|
176
|
+
DefaultArgs.new(ChromeArgOptions.new(options || {}))
|
181
177
|
end
|
182
178
|
|
183
179
|
private def create_profile(extra_prefs = {})
|
@@ -203,7 +199,7 @@ module Puppeteer::Launcher
|
|
203
199
|
# https://bugzilla.mozilla.org/show_bug.cgi?id=1543115
|
204
200
|
'browser.dom.window.dump.enabled': true,
|
205
201
|
# Disable topstories
|
206
|
-
'browser.newtabpage.activity-stream.feeds.
|
202
|
+
'browser.newtabpage.activity-stream.feeds.system.topstories': false,
|
207
203
|
# Always display a blank page
|
208
204
|
'browser.newtabpage.enabled': false,
|
209
205
|
# Background thumbnails in particular cause grief: and disabling
|
@@ -250,16 +246,15 @@ module Puppeteer::Launcher
|
|
250
246
|
# Do not warn on quitting Firefox
|
251
247
|
'browser.warnOnQuit': false,
|
252
248
|
|
253
|
-
#
|
254
|
-
# interfere with tests
|
255
|
-
'datareporting.healthreport.about.reportUrl': "http://#{server}/dummy/abouthealthreport/",
|
249
|
+
# Defensively disable data reporting systems
|
256
250
|
'datareporting.healthreport.documentServerURI': "http://#{server}/dummy/healthreport/",
|
257
251
|
'datareporting.healthreport.logging.consoleEnabled': false,
|
258
252
|
'datareporting.healthreport.service.enabled': false,
|
259
253
|
'datareporting.healthreport.service.firstRun': false,
|
260
254
|
'datareporting.healthreport.uploadEnabled': false,
|
255
|
+
|
256
|
+
# Do not show datareporting policy notifications which can interfere with tests
|
261
257
|
'datareporting.policy.dataSubmissionEnabled': false,
|
262
|
-
'datareporting.policy.dataSubmissionPolicyAccepted': false,
|
263
258
|
'datareporting.policy.dataSubmissionPolicyBypassNotification': true,
|
264
259
|
|
265
260
|
# DevTools JSONViewer sometimes fails to load dependencies with its require.js.
|
@@ -372,8 +367,6 @@ module Puppeteer::Launcher
|
|
372
367
|
# Disable browser animations (tabs, fullscreen, sliding alerts)
|
373
368
|
'toolkit.cosmeticAnimations.enabled': false,
|
374
369
|
|
375
|
-
# We want to collect telemetry, but we don't want to send in the results
|
376
|
-
'toolkit.telemetry.server': "https://#{server}/dummy/telemetry/",
|
377
370
|
# Prevent starting into safe mode after application crashes
|
378
371
|
'toolkit.startup.max_resumed_crashes': -1,
|
379
372
|
}
|
@@ -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
@@ -46,7 +46,7 @@ class Puppeteer::Page
|
|
46
46
|
@screenshot_task_queue = screenshot_task_queue
|
47
47
|
|
48
48
|
@workers = {}
|
49
|
-
@client.on_event
|
49
|
+
@client.on_event('Target.attachedToTarget') do |event|
|
50
50
|
if event['targetInfo']['type'] != 'worker'
|
51
51
|
# If we don't detach from service workers, they will never die.
|
52
52
|
await @client.send_message('Target.detachFromTarget', sessionId: event['sessionId'])
|
@@ -56,63 +56,69 @@ class Puppeteer::Page
|
|
56
56
|
session = Puppeteer::Connection.from_session(@client).session(event['sessionId']) # rubocop:disable Lint/UselessAssignment
|
57
57
|
# const worker = new Worker(session, event.targetInfo.url, this._addConsoleMessage.bind(this), this._handleException.bind(this));
|
58
58
|
# this._workers.set(event.sessionId, worker);
|
59
|
-
# this.emit(
|
59
|
+
# this.emit(PageEmittedEvents::WorkerCreated, worker);
|
60
60
|
end
|
61
|
-
@client.on_event
|
61
|
+
@client.on_event('Target.detachedFromTarget') do |event|
|
62
62
|
session_id = event['sessionId']
|
63
63
|
worker = @workers[session_id]
|
64
64
|
next unless worker
|
65
65
|
|
66
|
-
emit_event(
|
66
|
+
emit_event(PageEmittedEvents::WorkerDestroyed, worker)
|
67
67
|
@workers.delete(session_id)
|
68
68
|
end
|
69
69
|
|
70
|
-
@frame_manager.on_event
|
71
|
-
emit_event
|
70
|
+
@frame_manager.on_event(FrameManagerEmittedEvents::FrameAttached) do |event|
|
71
|
+
emit_event(PageEmittedEvents::FrameAttached, event)
|
72
72
|
end
|
73
|
-
@frame_manager.on_event
|
74
|
-
emit_event
|
73
|
+
@frame_manager.on_event(FrameManagerEmittedEvents::FrameDetached) do |event|
|
74
|
+
emit_event(PageEmittedEvents::FrameDetached, event)
|
75
75
|
end
|
76
|
-
@frame_manager.on_event
|
77
|
-
emit_event
|
76
|
+
@frame_manager.on_event(FrameManagerEmittedEvents::FrameNavigated) do |event|
|
77
|
+
emit_event(PageEmittedEvents::FrameNavigated, event)
|
78
78
|
end
|
79
79
|
|
80
80
|
network_manager = @frame_manager.network_manager
|
81
|
-
network_manager.on_event
|
82
|
-
emit_event
|
81
|
+
network_manager.on_event(NetworkManagerEmittedEvents::Request) do |event|
|
82
|
+
emit_event(PageEmittedEvents::Request, event)
|
83
83
|
end
|
84
|
-
network_manager.on_event
|
85
|
-
emit_event
|
84
|
+
network_manager.on_event(NetworkManagerEmittedEvents::Response) do |event|
|
85
|
+
emit_event(PageEmittedEvents::Response, event)
|
86
86
|
end
|
87
|
-
network_manager.on_event
|
88
|
-
emit_event
|
87
|
+
network_manager.on_event(NetworkManagerEmittedEvents::RequestFailed) do |event|
|
88
|
+
emit_event(PageEmittedEvents::RequestFailed, event)
|
89
89
|
end
|
90
|
-
network_manager.on_event
|
91
|
-
emit_event
|
90
|
+
network_manager.on_event(NetworkManagerEmittedEvents::RequestFinished) do |event|
|
91
|
+
emit_event(PageEmittedEvents::RequestFinished, event)
|
92
92
|
end
|
93
93
|
@file_chooser_interception_is_disabled = false
|
94
94
|
@file_chooser_interceptors = Set.new
|
95
95
|
|
96
|
-
@client.on_event
|
97
|
-
emit_event
|
96
|
+
@client.on_event('Page.domContentEventFired') do |event|
|
97
|
+
emit_event(PageEmittedEvents::DOMContentLoaded)
|
98
98
|
end
|
99
|
-
@client.on_event
|
100
|
-
emit_event
|
99
|
+
@client.on_event('Page.loadEventFired') do |event|
|
100
|
+
emit_event(PageEmittedEvents::Load)
|
101
101
|
end
|
102
102
|
# client.on('Runtime.consoleAPICalled', event => this._onConsoleAPI(event));
|
103
103
|
# client.on('Runtime.bindingCalled', event => this._onBindingCalled(event));
|
104
|
-
|
105
|
-
|
106
|
-
|
104
|
+
@client.on_event('Page.javascriptDialogOpening') do |event|
|
105
|
+
handle_dialog_opening(event)
|
106
|
+
end
|
107
|
+
@client.on_event('Runtime.exceptionThrown') do |exception|
|
108
|
+
handle_exception(exception['exceptionDetails'])
|
109
|
+
end
|
110
|
+
@client.on_event('Inspector.targetCrashed') do |event|
|
111
|
+
handle_target_crashed
|
112
|
+
end
|
107
113
|
# client.on('Performance.metrics', event => this._emitMetrics(event));
|
108
|
-
@client.on_event
|
114
|
+
@client.on_event('Log.entryAdded') do |event|
|
109
115
|
handle_log_entry_added(event)
|
110
116
|
end
|
111
|
-
@client.on_event
|
117
|
+
@client.on_event('Page.fileChooserOpened') do |event|
|
112
118
|
handle_file_chooser(event)
|
113
119
|
end
|
114
120
|
@target.is_closed_promise.then do
|
115
|
-
emit_event
|
121
|
+
emit_event(PageEmittedEvents::Close)
|
116
122
|
@closed = true
|
117
123
|
end
|
118
124
|
end
|
@@ -126,43 +132,22 @@ class Puppeteer::Page
|
|
126
132
|
)
|
127
133
|
end
|
128
134
|
|
129
|
-
EVENT_MAPPINGS = {
|
130
|
-
close: 'Events.Page.Close',
|
131
|
-
# console: 'Events.Page.Console',
|
132
|
-
# dialog: 'Events.Page.Dialog',
|
133
|
-
domcontentloaded: 'Events.Page.DOMContentLoaded',
|
134
|
-
# error:
|
135
|
-
frameattached: 'Events.Page.FrameAttached',
|
136
|
-
framedetached: 'Events.Page.FrameDetached',
|
137
|
-
framenavigated: 'Events.Page.FrameNavigated',
|
138
|
-
load: 'Events.Page.Load',
|
139
|
-
# metrics: 'Events.Page.Metrics',
|
140
|
-
# pageerror: 'Events.Page.PageError',
|
141
|
-
popup: 'Events.Page.Popup',
|
142
|
-
request: 'Events.Page.Request',
|
143
|
-
requestfailed: 'Events.Page.RequestFailed',
|
144
|
-
requestfinished: 'Events.Page.RequestFinished',
|
145
|
-
response: 'Events.Page.Response',
|
146
|
-
# workercreated: 'Events.Page.WorkerCreated',
|
147
|
-
# workerdestroyed: 'Events.Page.WorkerDestroyed',
|
148
|
-
}
|
149
|
-
|
150
135
|
# @param event_name [Symbol]
|
151
136
|
def on(event_name, &block)
|
152
|
-
unless
|
153
|
-
raise ArgumentError.new("Unknown event name: #{event_name}. Known events are #{
|
137
|
+
unless PageEmittedEvents.values.include?(event_name.to_s)
|
138
|
+
raise ArgumentError.new("Unknown event name: #{event_name}. Known events are #{PageEmittedEvents.values.to_a.join(", ")}")
|
154
139
|
end
|
155
140
|
|
156
|
-
|
141
|
+
super(event_name.to_s, &block)
|
157
142
|
end
|
158
143
|
|
159
144
|
# @param event_name [Symbol]
|
160
145
|
def once(event_name, &block)
|
161
|
-
unless
|
162
|
-
raise ArgumentError.new("Unknown event name: #{event_name}. Known events are #{
|
146
|
+
unless PageEmittedEvents.values.include?(event_name.to_s)
|
147
|
+
raise ArgumentError.new("Unknown event name: #{event_name}. Known events are #{PageEmittedEvents.values.to_a.join(", ")}")
|
163
148
|
end
|
164
149
|
|
165
|
-
|
150
|
+
super(event_name.to_s, &block)
|
166
151
|
end
|
167
152
|
|
168
153
|
def handle_file_chooser(event)
|
@@ -209,19 +194,10 @@ class Puppeteer::Page
|
|
209
194
|
|
210
195
|
define_async_method :async_wait_for_file_chooser
|
211
196
|
|
212
|
-
#
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
# const { longitude, latitude, accuracy = 0} = options;
|
217
|
-
# if (longitude < -180 || longitude > 180)
|
218
|
-
# throw new Error(`Invalid longitude "${longitude}": precondition -180 <= LONGITUDE <= 180 failed.`);
|
219
|
-
# if (latitude < -90 || latitude > 90)
|
220
|
-
# throw new Error(`Invalid latitude "${latitude}": precondition -90 <= LATITUDE <= 90 failed.`);
|
221
|
-
# if (accuracy < 0)
|
222
|
-
# throw new Error(`Invalid accuracy "${accuracy}": precondition 0 <= ACCURACY failed.`);
|
223
|
-
# await this._client.send('Emulation.setGeolocationOverride', {longitude, latitude, accuracy});
|
224
|
-
# }
|
197
|
+
# @param [Puppeteer::Geolocation]
|
198
|
+
def geolocation=(geolocation)
|
199
|
+
@client.send_message('Emulation.setGeolocationOverride', geolocation.to_h)
|
200
|
+
end
|
225
201
|
|
226
202
|
attr_reader :javascript_enabled, :target
|
227
203
|
|
@@ -236,7 +212,7 @@ class Puppeteer::Page
|
|
236
212
|
class TargetCrashedError < StandardError; end
|
237
213
|
|
238
214
|
private def handle_target_crashed
|
239
|
-
emit_event
|
215
|
+
emit_event(PageEmittedEvents::Error, TargetCrashedError.new('Page crashed!'))
|
240
216
|
end
|
241
217
|
|
242
218
|
private def handle_log_entry_added(event)
|
@@ -257,7 +233,7 @@ class Puppeteer::Page
|
|
257
233
|
url: url,
|
258
234
|
line_number: line_number,
|
259
235
|
)
|
260
|
-
emit_event(
|
236
|
+
emit_event(PageEmittedEvents::Console,
|
261
237
|
Puppeteer::ConsoleMessage.new(level, text, [], console_message_location))
|
262
238
|
end
|
263
239
|
end
|
@@ -365,47 +341,34 @@ class Puppeteer::Page
|
|
365
341
|
|
366
342
|
define_async_method :async_Sx
|
367
343
|
|
368
|
-
#
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
# async cookies(...urls) {
|
373
|
-
# return (await this._client.send('Network.getCookies', {
|
374
|
-
# urls: urls.length ? urls : [this.url()]
|
375
|
-
# })).cookies;
|
376
|
-
# }
|
344
|
+
# @return [Array<Hash>]
|
345
|
+
def cookies(*urls)
|
346
|
+
@client.send_message('Network.getCookies', urls: (urls.empty? ? [url] : urls))['cookies']
|
347
|
+
end
|
377
348
|
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
# item.url = pageURL;
|
387
|
-
# await this._client.send('Network.deleteCookies', item);
|
388
|
-
# }
|
389
|
-
# }
|
349
|
+
def delete_cookie(*cookies)
|
350
|
+
page_url = url
|
351
|
+
starts_with_http = page_url.start_with?("http")
|
352
|
+
cookies.each do |cookie|
|
353
|
+
item = (starts_with_http ? { url: page_url } : {}).merge(cookie)
|
354
|
+
@client.send_message("Network.deleteCookies", item)
|
355
|
+
end
|
356
|
+
end
|
390
357
|
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
# await this.deleteCookie(...items);
|
406
|
-
# if (items.length)
|
407
|
-
# await this._client.send('Network.setCookies', { cookies: items });
|
408
|
-
# }
|
358
|
+
def set_cookie(*cookies)
|
359
|
+
page_url = url
|
360
|
+
starts_with_http = page_url.start_with?("http")
|
361
|
+
items = cookies.map do |cookie|
|
362
|
+
(starts_with_http ? { url: page_url } : {}).merge(cookie).tap do |item|
|
363
|
+
raise ArgumentError.new("Blank page can not have cookie \"#{item[:name]}\"") if item[:url] == "about:blank"
|
364
|
+
raise ArgumetnError.new("Data URL page can not have cookie \"#{item[:name]}\"") if item[:url]&.start_with?("data:")
|
365
|
+
end
|
366
|
+
end
|
367
|
+
delete_cookie(*items)
|
368
|
+
unless items.empty?
|
369
|
+
@client.send_message("Network.setCookies", cookies: items)
|
370
|
+
end
|
371
|
+
end
|
409
372
|
|
410
373
|
class ScriptTag
|
411
374
|
# @param {!{content?: string, path?: string, type?: string, url?: string}} options
|
@@ -500,7 +463,7 @@ class Puppeteer::Page
|
|
500
463
|
# * @param {!Protocol.Performance.metricsPayload} event
|
501
464
|
# */
|
502
465
|
# _emitMetrics(event) {
|
503
|
-
# this.emit(
|
466
|
+
# this.emit(PageEmittedEvents::Metrics, {
|
504
467
|
# title: event.title,
|
505
468
|
# metrics: this._buildMetricsObject(event.metrics)
|
506
469
|
# });
|
@@ -519,15 +482,14 @@ class Puppeteer::Page
|
|
519
482
|
# return result;
|
520
483
|
# }
|
521
484
|
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
# }
|
485
|
+
class PageError < StandardError ; end
|
486
|
+
|
487
|
+
private def handle_exception(exception_details)
|
488
|
+
message = Puppeteer::ExceptionDetails.new(exception_details).message
|
489
|
+
err = PageError.new(message)
|
490
|
+
# err.stack = ''; // Don't report clientside error with a node stack attached
|
491
|
+
emit_event(PageEmittedEvents::PageError, err)
|
492
|
+
end
|
531
493
|
|
532
494
|
# /**
|
533
495
|
# * @param {!Protocol.Runtime.consoleAPICalledPayload} event
|
@@ -611,7 +573,7 @@ class Puppeteer::Page
|
|
611
573
|
# * @param {Protocol.Runtime.StackTrace=} stackTrace
|
612
574
|
# */
|
613
575
|
# _addConsoleMessage(type, args, stackTrace) {
|
614
|
-
# if (!this.listenerCount(
|
576
|
+
# if (!this.listenerCount(PageEmittedEvents::Console)) {
|
615
577
|
# args.forEach(arg => arg.dispose());
|
616
578
|
# return;
|
617
579
|
# }
|
@@ -629,23 +591,20 @@ class Puppeteer::Page
|
|
629
591
|
# columnNumber: stackTrace.callFrames[0].columnNumber,
|
630
592
|
# } : {};
|
631
593
|
# const message = new ConsoleMessage(type, textTokens.join(' '), args, location);
|
632
|
-
# this.emit(
|
594
|
+
# this.emit(PageEmittedEvents::Console, message);
|
633
595
|
# }
|
634
596
|
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
# const dialog = new Dialog(this._client, dialogType, event.message, event.defaultPrompt);
|
647
|
-
# this.emit(Events.Page.Dialog, dialog);
|
648
|
-
# }
|
597
|
+
private def handle_dialog_opening(event)
|
598
|
+
dialog_type = event['type']
|
599
|
+
unless %w(alert confirm prompt beforeunload).include?(dialog_type)
|
600
|
+
raise ArgumentError.new("Unknown javascript dialog type: #{dialog_type}")
|
601
|
+
end
|
602
|
+
dialog = Puppeteer::Dialog.new(@client,
|
603
|
+
type: dialog_type,
|
604
|
+
message: event['message'],
|
605
|
+
default_value: event['defaultPrompt'])
|
606
|
+
emit_event(PageEmittedEvents::Dialog, dialog)
|
607
|
+
end
|
649
608
|
|
650
609
|
# @return [String]
|
651
610
|
def url
|
@@ -727,7 +686,7 @@ class Puppeteer::Page
|
|
727
686
|
|
728
687
|
private def session_close_promise
|
729
688
|
@disconnect_promise ||= resolvable_future do |future|
|
730
|
-
@client.observe_first(
|
689
|
+
@client.observe_first(CDPSessionEmittedEvents::Disconnected) do
|
731
690
|
future.reject(Puppeteer::CDPSession::Error.new('Target Closed'))
|
732
691
|
end
|
733
692
|
end
|
@@ -747,7 +706,7 @@ class Puppeteer::Page
|
|
747
706
|
-> (request) { predicate.call(request) }
|
748
707
|
end
|
749
708
|
|
750
|
-
wait_for_network_manager_event(
|
709
|
+
wait_for_network_manager_event(NetworkManagerEmittedEvents::Request,
|
751
710
|
predicate: request_predicate,
|
752
711
|
timeout: timeout,
|
753
712
|
)
|
@@ -781,7 +740,7 @@ class Puppeteer::Page
|
|
781
740
|
-> (response) { predicate.call(response) }
|
782
741
|
end
|
783
742
|
|
784
|
-
wait_for_network_manager_event(
|
743
|
+
wait_for_network_manager_event(NetworkManagerEmittedEvents::Response,
|
785
744
|
predicate: response_predicate,
|
786
745
|
timeout: timeout,
|
787
746
|
)
|
@@ -940,16 +899,16 @@ class Puppeteer::Page
|
|
940
899
|
clip = { x: 0, y: 0, width: width, height: height, scale: 1 }
|
941
900
|
|
942
901
|
screen_orientation =
|
943
|
-
if @viewport
|
902
|
+
if @viewport&.landscape?
|
944
903
|
{ angle: 90, type: 'landscapePrimary' }
|
945
904
|
else
|
946
905
|
{ angle: 0, type: 'portraitPrimary' }
|
947
906
|
end
|
948
907
|
@client.send_message('Emulation.setDeviceMetricsOverride',
|
949
|
-
mobile: @viewport
|
908
|
+
mobile: @viewport&.mobile? || false,
|
950
909
|
width: width,
|
951
910
|
height: height,
|
952
|
-
deviceScaleFactor: @viewport
|
911
|
+
deviceScaleFactor: @viewport&.device_scale_factor || 1,
|
953
912
|
screenOrientation: screen_orientation)
|
954
913
|
end
|
955
914
|
|
@@ -1044,6 +1003,12 @@ class Puppeteer::Page
|
|
1044
1003
|
else
|
1045
1004
|
@client.connection.send_message('Target.closeTarget', targetId: @target.target_id)
|
1046
1005
|
await @target.is_closed_promise
|
1006
|
+
|
1007
|
+
# @closed sometimes remains false, so wait for @closed = true with 100ms timeout.
|
1008
|
+
25.times do
|
1009
|
+
break if @closed
|
1010
|
+
sleep 0.004
|
1011
|
+
end
|
1047
1012
|
end
|
1048
1013
|
end
|
1049
1014
|
|