ferrum 0.12 → 0.14
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +28 -22
- data/lib/ferrum/browser/client.rb +6 -5
- data/lib/ferrum/browser/command.rb +9 -6
- data/lib/ferrum/browser/options/base.rb +1 -4
- data/lib/ferrum/browser/options/chrome.rb +22 -10
- data/lib/ferrum/browser/options/firefox.rb +3 -6
- data/lib/ferrum/browser/options.rb +84 -0
- data/lib/ferrum/browser/process.rb +6 -7
- data/lib/ferrum/browser/version_info.rb +71 -0
- data/lib/ferrum/browser/web_socket.rb +1 -1
- data/lib/ferrum/browser/xvfb.rb +1 -1
- data/lib/ferrum/browser.rb +184 -64
- data/lib/ferrum/context.rb +3 -2
- data/lib/ferrum/contexts.rb +2 -2
- data/lib/ferrum/cookies/cookie.rb +183 -0
- data/lib/ferrum/cookies.rb +122 -49
- data/lib/ferrum/dialog.rb +30 -0
- data/lib/ferrum/frame/dom.rb +177 -0
- data/lib/ferrum/frame/runtime.rb +41 -61
- data/lib/ferrum/frame.rb +91 -3
- data/lib/ferrum/headers.rb +28 -0
- data/lib/ferrum/keyboard.rb +45 -2
- data/lib/ferrum/mouse.rb +84 -0
- data/lib/ferrum/network/exchange.rb +104 -5
- data/lib/ferrum/network/intercepted_request.rb +3 -12
- data/lib/ferrum/network/request.rb +58 -19
- data/lib/ferrum/network/request_params.rb +57 -0
- data/lib/ferrum/network/response.rb +106 -4
- data/lib/ferrum/network.rb +193 -8
- data/lib/ferrum/node.rb +21 -1
- data/lib/ferrum/page/animation.rb +16 -0
- data/lib/ferrum/page/frames.rb +66 -11
- data/lib/ferrum/page/screenshot.rb +97 -0
- data/lib/ferrum/page/tracing.rb +26 -0
- data/lib/ferrum/page.rb +158 -45
- data/lib/ferrum/proxy.rb +91 -2
- data/lib/ferrum/target.rb +6 -4
- data/lib/ferrum/version.rb +1 -1
- metadata +7 -101
data/lib/ferrum/frame.rb
CHANGED
@@ -14,8 +14,30 @@ module Ferrum
|
|
14
14
|
stopped_loading
|
15
15
|
].freeze
|
16
16
|
|
17
|
-
|
18
|
-
|
17
|
+
# The Frame's unique id.
|
18
|
+
#
|
19
|
+
# @return [String]
|
20
|
+
attr_accessor :id
|
21
|
+
|
22
|
+
# If frame was given a name it should be here.
|
23
|
+
#
|
24
|
+
# @return [String, nil]
|
25
|
+
attr_accessor :name
|
26
|
+
|
27
|
+
# The page the frame belongs to.
|
28
|
+
#
|
29
|
+
# @return [Page]
|
30
|
+
attr_reader :page
|
31
|
+
|
32
|
+
# Parent frame id if this one is nested in another one.
|
33
|
+
#
|
34
|
+
# @return [String, nil]
|
35
|
+
attr_reader :parent_id
|
36
|
+
|
37
|
+
# One of the states frame's in.
|
38
|
+
#
|
39
|
+
# @return [:started_loading, :navigated, :stopped_loading, nil]
|
40
|
+
attr_reader :state
|
19
41
|
|
20
42
|
def initialize(id, page, parent_id = nil)
|
21
43
|
@id = id
|
@@ -30,18 +52,60 @@ module Ferrum
|
|
30
52
|
@state = value
|
31
53
|
end
|
32
54
|
|
55
|
+
#
|
56
|
+
# Returns current frame's `location.href`.
|
57
|
+
#
|
58
|
+
# @return [String]
|
59
|
+
#
|
60
|
+
# @example
|
61
|
+
# browser.go_to("https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe")
|
62
|
+
# frame = browser.frames[1]
|
63
|
+
# frame.url # => https://interactive-examples.mdn.mozilla.net/pages/tabbed/iframe.html
|
64
|
+
#
|
33
65
|
def url
|
34
66
|
evaluate("document.location.href")
|
35
67
|
end
|
36
68
|
|
69
|
+
#
|
70
|
+
# Returns current frame's title.
|
71
|
+
#
|
72
|
+
# @return [String]
|
73
|
+
#
|
74
|
+
# @example
|
75
|
+
# browser.go_to("https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe")
|
76
|
+
# frame = browser.frames[1]
|
77
|
+
# frame.title # => HTML Demo: <iframe>
|
78
|
+
#
|
37
79
|
def title
|
38
80
|
evaluate("document.title")
|
39
81
|
end
|
40
82
|
|
83
|
+
#
|
84
|
+
# If current frame is the main frame of the page (top of the tree).
|
85
|
+
#
|
86
|
+
# @return [Boolean]
|
87
|
+
#
|
88
|
+
# @example
|
89
|
+
# browser.go_to("https://www.w3schools.com/tags/tag_frame.asp")
|
90
|
+
# frame = browser.frame_by(id: "C09C4E4404314AAEAE85928EAC109A93")
|
91
|
+
# frame.main? # => false
|
92
|
+
#
|
41
93
|
def main?
|
42
94
|
@parent_id.nil?
|
43
95
|
end
|
44
96
|
|
97
|
+
#
|
98
|
+
# Sets a content of a given frame.
|
99
|
+
#
|
100
|
+
# @param [String] html
|
101
|
+
#
|
102
|
+
# @example
|
103
|
+
# browser.go_to("https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe")
|
104
|
+
# frame = browser.frames[1]
|
105
|
+
# frame.body # <html lang="en"><head><style>body {transition: opacity ease-in 0.2s; }...
|
106
|
+
# frame.content = "<html><head></head><body><p>lol</p></body></html>"
|
107
|
+
# frame.body # => <html><head></head><body><p>lol</p></body></html>
|
108
|
+
#
|
45
109
|
def content=(html)
|
46
110
|
evaluate_async(%(
|
47
111
|
document.open();
|
@@ -49,16 +113,40 @@ module Ferrum
|
|
49
113
|
document.close();
|
50
114
|
arguments[1](true);
|
51
115
|
), @page.timeout, html)
|
116
|
+
@page.document_node_id
|
52
117
|
end
|
53
118
|
alias set_content content=
|
54
119
|
|
55
|
-
|
120
|
+
#
|
121
|
+
# Execution context id which is used by JS, each frame has it's own
|
122
|
+
# context in which JS evaluates. Locks for a page timeout and raises
|
123
|
+
# an error if an execution id hasn't been set yet, if id is set
|
124
|
+
# returns immediately.
|
125
|
+
#
|
126
|
+
# @return [Integer]
|
127
|
+
#
|
128
|
+
# @raise [NoExecutionContextError]
|
129
|
+
#
|
130
|
+
def execution_id!
|
56
131
|
value = @execution_id.borrow(@page.timeout, &:itself)
|
57
132
|
raise NoExecutionContextError if value.instance_of?(Object)
|
58
133
|
|
59
134
|
value
|
60
135
|
end
|
61
136
|
|
137
|
+
#
|
138
|
+
# Execution context id which is used by JS, each frame has it's own
|
139
|
+
# context in which JS evaluates.
|
140
|
+
#
|
141
|
+
# @return [Integer, nil]
|
142
|
+
#
|
143
|
+
def execution_id
|
144
|
+
value = @execution_id.value
|
145
|
+
return if value.instance_of?(Object)
|
146
|
+
|
147
|
+
value
|
148
|
+
end
|
149
|
+
|
62
150
|
def execution_id=(value)
|
63
151
|
if value.nil?
|
64
152
|
@execution_id.try_take!
|
data/lib/ferrum/headers.rb
CHANGED
@@ -7,20 +7,48 @@ module Ferrum
|
|
7
7
|
@headers = {}
|
8
8
|
end
|
9
9
|
|
10
|
+
#
|
11
|
+
# Get all headers.
|
12
|
+
#
|
13
|
+
# @return [Hash{String => String}]
|
14
|
+
#
|
10
15
|
def get
|
11
16
|
@headers
|
12
17
|
end
|
13
18
|
|
19
|
+
#
|
20
|
+
# Set given headers. Eventually clear all headers and set given ones.
|
21
|
+
#
|
22
|
+
# @param [Hash{String => String}] headers
|
23
|
+
# key-value pairs for example `"User-Agent" => "Browser"`.
|
24
|
+
#
|
25
|
+
# @return [true]
|
26
|
+
#
|
14
27
|
def set(headers)
|
15
28
|
clear
|
16
29
|
add(headers)
|
17
30
|
end
|
18
31
|
|
32
|
+
#
|
33
|
+
# Clear all headers.
|
34
|
+
#
|
35
|
+
# @return [true]
|
36
|
+
#
|
19
37
|
def clear
|
20
38
|
@headers = {}
|
21
39
|
true
|
22
40
|
end
|
23
41
|
|
42
|
+
#
|
43
|
+
# Adds given headers to already set ones.
|
44
|
+
#
|
45
|
+
# @param [Hash{String => String}] headers
|
46
|
+
# key-value pairs for example `"Referer" => "http://example.com"`.
|
47
|
+
#
|
48
|
+
# @param [Boolean] permanent
|
49
|
+
#
|
50
|
+
# @return [true]
|
51
|
+
#
|
24
52
|
def add(headers, permanent: true)
|
25
53
|
if headers["Referer"]
|
26
54
|
@page.referrer = headers["Referer"]
|
data/lib/ferrum/keyboard.rb
CHANGED
@@ -30,19 +30,44 @@ module Ferrum
|
|
30
30
|
@page = page
|
31
31
|
end
|
32
32
|
|
33
|
+
#
|
34
|
+
# Dispatches a `keydown` event.
|
35
|
+
#
|
36
|
+
# @param [String, Symbol] key
|
37
|
+
# Name of the key, such as `"a"`, `:enter`, or `:backspace`.
|
38
|
+
#
|
39
|
+
# @return [self]
|
40
|
+
#
|
33
41
|
def down(key)
|
34
|
-
key = normalize_keys(Array(key))
|
42
|
+
key = normalize_keys(Array(key)).first
|
35
43
|
type = key[:text] ? "keyDown" : "rawKeyDown"
|
36
44
|
@page.command("Input.dispatchKeyEvent", slowmoable: true, type: type, **key)
|
37
45
|
self
|
38
46
|
end
|
39
47
|
|
48
|
+
#
|
49
|
+
# Dispatches a `keyup` event.
|
50
|
+
#
|
51
|
+
# @param [String, Symbol] key
|
52
|
+
# Name of the key, such as `"a"`, `:enter`, or `:backspace`.
|
53
|
+
#
|
54
|
+
# @return [self]
|
55
|
+
#
|
40
56
|
def up(key)
|
41
|
-
key = normalize_keys(Array(key))
|
57
|
+
key = normalize_keys(Array(key)).first
|
42
58
|
@page.command("Input.dispatchKeyEvent", slowmoable: true, type: "keyUp", **key)
|
43
59
|
self
|
44
60
|
end
|
45
61
|
|
62
|
+
#
|
63
|
+
# Sends a keydown, keypress/input, and keyup event for each character in
|
64
|
+
# the text.
|
65
|
+
#
|
66
|
+
# @param [Array<String, Symbol, (Symbol, String)>] keys
|
67
|
+
# The text to type into a focused element, `[:Shift, "s"], "tring"`.
|
68
|
+
#
|
69
|
+
# @return [self]
|
70
|
+
#
|
46
71
|
def type(*keys)
|
47
72
|
keys = normalize_keys(Array(keys))
|
48
73
|
|
@@ -55,15 +80,27 @@ module Ferrum
|
|
55
80
|
self
|
56
81
|
end
|
57
82
|
|
83
|
+
#
|
84
|
+
# Returns bitfield for a given keys.
|
85
|
+
#
|
86
|
+
# @param [Array<:alt, :ctrl, :command, :shift>] keys
|
87
|
+
#
|
88
|
+
# @return [Integer]
|
89
|
+
#
|
58
90
|
def modifiers(keys)
|
59
91
|
keys.map { |k| MODIFIERS[k.to_s] }.compact.reduce(0, :|)
|
60
92
|
end
|
61
93
|
|
62
94
|
private
|
63
95
|
|
96
|
+
# TODO: Refactor it, and try to simplify complexity
|
97
|
+
# rubocop:disable Metrics/PerceivedComplexity
|
98
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
64
99
|
def normalize_keys(keys, pressed_keys = [], memo = [])
|
65
100
|
case keys
|
66
101
|
when Array
|
102
|
+
raise ArgumentError, "empty keys passed" if keys.empty?
|
103
|
+
|
67
104
|
pressed_keys.push([])
|
68
105
|
memo += combine_strings(keys).map do |key|
|
69
106
|
normalize_keys(key, pressed_keys, memo)
|
@@ -82,6 +119,8 @@ module Ferrum
|
|
82
119
|
to_options(key)
|
83
120
|
end
|
84
121
|
when String
|
122
|
+
raise ArgumentError, "empty keys passed" if keys.empty?
|
123
|
+
|
85
124
|
pressed = pressed_keys.flatten
|
86
125
|
keys.each_char.map do |char|
|
87
126
|
key = KEYS[char] || {}
|
@@ -102,8 +141,12 @@ module Ferrum
|
|
102
141
|
modifiers + [to_options(key)]
|
103
142
|
end.flatten
|
104
143
|
end
|
144
|
+
else
|
145
|
+
raise ArgumentError, "unexpected argument"
|
105
146
|
end
|
106
147
|
end
|
148
|
+
# rubocop:enable Metrics/PerceivedComplexity
|
149
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
107
150
|
|
108
151
|
def combine_strings(keys)
|
109
152
|
keys
|
data/lib/ferrum/mouse.rb
CHANGED
@@ -10,10 +10,50 @@ module Ferrum
|
|
10
10
|
@x = @y = 0
|
11
11
|
end
|
12
12
|
|
13
|
+
#
|
14
|
+
# Scroll page to a given x, y coordinates.
|
15
|
+
#
|
16
|
+
# @param [Integer] top
|
17
|
+
# The pixel along the horizontal axis of the document that you want
|
18
|
+
# displayed in the upper left.
|
19
|
+
#
|
20
|
+
# @param [Integer] left
|
21
|
+
# The pixel along the vertical axis of the document that you want
|
22
|
+
# displayed in the upper left.
|
23
|
+
#
|
24
|
+
# @example
|
25
|
+
# browser.go_to("https://www.google.com/search?q=Ruby+headless+driver+for+Capybara")
|
26
|
+
# browser.mouse.scroll_to(0, 400)
|
27
|
+
#
|
13
28
|
def scroll_to(top, left)
|
14
29
|
tap { @page.execute("window.scrollTo(#{top}, #{left})") }
|
15
30
|
end
|
16
31
|
|
32
|
+
#
|
33
|
+
# Click given coordinates, fires mouse move, down and up events.
|
34
|
+
#
|
35
|
+
# @param [Integer] x
|
36
|
+
#
|
37
|
+
# @param [Integer] y
|
38
|
+
#
|
39
|
+
# @param [Float] delay
|
40
|
+
# Delay between mouse down and mouse up events.
|
41
|
+
#
|
42
|
+
# @param [Float] wait
|
43
|
+
#
|
44
|
+
# @param [Hash{Symbol => Object}] options
|
45
|
+
# Additional keyword arguments.
|
46
|
+
#
|
47
|
+
# @option options [:left, :right] :button (:left)
|
48
|
+
# The mouse button to click.
|
49
|
+
#
|
50
|
+
# @option options [Integer] :count (1)
|
51
|
+
#
|
52
|
+
# @option options [Integer] :modifiers
|
53
|
+
# Bitfield for key modifiers. See`keyboard.modifiers`.
|
54
|
+
#
|
55
|
+
# @return [self]
|
56
|
+
#
|
17
57
|
def click(x:, y:, delay: 0, wait: CLICK_WAIT, **options)
|
18
58
|
move(x: x, y: y)
|
19
59
|
down(**options)
|
@@ -24,14 +64,58 @@ module Ferrum
|
|
24
64
|
self
|
25
65
|
end
|
26
66
|
|
67
|
+
#
|
68
|
+
# Mouse down for given coordinates.
|
69
|
+
#
|
70
|
+
# @param [Hash{Symbol => Object}] options
|
71
|
+
# Additional keyword arguments.
|
72
|
+
#
|
73
|
+
# @option options [:left, :right] :button (:left)
|
74
|
+
# The mouse button to click.
|
75
|
+
#
|
76
|
+
# @option options [Integer] :count (1)
|
77
|
+
#
|
78
|
+
# @option options [Integer] :modifiers
|
79
|
+
# Bitfield for key modifiers. See`keyboard.modifiers`.
|
80
|
+
#
|
81
|
+
# @return [self]
|
82
|
+
#
|
27
83
|
def down(**options)
|
28
84
|
tap { mouse_event(type: "mousePressed", **options) }
|
29
85
|
end
|
30
86
|
|
87
|
+
#
|
88
|
+
# Mouse up for given coordinates.
|
89
|
+
#
|
90
|
+
# @param [Hash{Symbol => Object}] options
|
91
|
+
# Additional keyword arguments.
|
92
|
+
#
|
93
|
+
# @option options [:left, :right] :button (:left)
|
94
|
+
# The mouse button to click.
|
95
|
+
#
|
96
|
+
# @option options [Integer] :count (1)
|
97
|
+
#
|
98
|
+
# @option options [Integer] :modifiers
|
99
|
+
# Bitfield for key modifiers. See`keyboard.modifiers`.
|
100
|
+
#
|
101
|
+
# @return [self]
|
102
|
+
#
|
31
103
|
def up(**options)
|
32
104
|
tap { mouse_event(type: "mouseReleased", **options) }
|
33
105
|
end
|
34
106
|
|
107
|
+
#
|
108
|
+
# Mouse move to given x and y.
|
109
|
+
#
|
110
|
+
# @param [Integer] x
|
111
|
+
#
|
112
|
+
# @param [Integer] y
|
113
|
+
#
|
114
|
+
# @param [Integer] steps
|
115
|
+
# Sends intermediate mousemove events.
|
116
|
+
#
|
117
|
+
# @return [self]
|
118
|
+
#
|
35
119
|
def move(x:, y:, steps: 1)
|
36
120
|
from_x = @x
|
37
121
|
from_y = @y
|
@@ -3,9 +3,38 @@
|
|
3
3
|
module Ferrum
|
4
4
|
class Network
|
5
5
|
class Exchange
|
6
|
+
# ID of the request.
|
7
|
+
#
|
8
|
+
# @return String
|
6
9
|
attr_reader :id
|
7
|
-
attr_accessor :intercepted_request, :request, :response, :error
|
8
10
|
|
11
|
+
# The intercepted request.
|
12
|
+
#
|
13
|
+
# @return [InterceptedRequest, nil]
|
14
|
+
attr_accessor :intercepted_request
|
15
|
+
|
16
|
+
# The request object.
|
17
|
+
#
|
18
|
+
# @return [Request, nil]
|
19
|
+
attr_accessor :request
|
20
|
+
|
21
|
+
# The response object.
|
22
|
+
#
|
23
|
+
# @return [Response, nil]
|
24
|
+
attr_accessor :response
|
25
|
+
|
26
|
+
# The error object.
|
27
|
+
#
|
28
|
+
# @return [Error, nil]
|
29
|
+
attr_accessor :error
|
30
|
+
|
31
|
+
#
|
32
|
+
# Initializes the network exchange.
|
33
|
+
#
|
34
|
+
# @param [Page] page
|
35
|
+
#
|
36
|
+
# @param [String] id
|
37
|
+
#
|
9
38
|
def initialize(page, id)
|
10
39
|
@id = id
|
11
40
|
@page = page
|
@@ -13,35 +42,105 @@ module Ferrum
|
|
13
42
|
@request = @response = @error = nil
|
14
43
|
end
|
15
44
|
|
45
|
+
#
|
46
|
+
# Determines if the network exchange was caused by a page navigation
|
47
|
+
# event.
|
48
|
+
#
|
49
|
+
# @param [String] frame_id
|
50
|
+
#
|
51
|
+
# @return [Boolean]
|
52
|
+
#
|
16
53
|
def navigation_request?(frame_id)
|
17
|
-
request
|
18
|
-
request.frame_id == frame_id
|
54
|
+
request&.type?(:document) && request&.frame_id == frame_id
|
19
55
|
end
|
20
56
|
|
57
|
+
#
|
58
|
+
# Determines if the network exchange has a request.
|
59
|
+
#
|
60
|
+
# @return [Boolean]
|
61
|
+
#
|
21
62
|
def blank?
|
22
63
|
!request
|
23
64
|
end
|
24
65
|
|
66
|
+
#
|
67
|
+
# Determines if the request was intercepted and blocked.
|
68
|
+
#
|
69
|
+
# @return [Boolean]
|
70
|
+
#
|
25
71
|
def blocked?
|
26
72
|
intercepted? && intercepted_request.status?(:aborted)
|
27
73
|
end
|
28
74
|
|
75
|
+
#
|
76
|
+
# Determines if the request was blocked, a response was returned, or if an
|
77
|
+
# error occurred.
|
78
|
+
#
|
79
|
+
# @return [Boolean]
|
80
|
+
#
|
29
81
|
def finished?
|
30
|
-
blocked? || response || error
|
82
|
+
blocked? || response&.loaded? || !error.nil?
|
31
83
|
end
|
32
84
|
|
85
|
+
#
|
86
|
+
# Determines if the network exchange is still not finished.
|
87
|
+
#
|
88
|
+
# @return [Boolean]
|
89
|
+
#
|
33
90
|
def pending?
|
34
91
|
!finished?
|
35
92
|
end
|
36
93
|
|
94
|
+
#
|
95
|
+
# Determines if the exchange's request was intercepted.
|
96
|
+
#
|
97
|
+
# @return [Boolean]
|
98
|
+
#
|
37
99
|
def intercepted?
|
38
|
-
intercepted_request
|
100
|
+
!intercepted_request.nil?
|
101
|
+
end
|
102
|
+
|
103
|
+
#
|
104
|
+
# Determines if the exchange is XHR.
|
105
|
+
#
|
106
|
+
# @return [Boolean]
|
107
|
+
#
|
108
|
+
def xhr?
|
109
|
+
!!request&.xhr?
|
110
|
+
end
|
111
|
+
|
112
|
+
#
|
113
|
+
# Determines if the exchange is a redirect.
|
114
|
+
#
|
115
|
+
# @return [Boolean]
|
116
|
+
#
|
117
|
+
def redirect?
|
118
|
+
response&.redirect?
|
119
|
+
end
|
120
|
+
|
121
|
+
#
|
122
|
+
# Returns request's URL.
|
123
|
+
#
|
124
|
+
# @return [String, nil]
|
125
|
+
#
|
126
|
+
def url
|
127
|
+
request&.url
|
39
128
|
end
|
40
129
|
|
130
|
+
#
|
131
|
+
# Converts the network exchange into a request, response, and error tuple.
|
132
|
+
#
|
133
|
+
# @return [Array]
|
134
|
+
#
|
41
135
|
def to_a
|
42
136
|
[request, response, error]
|
43
137
|
end
|
44
138
|
|
139
|
+
#
|
140
|
+
# Inspects the network exchange.
|
141
|
+
#
|
142
|
+
# @return [String]
|
143
|
+
#
|
45
144
|
def inspect
|
46
145
|
"#<#{self.class} " \
|
47
146
|
"@id=#{@id.inspect} " \
|
@@ -1,10 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "ferrum/network/request_params"
|
3
4
|
require "base64"
|
4
5
|
|
5
6
|
module Ferrum
|
6
7
|
class Network
|
7
8
|
class InterceptedRequest
|
9
|
+
include RequestParams
|
10
|
+
|
8
11
|
attr_accessor :request_id, :frame_id, :resource_type, :network_id, :status
|
9
12
|
|
10
13
|
def initialize(page, params)
|
@@ -54,18 +57,6 @@ module Ferrum
|
|
54
57
|
@page.command("Fetch.failRequest", requestId: request_id, errorReason: "BlockedByClient")
|
55
58
|
end
|
56
59
|
|
57
|
-
def url
|
58
|
-
@request["url"]
|
59
|
-
end
|
60
|
-
|
61
|
-
def method
|
62
|
-
@request["method"]
|
63
|
-
end
|
64
|
-
|
65
|
-
def headers
|
66
|
-
@request["headers"]
|
67
|
-
end
|
68
|
-
|
69
60
|
def initial_priority
|
70
61
|
@request["initialPriority"]
|
71
62
|
end
|
@@ -1,55 +1,94 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "ferrum/network/request_params"
|
3
4
|
require "time"
|
4
5
|
|
5
6
|
module Ferrum
|
6
7
|
class Network
|
8
|
+
#
|
9
|
+
# Represents a [Network.Request](https://chromedevtools.github.io/devtools-protocol/1-3/Network/#type-Request)
|
10
|
+
# object.
|
11
|
+
#
|
7
12
|
class Request
|
13
|
+
include RequestParams
|
14
|
+
|
15
|
+
#
|
16
|
+
# Initializes the request object.
|
17
|
+
#
|
18
|
+
# @param [Hash{String => Object}] params
|
19
|
+
# The parsed JSON attributes.
|
20
|
+
#
|
8
21
|
def initialize(params)
|
9
22
|
@params = params
|
10
23
|
@request = @params["request"]
|
11
24
|
end
|
12
25
|
|
26
|
+
#
|
27
|
+
# The request ID.
|
28
|
+
#
|
29
|
+
# @return [String]
|
30
|
+
#
|
13
31
|
def id
|
14
32
|
@params["requestId"]
|
15
33
|
end
|
16
34
|
|
35
|
+
#
|
36
|
+
# The request resouce type.
|
37
|
+
#
|
38
|
+
# @return [String]
|
39
|
+
#
|
17
40
|
def type
|
18
41
|
@params["type"]
|
19
42
|
end
|
20
43
|
|
44
|
+
#
|
45
|
+
# Determines if the request is of the given type.
|
46
|
+
#
|
47
|
+
# @param [String, Symbol] value
|
48
|
+
# The type value to compare against.
|
49
|
+
#
|
50
|
+
# @return [Boolean]
|
51
|
+
#
|
21
52
|
def type?(value)
|
22
53
|
type.downcase == value.to_s.downcase
|
23
54
|
end
|
24
55
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
56
|
+
#
|
57
|
+
# Determines if the request is XHR.
|
58
|
+
#
|
59
|
+
# @return [Boolean]
|
60
|
+
#
|
61
|
+
def xhr?
|
62
|
+
type?("xhr")
|
31
63
|
end
|
32
64
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
def headers
|
42
|
-
@request["headers"]
|
65
|
+
#
|
66
|
+
# The frame ID of the request.
|
67
|
+
#
|
68
|
+
# @return [String]
|
69
|
+
#
|
70
|
+
def frame_id
|
71
|
+
@params["frameId"]
|
43
72
|
end
|
44
73
|
|
74
|
+
#
|
75
|
+
# The request timestamp.
|
76
|
+
#
|
77
|
+
# @return [Time]
|
78
|
+
#
|
45
79
|
def time
|
46
80
|
@time ||= Time.strptime(@params["wallTime"].to_s, "%s")
|
47
81
|
end
|
48
82
|
|
49
|
-
|
50
|
-
|
83
|
+
#
|
84
|
+
# Converts the request to a Hash.
|
85
|
+
#
|
86
|
+
# @return [Hash{String => Object}]
|
87
|
+
# The params of the request.
|
88
|
+
#
|
89
|
+
def to_h
|
90
|
+
@params
|
51
91
|
end
|
52
|
-
alias body post_data
|
53
92
|
end
|
54
93
|
end
|
55
94
|
end
|