puppeteer-ruby 0.0.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (161) hide show
  1. checksums.yaml +7 -0
  2. data/.circleci/config.yml +71 -0
  3. data/.github/stale.yml +16 -0
  4. data/.gitignore +19 -0
  5. data/.rspec +3 -0
  6. data/.rubocop.yml +302 -0
  7. data/.travis.yml +7 -0
  8. data/Dockerfile +6 -0
  9. data/Gemfile +6 -0
  10. data/README.md +54 -0
  11. data/Rakefile +1 -0
  12. data/bin/console +11 -0
  13. data/bin/setup +8 -0
  14. data/docker-compose.yml +15 -0
  15. data/docs/Puppeteer.html +2020 -0
  16. data/docs/Puppeteer/AsyncAwaitBehavior.html +105 -0
  17. data/docs/Puppeteer/Browser.html +2148 -0
  18. data/docs/Puppeteer/BrowserContext.html +809 -0
  19. data/docs/Puppeteer/BrowserFetcher.html +214 -0
  20. data/docs/Puppeteer/BrowserRunner.html +914 -0
  21. data/docs/Puppeteer/BrowserRunner/BrowserProcess.html +477 -0
  22. data/docs/Puppeteer/CDPSession.html +813 -0
  23. data/docs/Puppeteer/CDPSession/Error.html +124 -0
  24. data/docs/Puppeteer/ConcurrentRubyUtils.html +430 -0
  25. data/docs/Puppeteer/Connection.html +960 -0
  26. data/docs/Puppeteer/Connection/MessageCallback.html +434 -0
  27. data/docs/Puppeteer/Connection/ProtocolError.html +216 -0
  28. data/docs/Puppeteer/Connection/RequestDebugPrinter.html +217 -0
  29. data/docs/Puppeteer/Connection/ResponseDebugPrinter.html +244 -0
  30. data/docs/Puppeteer/ConsoleMessage.html +565 -0
  31. data/docs/Puppeteer/ConsoleMessage/Location.html +433 -0
  32. data/docs/Puppeteer/DOMWorld.html +2219 -0
  33. data/docs/Puppeteer/DOMWorld/DetachedError.html +124 -0
  34. data/docs/Puppeteer/DOMWorld/DocumentEvaluationError.html +124 -0
  35. data/docs/Puppeteer/DebugPrint.html +233 -0
  36. data/docs/Puppeteer/Device.html +470 -0
  37. data/docs/Puppeteer/Devices.html +139 -0
  38. data/docs/Puppeteer/ElementHandle.html +2542 -0
  39. data/docs/Puppeteer/ElementHandle/ElementNotFoundError.html +206 -0
  40. data/docs/Puppeteer/ElementHandle/ElementNotVisibleError.html +206 -0
  41. data/docs/Puppeteer/ElementHandle/Point.html +492 -0
  42. data/docs/Puppeteer/ElementHandle/ScrollIntoViewError.html +124 -0
  43. data/docs/Puppeteer/EmulationManager.html +454 -0
  44. data/docs/Puppeteer/EventCallbackable.html +433 -0
  45. data/docs/Puppeteer/EventCallbackable/EventListeners.html +435 -0
  46. data/docs/Puppeteer/ExecutionContext.html +998 -0
  47. data/docs/Puppeteer/ExecutionContext/EvaluationError.html +124 -0
  48. data/docs/Puppeteer/ExecutionContext/JavaScriptExpression.html +357 -0
  49. data/docs/Puppeteer/ExecutionContext/JavaScriptFunction.html +389 -0
  50. data/docs/Puppeteer/FileChooser.html +455 -0
  51. data/docs/Puppeteer/Frame.html +3677 -0
  52. data/docs/Puppeteer/FrameManager.html +2410 -0
  53. data/docs/Puppeteer/FrameManager/NavigationError.html +124 -0
  54. data/docs/Puppeteer/IfPresent.html +222 -0
  55. data/docs/Puppeteer/JSHandle.html +1352 -0
  56. data/docs/Puppeteer/Keyboard.html +1557 -0
  57. data/docs/Puppeteer/Keyboard/KeyDefinition.html +831 -0
  58. data/docs/Puppeteer/Keyboard/KeyDescription.html +603 -0
  59. data/docs/Puppeteer/Launcher.html +237 -0
  60. data/docs/Puppeteer/Launcher/Base.html +385 -0
  61. data/docs/Puppeteer/Launcher/Base/ExecutablePathNotFound.html +124 -0
  62. data/docs/Puppeteer/Launcher/BrowserOptions.html +441 -0
  63. data/docs/Puppeteer/Launcher/Chrome.html +669 -0
  64. data/docs/Puppeteer/Launcher/Chrome/DefaultArgs.html +382 -0
  65. data/docs/Puppeteer/Launcher/ChromeArgOptions.html +531 -0
  66. data/docs/Puppeteer/Launcher/LaunchOptions.html +893 -0
  67. data/docs/Puppeteer/LifecycleWatcher.html +834 -0
  68. data/docs/Puppeteer/LifecycleWatcher/ExpectedLifecycle.html +363 -0
  69. data/docs/Puppeteer/LifecycleWatcher/FrameDetachedError.html +206 -0
  70. data/docs/Puppeteer/LifecycleWatcher/TerminatedError.html +124 -0
  71. data/docs/Puppeteer/Mouse.html +1105 -0
  72. data/docs/Puppeteer/Mouse/Button.html +136 -0
  73. data/docs/Puppeteer/NetworkManager.html +901 -0
  74. data/docs/Puppeteer/NetworkManager/Credentials.html +385 -0
  75. data/docs/Puppeteer/Page.html +5970 -0
  76. data/docs/Puppeteer/Page/FileChooserTimeoutError.html +206 -0
  77. data/docs/Puppeteer/Page/ScreenshotOptions.html +845 -0
  78. data/docs/Puppeteer/Page/ScriptTag.html +555 -0
  79. data/docs/Puppeteer/Page/StyleTag.html +448 -0
  80. data/docs/Puppeteer/Page/TargetCrashedError.html +124 -0
  81. data/docs/Puppeteer/RemoteObject.html +1087 -0
  82. data/docs/Puppeteer/Target.html +1336 -0
  83. data/docs/Puppeteer/Target/InitializeFailure.html +124 -0
  84. data/docs/Puppeteer/Target/TargetInfo.html +729 -0
  85. data/docs/Puppeteer/TimeoutError.html +135 -0
  86. data/docs/Puppeteer/TimeoutSettings.html +496 -0
  87. data/docs/Puppeteer/TouchScreen.html +464 -0
  88. data/docs/Puppeteer/Viewport.html +837 -0
  89. data/docs/Puppeteer/WaitTask.html +637 -0
  90. data/docs/Puppeteer/WaitTask/TerminatedError.html +124 -0
  91. data/docs/Puppeteer/WaitTask/TimeoutError.html +206 -0
  92. data/docs/Puppeteer/WebSocket.html +673 -0
  93. data/docs/Puppeteer/WebSocket/DriverImpl.html +412 -0
  94. data/docs/Puppeteer/WebSocketTransport.html +600 -0
  95. data/docs/Puppeteer/WebSocktTransportError.html +124 -0
  96. data/docs/_index.html +823 -0
  97. data/docs/class_list.html +51 -0
  98. data/docs/css/common.css +1 -0
  99. data/docs/css/full_list.css +58 -0
  100. data/docs/css/style.css +496 -0
  101. data/docs/file.README.html +123 -0
  102. data/docs/file_list.html +56 -0
  103. data/docs/frames.html +17 -0
  104. data/docs/index.html +123 -0
  105. data/docs/js/app.js +314 -0
  106. data/docs/js/full_list.js +216 -0
  107. data/docs/js/jquery.js +4 -0
  108. data/docs/method_list.html +4075 -0
  109. data/docs/top-level-namespace.html +126 -0
  110. data/lib/puppeteer.rb +200 -0
  111. data/lib/puppeteer/async_await_behavior.rb +38 -0
  112. data/lib/puppeteer/browser.rb +259 -0
  113. data/lib/puppeteer/browser_context.rb +90 -0
  114. data/lib/puppeteer/browser_fetcher.rb +6 -0
  115. data/lib/puppeteer/browser_runner.rb +161 -0
  116. data/lib/puppeteer/cdp_session.rb +100 -0
  117. data/lib/puppeteer/concurrent_ruby_utils.rb +37 -0
  118. data/lib/puppeteer/connection.rb +254 -0
  119. data/lib/puppeteer/console_message.rb +24 -0
  120. data/lib/puppeteer/debug_print.rb +20 -0
  121. data/lib/puppeteer/device.rb +12 -0
  122. data/lib/puppeteer/devices.rb +885 -0
  123. data/lib/puppeteer/dom_world.rb +484 -0
  124. data/lib/puppeteer/element_handle.rb +433 -0
  125. data/lib/puppeteer/element_handle/bounding_box.rb +12 -0
  126. data/lib/puppeteer/element_handle/box_model.rb +19 -0
  127. data/lib/puppeteer/element_handle/point.rb +26 -0
  128. data/lib/puppeteer/emulation_manager.rb +46 -0
  129. data/lib/puppeteer/errors.rb +2 -0
  130. data/lib/puppeteer/event_callbackable.rb +88 -0
  131. data/lib/puppeteer/execution_context.rb +254 -0
  132. data/lib/puppeteer/file_chooser.rb +29 -0
  133. data/lib/puppeteer/frame.rb +286 -0
  134. data/lib/puppeteer/frame_manager.rb +378 -0
  135. data/lib/puppeteer/if_present.rb +18 -0
  136. data/lib/puppeteer/js_handle.rb +142 -0
  137. data/lib/puppeteer/keyboard.rb +183 -0
  138. data/lib/puppeteer/keyboard/key_description.rb +19 -0
  139. data/lib/puppeteer/keyboard/us_keyboard_layout.rb +283 -0
  140. data/lib/puppeteer/launcher.rb +25 -0
  141. data/lib/puppeteer/launcher/base.rb +48 -0
  142. data/lib/puppeteer/launcher/browser_options.rb +41 -0
  143. data/lib/puppeteer/launcher/chrome.rb +211 -0
  144. data/lib/puppeteer/launcher/chrome_arg_options.rb +49 -0
  145. data/lib/puppeteer/launcher/launch_options.rb +68 -0
  146. data/lib/puppeteer/lifecycle_watcher.rb +171 -0
  147. data/lib/puppeteer/mouse.rb +123 -0
  148. data/lib/puppeteer/network_manager.rb +122 -0
  149. data/lib/puppeteer/page.rb +1065 -0
  150. data/lib/puppeteer/page/screenshot_options.rb +78 -0
  151. data/lib/puppeteer/remote_object.rb +143 -0
  152. data/lib/puppeteer/target.rb +150 -0
  153. data/lib/puppeteer/timeout_settings.rb +15 -0
  154. data/lib/puppeteer/touch_screen.rb +43 -0
  155. data/lib/puppeteer/version.rb +3 -0
  156. data/lib/puppeteer/viewport.rb +54 -0
  157. data/lib/puppeteer/wait_task.rb +188 -0
  158. data/lib/puppeteer/web_socket.rb +122 -0
  159. data/lib/puppeteer/web_socket_transport.rb +49 -0
  160. data/puppeteer-ruby.gemspec +32 -0
  161. metadata +355 -0
@@ -0,0 +1,126 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>
7
+ Top Level Namespace
8
+
9
+ &mdash; Documentation by YARD 0.9.24
10
+
11
+ </title>
12
+
13
+ <link rel="stylesheet" href="css/style.css" type="text/css" />
14
+
15
+ <link rel="stylesheet" href="css/common.css" type="text/css" />
16
+
17
+ <script type="text/javascript">
18
+ pathId = "";
19
+ relpath = '';
20
+ </script>
21
+
22
+
23
+ <script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
24
+
25
+ <script type="text/javascript" charset="utf-8" src="js/app.js"></script>
26
+
27
+
28
+ </head>
29
+ <body>
30
+ <div class="nav_wrap">
31
+ <iframe id="nav" src="class_list.html?1"></iframe>
32
+ <div id="resizer"></div>
33
+ </div>
34
+
35
+ <div id="main" tabindex="-1">
36
+ <div id="header">
37
+ <div id="menu">
38
+
39
+ <a href="_index.html">Index</a> &raquo;
40
+
41
+
42
+ <span class="title">Top Level Namespace</span>
43
+
44
+ </div>
45
+
46
+ <div id="search">
47
+
48
+ <a class="full_list_link" id="class_list_link"
49
+ href="class_list.html">
50
+
51
+ <svg width="24" height="24">
52
+ <rect x="0" y="4" width="24" height="4" rx="1" ry="1"></rect>
53
+ <rect x="0" y="12" width="24" height="4" rx="1" ry="1"></rect>
54
+ <rect x="0" y="20" width="24" height="4" rx="1" ry="1"></rect>
55
+ </svg>
56
+ </a>
57
+
58
+ </div>
59
+ <div class="clear"></div>
60
+ </div>
61
+
62
+ <div id="content"><h1>Top Level Namespace
63
+
64
+
65
+
66
+ </h1>
67
+ <div class="box_info">
68
+
69
+
70
+
71
+
72
+
73
+
74
+ <dl>
75
+ <dt>Includes:</dt>
76
+ <dd><span class='object_link'><a href="Puppeteer/ConcurrentRubyUtils.html" title="Puppeteer::ConcurrentRubyUtils (module)">Puppeteer::ConcurrentRubyUtils</a></span></dd>
77
+ </dl>
78
+
79
+
80
+
81
+
82
+
83
+
84
+ </div>
85
+
86
+ <h2>Defined Under Namespace</h2>
87
+ <p class="children">
88
+
89
+
90
+
91
+
92
+ <strong class="classes">Classes:</strong> <span class='object_link'><a href="Puppeteer.html" title="Puppeteer (class)">Puppeteer</a></span>
93
+
94
+
95
+ </p>
96
+
97
+
98
+
99
+
100
+
101
+
102
+
103
+
104
+
105
+
106
+
107
+
108
+
109
+
110
+ <h2>Method Summary</h2>
111
+
112
+ <h3 class="inherited">Methods included from <span class='object_link'><a href="Puppeteer/ConcurrentRubyUtils.html" title="Puppeteer::ConcurrentRubyUtils (module)">Puppeteer::ConcurrentRubyUtils</a></span></h3>
113
+ <p class="inherited"><span class='object_link'><a href="Puppeteer/ConcurrentRubyUtils.html#await-instance_method" title="Puppeteer::ConcurrentRubyUtils#await (method)">#await</a></span>, <span class='object_link'><a href="Puppeteer/ConcurrentRubyUtils.html#await_all-instance_method" title="Puppeteer::ConcurrentRubyUtils#await_all (method)">#await_all</a></span>, <span class='object_link'><a href="Puppeteer/ConcurrentRubyUtils.html#await_any-instance_method" title="Puppeteer::ConcurrentRubyUtils#await_any (method)">#await_any</a></span>, <span class='object_link'><a href="Puppeteer/ConcurrentRubyUtils.html#future-instance_method" title="Puppeteer::ConcurrentRubyUtils#future (method)">#future</a></span>, <span class='object_link'><a href="Puppeteer/ConcurrentRubyUtils.html#resolvable_future-instance_method" title="Puppeteer::ConcurrentRubyUtils#resolvable_future (method)">#resolvable_future</a></span></p>
114
+
115
+
116
+ </div>
117
+
118
+ <div id="footer">
119
+ Generated on Fri Jun 12 12:38:32 2020 by
120
+ <a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
121
+ 0.9.24 (ruby-2.6.3).
122
+ </div>
123
+
124
+ </div>
125
+ </body>
126
+ </html>
@@ -0,0 +1,200 @@
1
+ require 'concurrent'
2
+
3
+ class Puppeteer; end
4
+
5
+ # Custom data types.
6
+ require 'puppeteer/device'
7
+ require 'puppeteer/errors'
8
+ require 'puppeteer/viewport'
9
+
10
+ # Modules
11
+ require 'puppeteer/async_await_behavior'
12
+ require 'puppeteer/concurrent_ruby_utils'
13
+ require 'puppeteer/debug_print'
14
+ require 'puppeteer/event_callbackable'
15
+ require 'puppeteer/if_present'
16
+
17
+ # Classes & values.
18
+ require 'puppeteer/browser'
19
+ require 'puppeteer/browser_context'
20
+ require 'puppeteer/browser_runner'
21
+ require 'puppeteer/cdp_session'
22
+ require 'puppeteer/connection'
23
+ require 'puppeteer/console_message'
24
+ require 'puppeteer/devices'
25
+ require 'puppeteer/dom_world'
26
+ require 'puppeteer/emulation_manager'
27
+ require 'puppeteer/execution_context'
28
+ require 'puppeteer/file_chooser'
29
+ require 'puppeteer/frame'
30
+ require 'puppeteer/frame_manager'
31
+ require 'puppeteer/js_handle'
32
+ require 'puppeteer/keyboard'
33
+ require 'puppeteer/launcher'
34
+ require 'puppeteer/lifecycle_watcher'
35
+ require 'puppeteer/mouse'
36
+ require 'puppeteer/network_manager'
37
+ require 'puppeteer/page'
38
+ require 'puppeteer/remote_object'
39
+ require 'puppeteer/target'
40
+ require 'puppeteer/timeout_settings'
41
+ require 'puppeteer/touch_screen'
42
+ require 'puppeteer/version'
43
+ require 'puppeteer/wait_task'
44
+ require 'puppeteer/web_socket'
45
+ require 'puppeteer/web_socket_transport'
46
+
47
+ # subclasses
48
+ require 'puppeteer/element_handle'
49
+
50
+ # ref: https://github.com/puppeteer/puppeteer/blob/master/lib/Puppeteer.js
51
+ class Puppeteer
52
+ class << self
53
+ def method_missing(method, *args, **kwargs, &block)
54
+ instance.send(method, *args, **kwargs, &block)
55
+ end
56
+
57
+ def instance
58
+ @instance ||= Puppeteer.new(
59
+ project_root: __dir__,
60
+ preferred_revision: '706915',
61
+ is_puppeteer_core: true,
62
+ )
63
+ end
64
+ end
65
+
66
+ # @param {string} projectRoot
67
+ # @param {string} preferredRevision
68
+ # @param {boolean} isPuppeteerCore
69
+ def initialize(project_root:, preferred_revision:, is_puppeteer_core:)
70
+ @project_root = project_root
71
+ @preferred_revision = preferred_revision
72
+ @is_puppeteer_core = is_puppeteer_core
73
+ end
74
+
75
+ # @param {!(Launcher.LaunchOptions & Launcher.ChromeArgOptions & Launcher.BrowserOptions & {product?: string, extraPrefsFirefox?: !object})=} options
76
+ # @return {!Promise<!Puppeteer.Browser>}
77
+ def launch(
78
+ product: nil,
79
+ executable_path: nil,
80
+ ignore_default_args: nil,
81
+ handle_SIGINT: nil,
82
+ handle_SIGTERM: nil,
83
+ handle_SIGHUP: nil,
84
+ timeout: nil,
85
+ dumpio: nil,
86
+ env: nil,
87
+ pipe: nil,
88
+ args: nil,
89
+ user_data_dir: nil,
90
+ devtools: nil,
91
+ headless: nil,
92
+ ignore_https_errors: nil,
93
+ default_viewport: nil,
94
+ slow_mo: nil
95
+ )
96
+ options = {
97
+ executable_path: executable_path,
98
+ ignore_default_args: ignore_default_args,
99
+ handle_SIGINT: handle_SIGINT,
100
+ handle_SIGTERM: handle_SIGTERM,
101
+ handle_SIGHUP: handle_SIGHUP,
102
+ timeout: timeout,
103
+ dumpio: dumpio,
104
+ env: env,
105
+ pipe: pipe,
106
+ args: args,
107
+ user_data_dir: user_data_dir,
108
+ devtools: devtools,
109
+ headless: headless,
110
+ ignore_https_errors: ignore_https_errors,
111
+ default_viewport: default_viewport,
112
+ slow_mo: slow_mo,
113
+ }.compact
114
+
115
+ @product_name ||= product
116
+ browser = launcher.launch(options)
117
+ if block_given?
118
+ begin
119
+ yield(browser)
120
+ ensure
121
+ browser.close
122
+ end
123
+ else
124
+ browser
125
+ end
126
+ end
127
+
128
+ # @param {!(Launcher.BrowserOptions & {browserWSEndpoint?: string, browserURL?: string, transport?: !Puppeteer.ConnectionTransport})} options
129
+ # @return {!Promise<!Puppeteer.Browser>}
130
+ def connect(
131
+ browser_ws_endpoint: nil,
132
+ browser_url: nil,
133
+ transport: nil,
134
+ ignore_https_errors: nil,
135
+ default_viewport: nil,
136
+ slow_mo: nil
137
+ )
138
+ options = {
139
+ browser_ws_endpoint: browser_ws_endpoint,
140
+ browser_url: browser_url,
141
+ transport: transport,
142
+ ignore_https_errors: ignore_https_errors,
143
+ default_viewport: default_viewport,
144
+ slow_mo: slow_mo,
145
+ }.compact
146
+ browser = launcher.connect(options)
147
+ if block_given?
148
+ yield(browser)
149
+ else
150
+ browser
151
+ end
152
+ end
153
+
154
+ # @return {string}
155
+ def executable_path
156
+ launcher.executable_path
157
+ end
158
+
159
+ private def launcher
160
+ @launcher ||= Puppeteer::Launcher.new(
161
+ project_root: @project_root,
162
+ preferred_revision: @preferred_revision,
163
+ is_puppeteer_core: @is_puppeteer_core,
164
+ product: @product_name,
165
+ )
166
+ end
167
+
168
+ # @return {string}
169
+ def product
170
+ launcher.product
171
+ end
172
+
173
+ # @return {Puppeteer::Devices}
174
+ def devices
175
+ Puppeteer::Devices
176
+ end
177
+
178
+ # # @return {Object}
179
+ # def errors
180
+ # # ???
181
+ # end
182
+
183
+ # @param {!Launcher.ChromeArgOptions=} options
184
+ # @return {!Array<string>}
185
+ def default_args(args: nil, user_data_dir: nil, devtools: nil, headless: nil)
186
+ options = {
187
+ args: args,
188
+ user_data_dir: user_data_dir,
189
+ devtools: devtools,
190
+ headless: headless,
191
+ }.compact
192
+ launcher.default_args(options)
193
+ end
194
+
195
+ # @param {!BrowserFetcher.Options=} options
196
+ # @return {!BrowserFetcher}
197
+ def createBrowserFetcher(options = {})
198
+ BrowserFetcher.new(@project_root, options)
199
+ end
200
+ end
@@ -0,0 +1,38 @@
1
+ module Puppeteer::AsyncAwaitBehavior
2
+ refine Class do
3
+ # wrap with Concurrent::Promises.future
4
+ def async(method_name)
5
+ original_method = instance_method(method_name)
6
+
7
+ unless method_name.to_s.start_with?('async_')
8
+ puts "async method should start with 'async_': #{self.name}##{method_name}"
9
+ end
10
+
11
+ define_method(method_name) do |*args|
12
+ Concurrent::Promises.future do
13
+ original_method.bind(self).call(*args)
14
+ rescue => err
15
+ Logger.new(STDERR).warn(err)
16
+ raise err
17
+ end
18
+ end
19
+ rescue NameError
20
+ if respond_to?(method_name)
21
+ original_method = singleton_method(method_name)
22
+
23
+ unless method_name.to_s.start_with?('async_')
24
+ puts "async method should start with 'async_': #{method_name}"
25
+ end
26
+
27
+ define_singleton_method(method_name) do |*args|
28
+ Concurrent::Promises.future do
29
+ original_method.call(*args)
30
+ rescue => err
31
+ Logger.new(STDERR).warn(err)
32
+ raise err
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,259 @@
1
+ require 'thread'
2
+ require 'timeout'
3
+
4
+ class Puppeteer::Browser
5
+ include Puppeteer::DebugPrint
6
+ include Puppeteer::EventCallbackable
7
+ include Puppeteer::IfPresent
8
+ using Puppeteer::AsyncAwaitBehavior
9
+
10
+ # @param {!Puppeteer.Connection} connection
11
+ # @param {!Array<string>} contextIds
12
+ # @param {boolean} ignoreHTTPSErrors
13
+ # @param {?Puppeteer.Viewport} defaultViewport
14
+ # @param process [Puppeteer::BrowserRunner::BrowserProcess|NilClass]
15
+ # @param {function()=} closeCallback
16
+ def self.create(connection:, context_ids:, ignore_https_errors:, default_viewport:, process:, close_callback:)
17
+ browser = Puppeteer::Browser.new(
18
+ connection: connection,
19
+ context_ids: context_ids,
20
+ ignore_https_errors: ignore_https_errors,
21
+ default_viewport: default_viewport,
22
+ process: process,
23
+ close_callback: close_callback,
24
+ )
25
+ connection.send_message('Target.setDiscoverTargets', discover: true)
26
+ browser
27
+ end
28
+
29
+ # @param {!Puppeteer.Connection} connection
30
+ # @param {!Array<string>} contextIds
31
+ # @param {boolean} ignoreHTTPSErrors
32
+ # @param {?Puppeteer.Viewport} defaultViewport
33
+ # @param {?Puppeteer.ChildProcess} process
34
+ # @param {(function():Promise)=} closeCallback
35
+ def initialize(connection:, context_ids:, ignore_https_errors:, default_viewport:, process:, close_callback:)
36
+ @ignore_https_errors = ignore_https_errors
37
+ @default_viewport = default_viewport
38
+ @process = process
39
+ # @screenshot_task_queue = TaskQueue.new
40
+ @connection = connection
41
+ @close_callback = close_callback
42
+
43
+ @default_context = Puppeteer::BrowserContext.new(@connection, self, nil)
44
+ @contexts = {}
45
+ context_ids.each do |context_id|
46
+ @contexts[context_id] = Puppeteer::BrowserContext.new(@connection, self. context_id)
47
+ end
48
+ @targets = {}
49
+ @connection.on_event 'Events.CDPSession.Disconnected' do
50
+ emit_event 'Events.Browser.Disconnected'
51
+ end
52
+ @connection.on_event 'Target.targetCreated', &method(:handle_target_created)
53
+ @connection.on_event 'Target.targetDestroyed', &method(:handle_target_destroyed)
54
+ @connection.on_event 'Target.targetInfoChanged', &method(:handle_target_info_changed)
55
+ end
56
+
57
+ # @return [Puppeteer::BrowserRunner::BrowserProcess]
58
+ def process
59
+ @process
60
+ end
61
+
62
+ # @return [Puppeteer::BrowserContext]
63
+ def create_incognito_browser_context
64
+ result = @connection.send_message('Target.createBrowserContext')
65
+ browser_context_id = result['browserContextId']
66
+ @contexts[browser_context_id] = Puppeteer::BrowserContext.new(@connection, self, browser_context_id)
67
+ end
68
+
69
+ def browser_contexts
70
+ [@default_context].concat(@contexts.values)
71
+ end
72
+
73
+ # @return [Puppeteer::BrowserContext]
74
+ def default_browser_context
75
+ @default_context
76
+ end
77
+
78
+ # @param context_id [String]
79
+ def dispose_context(context_id)
80
+ @connection.send_message('Target.disposeBrowserContext', browserContextId: context_id)
81
+ @contexts.remove(context_id)
82
+ end
83
+
84
+ # @param {!Protocol.Target.targetCreatedPayload} event
85
+ def handle_target_created(event)
86
+ target_info = Puppeteer::Target::TargetInfo.new(event['targetInfo'])
87
+ browser_context_id = target_info.browser_context_id
88
+ context =
89
+ if browser_context_id && @contexts.has_key?(browser_context_id)
90
+ @contexts[browser_context_id]
91
+ else
92
+ @default_context
93
+ end
94
+
95
+ target = Puppeteer::Target.new(
96
+ target_info: target_info,
97
+ browser_context: context,
98
+ session_factory: -> { @connection.create_session(target_info) },
99
+ ignore_https_errors: @ignore_https_errors,
100
+ default_viewport: @default_viewport,
101
+ screenshot_task_queue: @screenshot_task_queue,
102
+ )
103
+ # assert(!this._targets.has(event.targetInfo.targetId), 'Target should not exist before targetCreated');
104
+ @targets[target_info.target_id] = target
105
+ if await target.initialized_promise
106
+ emit_event 'Events.Browser.TargetCreated', target
107
+ context.emit_event 'Events.BrowserContext.TargetCreated', target
108
+ end
109
+
110
+ if_present(pending_target_info_changed_event.delete(target_info.target_id)) do |pending_event|
111
+ handle_target_info_changed(pending_event)
112
+ end
113
+ end
114
+
115
+
116
+ # @param {{targetId: string}} event
117
+ def handle_target_destroyed(event)
118
+ target_id = event['targetId']
119
+ target = @targets[target_id]
120
+ target.ignore_initialize_callback_promise
121
+ @targets.delete(target_id)
122
+ target.closed_callback
123
+ if await target.initialized_promise
124
+ emit_event 'Events.Browser.TargetDestroyed', target
125
+ target.browser_context.emit_event 'Events.BrowserContext.TargetDestroyed', target
126
+ end
127
+ end
128
+
129
+ # @param {!Protocol.Target.targetInfoChangedPayload} event
130
+ def handle_target_info_changed(event)
131
+ target_info = Puppeteer::Target::TargetInfo.new(event['targetInfo'])
132
+ target = @targets[target_info.target_id]
133
+ if !target
134
+ # targetCreated is sometimes notified after targetInfoChanged.
135
+ # We don't raise error. Instead, keep the event as a pending change,
136
+ # and handle it on handle_target_created.
137
+ #
138
+ # D, [2020-04-22T00:22:26.630328 #79646] DEBUG -- : RECV << {"method"=>"Target.targetInfoChanged", "params"=>{"targetInfo"=>{"targetId"=>"8068CED48357B9557EEC85AA62165A8E", "type"=>"iframe", "title"=>"", "url"=>"", "attached"=>true, "browserContextId"=>"7895BFB24BF22CE40584808713D96E8D"}}}
139
+ # E, [2020-04-22T00:22:26.630448 #79646] ERROR -- : target should exist before targetInfoChanged (StandardError)
140
+ # D, [2020-04-22T00:22:26.630648 #79646] DEBUG -- : RECV << {"method"=>"Target.targetCreated", "params"=>{"targetInfo"=>{"targetId"=>"8068CED48357B9557EEC85AA62165A8E", "type"=>"iframe", "title"=>"", "url"=>"", "attached"=>false, "browserContextId"=>"7895BFB24BF22CE40584808713D96E8D"}}}
141
+ pending_target_info_changed_event[target_info.target_id] = event
142
+ return
143
+ # original implementation is:
144
+ #
145
+ # raise StandardError.new('target should exist before targetInfoChanged')
146
+ end
147
+ previous_url = target.url
148
+ was_initialized = target.initialized?
149
+ target.handle_target_info_changed(target_info)
150
+ if was_initialized && previous_url != target.url
151
+ emit_event 'Events.Browser.TargetChanged', target
152
+ target.browser_context.emit_event 'Events.BrowserContext.TargetChanged', target
153
+ end
154
+ end
155
+
156
+ private def pending_target_info_changed_event
157
+ @pending_target_info_changed_event ||= {}
158
+ end
159
+
160
+ # @return [String]
161
+ def websocket_endpoint
162
+ @connection.url
163
+ end
164
+
165
+ def new_page
166
+ @default_context.new_page
167
+ end
168
+
169
+ # @param {?string} contextId
170
+ # @return {!Promise<!Puppeteer.Page>}
171
+ def create_page_in_context(context_id)
172
+ create_target_params = { url: 'about:blank' }
173
+ if context_id
174
+ create_target_params[:browserContextId] = context_id
175
+ end
176
+ result = @connection.send_message('Target.createTarget', **create_target_params)
177
+ target_id = result['targetId']
178
+ target = @targets[target_id]
179
+ await target.initialized_promise
180
+ await target.page
181
+ end
182
+
183
+ # @return {!Array<!Target>}
184
+ def targets
185
+ @targets.values.select { |target| target.initialized? }
186
+ end
187
+
188
+
189
+ # @return {!Target}
190
+ def target
191
+ targets.first { |target| target.type == 'browser' }
192
+ end
193
+
194
+ # @param {function(!Target):boolean} predicate
195
+ # @param {{timeout?: number}=} options
196
+ # @return {!Promise<!Target>}
197
+ def wait_for_target(predicate:, timeout: nil)
198
+ timeout_in_sec = (timeout || 30000).to_i / 1000.0
199
+ existing_target = targets.first { |target| predicate.call(target) }
200
+ return existing_target if existing_target
201
+
202
+ event_listening_ids = []
203
+ target_promise = resolvable_future
204
+ event_listening_ids << add_event_listener('Events.Browser.TargetCreated') do |target|
205
+ if predicate.call(target)
206
+ target_promise.fulfill(target)
207
+ end
208
+ end
209
+ event_listening_ids << add_event_listener('Events.Browser.TargetChanged') do |target|
210
+ if predicate.call(target)
211
+ target_promise.fulfill(target)
212
+ end
213
+ end
214
+
215
+ begin
216
+ if timeout_in_sec > 0
217
+ Timeout.timeout(timeout_in_sec) do
218
+ target_promise.value!
219
+ end
220
+ else
221
+ target_promise.value!
222
+ end
223
+ ensure
224
+ remove_event_listener(*event_listening_ids)
225
+ end
226
+ end
227
+
228
+ # @return {!Promise<!Array<!Puppeteer.Page>>}
229
+ def pages
230
+ browser_contexts.flat_map(&:pages)
231
+ end
232
+
233
+ # @return [String]
234
+ def version
235
+ get_version.product
236
+ end
237
+
238
+ # @return [String]
239
+ def user_agent
240
+ get_version.user_agent
241
+ end
242
+
243
+ def close
244
+ @close_callback.call
245
+ disconnect
246
+ end
247
+
248
+ def disconnect
249
+ @connection.dispose
250
+ end
251
+
252
+ def connected?
253
+ !@connection.closed?
254
+ end
255
+
256
+ private def get_version
257
+ @connection.send_message('Browser.getVersion')
258
+ end
259
+ end