puppeteer-ruby 0.0.10

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.
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