puppeteer-ruby 0.0.10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.circleci/config.yml +71 -0
- data/.github/stale.yml +16 -0
- data/.gitignore +19 -0
- data/.rspec +3 -0
- data/.rubocop.yml +302 -0
- data/.travis.yml +7 -0
- data/Dockerfile +6 -0
- data/Gemfile +6 -0
- data/README.md +54 -0
- data/Rakefile +1 -0
- data/bin/console +11 -0
- data/bin/setup +8 -0
- data/docker-compose.yml +15 -0
- data/docs/Puppeteer.html +2020 -0
- data/docs/Puppeteer/AsyncAwaitBehavior.html +105 -0
- data/docs/Puppeteer/Browser.html +2148 -0
- data/docs/Puppeteer/BrowserContext.html +809 -0
- data/docs/Puppeteer/BrowserFetcher.html +214 -0
- data/docs/Puppeteer/BrowserRunner.html +914 -0
- data/docs/Puppeteer/BrowserRunner/BrowserProcess.html +477 -0
- data/docs/Puppeteer/CDPSession.html +813 -0
- data/docs/Puppeteer/CDPSession/Error.html +124 -0
- data/docs/Puppeteer/ConcurrentRubyUtils.html +430 -0
- data/docs/Puppeteer/Connection.html +960 -0
- data/docs/Puppeteer/Connection/MessageCallback.html +434 -0
- data/docs/Puppeteer/Connection/ProtocolError.html +216 -0
- data/docs/Puppeteer/Connection/RequestDebugPrinter.html +217 -0
- data/docs/Puppeteer/Connection/ResponseDebugPrinter.html +244 -0
- data/docs/Puppeteer/ConsoleMessage.html +565 -0
- data/docs/Puppeteer/ConsoleMessage/Location.html +433 -0
- data/docs/Puppeteer/DOMWorld.html +2219 -0
- data/docs/Puppeteer/DOMWorld/DetachedError.html +124 -0
- data/docs/Puppeteer/DOMWorld/DocumentEvaluationError.html +124 -0
- data/docs/Puppeteer/DebugPrint.html +233 -0
- data/docs/Puppeteer/Device.html +470 -0
- data/docs/Puppeteer/Devices.html +139 -0
- data/docs/Puppeteer/ElementHandle.html +2542 -0
- data/docs/Puppeteer/ElementHandle/ElementNotFoundError.html +206 -0
- data/docs/Puppeteer/ElementHandle/ElementNotVisibleError.html +206 -0
- data/docs/Puppeteer/ElementHandle/Point.html +492 -0
- data/docs/Puppeteer/ElementHandle/ScrollIntoViewError.html +124 -0
- data/docs/Puppeteer/EmulationManager.html +454 -0
- data/docs/Puppeteer/EventCallbackable.html +433 -0
- data/docs/Puppeteer/EventCallbackable/EventListeners.html +435 -0
- data/docs/Puppeteer/ExecutionContext.html +998 -0
- data/docs/Puppeteer/ExecutionContext/EvaluationError.html +124 -0
- data/docs/Puppeteer/ExecutionContext/JavaScriptExpression.html +357 -0
- data/docs/Puppeteer/ExecutionContext/JavaScriptFunction.html +389 -0
- data/docs/Puppeteer/FileChooser.html +455 -0
- data/docs/Puppeteer/Frame.html +3677 -0
- data/docs/Puppeteer/FrameManager.html +2410 -0
- data/docs/Puppeteer/FrameManager/NavigationError.html +124 -0
- data/docs/Puppeteer/IfPresent.html +222 -0
- data/docs/Puppeteer/JSHandle.html +1352 -0
- data/docs/Puppeteer/Keyboard.html +1557 -0
- data/docs/Puppeteer/Keyboard/KeyDefinition.html +831 -0
- data/docs/Puppeteer/Keyboard/KeyDescription.html +603 -0
- data/docs/Puppeteer/Launcher.html +237 -0
- data/docs/Puppeteer/Launcher/Base.html +385 -0
- data/docs/Puppeteer/Launcher/Base/ExecutablePathNotFound.html +124 -0
- data/docs/Puppeteer/Launcher/BrowserOptions.html +441 -0
- data/docs/Puppeteer/Launcher/Chrome.html +669 -0
- data/docs/Puppeteer/Launcher/Chrome/DefaultArgs.html +382 -0
- data/docs/Puppeteer/Launcher/ChromeArgOptions.html +531 -0
- data/docs/Puppeteer/Launcher/LaunchOptions.html +893 -0
- data/docs/Puppeteer/LifecycleWatcher.html +834 -0
- data/docs/Puppeteer/LifecycleWatcher/ExpectedLifecycle.html +363 -0
- data/docs/Puppeteer/LifecycleWatcher/FrameDetachedError.html +206 -0
- data/docs/Puppeteer/LifecycleWatcher/TerminatedError.html +124 -0
- data/docs/Puppeteer/Mouse.html +1105 -0
- data/docs/Puppeteer/Mouse/Button.html +136 -0
- data/docs/Puppeteer/NetworkManager.html +901 -0
- data/docs/Puppeteer/NetworkManager/Credentials.html +385 -0
- data/docs/Puppeteer/Page.html +5970 -0
- data/docs/Puppeteer/Page/FileChooserTimeoutError.html +206 -0
- data/docs/Puppeteer/Page/ScreenshotOptions.html +845 -0
- data/docs/Puppeteer/Page/ScriptTag.html +555 -0
- data/docs/Puppeteer/Page/StyleTag.html +448 -0
- data/docs/Puppeteer/Page/TargetCrashedError.html +124 -0
- data/docs/Puppeteer/RemoteObject.html +1087 -0
- data/docs/Puppeteer/Target.html +1336 -0
- data/docs/Puppeteer/Target/InitializeFailure.html +124 -0
- data/docs/Puppeteer/Target/TargetInfo.html +729 -0
- data/docs/Puppeteer/TimeoutError.html +135 -0
- data/docs/Puppeteer/TimeoutSettings.html +496 -0
- data/docs/Puppeteer/TouchScreen.html +464 -0
- data/docs/Puppeteer/Viewport.html +837 -0
- data/docs/Puppeteer/WaitTask.html +637 -0
- data/docs/Puppeteer/WaitTask/TerminatedError.html +124 -0
- data/docs/Puppeteer/WaitTask/TimeoutError.html +206 -0
- data/docs/Puppeteer/WebSocket.html +673 -0
- data/docs/Puppeteer/WebSocket/DriverImpl.html +412 -0
- data/docs/Puppeteer/WebSocketTransport.html +600 -0
- data/docs/Puppeteer/WebSocktTransportError.html +124 -0
- data/docs/_index.html +823 -0
- data/docs/class_list.html +51 -0
- data/docs/css/common.css +1 -0
- data/docs/css/full_list.css +58 -0
- data/docs/css/style.css +496 -0
- data/docs/file.README.html +123 -0
- data/docs/file_list.html +56 -0
- data/docs/frames.html +17 -0
- data/docs/index.html +123 -0
- data/docs/js/app.js +314 -0
- data/docs/js/full_list.js +216 -0
- data/docs/js/jquery.js +4 -0
- data/docs/method_list.html +4075 -0
- data/docs/top-level-namespace.html +126 -0
- data/lib/puppeteer.rb +200 -0
- data/lib/puppeteer/async_await_behavior.rb +38 -0
- data/lib/puppeteer/browser.rb +259 -0
- data/lib/puppeteer/browser_context.rb +90 -0
- data/lib/puppeteer/browser_fetcher.rb +6 -0
- data/lib/puppeteer/browser_runner.rb +161 -0
- data/lib/puppeteer/cdp_session.rb +100 -0
- data/lib/puppeteer/concurrent_ruby_utils.rb +37 -0
- data/lib/puppeteer/connection.rb +254 -0
- data/lib/puppeteer/console_message.rb +24 -0
- data/lib/puppeteer/debug_print.rb +20 -0
- data/lib/puppeteer/device.rb +12 -0
- data/lib/puppeteer/devices.rb +885 -0
- data/lib/puppeteer/dom_world.rb +484 -0
- data/lib/puppeteer/element_handle.rb +433 -0
- data/lib/puppeteer/element_handle/bounding_box.rb +12 -0
- data/lib/puppeteer/element_handle/box_model.rb +19 -0
- data/lib/puppeteer/element_handle/point.rb +26 -0
- data/lib/puppeteer/emulation_manager.rb +46 -0
- data/lib/puppeteer/errors.rb +2 -0
- data/lib/puppeteer/event_callbackable.rb +88 -0
- data/lib/puppeteer/execution_context.rb +254 -0
- data/lib/puppeteer/file_chooser.rb +29 -0
- data/lib/puppeteer/frame.rb +286 -0
- data/lib/puppeteer/frame_manager.rb +378 -0
- data/lib/puppeteer/if_present.rb +18 -0
- data/lib/puppeteer/js_handle.rb +142 -0
- data/lib/puppeteer/keyboard.rb +183 -0
- data/lib/puppeteer/keyboard/key_description.rb +19 -0
- data/lib/puppeteer/keyboard/us_keyboard_layout.rb +283 -0
- data/lib/puppeteer/launcher.rb +25 -0
- data/lib/puppeteer/launcher/base.rb +48 -0
- data/lib/puppeteer/launcher/browser_options.rb +41 -0
- data/lib/puppeteer/launcher/chrome.rb +211 -0
- data/lib/puppeteer/launcher/chrome_arg_options.rb +49 -0
- data/lib/puppeteer/launcher/launch_options.rb +68 -0
- data/lib/puppeteer/lifecycle_watcher.rb +171 -0
- data/lib/puppeteer/mouse.rb +123 -0
- data/lib/puppeteer/network_manager.rb +122 -0
- data/lib/puppeteer/page.rb +1065 -0
- data/lib/puppeteer/page/screenshot_options.rb +78 -0
- data/lib/puppeteer/remote_object.rb +143 -0
- data/lib/puppeteer/target.rb +150 -0
- data/lib/puppeteer/timeout_settings.rb +15 -0
- data/lib/puppeteer/touch_screen.rb +43 -0
- data/lib/puppeteer/version.rb +3 -0
- data/lib/puppeteer/viewport.rb +54 -0
- data/lib/puppeteer/wait_task.rb +188 -0
- data/lib/puppeteer/web_socket.rb +122 -0
- data/lib/puppeteer/web_socket_transport.rb +49 -0
- data/puppeteer-ruby.gemspec +32 -0
- metadata +355 -0
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'mime/types'
|
2
|
+
|
3
|
+
class Puppeteer::Page
|
4
|
+
# /**
|
5
|
+
# * @typedef {Object} ScreenshotOptions
|
6
|
+
# * @property {string=} type
|
7
|
+
# * @property {string=} path
|
8
|
+
# * @property {boolean=} fullPage
|
9
|
+
# * @property {{x: number, y: number, width: number, height: number}=} clip
|
10
|
+
# * @property {number=} quality
|
11
|
+
# * @property {boolean=} omitBackground
|
12
|
+
# * @property {string=} encoding
|
13
|
+
# */
|
14
|
+
class ScreenshotOptions
|
15
|
+
# @params options [Hash]
|
16
|
+
def initialize(options)
|
17
|
+
if options[:type]
|
18
|
+
unless [:png, :jpeg].include?(options[:type].to_sym)
|
19
|
+
raise ArgumentError.new("Unknown options.type value: #{options[:type]}")
|
20
|
+
end
|
21
|
+
@type = options[:type]
|
22
|
+
elsif options[:path]
|
23
|
+
mime_types = MIME::Types.type_for(options[:path])
|
24
|
+
if mime_types.include?('image/png')
|
25
|
+
@type = 'png'
|
26
|
+
elsif mime_types.include?('image/jpeg')
|
27
|
+
@type = 'jpeg'
|
28
|
+
else
|
29
|
+
raise ArgumentError.new("Unsupported screenshot mime type resolved: #{mime_types}, path: #{options[:path]}")
|
30
|
+
end
|
31
|
+
end
|
32
|
+
@type ||= 'png'
|
33
|
+
|
34
|
+
if options[:quality]
|
35
|
+
unless @type == 'png'
|
36
|
+
raise ArgumentError.new("options.quality is unsupported for the #{@type} screenshots")
|
37
|
+
end
|
38
|
+
unless options[:quality].is_a?(Numeric)
|
39
|
+
raise ArgumentError.new("Expected options.quality to be a number but found #{options[:quality].class}")
|
40
|
+
end
|
41
|
+
quality = options[:quality].to_i
|
42
|
+
unless (0..100).include?(qualizy)
|
43
|
+
raise ArgumentError.new("Expected options.quality to be between 0 and 100 (inclusive), got #{quality}")
|
44
|
+
end
|
45
|
+
@quality = quality
|
46
|
+
end
|
47
|
+
|
48
|
+
if options[:clip] && options[:full_page]
|
49
|
+
raise ArgumentError.new('options.clip and options.fullPage are exclusive')
|
50
|
+
end
|
51
|
+
|
52
|
+
# if (options.clip) {
|
53
|
+
# assert(typeof options.clip.x === 'number', 'Expected options.clip.x to be a number but found ' + (typeof options.clip.x));
|
54
|
+
# assert(typeof options.clip.y === 'number', 'Expected options.clip.y to be a number but found ' + (typeof options.clip.y));
|
55
|
+
# assert(typeof options.clip.width === 'number', 'Expected options.clip.width to be a number but found ' + (typeof options.clip.width));
|
56
|
+
# assert(typeof options.clip.height === 'number', 'Expected options.clip.height to be a number but found ' + (typeof options.clip.height));
|
57
|
+
# assert(options.clip.width !== 0, 'Expected options.clip.width not to be 0.');
|
58
|
+
# assert(options.clip.height !== 0, 'Expected options.clip.height not to be 0.');
|
59
|
+
# }
|
60
|
+
|
61
|
+
@path = options[:path]
|
62
|
+
@full_page = options[:full_page]
|
63
|
+
@clip = options[:clip]
|
64
|
+
@omit_background = options[:omit_background]
|
65
|
+
@encoding = options[:encoding]
|
66
|
+
end
|
67
|
+
|
68
|
+
attr_reader :type, :quality, :path, :clip, :encoding
|
69
|
+
|
70
|
+
def full_page?
|
71
|
+
@full_page
|
72
|
+
end
|
73
|
+
|
74
|
+
def omit_background?
|
75
|
+
@omit_background
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,143 @@
|
|
1
|
+
# providing #valueFromRemoteObject, #releaseObject
|
2
|
+
class Puppeteer::RemoteObject
|
3
|
+
include Puppeteer::DebugPrint
|
4
|
+
using Puppeteer::AsyncAwaitBehavior
|
5
|
+
|
6
|
+
# @param payload [Hash]
|
7
|
+
def initialize(payload)
|
8
|
+
@object_id = payload['objectId']
|
9
|
+
@sub_type = payload['subtype']
|
10
|
+
@unserializable_value = payload['unserializableValue']
|
11
|
+
@value = payload['value']
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_reader :sub_type
|
15
|
+
|
16
|
+
# @return [Future<Puppeteer::RemoteObject|nil>]
|
17
|
+
def evaluate_self(client)
|
18
|
+
# ported logic from JSHandle#json_value.
|
19
|
+
|
20
|
+
# original logic:
|
21
|
+
# if (this._remoteObject.objectId) {
|
22
|
+
# const response = await this._client.send('Runtime.callFunctionOn', {
|
23
|
+
# functionDeclaration: 'function() { return this; }',
|
24
|
+
# objectId: this._remoteObject.objectId,
|
25
|
+
# returnByValue: true,
|
26
|
+
# awaitPromise: true,
|
27
|
+
# });
|
28
|
+
# return helper.valueFromRemoteObject(response.result);
|
29
|
+
# }
|
30
|
+
|
31
|
+
if @object_id
|
32
|
+
params = {
|
33
|
+
'functionDeclaration': 'function() { return this; }',
|
34
|
+
'objectId': @object_id,
|
35
|
+
'returnByValue': true,
|
36
|
+
'awaitPromise': true,
|
37
|
+
}
|
38
|
+
response = client.send_message('Runtime.callFunctionOn', params)
|
39
|
+
Puppeteer::RemoteObject.new(response['result'])
|
40
|
+
else
|
41
|
+
nil
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# used in JSHandle#properties
|
46
|
+
def properties(client)
|
47
|
+
# original logic:
|
48
|
+
# const response = await this._client.send('Runtime.getProperties', {
|
49
|
+
# objectId: this._remoteObject.objectId,
|
50
|
+
# ownProperties: true
|
51
|
+
# });
|
52
|
+
client.send_message('Runtime.getProperties', objectId: @object_id, ownProperties: true)
|
53
|
+
end
|
54
|
+
|
55
|
+
# used in ElementHandle#content_frame, ElementHandle#upload_file
|
56
|
+
def node_info(client)
|
57
|
+
client.send_message('DOM.describeNode', objectId: @object_id)
|
58
|
+
end
|
59
|
+
|
60
|
+
# used in ElementHandle#clickable_point
|
61
|
+
def content_quads(client)
|
62
|
+
client.send_message('DOM.getContentQuads', objectId: @object_id)
|
63
|
+
end
|
64
|
+
|
65
|
+
# used in ElementHandle#_box_model
|
66
|
+
def box_model(client)
|
67
|
+
client.send_message('DOM.getBoxModel', objectId: @object_id)
|
68
|
+
rescue => err
|
69
|
+
debug_puts(err)
|
70
|
+
nil
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
# helper#valueFromRemoteObject
|
75
|
+
def value
|
76
|
+
if @unserializable_value
|
77
|
+
# if (remoteObject.type === 'bigint' && typeof BigInt !== 'undefined')
|
78
|
+
# return BigInt(remoteObject.unserializableValue.replace('n', ''));
|
79
|
+
# switch (remoteObject.unserializableValue) {
|
80
|
+
# case '-0':
|
81
|
+
# return -0;
|
82
|
+
# case 'NaN':
|
83
|
+
# return NaN;
|
84
|
+
# case 'Infinity':
|
85
|
+
# return Infinity;
|
86
|
+
# case '-Infinity':
|
87
|
+
# return -Infinity;
|
88
|
+
# default:
|
89
|
+
# throw new Error('Unsupported unserializable value: ' + remoteObject.unserializableValue);
|
90
|
+
# }
|
91
|
+
raise NotImplementedError.new('unserializable_value is not implemented yet')
|
92
|
+
else
|
93
|
+
@value
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
# @param client [Puppeteer::CDPSession]
|
98
|
+
def release(client)
|
99
|
+
return unless @object_id
|
100
|
+
|
101
|
+
begin
|
102
|
+
client.send_message('Runtime.releaseObject',
|
103
|
+
objectId: @object_id,
|
104
|
+
)
|
105
|
+
rescue => err
|
106
|
+
# Exceptions might happen in case of a page been navigated or closed.
|
107
|
+
# Swallow these since they are harmless and we don't leak anything in this case.
|
108
|
+
debug_puts(err)
|
109
|
+
end
|
110
|
+
|
111
|
+
nil
|
112
|
+
end
|
113
|
+
|
114
|
+
# @param client [Puppeteer::CDPSession]
|
115
|
+
async def async_release(client)
|
116
|
+
release(client)
|
117
|
+
end
|
118
|
+
|
119
|
+
def converted_arg
|
120
|
+
# ported logic from ExecutionContext#convertArgument
|
121
|
+
# https://github.com/puppeteer/puppeteer/blob/master/lib/ExecutionContext.js
|
122
|
+
#
|
123
|
+
# Original logic:
|
124
|
+
# if (objectHandle._remoteObject.unserializableValue)
|
125
|
+
# return { unserializableValue: objectHandle._remoteObject.unserializableValue };
|
126
|
+
# if (!objectHandle._remoteObject.objectId)
|
127
|
+
# return { value: objectHandle._remoteObject.value };
|
128
|
+
# return { objectId: objectHandle._remoteObject.objectId };
|
129
|
+
|
130
|
+
if @unserializable_value
|
131
|
+
{ unserializableValue: @unserializable_value }
|
132
|
+
elsif @object_id
|
133
|
+
{ objectId: @object_id }
|
134
|
+
else
|
135
|
+
{ value: value }
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
# used in ElementHandle#upload_file
|
140
|
+
def set_file_input_files(client, files, backend_node_id)
|
141
|
+
client.send_message('DOM.setFileInputFiles', objectId: @object_id, files: files, backendNodeId: backend_node_id)
|
142
|
+
end
|
143
|
+
end
|
@@ -0,0 +1,150 @@
|
|
1
|
+
# https://github.com/puppeteer/puppeteer/blob/master/lib/Target.js
|
2
|
+
class Puppeteer::Target
|
3
|
+
class TargetInfo
|
4
|
+
def initialize(options)
|
5
|
+
@target_id = options['targetId']
|
6
|
+
@type = options['type']
|
7
|
+
@title = options['title']
|
8
|
+
@url = options['url']
|
9
|
+
@attached = options['attached']
|
10
|
+
@browser_context_id = options['browserContextId']
|
11
|
+
@opener_id = options['openerId']
|
12
|
+
end
|
13
|
+
attr_reader :target_id, :type, :title, :url, :attached, :browser_context_id, :opener_id
|
14
|
+
end
|
15
|
+
|
16
|
+
# @param {!Protocol.Target.TargetInfo} targetInfo
|
17
|
+
# @param {!Puppeteer.BrowserContext} browserContext
|
18
|
+
# @param {!function():!Promise<!Puppeteer.CDPSession>} sessionFactory
|
19
|
+
# @param {boolean} ignoreHTTPSErrors
|
20
|
+
# @param {?Puppeteer.Viewport} defaultViewport
|
21
|
+
# @param {!Puppeteer.TaskQueue} screenshotTaskQueue
|
22
|
+
def initialize(target_info:, browser_context:, session_factory:, ignore_https_errors:, default_viewport:, screenshot_task_queue:)
|
23
|
+
@target_info = target_info
|
24
|
+
@browser_context = browser_context
|
25
|
+
@target_id = target_info.target_id
|
26
|
+
@session_factory = session_factory
|
27
|
+
@ignore_https_errors = ignore_https_errors
|
28
|
+
@default_viewport = default_viewport
|
29
|
+
@screenshot_task_queue = screenshot_task_queue
|
30
|
+
|
31
|
+
|
32
|
+
# /** @type {?Promise<!Puppeteer.Page>} */
|
33
|
+
# this._pagePromise = null;
|
34
|
+
# /** @type {?Promise<!Worker>} */
|
35
|
+
# this._workerPromise = null;
|
36
|
+
@initialize_callback_promise = resolvable_future
|
37
|
+
@initialized_promise = @initialize_callback_promise.then do |success|
|
38
|
+
handle_initialized(success)
|
39
|
+
end
|
40
|
+
@is_closed_promise = resolvable_future
|
41
|
+
|
42
|
+
@is_initialized = @target_info.type != 'page' || !@target_info.url.empty?
|
43
|
+
|
44
|
+
if @is_initialized
|
45
|
+
@initialize_callback_promise.fulfill(true)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
attr_reader :target_id, :initialized_promise, :is_closed_promise
|
50
|
+
|
51
|
+
def closed_callback
|
52
|
+
@is_closed_promise.fulfill(true)
|
53
|
+
end
|
54
|
+
|
55
|
+
class InitializeFailure < StandardError; end
|
56
|
+
|
57
|
+
def ignore_initialize_callback_promise
|
58
|
+
unless @initialize_callback_promise.fulfilled?
|
59
|
+
@initialize_callback_promise.fulfill(false)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
private def handle_initialized(success)
|
64
|
+
unless success
|
65
|
+
raise InitializeFailure.new('Failed to create target for page')
|
66
|
+
end
|
67
|
+
opener_page = opener&.page
|
68
|
+
if opener_page.nil? || type != 'page'
|
69
|
+
return true
|
70
|
+
end
|
71
|
+
# if (!openerPage.listenerCount(Events.Page.Popup))
|
72
|
+
# return true;
|
73
|
+
popup_page = page
|
74
|
+
opener_page.emit_event('Events.Page.Popup', popup_page)
|
75
|
+
|
76
|
+
true
|
77
|
+
end
|
78
|
+
|
79
|
+
def initialized?
|
80
|
+
@is_initialized
|
81
|
+
end
|
82
|
+
|
83
|
+
def create_cdp_session
|
84
|
+
@session_factory.call
|
85
|
+
end
|
86
|
+
|
87
|
+
def page
|
88
|
+
if ['page', 'background_page', 'webview'].include?(@target_info.type) && @page.nil?
|
89
|
+
client = @session_factory.call
|
90
|
+
@page = Puppeteer::Page.create(client, self, @ignore_https_errors, @default_viewport, @screenshot_task_queue)
|
91
|
+
end
|
92
|
+
@page
|
93
|
+
end
|
94
|
+
|
95
|
+
# /**
|
96
|
+
# * @return {!Promise<?Worker>}
|
97
|
+
# */
|
98
|
+
# async worker() {
|
99
|
+
# if (this._targetInfo.type !== 'service_worker' && this._targetInfo.type !== 'shared_worker')
|
100
|
+
# return null;
|
101
|
+
# if (!this._workerPromise) {
|
102
|
+
# // TODO(einbinder): Make workers send their console logs.
|
103
|
+
# this._workerPromise = this._sessionFactory()
|
104
|
+
# .then(client => new Worker(client, this._targetInfo.url, () => {} /* consoleAPICalled */, () => {} /* exceptionThrown */));
|
105
|
+
# }
|
106
|
+
# return this._workerPromise;
|
107
|
+
# }
|
108
|
+
|
109
|
+
# @return {string}
|
110
|
+
def url
|
111
|
+
@target_info.url
|
112
|
+
end
|
113
|
+
|
114
|
+
# @return {"page"|"background_page"|"service_worker"|"shared_worker"|"other"|"browser"}
|
115
|
+
def type
|
116
|
+
type = @target_info.type
|
117
|
+
if ['page', 'background_page', 'service_worker', 'shared_worker', 'browser'].include?(type)
|
118
|
+
type
|
119
|
+
else
|
120
|
+
'other'
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
# @return {!Puppeteer.Browser}
|
125
|
+
def browser
|
126
|
+
@browser_context.browser
|
127
|
+
end
|
128
|
+
|
129
|
+
# @return {!Puppeteer.BrowserContext}
|
130
|
+
def browser_context
|
131
|
+
@browser_context
|
132
|
+
end
|
133
|
+
|
134
|
+
# @return {?Puppeteer.Target}
|
135
|
+
def opener
|
136
|
+
opener_id = @target_info.opener_id
|
137
|
+
return nil if opener_id.nil?
|
138
|
+
browser.targets[opener_id]
|
139
|
+
end
|
140
|
+
|
141
|
+
# @param {!Protocol.Target.TargetInfo} targetInfo
|
142
|
+
def handle_target_info_changed(target_info)
|
143
|
+
@target_info = target_info
|
144
|
+
|
145
|
+
if !@is_initialized && (@target_info.type != 'page' || !@target_info.url.empty?)
|
146
|
+
@is_initialized = true
|
147
|
+
@initialize_callback_promise.fulfill(true)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class Puppeteer::TimeoutSettings
|
2
|
+
DEFAULT_TIMEOUT = 30000
|
3
|
+
|
4
|
+
attr_writer :default_timeout, :default_navigation_timeout
|
5
|
+
|
6
|
+
# @return {number}
|
7
|
+
def navigation_timeout
|
8
|
+
@default_navigation_timeout || @default_timeout || DEFAULT_TIMEOUT
|
9
|
+
end
|
10
|
+
|
11
|
+
# @return {number}
|
12
|
+
def timeout
|
13
|
+
@default_timeout || DEFAULT_TIMEOUT
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
class Puppeteer::TouchScreen
|
2
|
+
using Puppeteer::AsyncAwaitBehavior
|
3
|
+
|
4
|
+
# @param {Puppeteer.CDPSession} client
|
5
|
+
# @param keyboard [Puppeteer::Keyboard]
|
6
|
+
def initialize(client, keyboard)
|
7
|
+
@client = client
|
8
|
+
@keyboard = keyboard
|
9
|
+
end
|
10
|
+
|
11
|
+
# @param x [number]
|
12
|
+
# @param y [number]
|
13
|
+
def tap(x, y)
|
14
|
+
# Touches appear to be lost during the first frame after navigation.
|
15
|
+
# This waits a frame before sending the tap.
|
16
|
+
# @see https://crbug.com/613219
|
17
|
+
@client.send_message('Runtime.evaluate',
|
18
|
+
expression: 'new Promise(x => requestAnimationFrame(() => requestAnimationFrame(x)))',
|
19
|
+
awaitPromise: true,
|
20
|
+
)
|
21
|
+
|
22
|
+
touch_points = [
|
23
|
+
{ x: x.round, y: y.round },
|
24
|
+
]
|
25
|
+
@client.send_message('Input.dispatchTouchEvent',
|
26
|
+
type: 'touchStart',
|
27
|
+
touchPoints: touch_points,
|
28
|
+
modifiers: @keyboard.modifiers,
|
29
|
+
)
|
30
|
+
@client.send_message('Input.dispatchTouchEvent',
|
31
|
+
type: 'touchEnd',
|
32
|
+
touchPoints: [],
|
33
|
+
modifiers: @keyboard.modifiers,
|
34
|
+
)
|
35
|
+
end
|
36
|
+
|
37
|
+
# @param x [number]
|
38
|
+
# @param y [number]
|
39
|
+
# @return [Future]
|
40
|
+
async def async_tap(x, y)
|
41
|
+
tap(x, y)
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
class Puppeteer::Viewport
|
2
|
+
# @param width [int]
|
3
|
+
# @param height [int]
|
4
|
+
# @param device_scale_factor [double]
|
5
|
+
# @param is_mobile [boolean]
|
6
|
+
# @param has_touch [boolean]
|
7
|
+
# @param is_landscape [boolean]
|
8
|
+
def initialize(
|
9
|
+
width:,
|
10
|
+
height:,
|
11
|
+
device_scale_factor: 1.0,
|
12
|
+
is_mobile: false,
|
13
|
+
has_touch: false,
|
14
|
+
is_landscape: false)
|
15
|
+
@width = width
|
16
|
+
@height = height
|
17
|
+
@device_scale_factor = device_scale_factor
|
18
|
+
@is_mobile = is_mobile
|
19
|
+
@has_touch = has_touch
|
20
|
+
@is_landscape = is_landscape
|
21
|
+
end
|
22
|
+
|
23
|
+
attr_reader :width, :height, :device_scale_factor
|
24
|
+
|
25
|
+
def mobile?
|
26
|
+
@is_mobile
|
27
|
+
end
|
28
|
+
|
29
|
+
def has_touch?
|
30
|
+
@has_touch
|
31
|
+
end
|
32
|
+
|
33
|
+
def landscape?
|
34
|
+
@is_landscape
|
35
|
+
end
|
36
|
+
|
37
|
+
def merge(
|
38
|
+
width: nil,
|
39
|
+
height: nil,
|
40
|
+
device_scale_factor: nil,
|
41
|
+
is_mobile: nil,
|
42
|
+
has_touch: nil,
|
43
|
+
is_landscape: nil)
|
44
|
+
|
45
|
+
Puppeteer::Viewport.new(
|
46
|
+
width: width || @width,
|
47
|
+
height: height || @height,
|
48
|
+
device_scale_factor: device_scale_factor || @device_scale_factor,
|
49
|
+
is_mobile: is_mobile.nil? ? @is_mobile : is_mobile,
|
50
|
+
has_touch: has_touch.nil? ? @has_touch : has_touch,
|
51
|
+
is_landscape: is_landscape.nil? ? @is_landscape : is_landscape,
|
52
|
+
)
|
53
|
+
end
|
54
|
+
end
|