webkit_remote 0.2.0 → 0.3.0
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.
- data/.travis.yml +10 -0
- data/Gemfile +1 -0
- data/Gemfile.lock +3 -0
- data/README.md +8 -3
- data/VERSION +1 -1
- data/lib/webkit_remote.rb +2 -0
- data/lib/webkit_remote/client.rb +44 -7
- data/lib/webkit_remote/client/console.rb +11 -10
- data/lib/webkit_remote/client/console_events.rb +29 -20
- data/lib/webkit_remote/client/network.rb +155 -0
- data/lib/webkit_remote/client/network_events.rb +584 -0
- data/lib/webkit_remote/client/page.rb +2 -2
- data/lib/webkit_remote/client/runtime.rb +23 -2
- data/lib/webkit_remote/process.rb +7 -1
- data/test/fixtures/config.ru +16 -3
- data/test/fixtures/html/console.html +1 -1
- data/test/fixtures/html/network.html +10 -0
- data/test/webkit_remote/client/console_test.rb +22 -2
- data/test/webkit_remote/client/network_test.rb +123 -0
- data/test/webkit_remote/client/runtime_test.rb +21 -0
- data/test/webkit_remote/client_test.rb +6 -0
- data/webkit_remote.gemspec +10 -2
- metadata +24 -3
data/.travis.yml
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
language: ruby
|
2
|
+
rvm:
|
3
|
+
- 1.9.3
|
4
|
+
before_install:
|
5
|
+
- "export DISPLAY=:99.0"
|
6
|
+
- "sh -e /etc/init.d/xvfb start"
|
7
|
+
- "sudo sh -c \"echo \\\"deb https://dl.google.com/linux/deb/ stable main\\\" >> /etc/apt/sources.list\""
|
8
|
+
- "sudo wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add -"
|
9
|
+
- "sudo apt-get -qq update"
|
10
|
+
- "sudo apt-get -qq install google-chrome-stable"
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -17,6 +17,8 @@ GEM
|
|
17
17
|
puma (1.6.3)
|
18
18
|
rack (~> 1.2)
|
19
19
|
rack (1.4.1)
|
20
|
+
rack-contrib (1.1.0)
|
21
|
+
rack (>= 0.9.1)
|
20
22
|
rake (0.9.2.2)
|
21
23
|
rdoc (3.12)
|
22
24
|
json (~> 1.4)
|
@@ -39,6 +41,7 @@ DEPENDENCIES
|
|
39
41
|
posix-spawn (>= 0.3.6)
|
40
42
|
puma (>= 1.6.3)
|
41
43
|
rack (>= 1.4.1)
|
44
|
+
rack-contrib (>= 1.1.0)
|
42
45
|
rdoc (>= 3.12)
|
43
46
|
ruby-prof (>= 0.11.2)
|
44
47
|
simplecov (>= 0.7.1)
|
data/README.md
CHANGED
@@ -105,10 +105,10 @@ END_JS
|
|
105
105
|
client.remote_eval('window').bound_call js_code, element, '你好'
|
106
106
|
```
|
107
107
|
|
108
|
-
Finally, release the
|
108
|
+
Finally, release the WebKit state that the debugger is holding onto.
|
109
109
|
|
110
110
|
```ruby
|
111
|
-
|
111
|
+
client.clear_all
|
112
112
|
```
|
113
113
|
|
114
114
|
### Read the Console
|
@@ -130,8 +130,13 @@ message.params
|
|
130
130
|
message.stack_trace
|
131
131
|
```
|
132
132
|
|
133
|
+
Again, release the WebKit state.
|
133
134
|
|
134
|
-
|
135
|
+
```ruby
|
136
|
+
client.clear_all
|
137
|
+
```
|
138
|
+
|
139
|
+
### Close the Browser
|
135
140
|
|
136
141
|
```ruby
|
137
142
|
client.close
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.3.0
|
data/lib/webkit_remote.rb
CHANGED
@@ -9,6 +9,8 @@ require 'webkit_remote/client.rb'
|
|
9
9
|
require 'webkit_remote/event.rb'
|
10
10
|
require 'webkit_remote/client/console.rb'
|
11
11
|
require 'webkit_remote/client/console_events.rb'
|
12
|
+
require 'webkit_remote/client/network.rb'
|
13
|
+
require 'webkit_remote/client/network_events.rb'
|
12
14
|
require 'webkit_remote/client/page.rb'
|
13
15
|
require 'webkit_remote/client/page_events.rb'
|
14
16
|
require 'webkit_remote/client/runtime.rb'
|
data/lib/webkit_remote/client.rb
CHANGED
@@ -81,6 +81,23 @@ class Client
|
|
81
81
|
events
|
82
82
|
end
|
83
83
|
|
84
|
+
# Removes all the remote debugging data cached by this client.
|
85
|
+
#
|
86
|
+
# Some modules accumulate data throughout the debigging process. For example,
|
87
|
+
# WebkitRemote::Client::Remote#remote_eval and
|
88
|
+
# WebkitRemote::Events#ConsoleMessage build Ruby equivalents of the returned
|
89
|
+
# JavaScript objects, and prevent Chrome from garbage-collecting the
|
90
|
+
# returned JavaScript objects.
|
91
|
+
#
|
92
|
+
# Although modules have individual methods for releasing this data, such as
|
93
|
+
# WebkitRemote::Client::RemoteGroup#release, keeping track of individual data
|
94
|
+
# items is very inconvenient. Therefore, if you need to run a WebkitRemote
|
95
|
+
# client for an extended period of time, you might find it easier to
|
96
|
+
# periodically call this method.
|
97
|
+
def clear_all
|
98
|
+
clear_modules
|
99
|
+
end
|
100
|
+
|
84
101
|
# @return [WebkitRemote::Rpc] the WebSocket RPC client; useful for making raw
|
85
102
|
# RPC calls to unsupported methods
|
86
103
|
attr_reader :rpc
|
@@ -89,13 +106,6 @@ class Client
|
|
89
106
|
# tab debugged by this client
|
90
107
|
attr_reader :browser
|
91
108
|
|
92
|
-
# Call by the constructor. Replaced by the module initializers.
|
93
|
-
#
|
94
|
-
# @private Hook for module initializers to do their own setups.
|
95
|
-
def initialize_modules
|
96
|
-
# NOTE: this gets called after all the module initializers complete
|
97
|
-
end
|
98
|
-
|
99
109
|
# Registers a module initializer.
|
100
110
|
def self.initializer(name)
|
101
111
|
before_name = :"initialize_modules_before_#{name}"
|
@@ -108,6 +118,33 @@ class Client
|
|
108
118
|
end
|
109
119
|
END_METHOD
|
110
120
|
end
|
121
|
+
|
122
|
+
# Registers a module clearer.
|
123
|
+
def self.clearer(name)
|
124
|
+
before_name = :"clear_modules_before_#{name}"
|
125
|
+
alias_method before_name, :clear_modules
|
126
|
+
remove_method :clear_modules
|
127
|
+
eval <<END_METHOD
|
128
|
+
def clear_modules
|
129
|
+
#{name}
|
130
|
+
#{before_name.to_s}
|
131
|
+
end
|
132
|
+
END_METHOD
|
133
|
+
end
|
134
|
+
|
135
|
+
# Called by the constructor. Aliased by the module initializers.
|
136
|
+
#
|
137
|
+
# @private Hook for module initializers to do their own setups.
|
138
|
+
def initialize_modules
|
139
|
+
# NOTE: this gets called after all the module initializers complete
|
140
|
+
end
|
141
|
+
|
142
|
+
# Called by clear_all.
|
143
|
+
#
|
144
|
+
# @private Hook for modules to run their own clearing code.
|
145
|
+
def clear_modules
|
146
|
+
# NOTE: this gets called after all the module cleaners complete
|
147
|
+
end
|
111
148
|
end # class WebkitRemote::Client
|
112
149
|
|
113
150
|
end # namespace WebkitRemote
|
@@ -4,14 +4,6 @@ class Client
|
|
4
4
|
|
5
5
|
# API for the Console domain.
|
6
6
|
module Console
|
7
|
-
# Removes all the messages in the console.
|
8
|
-
#
|
9
|
-
# @return [WebkitRemote::Client] self
|
10
|
-
def clear_console
|
11
|
-
@rpc.call 'Console.clearMessages'
|
12
|
-
self
|
13
|
-
end
|
14
|
-
|
15
7
|
# Enables or disables the generation of events in the Console domain.
|
16
8
|
#
|
17
9
|
# @param [Boolean] new_console_events if true, the browser debugger will
|
@@ -19,22 +11,31 @@ module Console
|
|
19
11
|
def console_events=(new_console_events)
|
20
12
|
new_console_events = !!new_console_events
|
21
13
|
if new_console_events != console_events
|
14
|
+
@rpc.call(new_console_events ? 'Console.enable' : 'Console.disable')
|
22
15
|
@console_events = new_console_events
|
23
|
-
@rpc.call(@console_events ? 'Console.enable' : 'Console.disable')
|
24
16
|
end
|
25
17
|
new_console_events
|
26
18
|
end
|
27
19
|
|
20
|
+
# Removes all the messages in the console.
|
21
|
+
#
|
22
|
+
# @return [WebkitRemote::Client] self
|
23
|
+
def clear_console
|
24
|
+
@rpc.call 'Console.clearMessages'
|
25
|
+
self
|
26
|
+
end
|
27
|
+
|
28
28
|
# @return [Boolean] true if the debugger generates Console.* events
|
29
29
|
attr_reader :console_events
|
30
30
|
|
31
31
|
# @private Called by the Client constructor to set up Console data.
|
32
32
|
def initialize_console
|
33
|
-
@console_events =
|
33
|
+
@console_events = false
|
34
34
|
end
|
35
35
|
end # module WebkitRemote::Client::Console
|
36
36
|
|
37
37
|
initializer :initialize_console
|
38
|
+
clearer :clear_console
|
38
39
|
include WebkitRemote::Client::Console
|
39
40
|
|
40
41
|
end # namespace WebkitRemote::Client
|
@@ -65,26 +65,8 @@ class ConsoleMessage < WebkitRemote::Event
|
|
65
65
|
else
|
66
66
|
@reason = :other
|
67
67
|
end
|
68
|
-
|
69
|
-
|
70
|
-
frame = {}
|
71
|
-
if raw_frame['columnNumber']
|
72
|
-
frame[:column] = raw_frame['columnNumber'].to_i
|
73
|
-
end
|
74
|
-
if raw_frame['lineNumber']
|
75
|
-
frame[:line] = raw_frame['lineNumber'].to_i
|
76
|
-
end
|
77
|
-
if raw_frame['functionName']
|
78
|
-
frame[:function] = raw_frame['functionName']
|
79
|
-
end
|
80
|
-
if raw_frame['url']
|
81
|
-
frame[:url] = raw_frame['url']
|
82
|
-
end
|
83
|
-
frame
|
84
|
-
end
|
85
|
-
else
|
86
|
-
@trace = nil
|
87
|
-
end
|
68
|
+
@stack_trace = WebkitRemote::Event::ConsoleMessage.parse_stack_trace(
|
69
|
+
raw_message['stackTrace'])
|
88
70
|
@text = raw_message['text']
|
89
71
|
@type = raw_message['type'] ? raw_message['type'].to_sym : nil
|
90
72
|
@source_url = raw_message['url']
|
@@ -107,6 +89,33 @@ class ConsoleMessage < WebkitRemote::Event
|
|
107
89
|
def self.can_reach?(client)
|
108
90
|
client.console_events
|
109
91
|
end
|
92
|
+
|
93
|
+
|
94
|
+
# Parses a StackTrace object returned by a RPC request.
|
95
|
+
#
|
96
|
+
# @param [Array<String, Object>] raw_stack_trace the raw StackTrace object
|
97
|
+
# in the Console domain returned by a RPC request
|
98
|
+
# @return [Array<Symbol, Object>] Ruby-friendly stack trace
|
99
|
+
def self.parse_stack_trace(raw_stack_trace)
|
100
|
+
return nil unless raw_stack_trace
|
101
|
+
|
102
|
+
raw_stack_trace.map do |raw_frame|
|
103
|
+
frame = {}
|
104
|
+
if raw_frame['columnNumber']
|
105
|
+
frame[:column] = raw_frame['columnNumber'].to_i
|
106
|
+
end
|
107
|
+
if raw_frame['lineNumber']
|
108
|
+
frame[:line] = raw_frame['lineNumber'].to_i
|
109
|
+
end
|
110
|
+
if raw_frame['functionName']
|
111
|
+
frame[:function] = raw_frame['functionName']
|
112
|
+
end
|
113
|
+
if raw_frame['url']
|
114
|
+
frame[:url] = raw_frame['url']
|
115
|
+
end
|
116
|
+
frame
|
117
|
+
end
|
118
|
+
end
|
110
119
|
end # class WebkitRemote::Event::ConsoleMessage
|
111
120
|
|
112
121
|
# Emitted when the same console message is produced repeatedly.
|
@@ -0,0 +1,155 @@
|
|
1
|
+
module WebkitRemote
|
2
|
+
|
3
|
+
class Client
|
4
|
+
|
5
|
+
# API for the Network domain.
|
6
|
+
module Network
|
7
|
+
# Enables or disables the generation of events in the Network domain.
|
8
|
+
#
|
9
|
+
# @param [Boolean] new_network_events if true, the browser debugger will
|
10
|
+
# generate Network.* events
|
11
|
+
def network_events=(new_network_events)
|
12
|
+
new_network_events = !!new_network_events
|
13
|
+
if new_network_events != network_events
|
14
|
+
@rpc.call(new_network_events ? 'Network.enable' : 'Network.disable')
|
15
|
+
@network_events = new_network_events
|
16
|
+
end
|
17
|
+
new_network_events
|
18
|
+
end
|
19
|
+
|
20
|
+
# Enables or disables the use of the network cache.
|
21
|
+
#
|
22
|
+
# @param [Boolean] new_disable_cache if true, the browser will not use its
|
23
|
+
# network cache, and will always generate HTTP requests
|
24
|
+
def disable_cache=(new_disable_cache)
|
25
|
+
new_disable_cache = !!new_disable_cache
|
26
|
+
if new_disable_cache != disable_cache
|
27
|
+
@rpc.call 'Network.setCacheDisabled', cacheDisabled: new_disable_cache
|
28
|
+
@disable_cache = new_disable_cache
|
29
|
+
end
|
30
|
+
new_disable_cache
|
31
|
+
end
|
32
|
+
|
33
|
+
# Sets the User-Agent header that the browser will use to identify itself.
|
34
|
+
#
|
35
|
+
# @param [String] new_user_agent will be used instead of the browser's
|
36
|
+
# hard-coded User-Agent header
|
37
|
+
def user_agent=(new_user_agent)
|
38
|
+
if new_user_agent != user_agent
|
39
|
+
@rpc.call 'Network.setUserAgentOverride', userAgent: new_user_agent
|
40
|
+
@user_agent = new_user_agent
|
41
|
+
end
|
42
|
+
new_user_agent
|
43
|
+
end
|
44
|
+
|
45
|
+
# Sets extra headers to be sent with every HTTP request.
|
46
|
+
#
|
47
|
+
# @param [Hash<String, String>] new_extra_headers HTTP headers to be added to
|
48
|
+
# every HTTP request sent by the browser
|
49
|
+
def http_headers=(new_http_headers)
|
50
|
+
new_http_headers = Hash[new_http_headers.map { |k, v|
|
51
|
+
[k.to_s, v.to_s]
|
52
|
+
}].freeze
|
53
|
+
if new_http_headers != http_headers
|
54
|
+
@rpc.call 'Network.setExtraHTTPHeaders', headers: new_http_headers
|
55
|
+
@http_headers = new_http_headers
|
56
|
+
end
|
57
|
+
new_http_headers
|
58
|
+
end
|
59
|
+
|
60
|
+
# Checks if the debugger can clear the browser's cookies.
|
61
|
+
#
|
62
|
+
# @return [Boolean] true if WebkitRemote::Client::Network#clear_cookies can
|
63
|
+
# be succesfully called
|
64
|
+
def can_clear_cookies?
|
65
|
+
response = @rpc.call 'Network.canClearBrowserCookies'
|
66
|
+
!!response['result']
|
67
|
+
end
|
68
|
+
|
69
|
+
# Removes all the cookies in the debugged browser.
|
70
|
+
#
|
71
|
+
# @return [WebkitRemote::Client] self
|
72
|
+
def clear_cookies
|
73
|
+
@rpc.call 'Network.clearBrowserCookies'
|
74
|
+
self
|
75
|
+
end
|
76
|
+
|
77
|
+
# Checks if the debugger can clear the browser's cache.
|
78
|
+
#
|
79
|
+
# @return [Boolean] true if WebkitRemote::Client::Network#clear_network_cache
|
80
|
+
# can be succesfully called
|
81
|
+
def can_clear_network_cache?
|
82
|
+
response = @rpc.call 'Network.canClearBrowserCache'
|
83
|
+
!!response['result']
|
84
|
+
end
|
85
|
+
|
86
|
+
# Removes all the cached data in the debugged browser.
|
87
|
+
#
|
88
|
+
# @return [WebkitRemote::Client] self
|
89
|
+
def clear_network_cache
|
90
|
+
@rpc.call 'Network.clearBrowserCache'
|
91
|
+
self
|
92
|
+
end
|
93
|
+
|
94
|
+
# @return [Boolean] true if the debugger generates Network.* events
|
95
|
+
attr_reader :network_events
|
96
|
+
|
97
|
+
# @return [Array<WebkitRemote::Client::NetworkResource>] the resources
|
98
|
+
# fetched during the debugging session
|
99
|
+
#
|
100
|
+
# This is only populated when Network events are received.
|
101
|
+
attr_reader :network_resources
|
102
|
+
|
103
|
+
# @return [Boolean] true if the browser's network cache is disabled, so every
|
104
|
+
# resource load generates an HTTP request
|
105
|
+
attr_reader :disable_cache
|
106
|
+
|
107
|
+
# @return [String] replaces the brower's built-in User-Agent string
|
108
|
+
attr_reader :user_agent
|
109
|
+
|
110
|
+
# @return [Hash<String, String>]
|
111
|
+
attr_reader :http_headers
|
112
|
+
|
113
|
+
# Looks up network resources by IDs assigned by the WebKit remote debugger.
|
114
|
+
#
|
115
|
+
# @private Use the #resource property of Network events instead of calling
|
116
|
+
# this directly.
|
117
|
+
#
|
118
|
+
# @param [String] remote_id the WebKit-assigned request_id
|
119
|
+
# @return [WebkitRemote::Client::NetworkResource] the cached information
|
120
|
+
# about the resource with the given ID
|
121
|
+
def network_resource(remote_id)
|
122
|
+
if @network_resource_hash[remote_id]
|
123
|
+
return @network_resource_hash[remote_id]
|
124
|
+
end
|
125
|
+
resource = WebkitRemote::Client::NetworkResource.new remote_id, self
|
126
|
+
|
127
|
+
@network_resources << resource
|
128
|
+
@network_resource_hash[remote_id] = resource
|
129
|
+
end
|
130
|
+
|
131
|
+
# Removes the cached network request information.
|
132
|
+
#
|
133
|
+
# @return [WebkitRemote::Client] self
|
134
|
+
def clear_network
|
135
|
+
@network_resource_hash.clear
|
136
|
+
@network_resources.clear
|
137
|
+
self
|
138
|
+
end
|
139
|
+
|
140
|
+
# @private Called by the Client constructor to set up Network data.
|
141
|
+
def initialize_network
|
142
|
+
@disable_cache = false
|
143
|
+
@network_events = false
|
144
|
+
@network_resources = []
|
145
|
+
@network_resource_hash = {}
|
146
|
+
@user_agent = nil
|
147
|
+
end
|
148
|
+
end # module WebkitRemote::Client::Network
|
149
|
+
|
150
|
+
initializer :initialize_network
|
151
|
+
include WebkitRemote::Client::Network
|
152
|
+
|
153
|
+
end # namespace WebkitRemote::Client
|
154
|
+
|
155
|
+
end # namespace WebkitRemote
|
@@ -0,0 +1,584 @@
|
|
1
|
+
module WebkitRemote
|
2
|
+
|
3
|
+
class Event
|
4
|
+
|
5
|
+
# Emitted when a chunk of data is received over the network.
|
6
|
+
class NetworkData < WebkitRemote::Event
|
7
|
+
register 'Network.dataReceived'
|
8
|
+
|
9
|
+
# @return [WebkitRemote::Client::NetworkResource] information about the
|
10
|
+
# resource fetched by this network operation
|
11
|
+
attr_reader :resource
|
12
|
+
|
13
|
+
# @return [Number] the event timestamp
|
14
|
+
attr_reader :timestamp
|
15
|
+
|
16
|
+
# @return [Number] number of bytes actually received
|
17
|
+
attr_reader :bytes_received
|
18
|
+
|
19
|
+
# @return [Number] number of data bytes received (after decompression)
|
20
|
+
attr_reader :data_length
|
21
|
+
|
22
|
+
# @private Use Event#for instead of calling this constructor directly.
|
23
|
+
def initialize(rpc_event, client)
|
24
|
+
super
|
25
|
+
@data_length = raw_data['dataLength']
|
26
|
+
@bytes_received = raw_data['encodedDataLength']
|
27
|
+
@timestamp = raw_data['timestamp']
|
28
|
+
|
29
|
+
@resource = client.network_resource raw_data['requestId']
|
30
|
+
@resource.add_event self
|
31
|
+
end
|
32
|
+
end # class WebkitRemote::Event::NetworkData
|
33
|
+
|
34
|
+
# Emitted when a resource fails to load.
|
35
|
+
class NetworkFailure < WebkitRemote::Event
|
36
|
+
register 'Network.loadingFailed'
|
37
|
+
|
38
|
+
# @return [WebkitRemote::Client::NetworkResource] information about the
|
39
|
+
# resource fetched by this network operation
|
40
|
+
attr_reader :resource
|
41
|
+
|
42
|
+
# @return [Number] the event timestamp
|
43
|
+
attr_reader :timestamp
|
44
|
+
|
45
|
+
# @return [String] the error message
|
46
|
+
attr_reader :error
|
47
|
+
|
48
|
+
# @return [Boolean] true if the request was canceled
|
49
|
+
#
|
50
|
+
# For example, CORS violations cause requests to be canceled.
|
51
|
+
attr_reader :canceled
|
52
|
+
|
53
|
+
# @private Use Event#for instead of calling this constructor directly.
|
54
|
+
def initialize(rpc_event, client)
|
55
|
+
super
|
56
|
+
@canceled = !!raw_data['canceled']
|
57
|
+
@error = raw_data['errorText']
|
58
|
+
@timestamp = raw_data['timestamp']
|
59
|
+
|
60
|
+
@resource = client.network_resource raw_data['requestId']
|
61
|
+
@resource.set_canceled @canceled
|
62
|
+
@resource.set_error @error
|
63
|
+
@resource.add_event self
|
64
|
+
end
|
65
|
+
end # class WebkitRemote::Event::NetworkFailure
|
66
|
+
|
67
|
+
# Emitted when a resource finishes loading from the network.
|
68
|
+
class NetworkLoad < WebkitRemote::Event
|
69
|
+
register 'Network.loadingFinished'
|
70
|
+
|
71
|
+
# @return [WebkitRemote::Client::NetworkResource] information about the
|
72
|
+
# resource fetched by this network operation
|
73
|
+
attr_reader :resource
|
74
|
+
|
75
|
+
# @return [Number] the event timestamp
|
76
|
+
attr_reader :timestamp
|
77
|
+
|
78
|
+
# @private Use Event#for instead of calling this constructor directly.
|
79
|
+
def initialize(rpc_event, client)
|
80
|
+
super
|
81
|
+
@timestamp = raw_data['timestamp']
|
82
|
+
|
83
|
+
@resource = client.network_resource raw_data['requestId']
|
84
|
+
@resource.add_event self
|
85
|
+
end
|
86
|
+
end # class WebkitRemote::Event::NetworkLoad
|
87
|
+
|
88
|
+
# Emitted when a resource is served from the local cache.
|
89
|
+
class NetworkCacheHit < WebkitRemote::Event
|
90
|
+
register 'Network.requestServedFromCache'
|
91
|
+
|
92
|
+
# @return [WebkitRemote::Client::NetworkResource] information about the
|
93
|
+
# resource fetched by this network operation
|
94
|
+
attr_reader :resource
|
95
|
+
|
96
|
+
# @private Use Event#for instead of calling this constructor directly.
|
97
|
+
def initialize(rpc_event, client)
|
98
|
+
super
|
99
|
+
|
100
|
+
@resource = client.network_resource raw_data['requestId']
|
101
|
+
@resource.add_event self
|
102
|
+
end
|
103
|
+
end # class WebkitRemote::Event::NetworkCacheHit
|
104
|
+
|
105
|
+
# Emitted when a resource is served from the local cache.
|
106
|
+
class NetworkMemoryCacheHit < WebkitRemote::Event
|
107
|
+
register 'Network.requestServedFromMemoryCache'
|
108
|
+
|
109
|
+
# @return [WebkitRemote::Client::NetworkResource] information about the
|
110
|
+
# resource fetched by this network operation
|
111
|
+
attr_reader :resource
|
112
|
+
|
113
|
+
# @return [WebkitRemote::Client::NetworkCacheEntry] cached information used
|
114
|
+
# to produce the resource
|
115
|
+
attr_reader :cache_data
|
116
|
+
|
117
|
+
# @return [String] the URL of the document that caused this network request
|
118
|
+
attr_reader :document_url
|
119
|
+
|
120
|
+
# @return [WebkitRemote::Client::NetworkRequestInitiator] cause for this
|
121
|
+
# network request
|
122
|
+
attr_reader :initiator
|
123
|
+
|
124
|
+
# @return [Number] the event timestamp
|
125
|
+
attr_reader :timestamp
|
126
|
+
|
127
|
+
# @private Use Event#for instead of calling this constructor directly.
|
128
|
+
def initialize(rpc_event, client)
|
129
|
+
super
|
130
|
+
|
131
|
+
if raw_data['resource']
|
132
|
+
@cache_data = raw_data['resource']
|
133
|
+
end
|
134
|
+
@document_url = raw_data['documentURL']
|
135
|
+
if raw_data['initiator']
|
136
|
+
@initiator = WebkitRemote::Client::NetworkRequestInitiator.new(
|
137
|
+
raw_data['initiator'])
|
138
|
+
end
|
139
|
+
@loader_id = raw_data['loaderId']
|
140
|
+
@timestamp = raw_data['timestamp']
|
141
|
+
|
142
|
+
@resource = client.network_resource raw_data['requestId']
|
143
|
+
@resource.set_document_url @document_url
|
144
|
+
@resource.set_initiator @initiator
|
145
|
+
if @cache_data
|
146
|
+
@resource.set_response @cache_data.response
|
147
|
+
@resource.set_type @cache_data.type
|
148
|
+
end
|
149
|
+
@resource.add_event self
|
150
|
+
end
|
151
|
+
end # class WebkitRemote::Event::NetworkMemoryCacheHit
|
152
|
+
|
153
|
+
# Emitted right before a network request.
|
154
|
+
class NetworkRequest < WebkitRemote::Event
|
155
|
+
register 'Network.requestWillBeSent'
|
156
|
+
|
157
|
+
# @return [WebkitRemote::Client::NetworkResource] information about the
|
158
|
+
# resource fetched by this network operation
|
159
|
+
attr_reader :resource
|
160
|
+
|
161
|
+
# @return [WebkitRemote::Client::NetworkRequest] information about this
|
162
|
+
# network request
|
163
|
+
attr_reader :request
|
164
|
+
|
165
|
+
# @return [String] the URL of the document that caused this network request
|
166
|
+
attr_reader :document_url
|
167
|
+
|
168
|
+
# @return [WebkitRemote::Client::NetworkRequestInitiator] cause for this
|
169
|
+
# network request
|
170
|
+
attr_reader :initiator
|
171
|
+
|
172
|
+
# @return [WebkitRemote::Client::NetworkResponse] the HTTP redirect that
|
173
|
+
# caused this request; can be nil
|
174
|
+
attr_reader :redirect_response
|
175
|
+
|
176
|
+
# @return [String] used to correlate events
|
177
|
+
attr_reader :loader_id
|
178
|
+
|
179
|
+
# @return [Number] the event timestamp
|
180
|
+
attr_reader :timestamp
|
181
|
+
|
182
|
+
# @private Use Event#for instead of calling this constructor directly.
|
183
|
+
def initialize(rpc_event, client)
|
184
|
+
super
|
185
|
+
if raw_data['initiator']
|
186
|
+
@initiator = WebkitRemote::Client::NetworkRequestInitiator.new(
|
187
|
+
raw_data['initiator'])
|
188
|
+
end
|
189
|
+
@loader_id = raw_data['loaderId']
|
190
|
+
if raw_data['request']
|
191
|
+
@request = WebkitRemote::Client::NetworkRequest.new(
|
192
|
+
raw_data['request'])
|
193
|
+
end
|
194
|
+
if raw_data['redirectResponse']
|
195
|
+
@redirect_response = WebkitRemote::Client::NetworkResponse.new(
|
196
|
+
raw_data['redirectResponse'])
|
197
|
+
end
|
198
|
+
if raw_data['stackTrace']
|
199
|
+
@stack_trace = WebkitRemote::Event::ConsoleMessage.parse_stack_trace(
|
200
|
+
raw_initiator['stackTrace'])
|
201
|
+
else
|
202
|
+
@stack_trace = nil
|
203
|
+
end
|
204
|
+
@timestamp = raw_data['timestamp']
|
205
|
+
|
206
|
+
@resource = client.network_resource raw_data['requestId']
|
207
|
+
@resource.set_initiator @initiator
|
208
|
+
@resource.set_request @request
|
209
|
+
# TODO(pwnall): consider tracking redirects
|
210
|
+
@resource.add_event self
|
211
|
+
end
|
212
|
+
|
213
|
+
# @private Use Event#can_receive instead of calling this directly.
|
214
|
+
def self.can_reach?(client)
|
215
|
+
client.network_events
|
216
|
+
end
|
217
|
+
end # class WebkitRemote::Event::NetworkRequest
|
218
|
+
|
219
|
+
# Emitted right after receiving a response to a network request.
|
220
|
+
class NetworkResponse < WebkitRemote::Event
|
221
|
+
register 'Network.responseReceived'
|
222
|
+
|
223
|
+
# @return [WebkitRemote::Client::NetworkResource] information about the
|
224
|
+
# resource fetched by this network operation
|
225
|
+
attr_reader :resource
|
226
|
+
|
227
|
+
# @return [WebkitRemote::Client::NetworkResponse] information about the HTTP
|
228
|
+
# response behind this event
|
229
|
+
attr_reader :response
|
230
|
+
|
231
|
+
# @return [Symbol] the type of resource returned by this response; documented
|
232
|
+
# values are :document, :font, :image, :other, :script, :stylesheet,
|
233
|
+
# :websocket and :xhr
|
234
|
+
attr_reader :type
|
235
|
+
|
236
|
+
# @return [Number] the event timestamp
|
237
|
+
attr_reader :timestamp
|
238
|
+
|
239
|
+
# @return [String] used to correlate events
|
240
|
+
attr_reader :loader_id
|
241
|
+
|
242
|
+
# @private Use Event#for instead of calling this constructor directly.
|
243
|
+
def initialize(rpc_event, client)
|
244
|
+
super
|
245
|
+
@loader_id = raw_data['loaderId']
|
246
|
+
if raw_data['response']
|
247
|
+
@response = WebkitRemote::Client::NetworkResponse.new(
|
248
|
+
raw_data['response'])
|
249
|
+
end
|
250
|
+
@type = (raw_data['type'] || 'other').downcase.to_sym
|
251
|
+
@timestamp = raw_data['timestamp']
|
252
|
+
|
253
|
+
@resource = client.network_resource raw_data['requestId']
|
254
|
+
@resource.set_response @response
|
255
|
+
@resource.set_type @type
|
256
|
+
@resource.add_event self
|
257
|
+
end
|
258
|
+
|
259
|
+
# @private Use Event#can_receive instead of calling this directly.
|
260
|
+
def self.can_reach?(client)
|
261
|
+
client.network_events
|
262
|
+
end
|
263
|
+
end # class WebkitRemote::Event::NetworkResponse
|
264
|
+
|
265
|
+
end # namespace WebkitRemote::Event
|
266
|
+
|
267
|
+
|
268
|
+
class Client
|
269
|
+
|
270
|
+
# Wraps information about the network operations for retrieving a resource.
|
271
|
+
class NetworkResource
|
272
|
+
# @return [WebkitRemote::Client::NetworkRequest] network request (most likely
|
273
|
+
# HTTP) used to fetch this resource
|
274
|
+
attr_reader :request
|
275
|
+
|
276
|
+
# @return [WebkitRemote::Client::NetworkRequest] network response that
|
277
|
+
# contains this resource
|
278
|
+
attr_reader :response
|
279
|
+
|
280
|
+
# @return [Symbol] the type of this resource; documented values are
|
281
|
+
# :document, :font, :image, :other, :script, :stylesheet, :websocket and
|
282
|
+
# :xhr
|
283
|
+
attr_reader :type
|
284
|
+
|
285
|
+
# @return [String] the URL of the document that referenced this resource
|
286
|
+
attr_reader :document_url
|
287
|
+
|
288
|
+
# @return [WebkitRemote::Client::NetworkRequestInitiator] cause for this
|
289
|
+
# resource to be fetched from the network
|
290
|
+
attr_reader :initiator
|
291
|
+
|
292
|
+
# @return [Boolean] true if the request fetch was canceled
|
293
|
+
attr_reader :canceled
|
294
|
+
|
295
|
+
# @return [String] error message, if the resource fetching failed
|
296
|
+
attr_reader :error
|
297
|
+
|
298
|
+
# @return [WebkitRemote::Event] last event connected to this resource; can be
|
299
|
+
# used to determine the resource's status
|
300
|
+
attr_reader :last_event
|
301
|
+
|
302
|
+
# @return [WebkitRemote::Client] remote debugging client that reported this
|
303
|
+
attr_reader :client
|
304
|
+
|
305
|
+
# @return [String] request_id assigned by the remote WebKit debugger
|
306
|
+
attr_reader :remote_id
|
307
|
+
|
308
|
+
# Creates an empty network operation wrapper.
|
309
|
+
#
|
310
|
+
# @private Use WebkitRemote::Client::Network#network_op instead of calling
|
311
|
+
# this directly.
|
312
|
+
# @param [String] remote_id the request_id used by the remote debugging
|
313
|
+
# server to identify this network operation
|
314
|
+
# @param [WebkitRemote::Client]
|
315
|
+
def initialize(remote_id, client)
|
316
|
+
@remote_id = remote_id
|
317
|
+
@client = client
|
318
|
+
@request = nil
|
319
|
+
@response = nil
|
320
|
+
@type = nil
|
321
|
+
@document_url = nil
|
322
|
+
@initiator = nil
|
323
|
+
@canceled = false
|
324
|
+
@last_event = nil
|
325
|
+
end
|
326
|
+
|
327
|
+
# @private Rely on the event processing code to set this property.
|
328
|
+
def set_canceled(new_canceled)
|
329
|
+
@canceled ||= new_canceled
|
330
|
+
end
|
331
|
+
|
332
|
+
# @private Rely on the event processing code to set this property.
|
333
|
+
def set_document_url(new_document_url)
|
334
|
+
return if new_document_url == nil
|
335
|
+
@document_url = new_document_url
|
336
|
+
end
|
337
|
+
|
338
|
+
# @private Rely on the event processing code to set this property.
|
339
|
+
def set_error(new_error)
|
340
|
+
return if new_error == nil
|
341
|
+
@error = new_error
|
342
|
+
end
|
343
|
+
|
344
|
+
# @private Rely on the event processing code to set this property.
|
345
|
+
def set_initiator(new_initiator)
|
346
|
+
return if new_initiator == nil
|
347
|
+
@initiator = new_initiator
|
348
|
+
end
|
349
|
+
|
350
|
+
# @private Rely on the event processing code to set this property.
|
351
|
+
def set_request(new_request)
|
352
|
+
return if new_request == nil
|
353
|
+
# TODO(pwnall): consider handling multiple requests
|
354
|
+
@request = new_request
|
355
|
+
end
|
356
|
+
|
357
|
+
# @private Rely on the event processing code to set this property.
|
358
|
+
def set_response(new_response)
|
359
|
+
return if new_response == nil
|
360
|
+
@response = new_response
|
361
|
+
end
|
362
|
+
|
363
|
+
# @private Rely on the event processing code to set this property.
|
364
|
+
def set_type(new_type)
|
365
|
+
return if new_type == nil
|
366
|
+
@type = new_type
|
367
|
+
end
|
368
|
+
|
369
|
+
# @private Rely on the event processing code to set this property.
|
370
|
+
def add_event(event)
|
371
|
+
@last_event = event
|
372
|
+
# TODO(pwnall): consider keeping track of all events
|
373
|
+
end
|
374
|
+
end # namespace WebkitRemote::Event
|
375
|
+
|
376
|
+
# Wraps information about HTTP requests.
|
377
|
+
class NetworkRequest
|
378
|
+
# @return [String] the URL of the request
|
379
|
+
attr_reader :url
|
380
|
+
|
381
|
+
# @return [Symbol, nil] HTTP request method, e.g. :get
|
382
|
+
attr_reader :method
|
383
|
+
|
384
|
+
# @return [Hash<String, String>] the HTTP headers of the request
|
385
|
+
attr_reader :headers
|
386
|
+
|
387
|
+
# @return [String] the body of a POST request
|
388
|
+
attr_reader :body
|
389
|
+
|
390
|
+
# @private use Event#for instead of calling this constructor directly
|
391
|
+
#
|
392
|
+
# @param [Hash<String, Number>] the raw RPC data for a Response object
|
393
|
+
# in the Network domain
|
394
|
+
def initialize(raw_response)
|
395
|
+
@headers = raw_response['headers'] || {}
|
396
|
+
@method = raw_response['method'] ? raw_response['method'].downcase.to_sym :
|
397
|
+
nil
|
398
|
+
@body = raw_response['postData']
|
399
|
+
@url = raw_response['url']
|
400
|
+
end
|
401
|
+
end # class WebkitRemote::Client::NetworkRequest
|
402
|
+
|
403
|
+
# Wraps information about responses to network requests.
|
404
|
+
class NetworkResponse
|
405
|
+
# @return [String] the URL of the response
|
406
|
+
attr_reader :url
|
407
|
+
|
408
|
+
# @return [Number] HTTP status code
|
409
|
+
attr_reader :status
|
410
|
+
|
411
|
+
# @return [String] HTTP status message
|
412
|
+
attr_reader :status_text
|
413
|
+
|
414
|
+
# @return [Hash<String, String>] HTTP response headers
|
415
|
+
attr_reader :headers
|
416
|
+
|
417
|
+
# @return [String] the browser-determined response MIME type
|
418
|
+
attr_reader :mime_type
|
419
|
+
|
420
|
+
# @return [Hash<String, String>] HTTP request headers
|
421
|
+
attr_reader :request_headers
|
422
|
+
|
423
|
+
# @return [Boolean] true if the request was served from cache
|
424
|
+
attr_reader :from_cache
|
425
|
+
|
426
|
+
# @return [Number] id of the network connection used by the browser to fetch
|
427
|
+
# this resource
|
428
|
+
attr_reader :connection_id
|
429
|
+
|
430
|
+
# @return [Boolean] true if the network connection used for this request was
|
431
|
+
# already open
|
432
|
+
attr_reader :connection_reused
|
433
|
+
|
434
|
+
# @private use Event#for instead of calling this constructor directly
|
435
|
+
#
|
436
|
+
# @param [Hash<String, Number>] the raw RPC data for a Response object
|
437
|
+
# in the Network domain
|
438
|
+
def initialize(raw_response)
|
439
|
+
@connection_id = raw_response['connectionId']
|
440
|
+
@connection_reused = raw_response['connectionReused'] || false
|
441
|
+
@from_cache = raw_response['fromDiskCache'] || false
|
442
|
+
@headers = raw_response['headers'] || {}
|
443
|
+
@mime_type = raw_response['mimeType']
|
444
|
+
@request_headers = raw_response['requestHeaders'] || {}
|
445
|
+
@status = raw_response['status']
|
446
|
+
@status_text = raw_response['statusText']
|
447
|
+
if raw_response['timing']
|
448
|
+
@timing = WebkitRemote::Client::NetworkResourceTiming.new(
|
449
|
+
raw_response['timing'])
|
450
|
+
else
|
451
|
+
@timing = nil
|
452
|
+
end
|
453
|
+
@url = raw_response['url']
|
454
|
+
end
|
455
|
+
end # class WebkitRemote::Client::NetworkResponse
|
456
|
+
|
457
|
+
# Wraps timing information for network events.
|
458
|
+
class NetworkResourceTiming
|
459
|
+
# @param [Number] baseline time for the HTTP request used to fetch a resource
|
460
|
+
attr_reader :time
|
461
|
+
|
462
|
+
# @param [Number] milliseconds from {#time} until the start of the server DNS
|
463
|
+
# resolution
|
464
|
+
attr_reader :dns_start_ms
|
465
|
+
|
466
|
+
# @param [Number] milliseconds from {#time} until the server DNS resolution
|
467
|
+
# completed
|
468
|
+
attr_reader :dns_end_ms
|
469
|
+
|
470
|
+
# @param [Number] milliseconds from {#time} until the start of the proxy DNS
|
471
|
+
# resolution
|
472
|
+
attr_reader :proxy_start_ms
|
473
|
+
|
474
|
+
# @param [Number] milliseconds from {#time} until the proxy DNS resolution
|
475
|
+
# completed
|
476
|
+
attr_reader :proxy_end_ms
|
477
|
+
|
478
|
+
# @param [Number] milliseconds from {#time} until the TCP connection
|
479
|
+
# started being established
|
480
|
+
attr_reader :connect_start_ms
|
481
|
+
|
482
|
+
# @param [Number] milliseconds from {#time} until the TCP connection
|
483
|
+
# was established
|
484
|
+
attr_reader :connect_end_ms
|
485
|
+
|
486
|
+
# @param [Number] milliseconds from {#time} until the start of the SSL
|
487
|
+
# handshake
|
488
|
+
attr_reader :ssl_start_ms
|
489
|
+
|
490
|
+
# @param [Number] milliseconds from {#time} until the SSL handshake completed
|
491
|
+
attr_reader :ssl_end_ms
|
492
|
+
|
493
|
+
# @param [Number] milliseconds from {#time} until the HTTP request started
|
494
|
+
# being transmitted
|
495
|
+
attr_reader :send_start_ms
|
496
|
+
|
497
|
+
# @param [Number] milliseconds from {#time} until the HTTP request finished
|
498
|
+
# transmitting
|
499
|
+
attr_reader :send_end_ms
|
500
|
+
|
501
|
+
# @param [Number] milliseconds from {#time} until all the response HTTP
|
502
|
+
# headers were received
|
503
|
+
attr_reader :receive_headers_end_ms
|
504
|
+
|
505
|
+
# @private use Event#for instead of calling this constructor directly
|
506
|
+
#
|
507
|
+
# @param [Hash<String, Number>] the raw RPC data for a ResourceTiming object
|
508
|
+
# in the Network domain
|
509
|
+
def initialize(raw_timing)
|
510
|
+
@time = raw_timing['requestTime'].to_f
|
511
|
+
|
512
|
+
@connect_start_ms = raw_timing['connectStart'].to_f
|
513
|
+
@connect_end_ms = raw_timing['connectEnd'].to_f
|
514
|
+
@dns_start_ms = raw_timing['dnsStart'].to_f
|
515
|
+
@dns_end_ms = raw_timing['dnsEnd'].to_f
|
516
|
+
@proxy_start_ms = raw_timing['proxyStart'].to_f
|
517
|
+
@proxy_end_ms = raw_timing['proxyEnd'].to_f
|
518
|
+
@receive_headers_end_ms = raw_timing['receiveHeadersEnd'].to_f
|
519
|
+
@send_start_ms = raw_timing['sendStart'].to_f
|
520
|
+
@send_end_ms = raw_timing['sendEnd'].to_f
|
521
|
+
@ssl_start_ms = raw_timing['sslStart'].to_f
|
522
|
+
@ssl_end_ms = raw_timing['sslEnd'].to_f
|
523
|
+
end
|
524
|
+
end # class WebkitRemote::Client::NetworkResourceTiming
|
525
|
+
|
526
|
+
# Wraps information about the reason behind a network request.
|
527
|
+
class NetworkRequestInitiator
|
528
|
+
# @return [Symbol] reason behind the request; documented values are :parser,
|
529
|
+
# :script and :other
|
530
|
+
attr_reader :type
|
531
|
+
|
532
|
+
# @return [String] URL of the document that references the requested resource
|
533
|
+
attr_reader :url
|
534
|
+
|
535
|
+
# @return [Number] number of the line that references the requested resource
|
536
|
+
attr_reader :line
|
537
|
+
|
538
|
+
# @return [WebkitRemote::Console
|
539
|
+
attr_reader :stack_trace
|
540
|
+
|
541
|
+
# @private Use Event#for instead of calling this constructor directly
|
542
|
+
def initialize(raw_initiator)
|
543
|
+
if raw_initiator['lineNumber']
|
544
|
+
@line = raw_initiator['lineNumber'].to_i
|
545
|
+
else
|
546
|
+
@line = nil
|
547
|
+
end
|
548
|
+
@stack_trace = WebkitRemote::Event::ConsoleMessage.parse_stack_trace(
|
549
|
+
raw_initiator['stackTrace'])
|
550
|
+
@type = (raw_initiator['type'] || 'other').to_sym
|
551
|
+
@url = raw_initiator['url']
|
552
|
+
end
|
553
|
+
end # class WebkitRemote::Client::NetworkRequestInitiator
|
554
|
+
|
555
|
+
|
556
|
+
# Wraps information about a resource served out of the browser's cache.
|
557
|
+
class NetworkCacheEntry
|
558
|
+
# @return [Symbol] the type of resource returned by this response; documented
|
559
|
+
# values are :document, :font, :image, :other, :script, :stylesheet,
|
560
|
+
# :websocket and :xhr
|
561
|
+
attr_reader :type
|
562
|
+
|
563
|
+
# @return [String] the URL of the response
|
564
|
+
attr_reader :url
|
565
|
+
|
566
|
+
# @return [WebkitRemote::Client::NetworkResponse] the cached response data
|
567
|
+
attr_reader :response
|
568
|
+
|
569
|
+
# @private Use Event#for instead of calling this constructor directly
|
570
|
+
def initialize(raw_cached_resource)
|
571
|
+
if raw_cached_resource['response']
|
572
|
+
@response = WebkitRemote::Client::NetworkResponse.new(
|
573
|
+
raw_cached_resource['response'])
|
574
|
+
else
|
575
|
+
@response = nil
|
576
|
+
end
|
577
|
+
@type = (raw_cached_resource['type'] || 'other').downcase.to_sym
|
578
|
+
@url = raw_cached_resource['url']
|
579
|
+
end
|
580
|
+
end # namespace WebkitRemote::Client::NetworkCacheEntry
|
581
|
+
|
582
|
+
end # namespace WebkitRemote::Client
|
583
|
+
|
584
|
+
end # namepspace WebkitRemote
|