puppeteer-ruby 0.38.0 → 0.40.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d18f0aae5e331fee42f66c8140bdc3cced9c0514a03ab65460c4036a94bc6eb2
4
- data.tar.gz: babeb261ac3661a6738eb3d02dddeef22685590791fbd579483edd2da7800606
3
+ metadata.gz: e88033f07007a1841f99535a96497bef2aa35b58e0599d51886ec760ef8f8201
4
+ data.tar.gz: 3b4b69f023861cc24a4ecf402e2b6eff0cba0d57fbef37991996964a1b57007b
5
5
  SHA512:
6
- metadata.gz: 0d70da4b6dc257f39d020286672180d93a4fe2aa321828035eeba80aeff92e7b1f28ff07acd15396d03aad33ab84b4f3474f1c75b587cb833d90f17dde4b024f
7
- data.tar.gz: ccb8a58f1ffff28d1498c560c8f17671064ca00ce4b98af9dbc5e844ab1c77d9c28fc503c021ae019d9e799a287976fe01a88bbce3f87979d163f7d384336c0e
6
+ metadata.gz: 6e63bd3b526e4cc09f309fc206f9395618393ab104438e93eebc190e3efa36a7e12e3037388480b9dd735121f752cbbd0bd5dc1152ae39a57be6f855dc41b41f
7
+ data.tar.gz: fe6dff5b5b82813c003e67725868a467e2e9b43e16c4bf4bca1eb48c588daa2efd782d4c1c6b351117a3cfbf7daea4feb37b36fde3637abacea33cd2e3244cb4
data/.rubocop.yml CHANGED
@@ -149,6 +149,8 @@ Style/MethodCallWithArgsParentheses:
149
149
  # utils
150
150
  - debug_print
151
151
  - debug_puts
152
+ - exit
153
+ - puts
152
154
 
153
155
  Style/MethodCallWithoutArgsParentheses:
154
156
  Enabled: true
data/CHANGELOG.md CHANGED
@@ -1,7 +1,35 @@
1
- ### main [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.38.0...main)]
1
+ ### main [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.40.2...main)]
2
2
 
3
3
  - xxx
4
4
 
5
+ ### 0.40.2 [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.40.1...0.40.2)]
6
+
7
+ Bugfix:
8
+
9
+ - Fix crash on setting response listener [#195](https://github.com/YusukeIwaki/puppeteer-ruby/pull/195)
10
+
11
+ ### 0.40.1 [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.40.0...0.40.1)]
12
+
13
+ Bugfix:
14
+
15
+ - Fix error on reload [#190](https://github.com/YusukeIwaki/puppeteer-ruby/pull/190)
16
+ - Fix error message on failing to find Chrome executable.
17
+ - Fix apidoc
18
+
19
+ ### 0.40.0 [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.39.0...0.40.0)]
20
+
21
+ New features:
22
+
23
+ - Puppeteer 13.0, 13.1 functionalities
24
+ - Support Ruby 3.1
25
+
26
+
27
+ ### 0.39.0 [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.38.0...0.39.0)]
28
+
29
+ New features:
30
+
31
+ - Puppeteer 12.0 functionalities
32
+
5
33
  ### 0.38.0 [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.37.4...0.38.0)]
6
34
 
7
35
  New features:
data/docs/api_coverage.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # API coverages
2
- - Puppeteer version: v12.0.0
3
- - puppeteer-ruby version: 0.38.0
2
+ - Puppeteer version: v13.0.1
3
+ - puppeteer-ruby version: 0.40.2
4
4
 
5
5
  ## Puppeteer
6
6
 
@@ -296,6 +296,7 @@
296
296
  * ~~toString~~
297
297
  * type => `#type_text`
298
298
  * uploadFile => `#upload_file`
299
+ * waitForSelector => `#wait_for_selector`
299
300
 
300
301
  ## HTTPRequest
301
302
 
@@ -309,6 +310,8 @@
309
310
  * frame
310
311
  * headers
311
312
  * initiator
313
+ * ~~interceptResolutionState~~
314
+ * ~~isInterceptResolutionHandled~~
312
315
  * isNavigationRequest => `#navigation_request?`
313
316
  * method
314
317
  * postData => `#post_data`
@@ -7,10 +7,10 @@ class Puppeteer::AriaQueryHandler
7
7
  private def parse_aria_selector(selector)
8
8
  known_attributes = %w(name role)
9
9
  query_options = {}
10
- attribute_regexp = /\[\s*(?<attribute>\w+)\s*=\s*"(?<value>\\.|[^"\\]*)"\s*\]/
10
+ attribute_regexp = /\[\s*(?<attribute>\w+)\s*=\s*(?<quote>"|')(?<value>\\.|.*?(?=\k<quote>))\k<quote>\s*\]/
11
11
  default_name = selector.gsub(attribute_regexp) do
12
12
  attribute = $1.strip
13
- value = $2
13
+ value = $3
14
14
  unless known_attributes.include?(attribute)
15
15
  raise ArgumentError.new("Unkown aria attribute \"#{attribute}\" in selector")
16
16
  end
@@ -36,10 +36,11 @@ class Puppeteer::AriaQueryHandler
36
36
  end
37
37
  end
38
38
 
39
- def wait_for(dom_world, selector, visible: nil, hidden: nil, timeout: nil)
39
+ def wait_for(dom_world, selector, visible: nil, hidden: nil, timeout: nil, root: nil)
40
+ # addHandlerToWorld
40
41
  binding_function = Puppeteer::DOMWorld::BindingFunction.new(
41
42
  name: 'ariaQuerySelector',
42
- proc: -> (selector) { query_one(dom_world.send(:document), selector) },
43
+ proc: -> (sel) { query_one(root || dom_world.send(:document), sel) },
43
44
  )
44
45
  dom_world.send(:wait_for_selector_in_page,
45
46
  '(_, selector) => globalThis.ariaQuerySelector(selector)',
@@ -47,7 +48,9 @@ class Puppeteer::AriaQueryHandler
47
48
  visible: visible,
48
49
  hidden: hidden,
49
50
  timeout: timeout,
50
- binding_function: binding_function)
51
+ binding_function: binding_function,
52
+ root: root,
53
+ )
51
54
  end
52
55
 
53
56
  def query_all(element, selector)
@@ -4,13 +4,17 @@ require 'timeout'
4
4
 
5
5
  # https://github.com/puppeteer/puppeteer/blob/master/lib/Launcher.js
6
6
  class Puppeteer::BrowserRunner
7
+ include Puppeteer::DebugPrint
8
+
7
9
  # @param {string} executablePath
8
10
  # @param {!Array<string>} processArguments
9
11
  # @param {string=} tempDirectory
10
- def initialize(executable_path, process_arguments, temp_directory)
12
+ def initialize(for_firefox, executable_path, process_arguments, user_data_dir, using_temp_user_data_dir)
13
+ @for_firefox = for_firefox
11
14
  @executable_path = executable_path
12
15
  @process_arguments = process_arguments
13
- @temp_directory = temp_directory
16
+ @user_data_dir = user_data_dir
17
+ @using_temp_user_data_dir = using_temp_user_data_dir
14
18
  @proc = nil
15
19
  @connection = nil
16
20
  @closed = true
@@ -90,8 +94,8 @@ class Puppeteer::BrowserRunner
90
94
  @process_closing = -> {
91
95
  @proc.dispose
92
96
  @closed = true
93
- if @temp_directory
94
- FileUtils.rm_rf(@temp_directory)
97
+ if @using_temp_user_data_dir
98
+ FileUtils.rm_rf(@user_data_dir)
95
99
  end
96
100
  }
97
101
  at_exit do
@@ -122,7 +126,7 @@ class Puppeteer::BrowserRunner
122
126
  def close
123
127
  return if @closed
124
128
 
125
- if @temp_directory
129
+ if @using_temp_user_data_dir && !@for_firefox
126
130
  kill
127
131
  elsif @connection
128
132
  begin
@@ -137,11 +141,18 @@ class Puppeteer::BrowserRunner
137
141
 
138
142
  # @return {Promise}
139
143
  def kill
140
- if @temp_directory
141
- FileUtils.rm_rf(@temp_directory)
142
- end
143
- unless @closed
144
- @proc.kill
144
+ # If the process failed to launch (for example if the browser executable path
145
+ # is invalid), then the process does not get a pid assigned. A call to
146
+ # `proc.kill` would error, as the `pid` to-be-killed can not be found.
147
+ @proc&.kill
148
+
149
+ # Attempt to remove temporary profile directory to avoid littering.
150
+ begin
151
+ if @using_temp_user_data_dir
152
+ FileUtils.rm_rf(@user_data_dir)
153
+ end
154
+ rescue => err
155
+ debug_puts(err)
145
156
  end
146
157
  end
147
158
 
@@ -21,12 +21,12 @@ class Puppeteer::CustomQueryHandler
21
21
  nil
22
22
  end
23
23
 
24
- def wait_for(dom_world, selector, visible: nil, hidden: nil, timeout: nil)
24
+ def wait_for(dom_world, selector, visible: nil, hidden: nil, timeout: nil, root: nil)
25
25
  unless @query_one
26
26
  raise NotImplementedError.new("#{self.class}##{__method__} is not implemented.")
27
27
  end
28
28
 
29
- dom_world.send(:wait_for_selector_in_page, @query_one, selector, visible: visible, hidden: hidden, timeout: timeout)
29
+ dom_world.send(:wait_for_selector_in_page, @query_one, selector, visible: visible, hidden: hidden, timeout: timeout, root: root)
30
30
  end
31
31
 
32
32
  def query_all(element, selector)
@@ -420,10 +420,10 @@ class Puppeteer::DOMWorld
420
420
  # @param visible [Boolean] Wait for element visible (not 'display: none' nor 'visibility: hidden') on true. default to false.
421
421
  # @param hidden [Boolean] Wait for element invisible ('display: none' nor 'visibility: hidden') on true. default to false.
422
422
  # @param timeout [Integer]
423
- def wait_for_selector(selector, visible: nil, hidden: nil, timeout: nil)
423
+ def wait_for_selector(selector, visible: nil, hidden: nil, timeout: nil, root: nil)
424
424
  # call wait_for_selector_in_page with custom query selector.
425
425
  query_selector_manager = Puppeteer::QueryHandlerManager.instance
426
- query_selector_manager.detect_query_handler(selector).wait_for(self, visible: visible, hidden: hidden, timeout: timeout)
426
+ query_selector_manager.detect_query_handler(selector).wait_for(self, visible: visible, hidden: hidden, timeout: timeout, root: root)
427
427
  end
428
428
 
429
429
  private def binding_identifier(name, context)
@@ -497,10 +497,11 @@ class Puppeteer::DOMWorld
497
497
  # @param visible [Boolean] Wait for element visible (not 'display: none' nor 'visibility: hidden') on true. default to false.
498
498
  # @param hidden [Boolean] Wait for element invisible ('display: none' nor 'visibility: hidden') on true. default to false.
499
499
  # @param timeout [Integer]
500
- private def wait_for_selector_in_page(query_one, selector, visible: nil, hidden: nil, timeout: nil, binding_function: nil)
500
+ private def wait_for_selector_in_page(query_one, selector, visible: nil, hidden: nil, timeout: nil, root: nil, binding_function: nil)
501
501
  option_wait_for_visible = visible || false
502
502
  option_wait_for_hidden = hidden || false
503
503
  option_timeout = timeout || @timeout_settings.timeout
504
+ option_root = root
504
505
 
505
506
  polling =
506
507
  if option_wait_for_visible || option_wait_for_hidden
@@ -511,11 +512,11 @@ class Puppeteer::DOMWorld
511
512
  title = "selector #{selector}#{option_wait_for_hidden ? 'to be hidden' : ''}"
512
513
 
513
514
  selector_predicate = make_predicate_string(
514
- predicate_arg_def: '(selector, waitForVisible, waitForHidden)',
515
+ predicate_arg_def: '(root, selector, waitForVisible, waitForHidden)',
515
516
  predicate_query_handler: query_one,
516
517
  async: true,
517
518
  predicate_body: <<~JAVASCRIPT
518
- const node = await predicateQueryHandler(document, selector)
519
+ const node = await predicateQueryHandler(root, selector)
519
520
  return checkWaitForOptions(node, waitForVisible, waitForHidden);
520
521
  JAVASCRIPT
521
522
  )
@@ -527,6 +528,7 @@ class Puppeteer::DOMWorld
527
528
  polling: polling,
528
529
  timeout: option_timeout,
529
530
  args: [selector, option_wait_for_visible, option_wait_for_hidden],
531
+ root: option_root,
530
532
  binding_function: binding_function,
531
533
  )
532
534
  handle = wait_task.await_promise
@@ -541,10 +543,11 @@ class Puppeteer::DOMWorld
541
543
  # @param visible [Boolean] Wait for element visible (not 'display: none' nor 'visibility: hidden') on true. default to false.
542
544
  # @param hidden [Boolean] Wait for element invisible ('display: none' nor 'visibility: hidden') on true. default to false.
543
545
  # @param timeout [Integer]
544
- def wait_for_xpath(xpath, visible: nil, hidden: nil, timeout: nil)
546
+ def wait_for_xpath(xpath, visible: nil, hidden: nil, timeout: nil, root: nil)
545
547
  option_wait_for_visible = visible || false
546
548
  option_wait_for_hidden = hidden || false
547
549
  option_timeout = timeout || @timeout_settings.timeout
550
+ option_root = root
548
551
 
549
552
  polling =
550
553
  if option_wait_for_visible || option_wait_for_hidden
@@ -555,9 +558,9 @@ class Puppeteer::DOMWorld
555
558
  title = "XPath #{xpath}#{option_wait_for_hidden ? 'to be hidden' : ''}"
556
559
 
557
560
  xpath_predicate = make_predicate_string(
558
- predicate_arg_def: '(selector, waitForVisible, waitForHidden)',
561
+ predicate_arg_def: '(root, selector, waitForVisible, waitForHidden)',
559
562
  predicate_body: <<~JAVASCRIPT
560
- const node = document.evaluate(selector, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
563
+ const node = document.evaluate(selector, root, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
561
564
  return checkWaitForOptions(node, waitForVisible, waitForHidden);
562
565
  JAVASCRIPT
563
566
  )
@@ -569,6 +572,7 @@ class Puppeteer::DOMWorld
569
572
  polling: polling,
570
573
  timeout: option_timeout,
571
574
  args: [xpath, option_wait_for_visible, option_wait_for_hidden],
575
+ root: option_root,
572
576
  )
573
577
  handle = wait_task.await_promise
574
578
  unless handle.as_element
@@ -20,6 +20,60 @@ class Puppeteer::ElementHandle < Puppeteer::JSHandle
20
20
  @disposed = false
21
21
  end
22
22
 
23
+ def inspect
24
+ values = %i[context remote_object page disposed].map do |sym|
25
+ value = instance_variable_get(:"@#{sym}")
26
+ "@#{sym}=#{value}"
27
+ end
28
+ "#<Puppeteer::ElementHandle #{values.join(' ')}>"
29
+ end
30
+
31
+ #
32
+ # Wait for the `selector` to appear within the element. If at the moment of calling the
33
+ # method the `selector` already exists, the method will return immediately. If
34
+ # the `selector` doesn't appear after the `timeout` milliseconds of waiting, the
35
+ # function will throw.
36
+ #
37
+ # This method does not work across navigations or if the element is detached from DOM.
38
+ #
39
+ # @param selector - A
40
+ # {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors | selector}
41
+ # of an element to wait for
42
+ # @param options - Optional waiting parameters
43
+ # @returns Promise which resolves when element specified by selector string
44
+ # is added to DOM. Resolves to `null` if waiting for hidden: `true` and
45
+ # selector is not found in DOM.
46
+ # @remarks
47
+ # The optional parameters in `options` are:
48
+ #
49
+ # - `visible`: wait for the selected element to be present in DOM and to be
50
+ # visible, i.e. to not have `display: none` or `visibility: hidden` CSS
51
+ # properties. Defaults to `false`.
52
+ #
53
+ # - `hidden`: wait for the selected element to not be found in the DOM or to be hidden,
54
+ # i.e. have `display: none` or `visibility: hidden` CSS properties. Defaults to
55
+ # `false`.
56
+ #
57
+ # - `timeout`: maximum time to wait in milliseconds. Defaults to `30000`
58
+ # (30 seconds). Pass `0` to disable timeout. The default value can be changed
59
+ # by using the {@link Page.setDefaultTimeout} method.
60
+ def wait_for_selector(selector, visible: nil, hidden: nil, timeout: nil)
61
+ frame = @context.frame
62
+
63
+ secondary_world = frame.secondary_world
64
+ adopted_root = secondary_world.execution_context.adopt_element_handle(self)
65
+ handle = secondary_world.wait_for_selector(selector, visible: visible, hidden: hidden, timeout: timeout, root: adopted_root)
66
+ adopted_root.dispose
67
+ return nil unless handle
68
+
69
+ main_world = frame.main_world
70
+ result = main_world.execution_context.adopt_element_handle(handle)
71
+ handle.dispose
72
+ result
73
+ end
74
+
75
+ define_async_method :async_wait_for_selector
76
+
23
77
  def as_element
24
78
  self
25
79
  end
@@ -81,6 +81,7 @@ module NetworkManagerEmittedEvents ; end
81
81
 
82
82
  {
83
83
  Request: EventsDefinitionUtils.symbol('NetworkManager.Request'),
84
+ RequestServedFromCache: EventsDefinitionUtils.symbol('NetworkManager.RequestServedFromCache'),
84
85
  Response: EventsDefinitionUtils.symbol('NetworkManager.Response'),
85
86
  RequestFailed: EventsDefinitionUtils.symbol('NetworkManager.RequestFailed'),
86
87
  RequestFinished: EventsDefinitionUtils.symbol('NetworkManager.RequestFinished'),
@@ -382,7 +382,7 @@ class Puppeteer::FrameManager
382
382
  @isolated_worlds << context_payload['name']
383
383
  end
384
384
 
385
- context = Puppeteer::ExecutionContext.new(frame._client || @client, context_payload, world)
385
+ context = Puppeteer::ExecutionContext.new(frame&._client || @client, context_payload, world)
386
386
  if world
387
387
  world.context = context
388
388
  end
@@ -31,7 +31,8 @@ class Puppeteer::HTTPResponse
31
31
  # @param client [Puppeteer::CDPSession]
32
32
  # @param request [Puppeteer::HTTPRequest]
33
33
  # @param response_payload [Hash]
34
- def initialize(client, request, response_payload)
34
+ # @param extra_info [Hash|nil]
35
+ def initialize(client, request, response_payload, extra_info)
35
36
  @client = client
36
37
  @request = request
37
38
 
@@ -41,14 +42,15 @@ class Puppeteer::HTTPResponse
41
42
  port: response_payload['remotePort'],
42
43
  )
43
44
 
44
- @status = response_payload['status']
45
- @status_text = response_payload['statusText']
45
+ @status_text = parse_štatus_text_from_extra_info(extra_info) || response_payload['statusText']
46
46
  @url = request.url
47
47
  @from_disk_cache = !!response_payload['fromDiskCache']
48
48
  @from_service_worker = !!response_payload['fromServiceWorker']
49
49
 
50
+ @status = extra_info ? extra_info['statusCode'] : response_payload['status']
50
51
  @headers = {}
51
- response_payload['headers'].each do |key, value|
52
+ headers = extra_info ? extra_info['headers'] : response_payload['headers']
53
+ headers.each do |key, value|
52
54
  @headers[key.downcase] = value
53
55
  end
54
56
  @security_details = if_present(response_payload['securityDetails']) do |security_payload|
@@ -62,6 +64,25 @@ class Puppeteer::HTTPResponse
62
64
 
63
65
  attr_reader :remote_address, :url, :status, :status_text, :headers, :security_details, :request
64
66
 
67
+ def inspect
68
+ values = %i[remote_address url status status_text headers security_details request].map do |sym|
69
+ value = instance_variable_get(:"@#{sym}")
70
+ "@#{sym}=#{value}"
71
+ end
72
+ "#<Puppeteer::HTTPRequest #{values.join(' ')}>"
73
+ end
74
+
75
+ private def parse_štatus_text_from_extra_info(extra_info)
76
+ return nil if !extra_info || !extra_info['headersText']
77
+ first_line = extra_info['headersText'].split("\r").first
78
+ return nil unless first_line
79
+ /[^ ]* [^ ]* (.*)/.match(first_line) do |m|
80
+ return m[1]
81
+ end
82
+
83
+ nil
84
+ end
85
+
65
86
  # @return [Boolean]
66
87
  def ok?
67
88
  @status == 0 || (@status >= 200 && @status <= 299)
@@ -36,6 +36,14 @@ class Puppeteer::JSHandle
36
36
 
37
37
  attr_reader :context, :remote_object
38
38
 
39
+ def inspect
40
+ values = %i[context remote_object disposed].map do |sym|
41
+ value = instance_variable_get(:"@#{sym}")
42
+ "@#{sym}=#{value}"
43
+ end
44
+ "#<Puppeteer::JSHandle #{values.join(' ')}>"
45
+ end
46
+
39
47
  # @return [Puppeteer::ExecutionContext]
40
48
  def execution_context
41
49
  @context
@@ -27,9 +27,6 @@ module Puppeteer::Launcher
27
27
  @chrome_arg_options.args.dup
28
28
  end
29
29
 
30
- #
31
- # let temporaryUserDataDir = null;
32
-
33
30
  if chrome_arguments.none? { |arg| arg.start_with?('--remote-debugging-') }
34
31
  if @launch_options.pipe?
35
32
  chrome_arguments << '--remote-debugging-pipe'
@@ -38,10 +35,17 @@ module Puppeteer::Launcher
38
35
  end
39
36
  end
40
37
 
41
- temporary_user_data_dir = nil
42
- if chrome_arguments.none? { |arg| arg.start_with?('--user-data-dir') }
43
- temporary_user_data_dir = Dir.mktmpdir('puppeteer_dev_chrome_profile-', ENV['PUPPETEER_TMP_DIR'])
44
- chrome_arguments << "--user-data-dir=#{temporary_user_data_dir}"
38
+ user_data_dir = chrome_arguments.find { |arg| arg.start_with?('--user-data-dir') }
39
+ if user_data_dir
40
+ user_data_dir = user_data_dir.split('=').last
41
+ unless File.exist?(user_data_dir)
42
+ raise ArgumentError.new("Chrome user data dir not found at '#{user_data_dir}'")
43
+ end
44
+ using_temp_user_data_dir = false
45
+ else
46
+ user_data_dir = Dir.mktmpdir('puppeteer_dev_chrome_profile-', ENV['PUPPETEER_TMP_DIR'])
47
+ chrome_arguments << "--user-data-dir=#{user_data_dir}"
48
+ using_temp_user_data_dir = true
45
49
  end
46
50
 
47
51
  chrome_executable =
@@ -51,7 +55,13 @@ module Puppeteer::Launcher
51
55
  @launch_options.executable_path || fallback_executable_path
52
56
  end
53
57
  use_pipe = chrome_arguments.include?('--remote-debugging-pipe')
54
- runner = Puppeteer::BrowserRunner.new(chrome_executable, chrome_arguments, temporary_user_data_dir)
58
+ runner = Puppeteer::BrowserRunner.new(
59
+ false,
60
+ chrome_executable,
61
+ chrome_arguments,
62
+ user_data_dir,
63
+ using_temp_user_data_dir,
64
+ )
55
65
  runner.start(
56
66
  handle_SIGHUP: @launch_options.handle_SIGHUP?,
57
67
  handle_SIGTERM: @launch_options.handle_SIGTERM?,
@@ -61,33 +71,39 @@ module Puppeteer::Launcher
61
71
  pipe: use_pipe,
62
72
  )
63
73
 
64
- begin
65
- connection = runner.setup_connection(
66
- use_pipe: use_pipe,
67
- timeout: @launch_options.timeout,
68
- slow_mo: @browser_options.slow_mo,
69
- preferred_revision: @preferred_revision,
70
- )
71
-
72
- browser = Puppeteer::Browser.create(
73
- connection: connection,
74
- context_ids: [],
75
- ignore_https_errors: @browser_options.ignore_https_errors?,
76
- default_viewport: @browser_options.default_viewport,
77
- process: runner.proc,
78
- close_callback: -> { runner.close },
79
- )
74
+ browser =
75
+ begin
76
+ connection = runner.setup_connection(
77
+ use_pipe: use_pipe,
78
+ timeout: @launch_options.timeout,
79
+ slow_mo: @browser_options.slow_mo,
80
+ preferred_revision: @preferred_revision,
81
+ )
82
+
83
+ Puppeteer::Browser.create(
84
+ connection: connection,
85
+ context_ids: [],
86
+ ignore_https_errors: @browser_options.ignore_https_errors?,
87
+ default_viewport: @browser_options.default_viewport,
88
+ process: runner.proc,
89
+ close_callback: -> { runner.close },
90
+ )
91
+ rescue
92
+ runner.kill
93
+ raise
94
+ end
80
95
 
96
+ begin
81
97
  browser.wait_for_target(
82
98
  predicate: ->(target) { target.type == 'page' },
83
99
  timeout: @launch_options.timeout,
84
100
  )
85
-
86
- browser
87
101
  rescue
88
- runner.kill
102
+ browser.close
89
103
  raise
90
104
  end
105
+
106
+ browser
91
107
  end
92
108
 
93
109
  class DefaultArgs
@@ -270,15 +286,15 @@ module Puppeteer::Launcher
270
286
  end
271
287
 
272
288
  chrome_path = chrome_path_map[channel]
273
- if chrome_path.is_a?(Proc)
274
- chrome_path = chrome_path.call
275
- end
276
-
277
289
  unless chrome_path
278
290
  raise ArgumentError.new("Invalid channel: '#{channel}'. Allowed channel is #{chrome_path_map.keys}")
279
291
  end
280
292
 
281
- unless File.exist?(chrome_path)
293
+ if chrome_path.is_a?(Proc)
294
+ chrome_path = chrome_path.call
295
+ end
296
+
297
+ if !chrome_path || !File.exist?(chrome_path)
282
298
  raise "#{channel} is not installed on this system.\nExpected path: #{chrome_path}"
283
299
  end
284
300