bidi2pdf 0.1.3 → 0.1.4

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 (76) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +19 -1
  3. data/CHANGELOG.md +27 -3
  4. data/docker/Dockerfile.chromedriver +5 -0
  5. data/docker/entrypoint.sh +11 -1
  6. data/lib/bidi2pdf/bidi/add_headers_interceptor.rb +18 -21
  7. data/lib/bidi2pdf/bidi/auth_interceptor.rb +31 -38
  8. data/lib/bidi2pdf/bidi/browser_tab.rb +32 -52
  9. data/lib/bidi2pdf/bidi/client.rb +24 -52
  10. data/lib/bidi2pdf/bidi/command_manager.rb +50 -28
  11. data/lib/bidi2pdf/bidi/commands/add_intercept.rb +41 -0
  12. data/lib/bidi2pdf/bidi/commands/base.rb +73 -0
  13. data/lib/bidi2pdf/bidi/commands/browser_close.rb +15 -0
  14. data/lib/bidi2pdf/bidi/commands/browser_create_user_context.rb +15 -0
  15. data/lib/bidi2pdf/bidi/commands/browsing_context_close.rb +25 -0
  16. data/lib/bidi2pdf/bidi/commands/browsing_context_navigate.rb +31 -0
  17. data/lib/bidi2pdf/bidi/commands/browsing_context_print.rb +28 -0
  18. data/lib/bidi2pdf/bidi/commands/cancel_auth.rb +26 -0
  19. data/lib/bidi2pdf/bidi/commands/create_tab.rb +11 -0
  20. data/lib/bidi2pdf/bidi/commands/create_window.rb +32 -0
  21. data/lib/bidi2pdf/bidi/commands/get_user_contexts.rb +15 -0
  22. data/lib/bidi2pdf/bidi/commands/network_continue.rb +29 -0
  23. data/lib/bidi2pdf/bidi/commands/print_parameters_validator.rb +116 -0
  24. data/lib/bidi2pdf/bidi/commands/provide_credentials.rb +33 -0
  25. data/lib/bidi2pdf/bidi/commands/script_evaluate.rb +33 -0
  26. data/lib/bidi2pdf/bidi/commands/session_end.rb +15 -0
  27. data/lib/bidi2pdf/bidi/commands/session_status.rb +15 -0
  28. data/lib/bidi2pdf/bidi/commands/session_subscribe.rb +25 -0
  29. data/lib/bidi2pdf/bidi/commands/set_tab_cookie.rb +63 -0
  30. data/lib/bidi2pdf/bidi/commands/set_usercontext_cookie.rb +67 -0
  31. data/lib/bidi2pdf/bidi/commands.rb +27 -0
  32. data/lib/bidi2pdf/bidi/connection_manager.rb +16 -13
  33. data/lib/bidi2pdf/bidi/event_manager.rb +2 -0
  34. data/lib/bidi2pdf/bidi/interceptor.rb +75 -0
  35. data/lib/bidi2pdf/bidi/network_events.rb +0 -1
  36. data/lib/bidi2pdf/bidi/session.rb +139 -65
  37. data/lib/bidi2pdf/bidi/user_context.rb +25 -31
  38. data/lib/bidi2pdf/bidi/web_socket_dispatcher.rb +2 -0
  39. data/lib/bidi2pdf/chromedriver_manager.rb +2 -1
  40. data/lib/bidi2pdf/cli.rb +1 -3
  41. data/lib/bidi2pdf/launcher.rb +3 -1
  42. data/lib/bidi2pdf/version.rb +1 -1
  43. data/lib/bidi2pdf.rb +12 -0
  44. data/sig/bidi2pdf/bidi/command_manager.rbs +41 -0
  45. data/sig/bidi2pdf/bidi/commands/add_intercept.rbs +21 -0
  46. data/sig/bidi2pdf/bidi/commands/base.rbs +27 -0
  47. data/sig/bidi2pdf/bidi/commands/browser_close.rbs +9 -0
  48. data/sig/bidi2pdf/bidi/commands/browser_create_user_context.rbs +9 -0
  49. data/sig/bidi2pdf/bidi/commands/browsing_context_close.rbs +11 -0
  50. data/sig/bidi2pdf/bidi/commands/browsing_context_navigate.rbs +15 -0
  51. data/sig/bidi2pdf/bidi/commands/browsing_context_print.rbs +14 -0
  52. data/sig/bidi2pdf/bidi/commands/cancel_auth.rbs +11 -0
  53. data/sig/bidi2pdf/bidi/commands/create_tab.rbs +9 -0
  54. data/sig/bidi2pdf/bidi/commands/create_window.rbs +19 -0
  55. data/sig/bidi2pdf/bidi/commands/get_user_contexts.rbs +9 -0
  56. data/sig/bidi2pdf/bidi/commands/network_continue.rbs +19 -0
  57. data/sig/bidi2pdf/bidi/commands/print_parameters_validator.rbs +53 -0
  58. data/sig/bidi2pdf/bidi/commands/provide_credentials.rbs +15 -0
  59. data/sig/bidi2pdf/bidi/commands/script_evaluate.rbs +17 -0
  60. data/sig/bidi2pdf/bidi/commands/session_end.rbs +9 -0
  61. data/sig/bidi2pdf/bidi/commands/session_status.rbs +9 -0
  62. data/sig/bidi2pdf/bidi/commands/session_subscribe.rbs +15 -0
  63. data/sig/bidi2pdf/bidi/commands/set_tab_cookie.rbs +31 -0
  64. data/sig/bidi2pdf/bidi/commands/set_usercontext_cookie.rbs +27 -0
  65. data/sig/bidi2pdf/bidi/commands.rbs +6 -0
  66. data/sig/bidi2pdf/bidi/connection_manager.rbs +17 -0
  67. data/sig/bidi2pdf/bidi/interceptor.rbs +31 -0
  68. data/tasks/coverage.rake +16 -0
  69. metadata +65 -11
  70. data/lib/bidi2pdf/bidi/print_parameters_validator.rb +0 -114
  71. data/sig/bidi2pdf/bidi/print_parameters_validator.rbs +0 -44
  72. data/sig/bidi2pdf/chrome/chromedriver_downloader.rbs +0 -11
  73. data/sig/bidi2pdf/chrome/downloader_helper.rbs +0 -9
  74. data/sig/bidi2pdf/chrome/finder.rbs +0 -27
  75. data/sig/bidi2pdf/chrome/platform.rbs +0 -13
  76. data/sig/bidi2pdf/chrome/version_resolver.rbs +0 -19
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bidi2pdf
4
+ module Bidi
5
+ module Commands
6
+ class SetUsercontextCookie < SetTabCookie
7
+ include Base
8
+
9
+ attr_reader :user_context_id, :source_origin
10
+
11
+ def initialize(name:,
12
+ value:,
13
+ domain:,
14
+ user_context_id:,
15
+ source_origin:,
16
+ path: "/",
17
+ secure: true,
18
+ http_only: false,
19
+ same_site: "strict",
20
+ ttl: 30)
21
+ super(name: name, value: value,
22
+ domain: domain,
23
+ path: path,
24
+ secure: secure,
25
+ http_only: http_only,
26
+ same_site: same_site,
27
+ ttl: ttl,
28
+ browsing_context_id: nil)
29
+
30
+ @user_context_id = user_context_id
31
+ @source_origin = source_origin
32
+ end
33
+
34
+ def expiry
35
+ Time.now.to_i + ttl
36
+ end
37
+
38
+ def method_name
39
+ "storage.setCookie"
40
+ end
41
+
42
+ def params
43
+ {
44
+ cookie: {
45
+ name: name,
46
+ value: {
47
+ type: "string",
48
+ value: value
49
+ },
50
+ domain: domain,
51
+ path: path,
52
+ secure: secure,
53
+ httpOnly: http_only,
54
+ sameSite: same_site,
55
+ expiry: expiry
56
+ },
57
+ partition: {
58
+ type: "storageKey",
59
+ userContext: user_context_id,
60
+ sourceOrigin: source_origin
61
+ }
62
+ }.compact
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bidi2pdf
4
+ module Bidi
5
+ module Commands
6
+ require_relative "commands/base"
7
+ require_relative "commands/create_window"
8
+ require_relative "commands/create_tab"
9
+ require_relative "commands/add_intercept"
10
+ require_relative "commands/set_tab_cookie"
11
+ require_relative "commands/set_usercontext_cookie"
12
+ require_relative "commands/session_status"
13
+ require_relative "commands/get_user_contexts"
14
+ require_relative "commands/script_evaluate"
15
+ require_relative "commands/browser_create_user_context"
16
+ require_relative "commands/browser_close"
17
+ require_relative "commands/browsing_context_close"
18
+ require_relative "commands/browsing_context_navigate"
19
+ require_relative "commands/browsing_context_print"
20
+ require_relative "commands/session_subscribe"
21
+ require_relative "commands/session_end"
22
+ require_relative "commands/cancel_auth"
23
+ require_relative "commands/network_continue"
24
+ require_relative "commands/provide_credentials"
25
+ end
26
+ end
27
+ end
@@ -6,28 +6,31 @@ module Bidi2pdf
6
6
  def initialize(logger:)
7
7
  @logger = logger
8
8
  @connected = false
9
- @mutex = Mutex.new
10
- @cv = ConditionVariable.new
9
+ @connection_queue = Thread::Queue.new
11
10
  end
12
11
 
13
12
  def mark_connected
14
- @mutex.synchronize do
15
- @connected = true
16
- @cv.broadcast
17
- end
13
+ return if @connected
14
+
15
+ @connected = true
16
+ @logger.debug "WebSocket connection is open"
17
+ @connection_queue.push(true)
18
18
  end
19
19
 
20
20
  def wait_until_open(timeout:)
21
- @mutex.synchronize do
22
- unless @connected
23
- @logger.debug "Waiting for WebSocket connection to open"
24
- @cv.wait(@mutex, timeout)
21
+ return true if @connected
22
+
23
+ @logger.debug "Waiting for WebSocket connection to open"
24
+
25
+ begin
26
+ Timeout.timeout(timeout) do
27
+ @connection_queue.pop
25
28
  end
29
+ rescue Timeout::Error
30
+ raise Bidi2pdf::WebsocketError, "WebSocket connection did not open in time #{timeout} sec."
26
31
  end
27
32
 
28
- raise "WebSocket connection did not open in time" unless @connected
29
-
30
- @logger.debug "WebSocket connection is open"
33
+ true
31
34
  end
32
35
  end
33
36
  end
@@ -39,6 +39,8 @@ module Bidi2pdf
39
39
  end
40
40
  end
41
41
 
42
+ private
43
+
42
44
  def log_msg(prefix, data)
43
45
  message = truncate_large_values(data)
44
46
  Bidi2pdf.logger.debug "#{prefix}: #{message.inspect}"
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bidi2pdf
4
+ module Bidi
5
+ module Interceptor
6
+ def self.included(base)
7
+ base.extend(ClassMethods)
8
+ end
9
+
10
+ module ClassMethods
11
+ def phases = raise(NotImplementedError, "Interceptors must implement phases")
12
+
13
+ def events = raise(NotImplementedError, "Interceptors must implement events")
14
+ end
15
+
16
+ def url_patterns = raise(NotImplementedError, "Interceptors must implement url_patterns")
17
+
18
+ def context = raise(NotImplementedError, "Interceptors must implement context")
19
+
20
+ def process_interception(_event_response, _navigation_id, _network_id, _url) = raise(NotImplementedError, "Interceptors must implement process_interception")
21
+
22
+ def register_with_client(client:)
23
+ @client = client
24
+
25
+ cmd = Bidi2pdf::Bidi::Commands::AddIntercept.new context: context, phases: self.class.phases, url_patterns: url_patterns
26
+
27
+ client.send_cmd_and_wait(cmd) do |response|
28
+ @interceptor_id = response["result"]["intercept"]
29
+
30
+ Bidi2pdf.logger.debug "Interceptor added: #{@interceptor_id}"
31
+
32
+ client.on_event(*self.class.events, &method(:handle_event))
33
+
34
+ self
35
+ end
36
+ end
37
+
38
+ # rubocop: disable Metrics/AbcSize
39
+ def handle_event(response)
40
+ event_response = response["params"]
41
+
42
+ return unless event_response["intercepts"]&.include?(interceptor_id) && event_response["isBlocked"]
43
+
44
+ navigation_id = event_response["navigation"]
45
+ network_id = event_response["request"]["request"]
46
+ url = event_response["request"]["url"]
47
+
48
+ # Log the interception
49
+ Bidi2pdf.logger.debug "Interceptor #{interceptor_id} handling event: #{navigation_id}/#{network_id}/#{url}"
50
+
51
+ process_interception(event_response, navigation_id, network_id, url)
52
+ rescue StandardError => e
53
+ Bidi2pdf.logger.error "Error handling event: #{e.message}"
54
+ Bidi2pdf.logger.error e.backtrace.join("\n")
55
+ raise e
56
+ end
57
+
58
+ # rubocop: enable Metrics/AbcSize
59
+
60
+ def interceptor_id
61
+ @interceptor_id
62
+ end
63
+
64
+ def client
65
+ @client
66
+ end
67
+
68
+ def validate_phases!
69
+ valid_phases = [Phases::BEFORE_REQUEST, Phases::RESPONSE_STARTED, Phases::AUTH_REQUIRED]
70
+
71
+ raise ArgumentError, "Unsupported phase(s): #{self.class.phases}" unless self.class.phases.all? { |phase| valid_phases.include?(phase) }
72
+ end
73
+ end
74
+ end
75
+ end
@@ -68,7 +68,6 @@ module Bidi2pdf
68
68
  end
69
69
 
70
70
  if Time.now - start_time > timeout
71
- # rubocop:disable Layout/LineLength
72
71
  Bidi2pdf.logger.warn "⏰ Timeout while waiting for network events to complete. Still in progress: #{in_progress.map(&:id)}"
73
72
  # rubocop:enable Layout/LineLength
74
73
  break
@@ -10,134 +10,208 @@ require_relative "user_context"
10
10
  module Bidi2pdf
11
11
  module Bidi
12
12
  class Session
13
- SUBSCRIBE_EVENTS = %w[
14
- log
15
- script
16
- ].freeze
13
+ SUBSCRIBE_EVENTS = %w[log script].freeze
14
+ DEFAULT_CHROME_ARGS = %w[--disable-gpu --disable-popup-blocking --disable-hang-monitor].freeze
17
15
 
18
- attr_reader :session_uri, :started
16
+ attr_reader :session_uri, :started, :chrome_args
19
17
 
20
- def initialize(session_url:, headless: true)
18
+ def initialize(session_url:, headless: true, chrome_args: DEFAULT_CHROME_ARGS)
21
19
  @session_uri = URI(session_url)
22
20
  @headless = headless
23
- @client = nil
24
- @browser = nil
25
- @websocket_url = nil
26
21
  @started = false
22
+ @chrome_args = chrome_args.dup
27
23
  end
28
24
 
29
25
  def start
26
+ return if started?
27
+
30
28
  @started = true
31
29
  client
30
+ rescue StandardError => e
31
+ @started = false
32
+ raise e
32
33
  end
33
34
 
34
35
  def client
35
- @client ||= @started ? create_client : nil
36
- end
37
-
38
- def close
39
- client&.send_cmd_and_wait("session.end", {}) do |response|
40
- Bidi2pdf.logger.debug "Session ended: #{response}"
41
- @client&.close
42
- @client = nil
43
- @websocket_url = nil
44
- @browser = nil
45
- end
36
+ @client ||= started? ? create_client : nil
46
37
  end
47
38
 
48
39
  def browser
49
40
  @browser ||= create_browser
50
41
  end
51
42
 
52
- def user_contexts
53
- client&.send_cmd_and_wait("browser.getUserContexts", {}) do |response|
54
- Bidi2pdf.logger.debug "User contexts: #{response}"
43
+ def close
44
+ return unless started?
45
+
46
+ 2.times do |attempt|
47
+ client&.send_cmd_and_wait(Bidi2pdf::Bidi::Commands::SessionEnd.new, timeout: 1) do |response|
48
+ Bidi2pdf.logger.info "Session ended: #{response}"
49
+
50
+ cleanup
51
+ end
52
+ break
53
+ rescue CmdTimeoutError
54
+ Bidi2pdf.logger.error "Session end command timed out. Retrying... (#{attempt + 1})"
55
55
  end
56
56
  end
57
57
 
58
+ def user_contexts
59
+ send_cmd(Bidi2pdf::Bidi::Commands::GetUserContexts.new) { |resp| Bidi2pdf.logger.debug "User contexts: #{resp}" }
60
+ end
61
+
58
62
  def status
59
- client&.send_cmd_and_wait("session.status", {}) do |response|
60
- Bidi2pdf.logger.info "Session status: #{response.inspect}"
61
- end
63
+ send_cmd(Bidi2pdf::Bidi::Commands::SessionStatus.new) { |resp| Bidi2pdf.logger.info "Session status: #{resp.inspect}" }
64
+ end
65
+
66
+ def started?
67
+ @started
68
+ end
69
+
70
+ def websocket_url
71
+ return @websocket_url if @websocket_url
72
+
73
+ @websocket_url = if %w[ws wss].include?(session_uri.scheme)
74
+ session_uri.to_s
75
+ else
76
+ create_new_session
77
+ end
62
78
  end
63
79
 
64
80
  private
65
81
 
82
+ def send_cmd(command, &block)
83
+ client&.send_cmd_and_wait(command, &block)
84
+ end
85
+
86
+ # rubocop: disable Metrics/AbcSize
66
87
  def create_browser
67
88
  start
68
-
69
- @client.start
70
- @client.wait_until_open
89
+ client.start
90
+ client.wait_until_open
71
91
 
72
92
  Bidi2pdf.logger.info "Subscribing to events"
73
93
 
74
- event_client = Bidi::Client.new(websocket_url).tap(&:start)
75
- event_client.wait_until_open
94
+ Bidi::Client.new(websocket_url).tap do |event_client|
95
+ event_client.start
96
+ event_client.wait_until_open
76
97
 
77
- event_client.on_event(*SUBSCRIBE_EVENTS) do |data|
78
- Bidi2pdf.logger.debug "Received event: #{data["method"]}, params: #{data["params"]}"
98
+ event_client.on_event(*SUBSCRIBE_EVENTS) do |data|
99
+ Bidi2pdf.logger.debug "Received event: #{data["method"]}, params: #{data["params"]}"
100
+ end
79
101
  end
80
102
 
81
- Bidi::Browser.new(@client)
103
+ Bidi::Browser.new(client)
82
104
  end
83
105
 
106
+ # rubocop: enable Metrics/AbcSize
107
+
84
108
  def create_client
85
109
  Bidi::Client.new(websocket_url).tap(&:start)
86
110
  end
87
111
 
88
- # rubocop:disable Metrics/AbcSize
89
- def websocket_url
90
- return @websocket_url if @websocket_url
112
+ def create_new_session
113
+ session_data = exec_api_call(session_request)
114
+ Bidi2pdf.logger.debug "Session data: #{session_data}"
91
115
 
92
- if %w[ws wss].include?(session_uri.scheme)
93
- @websocket_url = session_uri.to_s
94
- return @websocket_url
95
- end
116
+ value = session_data["value"]
117
+ handle_error(value) if value.nil? || value["error"]
96
118
 
97
- args = %w[
98
- --disable-gpu
99
- --disable-popup-blocking
100
- --disable-hang-monitor
101
- ]
119
+ session_id = value["sessionId"]
120
+ ws_url = value["capabilities"]["webSocketUrl"]
121
+
122
+ Bidi2pdf.logger.info "Created session with ID: #{session_id}"
123
+ Bidi2pdf.logger.info "WebSocket URL: #{ws_url}"
124
+ ws_url
125
+ end
102
126
 
103
- args << "--headless" if @headless
127
+ def session_request
128
+ session_chrome_args = chrome_args.dup
129
+ session_chrome_args << "--headless" if @headless
104
130
 
105
- session_request = {
131
+ {
106
132
  "capabilities" => {
107
133
  "alwaysMatch" => {
108
134
  "browserName" => "chrome",
109
- "goog:chromeOptions" => {
110
- "args" => args
111
- },
135
+ "goog:chromeOptions" => { "args" => session_chrome_args },
112
136
  "goog:prerenderingDisabled" => true,
113
- "unhandledPromptBehavior" => {
114
- default: "ignore"
115
- },
137
+ "unhandledPromptBehavior" => { default: "ignore" },
116
138
  "acceptInsecureCerts" => true,
117
139
  "webSocketUrl" => true
118
140
  }
119
141
  }
120
142
  }
143
+ end
121
144
 
122
- response = Net::HTTP.post(session_uri, session_request.to_json, "Content-Type" => "application/json")
145
+ def exec_api_call(payload)
146
+ response = Net::HTTP.post(session_uri, payload.to_json, "Content-Type" => "application/json")
147
+ body = response.body
148
+ code = response.code.to_i
123
149
 
124
- Bidi2pdf.logger.debug "Response code: #{response.code}"
125
- Bidi2pdf.logger.debug "Response body: #{response.body}"
150
+ if code != 200
151
+ log_api_error("Failed to create session", code, body)
152
+ return build_error("Session creation failed", "Response code: #{code}")
153
+ end
126
154
 
127
- session_data = JSON.parse(response.body)
155
+ JSON.parse(body)
156
+ rescue StandardError => e
157
+ error_type = error_category(e)
158
+ build_error(error_type, "#{error_description(error_type)} #{e.message}", e.backtrace)
159
+ end
128
160
 
129
- Bidi2pdf.logger.debug "Session data: #{session_data}"
161
+ def log_api_error(message, code, body)
162
+ Bidi2pdf.logger.error "#{message}. Response code: #{code}"
163
+ Bidi2pdf.logger.error "Response body: #{body}"
164
+ end
130
165
 
131
- session_id = session_data["value"]["sessionId"]
132
- @websocket_url = session_data["value"]["capabilities"]["webSocketUrl"]
166
+ def error_category(exception)
167
+ case exception
168
+ when Errno::ECONNREFUSED then "Connection refused"
169
+ when JSON::ParserError then "Invalid JSON response"
170
+ else "Unknown error"
171
+ end
172
+ end
133
173
 
134
- Bidi2pdf.logger.info "Created session with ID: #{session_id}"
135
- Bidi2pdf.logger.info "WebSocket URL: #{@websocket_url}"
174
+ def error_description(type)
175
+ {
176
+ "Connection refused" => "Could not connect to the session URL:",
177
+ "Invalid JSON response" => "Could not parse the response:",
178
+ "Unknown error" => "An unknown error occurred:"
179
+ }[type]
180
+ end
181
+
182
+ def build_error(error, message, backtrace = nil)
183
+ {
184
+ "value" => {
185
+ "error" => error,
186
+ "message" => message,
187
+ "stacktrace" => backtrace&.join("\n")
188
+ }.compact
189
+ }
190
+ end
136
191
 
137
- @websocket_url
192
+ def handle_error(value)
193
+ error = value["error"]
194
+ return unless error
195
+
196
+ msg = value["message"]
197
+ trace = value["stacktrace"]
198
+
199
+ Bidi2pdf.logger.error "Error: #{error} message: #{msg}"
200
+ Bidi2pdf.logger.error "Stacktrace: #{trace}" if trace
201
+
202
+ if msg =~ /probably user data directory is already in use/
203
+ Bidi2pdf.logger.info "Container detected with headless-only support, ensure xvfb is started" unless @headless
204
+ Bidi2pdf.logger.info "Check chromedriver permissions and --user-data-dir"
205
+ end
206
+
207
+ raise SessionNotStartedError,
208
+ "Session not started. Check logs for more details. Error: #{error} message: #{msg}"
138
209
  end
139
210
 
140
- # rubocop:enable Metrics/AbcSize
211
+ def cleanup
212
+ @client&.close
213
+ @client = @websocket_url = @browser = nil
214
+ end
141
215
  end
142
216
  end
143
217
  end
@@ -14,14 +14,16 @@ module Bidi2pdf
14
14
 
15
15
  def context_id
16
16
  @context_id ||= begin
17
- res = client.send_cmd_and_wait("browser.createUserContext", {}) do |response|
18
- response["result"]["userContext"]
19
- end
17
+ res = client.send_cmd_and_wait(Bidi2pdf::Bidi::Commands::BrowserCreateUserContext.new) do |response|
18
+ raise "Error creating user context: #{response.inspect}" if response["error"]
20
19
 
21
- Bidi2pdf.logger.debug "User context created: #{res.inspect}"
20
+ response["result"]["userContext"]
21
+ end
22
22
 
23
- res
24
- end
23
+ Bidi2pdf.logger.debug "User context created: #{res.inspect}"
24
+
25
+ res
26
+ end
25
27
  end
26
28
 
27
29
  def set_cookie(
@@ -35,36 +37,28 @@ module Bidi2pdf
35
37
  same_site: "strict",
36
38
  ttl: 30
37
39
  )
38
- expiry = Time.now.to_i + ttl
39
- client.send_cmd_and_wait("storage.setCookie", {
40
- cookie: {
41
- name: name,
42
- value: {
43
- type: "string",
44
- value: value
45
- },
46
- domain: domain,
47
- path: path,
48
- secure: secure,
49
- httpOnly: http_only,
50
- sameSite: same_site,
51
- expiry: expiry
52
- },
53
- partition: {
54
- type: "storageKey",
55
- userContext: context_id,
56
- sourceOrigin: source_origin
57
- }
58
- }) do |response|
40
+ cmd = Bidi2pdf::Bidi::Commands::SetUsercontextCookie.new(
41
+ user_context_id: context_id,
42
+ source_origin: source_origin,
43
+ name: name,
44
+ value: value,
45
+ domain: domain,
46
+ path: path,
47
+ secure: secure,
48
+ http_only: http_only,
49
+ same_site: same_site,
50
+ ttl: ttl
51
+ )
52
+
53
+ client.send_cmd_and_wait(cmd) do |response|
59
54
  Bidi2pdf.logger.debug "Cookie set: #{response.inspect}"
60
55
  end
61
56
  end
62
57
 
63
58
  def create_browser_window
64
- client.send_cmd_and_wait("browsingContext.create", {
65
- type: "window",
66
- userContext: context_id
67
- }) do |response|
59
+ cmd = Bidi2pdf::Bidi::Commands::CreateWindow.new(user_context_id: context_id)
60
+
61
+ client.send_cmd_and_wait(cmd) do |response|
68
62
  browsing_context_id = response["result"]["context"]
69
63
 
70
64
  BrowserTab.new(client, browsing_context_id, context_id)
@@ -42,6 +42,8 @@ module Bidi2pdf
42
42
 
43
43
  def remove_error_listener(block) = socket_events.off(:error, block)
44
44
 
45
+ private
46
+
45
47
  def setup_message_handler
46
48
  that = self
47
49
 
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "chromedriver/binary"
4
+ require "securerandom"
4
5
 
5
6
  module Bidi2pdf
6
7
  class ChromedriverManager
@@ -140,7 +141,7 @@ module Bidi2pdf
140
141
 
141
142
  def build_cmd
142
143
  bin = Chromedriver::Binary::ChromedriverDownloader.driver_path
143
- user_data_dir = File.join(Dir.tmpdir, "bidi2pdf", "user_data")
144
+ user_data_dir = File.join(Dir.tmpdir, "bidi2pdf", "user_data", SecureRandom.hex(8))
144
145
 
145
146
  cmd = [bin]
146
147
  cmd << "--port=#{@port}" unless @port.zero?
data/lib/bidi2pdf/cli.rb CHANGED
@@ -122,7 +122,7 @@ module Bidi2pdf
122
122
  end
123
123
 
124
124
  def validate_print_options(opts)
125
- Bidi2pdf::Bidi::PrintParametersValidator.validate!(opts)
125
+ Bidi2pdf::Bidi::Commands::PrintParametersValidator.validate!(opts)
126
126
  rescue ArgumentError => e
127
127
  raise Thor::Error, "Invalid print option: #{e.message}"
128
128
  end
@@ -177,7 +177,6 @@ module Bidi2pdf
177
177
  end
178
178
 
179
179
  def launcher
180
- # rubocop:disable Layout/BeginEndAlignment
181
180
  @launcher ||= begin
182
181
  username, password = parse_auth(merged_options[:auth]) if merged_options[:auth]
183
182
 
@@ -195,7 +194,6 @@ module Bidi2pdf
195
194
  print_options: print_options
196
195
  )
197
196
  end
198
- # rubocop:enable Layout/BeginEndAlignment
199
197
  end
200
198
 
201
199
  # rubocop:enable Metrics/AbcSize
@@ -21,6 +21,7 @@ module Bidi2pdf
21
21
  @wait_network_idle = wait_network_idle
22
22
  @print_options = print_options || {}
23
23
  @remote_browser_url = remote_browser_url
24
+ @custom_session = nil
24
25
  end
25
26
 
26
27
  # rubocop:enable Metrics/ParameterLists
@@ -42,13 +43,14 @@ module Bidi2pdf
42
43
 
43
44
  def stop
44
45
  @manager&.stop
46
+ @custom_session&.close
45
47
  end
46
48
 
47
49
  private
48
50
 
49
51
  def session
50
52
  if @remote_browser_url
51
- Bidi::Session.new(session_url: @remote_browser_url, headless: @headless)
53
+ @custom_session = Bidi::Session.new(session_url: @remote_browser_url, headless: @headless)
52
54
  else
53
55
  @manager = ChromedriverManager.new(port: @port, headless: @headless)
54
56
  @manager.start
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Bidi2pdf
4
- VERSION = "0.1.3"
4
+ VERSION = "0.1.4"
5
5
  end