puppeteer-ruby 0.0.16 → 0.0.21

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.
@@ -20,15 +20,25 @@ module Puppeteer::Launcher
20
20
  return executable_path
21
21
  end
22
22
  raise ExecutablePathNotFound.new(
23
- "Tried to use PUPPETEER_EXECUTABLE_PATH env variable to launch browser but did not find any executable at: #{executablePath}",
23
+ "Tried to use PUPPETEER_EXECUTABLE_PATH env variable to launch browser but did not find any executable at: #{executable_path}",
24
24
  )
25
25
  end
26
26
 
27
27
  # temporal logic.
28
- if RUBY_PLATFORM.include?('darwin') # MacOS
29
- '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome'
28
+ if Puppeteer.env.darwin?
29
+ case self
30
+ when Chrome
31
+ '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome'
32
+ when Firefox
33
+ '/Applications/Firefox Nightly.app/Contents/MacOS/firefox'
34
+ end
30
35
  else
31
- '/usr/bin/google-chrome'
36
+ case self
37
+ when Chrome
38
+ '/usr/bin/google-chrome'
39
+ when Firefox
40
+ '/usr/bin/firefox'
41
+ end
32
42
  end
33
43
 
34
44
  # const browserFetcher = new BrowserFetcher(launcher._projectRoot);
@@ -34,7 +34,7 @@ module Puppeteer::Launcher
34
34
 
35
35
  temporary_user_data_dir = nil
36
36
  if chrome_arguments.none? { |arg| arg.start_with?('--user-data-dir') }
37
- temporary_user_data_dir = Dir.mktmpdir('puppeteer_dev_profile-')
37
+ temporary_user_data_dir = Dir.mktmpdir('puppeteer_dev_chrome_profile-')
38
38
  chrome_arguments << "--user-data-dir=#{temporary_user_data_dir}"
39
39
  end
40
40
 
@@ -0,0 +1,389 @@
1
+ require 'tmpdir'
2
+
3
+ # https://github.com/puppeteer/puppeteer/blob/main/src/node/Launcher.ts
4
+ module Puppeteer::Launcher
5
+ class Firefox < Base
6
+ # @param {!(Launcher.LaunchOptions & Launcher.ChromeArgOptions & Launcher.BrowserOptions)=} options
7
+ # @return {!Promise<!Browser>}
8
+ def launch(options = {})
9
+ @chrome_arg_options = ChromeArgOptions.new(options)
10
+ @launch_options = LaunchOptions.new(options)
11
+ @browser_options = BrowserOptions.new(options)
12
+
13
+ firefox_arguments =
14
+ if !@launch_options.ignore_default_args
15
+ default_args.to_a
16
+ elsif @launch_options.ignore_default_args.is_a?(Enumerable)
17
+ default_args.reject do |arg|
18
+ @launch_options.ignore_default_args.include?(arg)
19
+ end.to_a
20
+ else
21
+ @chrome_arg_options.args.dup
22
+ end
23
+
24
+ if firefox_arguments.none? { |arg| arg.start_with?('--remote-debugging-') }
25
+ firefox_arguments << '--remote-debugging-port=0'
26
+ end
27
+
28
+ temporary_user_data_dir = nil
29
+ if firefox_arguments.none? { |arg| arg.start_with?('--profile') || arg.start_with?('-profile') }
30
+ temporary_user_data_dir = create_profile
31
+ firefox_arguments << "--profile"
32
+ firefox_arguments << temporary_user_data_dir
33
+ end
34
+
35
+ firefox_executable = @launch_options.executable_path || resolve_executable_path
36
+ runner = Puppeteer::BrowserRunner.new(firefox_executable, firefox_arguments, temporary_user_data_dir)
37
+ runner.start(
38
+ handle_SIGHUP: @launch_options.handle_SIGHUP?,
39
+ handle_SIGTERM: @launch_options.handle_SIGTERM?,
40
+ handle_SIGINT: @launch_options.handle_SIGINT?,
41
+ dumpio: @launch_options.dumpio?,
42
+ env: @launch_options.env,
43
+ pipe: @launch_options.pipe?,
44
+ )
45
+
46
+ begin
47
+ connection = runner.setup_connection(
48
+ use_pipe: @launch_options.pipe?,
49
+ timeout: @launch_options.timeout,
50
+ slow_mo: @browser_options.slow_mo,
51
+ preferred_revision: @preferred_revision,
52
+ )
53
+
54
+ browser = Puppeteer::Browser.create(
55
+ connection: connection,
56
+ context_ids: [],
57
+ ignore_https_errors: @browser_options.ignore_https_errors?,
58
+ default_viewport: @browser_options.default_viewport,
59
+ process: runner.proc,
60
+ close_callback: -> { runner.close },
61
+ )
62
+
63
+ browser.wait_for_target(predicate: ->(target) { target.type == 'page' })
64
+
65
+ browser
66
+ rescue
67
+ runner.kill
68
+ raise
69
+ end
70
+ end
71
+
72
+ # @return [Puppeteer::Browser]
73
+ def connect(options = {})
74
+ @browser_options = BrowserOptions.new(options)
75
+ browser_ws_endpoint = options[:browser_ws_endpoint]
76
+ browser_url = options[:browser_url]
77
+ transport = options[:transport]
78
+
79
+ connection =
80
+ if browser_ws_endpoint && browser_url.nil? && transport.nil?
81
+ connect_with_browser_ws_endpoint(browser_ws_endpoint)
82
+ elsif browser_ws_endpoint.nil? && browser_url && transport.nil?
83
+ connect_with_browser_url(browser_url)
84
+ elsif browser_ws_endpoint.nil? && browser_url.nil? && transport
85
+ connect_with_transport(transport)
86
+ else
87
+ raise ArgumentError.new("Exactly one of browserWSEndpoint, browserURL or transport must be passed to puppeteer.connect")
88
+ end
89
+
90
+ result = connection.send_message('Target.getBrowserContexts')
91
+ browser_context_ids = result['browserContextIds']
92
+
93
+ Puppeteer::Browser.create(
94
+ connection: connection,
95
+ context_ids: browser_context_ids,
96
+ ignore_https_errors: @browser_options.ignore_https_errors?,
97
+ default_viewport: @browser_options.default_viewport,
98
+ process: nil,
99
+ close_callback: -> { connection.send_message('Browser.close') },
100
+ )
101
+ end
102
+
103
+ # @return [Puppeteer::Connection]
104
+ private def connect_with_browser_ws_endpoint(browser_ws_endpoint)
105
+ transport = Puppeteer::WebSocketTransport.create(browser_ws_endpoint)
106
+ Puppeteer::Connection.new(browser_ws_endpoint, transport, @browser_options.slow_mo)
107
+ end
108
+
109
+ # @return [Puppeteer::Connection]
110
+ private def connect_with_browser_url(browser_url)
111
+ require 'net/http'
112
+ uri = URI(browser_url)
113
+ uri.path = '/json/version'
114
+ response_body = Net::HTTP.get(uri)
115
+ json = JSON.parse(response_body)
116
+ connection_url = json['webSocketDebuggerUrl']
117
+ connect_with_browser_ws_endpoint(connection_url)
118
+ end
119
+
120
+ # @return [Puppeteer::Connection]
121
+ private def connect_with_transport(transport)
122
+ Puppeteer::Connection.new('', transport, @browser_options.slow_mo)
123
+ end
124
+
125
+ # @return {string}
126
+ def executable_path
127
+ resolve_executable_path
128
+ end
129
+
130
+ private def product
131
+ 'firefox'
132
+ end
133
+
134
+ class DefaultArgs
135
+ include Enumerable
136
+
137
+ # @param options [Launcher::ChromeArgOptions]
138
+ def initialize(chrome_arg_options)
139
+ firefox_arguments = ['--no-remote', '--foreground']
140
+
141
+ # if (os.platform().startsWith('win')) {
142
+ # firefoxArguments.push('--wait-for-browser');
143
+ # }
144
+
145
+ if chrome_arg_options.user_data_dir
146
+ firefox_arguments << "--profile"
147
+ firefox_arguments << chrome_arg_options.user_data_dir
148
+ end
149
+
150
+ if chrome_arg_options.headless?
151
+ firefox_arguments << '--headless'
152
+ end
153
+
154
+ if chrome_arg_options.devtools?
155
+ firefox_arguments << '--devtools'
156
+ end
157
+
158
+ if chrome_arg_options.args.all? { |arg| arg.start_with?('-') }
159
+ firefox_arguments << 'about:blank'
160
+ end
161
+
162
+ firefox_arguments.concat(chrome_arg_options.args)
163
+
164
+ @firefox_arguments = firefox_arguments
165
+ end
166
+
167
+ def each(&block)
168
+ @firefox_arguments.each do |opt|
169
+ block.call(opt)
170
+ end
171
+ end
172
+ end
173
+
174
+ # @return [DefaultArgs]
175
+ def default_args(options = nil)
176
+ if options.nil?
177
+ @default_args ||= DefaultArgs.new(@chrome_arg_options)
178
+ else
179
+ DefaultArgs.new(ChromeArgOptions.new(options))
180
+ end
181
+ end
182
+
183
+ private def create_profile(extra_prefs = {})
184
+ Dir.mktmpdir('puppeteer_dev_firefox_profile-').tap do |profile_path|
185
+ server = 'dummy.test'
186
+ default_preferences = {
187
+ # Make sure Shield doesn't hit the network.
188
+ 'app.normandy.api_url': '',
189
+ # Disable Firefox old build background check
190
+ 'app.update.checkInstallTime': false,
191
+ # Disable automatically upgrading Firefox
192
+ 'app.update.disabledForTesting': true,
193
+
194
+ # Increase the APZ content response timeout to 1 minute
195
+ 'apz.content_response_timeout': 60000,
196
+
197
+ # Prevent various error message on the console
198
+ # jest-puppeteer asserts that no error message is emitted by the console
199
+ 'browser.contentblocking.features.standard': '-tp,tpPrivate,cookieBehavior0,-cm,-fp',
200
+
201
+ # Enable the dump function: which sends messages to the system
202
+ # console
203
+ # https://bugzilla.mozilla.org/show_bug.cgi?id=1543115
204
+ 'browser.dom.window.dump.enabled': true,
205
+ # Disable topstories
206
+ 'browser.newtabpage.activity-stream.feeds.system.topstories': false,
207
+ # Always display a blank page
208
+ 'browser.newtabpage.enabled': false,
209
+ # Background thumbnails in particular cause grief: and disabling
210
+ # thumbnails in general cannot hurt
211
+ 'browser.pagethumbnails.capturing_disabled': true,
212
+
213
+ # Disable safebrowsing components.
214
+ 'browser.safebrowsing.blockedURIs.enabled': false,
215
+ 'browser.safebrowsing.downloads.enabled': false,
216
+ 'browser.safebrowsing.malware.enabled': false,
217
+ 'browser.safebrowsing.passwords.enabled': false,
218
+ 'browser.safebrowsing.phishing.enabled': false,
219
+
220
+ # Disable updates to search engines.
221
+ 'browser.search.update': false,
222
+ # Do not restore the last open set of tabs if the browser has crashed
223
+ 'browser.sessionstore.resume_from_crash': false,
224
+ # Skip check for default browser on startup
225
+ 'browser.shell.checkDefaultBrowser': false,
226
+
227
+ # Disable newtabpage
228
+ 'browser.startup.homepage': 'about:blank',
229
+ # Do not redirect user when a milstone upgrade of Firefox is detected
230
+ 'browser.startup.homepage_override.mstone': 'ignore',
231
+ # Start with a blank page about:blank
232
+ 'browser.startup.page': 0,
233
+
234
+ # Do not allow background tabs to be zombified on Android: otherwise for
235
+ # tests that open additional tabs: the test harness tab itself might get
236
+ # unloaded
237
+ 'browser.tabs.disableBackgroundZombification': false,
238
+ # Do not warn when closing all other open tabs
239
+ 'browser.tabs.warnOnCloseOtherTabs': false,
240
+ # Do not warn when multiple tabs will be opened
241
+ 'browser.tabs.warnOnOpen': false,
242
+
243
+ # Disable the UI tour.
244
+ 'browser.uitour.enabled': false,
245
+ # Turn off search suggestions in the location bar so as not to trigger
246
+ # network connections.
247
+ 'browser.urlbar.suggest.searches': false,
248
+ # Disable first run splash page on Windows 10
249
+ 'browser.usedOnWindows10.introURL': '',
250
+ # Do not warn on quitting Firefox
251
+ 'browser.warnOnQuit': false,
252
+
253
+ # Defensively disable data reporting systems
254
+ 'datareporting.healthreport.documentServerURI': "http://#{server}/dummy/healthreport/",
255
+ 'datareporting.healthreport.logging.consoleEnabled': false,
256
+ 'datareporting.healthreport.service.enabled': false,
257
+ 'datareporting.healthreport.service.firstRun': false,
258
+ 'datareporting.healthreport.uploadEnabled': false,
259
+
260
+ # Do not show datareporting policy notifications which can interfere with tests
261
+ 'datareporting.policy.dataSubmissionEnabled': false,
262
+ 'datareporting.policy.dataSubmissionPolicyBypassNotification': true,
263
+
264
+ # DevTools JSONViewer sometimes fails to load dependencies with its require.js.
265
+ # This doesn't affect Puppeteer but spams console (Bug 1424372)
266
+ 'devtools.jsonview.enabled': false,
267
+
268
+ # Disable popup-blocker
269
+ 'dom.disable_open_during_load': false,
270
+
271
+ # Enable the support for File object creation in the content process
272
+ # Required for |Page.setFileInputFiles| protocol method.
273
+ 'dom.file.createInChild': true,
274
+
275
+ # Disable the ProcessHangMonitor
276
+ 'dom.ipc.reportProcessHangs': false,
277
+
278
+ # Disable slow script dialogues
279
+ 'dom.max_chrome_script_run_time': 0,
280
+ 'dom.max_script_run_time': 0,
281
+
282
+ # Only load extensions from the application and user profile
283
+ # AddonManager.SCOPE_PROFILE + AddonManager.SCOPE_APPLICATION
284
+ 'extensions.autoDisableScopes': 0,
285
+ 'extensions.enabledScopes': 5,
286
+
287
+ # Disable metadata caching for installed add-ons by default
288
+ 'extensions.getAddons.cache.enabled': false,
289
+
290
+ # Disable installing any distribution extensions or add-ons.
291
+ 'extensions.installDistroAddons': false,
292
+
293
+ # Disabled screenshots extension
294
+ 'extensions.screenshots.disabled': true,
295
+
296
+ # Turn off extension updates so they do not bother tests
297
+ 'extensions.update.enabled': false,
298
+
299
+ # Turn off extension updates so they do not bother tests
300
+ 'extensions.update.notifyUser': false,
301
+
302
+ # Make sure opening about:addons will not hit the network
303
+ 'extensions.webservice.discoverURL': "http://#{server}/dummy/discoveryURL",
304
+
305
+ # Allow the application to have focus even it runs in the background
306
+ 'focusmanager.testmode': true,
307
+ # Disable useragent updates
308
+ 'general.useragent.updates.enabled': false,
309
+ # Always use network provider for geolocation tests so we bypass the
310
+ # macOS dialog raised by the corelocation provider
311
+ 'geo.provider.testing': true,
312
+ # Do not scan Wifi
313
+ 'geo.wifi.scan': false,
314
+ # No hang monitor
315
+ 'hangmonitor.timeout': 0,
316
+ # Show chrome errors and warnings in the error console
317
+ 'javascript.options.showInConsole': true,
318
+
319
+ # Disable download and usage of OpenH264: and Widevine plugins
320
+ 'media.gmp-manager.updateEnabled': false,
321
+ # Prevent various error message on the console
322
+ # jest-puppeteer asserts that no error message is emitted by the console
323
+ 'network.cookie.cookieBehavior': 0,
324
+
325
+ # Do not prompt for temporary redirects
326
+ 'network.http.prompt-temp-redirect': false,
327
+
328
+ # Disable speculative connections so they are not reported as leaking
329
+ # when they are hanging around
330
+ 'network.http.speculative-parallel-limit': 0,
331
+
332
+ # Do not automatically switch between offline and online
333
+ 'network.manage-offline-status': false,
334
+
335
+ # Make sure SNTP requests do not hit the network
336
+ 'network.sntp.pools': server,
337
+
338
+ # Disable Flash.
339
+ 'plugin.state.flash': 0,
340
+
341
+ 'privacy.trackingprotection.enabled': false,
342
+
343
+ # Enable Remote Agent
344
+ # https://bugzilla.mozilla.org/show_bug.cgi?id=1544393
345
+ 'remote.enabled': true,
346
+
347
+ # Don't do network connections for mitm priming
348
+ 'security.certerrors.mitm.priming.enabled': false,
349
+ # Local documents have access to all other local documents,
350
+ # including directory listings
351
+ 'security.fileuri.strict_origin_policy': false,
352
+ # Do not wait for the notification button security delay
353
+ 'security.notification_enable_delay': 0,
354
+
355
+ # Ensure blocklist updates do not hit the network
356
+ 'services.settings.server': "http://#{server}/dummy/blocklist/",
357
+
358
+ # Do not automatically fill sign-in forms with known usernames and
359
+ # passwords
360
+ 'signon.autofillForms': false,
361
+ # Disable password capture, so that tests that include forms are not
362
+ # influenced by the presence of the persistent doorhanger notification
363
+ 'signon.rememberSignons': false,
364
+
365
+ # Disable first-run welcome page
366
+ 'startup.homepage_welcome_url': 'about:blank',
367
+
368
+ # Disable first-run welcome page
369
+ 'startup.homepage_welcome_url.additional': '',
370
+
371
+ # Disable browser animations (tabs, fullscreen, sliding alerts)
372
+ 'toolkit.cosmeticAnimations.enabled': false,
373
+
374
+ # Prevent starting into safe mode after application crashes
375
+ 'toolkit.startup.max_resumed_crashes': -1,
376
+ }
377
+
378
+ preferences = default_preferences.merge(extra_prefs)
379
+
380
+ File.open(File.join(profile_path, 'user.js'), 'w') do |f|
381
+ preferences.each do |key, value|
382
+ f.write("user_pref(#{JSON.generate(key)}, #{JSON.generate(value)});\n")
383
+ end
384
+ end
385
+ IO.write(File.join(profile_path, 'prefs.js'), "")
386
+ end
387
+ end
388
+ end
389
+ end
@@ -94,5 +94,21 @@ class Puppeteer::Mouse
94
94
  )
95
95
  end
96
96
 
97
+ # Dispatches a `mousewheel` event.
98
+ #
99
+ # @param delta_x [Integer]
100
+ # @param delta_y [Integer]
101
+ def wheel(delta_x: 0, delta_y: 0)
102
+ @client.send_message('Input.dispatchMouseEvent',
103
+ type: 'mouseWheel',
104
+ x: @x,
105
+ y: @y,
106
+ deltaX: delta_x,
107
+ deltaY: delta_y,
108
+ modifiers: @keyboard.modifiers,
109
+ pointerType: 'mouse',
110
+ )
111
+ end
112
+
97
113
  define_async_method :async_up
98
114
  end