bidi2pdf 0.1.3 → 0.1.5
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.
- checksums.yaml +4 -4
- data/.rubocop.yml +19 -1
- data/CHANGELOG.md +40 -3
- data/README.md +145 -55
- data/docker/Dockerfile.chromedriver +5 -0
- data/docker/entrypoint.sh +11 -1
- data/lib/bidi2pdf/bidi/add_headers_interceptor.rb +18 -21
- data/lib/bidi2pdf/bidi/auth_interceptor.rb +31 -38
- data/lib/bidi2pdf/bidi/browser_tab.rb +47 -53
- data/lib/bidi2pdf/bidi/client.rb +24 -52
- data/lib/bidi2pdf/bidi/command_manager.rb +50 -28
- data/lib/bidi2pdf/bidi/commands/add_intercept.rb +41 -0
- data/lib/bidi2pdf/bidi/commands/base.rb +73 -0
- data/lib/bidi2pdf/bidi/commands/browser_close.rb +15 -0
- data/lib/bidi2pdf/bidi/commands/browser_create_user_context.rb +15 -0
- data/lib/bidi2pdf/bidi/commands/browsing_context_close.rb +25 -0
- data/lib/bidi2pdf/bidi/commands/browsing_context_navigate.rb +31 -0
- data/lib/bidi2pdf/bidi/commands/browsing_context_print.rb +28 -0
- data/lib/bidi2pdf/bidi/commands/cancel_auth.rb +26 -0
- data/lib/bidi2pdf/bidi/commands/create_tab.rb +11 -0
- data/lib/bidi2pdf/bidi/commands/create_window.rb +32 -0
- data/lib/bidi2pdf/bidi/commands/get_user_contexts.rb +15 -0
- data/lib/bidi2pdf/bidi/commands/network_continue.rb +29 -0
- data/lib/bidi2pdf/bidi/commands/print_parameters_validator.rb +116 -0
- data/lib/bidi2pdf/bidi/commands/provide_credentials.rb +33 -0
- data/lib/bidi2pdf/bidi/commands/script_evaluate.rb +33 -0
- data/lib/bidi2pdf/bidi/commands/session_end.rb +15 -0
- data/lib/bidi2pdf/bidi/commands/session_status.rb +15 -0
- data/lib/bidi2pdf/bidi/commands/session_subscribe.rb +25 -0
- data/lib/bidi2pdf/bidi/commands/set_tab_cookie.rb +71 -0
- data/lib/bidi2pdf/bidi/commands/set_usercontext_cookie.rb +67 -0
- data/lib/bidi2pdf/bidi/commands.rb +27 -0
- data/lib/bidi2pdf/bidi/connection_manager.rb +16 -13
- data/lib/bidi2pdf/bidi/event_manager.rb +2 -0
- data/lib/bidi2pdf/bidi/interceptor.rb +75 -0
- data/lib/bidi2pdf/bidi/network_events.rb +0 -1
- data/lib/bidi2pdf/bidi/session.rb +139 -65
- data/lib/bidi2pdf/bidi/user_context.rb +25 -31
- data/lib/bidi2pdf/bidi/web_socket_dispatcher.rb +2 -0
- data/lib/bidi2pdf/chromedriver_manager.rb +2 -1
- data/lib/bidi2pdf/cli.rb +12 -7
- data/lib/bidi2pdf/dsl.rb +45 -0
- data/lib/bidi2pdf/launcher.rb +6 -2
- data/lib/bidi2pdf/session_runner.rb +9 -2
- data/lib/bidi2pdf/version.rb +1 -1
- data/lib/bidi2pdf.rb +16 -1
- data/sig/bidi2pdf/bidi/command_manager.rbs +41 -0
- data/sig/bidi2pdf/bidi/commands/add_intercept.rbs +21 -0
- data/sig/bidi2pdf/bidi/commands/base.rbs +27 -0
- data/sig/bidi2pdf/bidi/commands/browser_close.rbs +9 -0
- data/sig/bidi2pdf/bidi/commands/browser_create_user_context.rbs +9 -0
- data/sig/bidi2pdf/bidi/commands/browsing_context_close.rbs +11 -0
- data/sig/bidi2pdf/bidi/commands/browsing_context_navigate.rbs +15 -0
- data/sig/bidi2pdf/bidi/commands/browsing_context_print.rbs +14 -0
- data/sig/bidi2pdf/bidi/commands/cancel_auth.rbs +11 -0
- data/sig/bidi2pdf/bidi/commands/create_tab.rbs +9 -0
- data/sig/bidi2pdf/bidi/commands/create_window.rbs +19 -0
- data/sig/bidi2pdf/bidi/commands/get_user_contexts.rbs +9 -0
- data/sig/bidi2pdf/bidi/commands/network_continue.rbs +19 -0
- data/sig/bidi2pdf/bidi/commands/print_parameters_validator.rbs +53 -0
- data/sig/bidi2pdf/bidi/commands/provide_credentials.rbs +15 -0
- data/sig/bidi2pdf/bidi/commands/script_evaluate.rbs +17 -0
- data/sig/bidi2pdf/bidi/commands/session_end.rbs +9 -0
- data/sig/bidi2pdf/bidi/commands/session_status.rbs +9 -0
- data/sig/bidi2pdf/bidi/commands/session_subscribe.rbs +15 -0
- data/sig/bidi2pdf/bidi/commands/set_tab_cookie.rbs +31 -0
- data/sig/bidi2pdf/bidi/commands/set_usercontext_cookie.rbs +27 -0
- data/sig/bidi2pdf/bidi/commands.rbs +6 -0
- data/sig/bidi2pdf/bidi/connection_manager.rbs +17 -0
- data/sig/bidi2pdf/bidi/interceptor.rbs +31 -0
- data/tasks/coverage.rake +16 -0
- metadata +66 -11
- data/lib/bidi2pdf/bidi/print_parameters_validator.rb +0 -114
- data/sig/bidi2pdf/bidi/print_parameters_validator.rbs +0 -44
- data/sig/bidi2pdf/chrome/chromedriver_downloader.rbs +0 -11
- data/sig/bidi2pdf/chrome/downloader_helper.rbs +0 -9
- data/sig/bidi2pdf/chrome/finder.rbs +0 -27
- data/sig/bidi2pdf/chrome/platform.rbs +0 -13
- data/sig/bidi2pdf/chrome/version_resolver.rbs +0 -19
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Bidi2pdf
|
4
|
+
module Bidi
|
5
|
+
module Commands
|
6
|
+
class CreateWindow
|
7
|
+
include Base
|
8
|
+
|
9
|
+
def initialize(user_context_id: nil, reference_context: nil, background: false)
|
10
|
+
@user_context_id = user_context_id
|
11
|
+
@reference_context = reference_context
|
12
|
+
@background = background
|
13
|
+
end
|
14
|
+
|
15
|
+
def method_name
|
16
|
+
"browsingContext.create"
|
17
|
+
end
|
18
|
+
|
19
|
+
def params
|
20
|
+
{
|
21
|
+
type: type,
|
22
|
+
userContext: @user_context_id,
|
23
|
+
referenceContext: @reference_context,
|
24
|
+
background: @background
|
25
|
+
}.compact
|
26
|
+
end
|
27
|
+
|
28
|
+
def type = "window"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Bidi2pdf
|
4
|
+
module Bidi
|
5
|
+
module Commands
|
6
|
+
class NetworkContinue
|
7
|
+
include Base
|
8
|
+
|
9
|
+
attr_reader :request, :headers
|
10
|
+
|
11
|
+
def initialize(request:, headers:)
|
12
|
+
@headers = headers
|
13
|
+
@request = request
|
14
|
+
end
|
15
|
+
|
16
|
+
def method_name
|
17
|
+
"network.continueRequest"
|
18
|
+
end
|
19
|
+
|
20
|
+
def params
|
21
|
+
{
|
22
|
+
request: request,
|
23
|
+
headers: headers
|
24
|
+
}.compact
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Bidi2pdf
|
4
|
+
module Bidi
|
5
|
+
module Commands
|
6
|
+
# Validates parameters for the BiDi method `browsingContext.print`.
|
7
|
+
#
|
8
|
+
# Allowed structure of the params hash:
|
9
|
+
#
|
10
|
+
# {
|
11
|
+
# background: Boolean (optional, default: false) – print background graphics,
|
12
|
+
# margin: {
|
13
|
+
# top: Float >= 0.0 (optional, default: 1.0),
|
14
|
+
# bottom: Float >= 0.0 (optional, default: 1.0),
|
15
|
+
# left: Float >= 0.0 (optional, default: 1.0),
|
16
|
+
# right: Float >= 0.0 (optional, default: 1.0)
|
17
|
+
# },
|
18
|
+
# orientation: "portrait" or "landscape" (optional, default: "portrait"),
|
19
|
+
# page: {
|
20
|
+
# width: Float >= 0.0352 (optional, default: 21.59),
|
21
|
+
# height: Float >= 0.0352 (optional, default: 27.94)
|
22
|
+
# },
|
23
|
+
# pageRanges: Array of Integers or Strings (optional),
|
24
|
+
# scale: Float between 0.1 and 2.0 (optional, default: 1.0),
|
25
|
+
# shrinkToFit: Boolean (optional, default: true)
|
26
|
+
# }
|
27
|
+
#
|
28
|
+
# This validator checks presence, types, allowed ranges, and values,
|
29
|
+
# and raises ArgumentError with a descriptive message if validation fails.
|
30
|
+
class PrintParametersValidator
|
31
|
+
def self.validate!(params)
|
32
|
+
new(params).validate!
|
33
|
+
end
|
34
|
+
|
35
|
+
def initialize(params)
|
36
|
+
@params = params
|
37
|
+
end
|
38
|
+
|
39
|
+
def validate!
|
40
|
+
raise ArgumentError, "params must be a Hash" unless @params.is_a?(Hash)
|
41
|
+
|
42
|
+
validate_boolean(:background)
|
43
|
+
validate_boolean(:shrinkToFit)
|
44
|
+
validate_orientation
|
45
|
+
validate_scale
|
46
|
+
validate_page_ranges
|
47
|
+
validate_margin
|
48
|
+
validate_page_size
|
49
|
+
|
50
|
+
true
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def validate_boolean(key)
|
56
|
+
return unless @params.key?(key)
|
57
|
+
return if [true, false].include?(@params[key])
|
58
|
+
|
59
|
+
raise ArgumentError, ":#{key} must be a boolean"
|
60
|
+
end
|
61
|
+
|
62
|
+
def validate_orientation
|
63
|
+
return unless @params.key?(:orientation)
|
64
|
+
return if %w[portrait landscape].include?(@params[:orientation])
|
65
|
+
|
66
|
+
raise ArgumentError, ":orientation must be 'portrait' or 'landscape'"
|
67
|
+
end
|
68
|
+
|
69
|
+
def validate_scale
|
70
|
+
return unless @params.key?(:scale)
|
71
|
+
|
72
|
+
scale = @params[:scale]
|
73
|
+
return if scale.is_a?(Numeric) && scale >= 0.1 && scale <= 2.0
|
74
|
+
|
75
|
+
raise ArgumentError, ":scale must be a number between 0.1 and 2.0"
|
76
|
+
end
|
77
|
+
|
78
|
+
def validate_page_ranges
|
79
|
+
return unless @params.key?(:pageRanges)
|
80
|
+
unless @params[:pageRanges].is_a?(Array) &&
|
81
|
+
@params[:pageRanges].all? { |v| v.is_a?(Integer) || v.is_a?(String) }
|
82
|
+
raise ArgumentError, ":pageRanges must be an array of integers or strings"
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def validate_margin
|
87
|
+
return unless @params.key?(:margin)
|
88
|
+
|
89
|
+
margin = @params[:margin]
|
90
|
+
raise ArgumentError, ":margin must be a Hash" unless margin.is_a?(Hash)
|
91
|
+
|
92
|
+
%i[top bottom left right].each do |side|
|
93
|
+
next unless margin.key?(side)
|
94
|
+
|
95
|
+
val = margin[side]
|
96
|
+
raise ArgumentError, "margin[:#{side}] must be a float >= 0.0" unless val.is_a?(Numeric) && val >= 0.0
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def validate_page_size
|
101
|
+
return unless @params.key?(:page)
|
102
|
+
|
103
|
+
page = @params[:page]
|
104
|
+
raise ArgumentError, ":page must be a Hash" unless page.is_a?(Hash)
|
105
|
+
|
106
|
+
%i[width height].each do |dim|
|
107
|
+
next unless page.key?(dim)
|
108
|
+
|
109
|
+
val = page[dim]
|
110
|
+
raise ArgumentError, "page[:#{dim}] must be a float >= 0.0352" unless val.is_a?(Numeric) && val >= 0.0352
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Bidi2pdf
|
4
|
+
module Bidi
|
5
|
+
module Commands
|
6
|
+
class ProvideCredentials
|
7
|
+
include Base
|
8
|
+
|
9
|
+
def initialize(request:, username:, password:)
|
10
|
+
@request = request
|
11
|
+
@username = username
|
12
|
+
@password = password
|
13
|
+
end
|
14
|
+
|
15
|
+
def params
|
16
|
+
{
|
17
|
+
request: @request,
|
18
|
+
action: "provideCredentials",
|
19
|
+
credentials: {
|
20
|
+
type: "password",
|
21
|
+
username: @username,
|
22
|
+
password: @password
|
23
|
+
}
|
24
|
+
}
|
25
|
+
end
|
26
|
+
|
27
|
+
def method_name
|
28
|
+
"network.continueWithAuth"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Bidi2pdf
|
4
|
+
module Bidi
|
5
|
+
module Commands
|
6
|
+
class ScriptEvaluate
|
7
|
+
include Base
|
8
|
+
|
9
|
+
def initialize(expression:,
|
10
|
+
context:,
|
11
|
+
await_promise: true)
|
12
|
+
@expression = expression
|
13
|
+
@context = context
|
14
|
+
@await_promise = await_promise
|
15
|
+
end
|
16
|
+
|
17
|
+
def params
|
18
|
+
{
|
19
|
+
expression: @expression,
|
20
|
+
target: {
|
21
|
+
context: @context
|
22
|
+
},
|
23
|
+
awaitPromise: @await_promise
|
24
|
+
}
|
25
|
+
end
|
26
|
+
|
27
|
+
def method_name
|
28
|
+
"script.evaluate"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Bidi2pdf
|
4
|
+
module Bidi
|
5
|
+
module Commands
|
6
|
+
class SessionSubscribe
|
7
|
+
include Base
|
8
|
+
|
9
|
+
attr_reader :events
|
10
|
+
|
11
|
+
def initialize(events:)
|
12
|
+
@events = events
|
13
|
+
end
|
14
|
+
|
15
|
+
def method_name
|
16
|
+
"session.subscribe"
|
17
|
+
end
|
18
|
+
|
19
|
+
def params
|
20
|
+
{ events: events }.compact
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Bidi2pdf
|
4
|
+
module Bidi
|
5
|
+
module Commands
|
6
|
+
class SetTabCookie
|
7
|
+
include Base
|
8
|
+
|
9
|
+
class << self
|
10
|
+
attr_writer :time_provider
|
11
|
+
|
12
|
+
def time_provider
|
13
|
+
@time_provider ||= -> { Time.now }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
attr_reader :name, :value, :domain, :path, :secure, :http_only, :same_site, :ttl, :browsing_context_id
|
18
|
+
|
19
|
+
def initialize(name:,
|
20
|
+
value:,
|
21
|
+
domain:,
|
22
|
+
browsing_context_id:,
|
23
|
+
path: "/",
|
24
|
+
secure: true,
|
25
|
+
http_only: false,
|
26
|
+
same_site: "strict",
|
27
|
+
ttl: 30)
|
28
|
+
@name = name
|
29
|
+
@value = value
|
30
|
+
@domain = domain
|
31
|
+
@path = path
|
32
|
+
@secure = secure
|
33
|
+
@http_only = http_only
|
34
|
+
@same_site = same_site
|
35
|
+
@ttl = ttl
|
36
|
+
@browsing_context_id = browsing_context_id
|
37
|
+
end
|
38
|
+
|
39
|
+
def expiry
|
40
|
+
self.class.time_provider.call.to_i + ttl
|
41
|
+
end
|
42
|
+
|
43
|
+
def method_name
|
44
|
+
"storage.setCookie"
|
45
|
+
end
|
46
|
+
|
47
|
+
def params
|
48
|
+
{
|
49
|
+
cookie: {
|
50
|
+
name: name,
|
51
|
+
value: {
|
52
|
+
type: "string",
|
53
|
+
value: value
|
54
|
+
},
|
55
|
+
domain: domain,
|
56
|
+
path: path,
|
57
|
+
secure: secure,
|
58
|
+
httpOnly: http_only,
|
59
|
+
sameSite: same_site,
|
60
|
+
expiry: expiry
|
61
|
+
},
|
62
|
+
partition: {
|
63
|
+
type: "context",
|
64
|
+
context: browsing_context_id
|
65
|
+
}
|
66
|
+
}.compact
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -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
|
-
@
|
10
|
-
@cv = ConditionVariable.new
|
9
|
+
@connection_queue = Thread::Queue.new
|
11
10
|
end
|
12
11
|
|
13
12
|
def mark_connected
|
14
|
-
@
|
15
|
-
|
16
|
-
|
17
|
-
|
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
|
-
@
|
22
|
-
|
23
|
-
|
24
|
-
|
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
|
-
|
29
|
-
|
30
|
-
@logger.debug "WebSocket connection is open"
|
33
|
+
true
|
31
34
|
end
|
32
35
|
end
|
33
36
|
end
|
@@ -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
|