Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(138)

Side by Side Diff: content/browser/debugger/devtools_netlog_observer.cc

Issue 11630004: DevTools: rename debugger/ to devtools/, move DevTools files into content/renderer/devtools. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: For landing Created 8 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/browser/debugger/devtools_netlog_observer.h"
6
7 #include "base/string_tokenizer.h"
8 #include "base/string_util.h"
9 #include "base/values.h"
10 #include "content/public/browser/browser_thread.h"
11 #include "content/public/browser/content_browser_client.h"
12 #include "content/public/common/resource_response.h"
13 #include "net/base/load_flags.h"
14 #include "net/http/http_response_headers.h"
15 #include "net/http/http_util.h"
16 #include "net/spdy/spdy_header_block.h"
17 #include "net/url_request/url_request.h"
18 #include "net/url_request/url_request_netlog_params.h"
19 #include "webkit/glue/resource_loader_bridge.h"
20
21 namespace content {
22 const size_t kMaxNumEntries = 1000;
23
24 DevToolsNetLogObserver* DevToolsNetLogObserver::instance_ = NULL;
25
26 DevToolsNetLogObserver::DevToolsNetLogObserver() {
27 }
28
29 DevToolsNetLogObserver::~DevToolsNetLogObserver() {
30 }
31
32 DevToolsNetLogObserver::ResourceInfo*
33 DevToolsNetLogObserver::GetResourceInfo(uint32 id) {
34 RequestToInfoMap::iterator it = request_to_info_.find(id);
35 if (it != request_to_info_.end())
36 return it->second;
37 return NULL;
38 }
39
40 void DevToolsNetLogObserver::OnAddEntry(const net::NetLog::Entry& entry) {
41 // The events that the Observer is interested in only occur on the IO thread.
42 if (!BrowserThread::CurrentlyOn(BrowserThread::IO))
43 return;
44
45 if (entry.source().type == net::NetLog::SOURCE_URL_REQUEST)
46 OnAddURLRequestEntry(entry);
47 else if (entry.source().type == net::NetLog::SOURCE_HTTP_STREAM_JOB)
48 OnAddHTTPStreamJobEntry(entry);
49 else if (entry.source().type == net::NetLog::SOURCE_SOCKET)
50 OnAddSocketEntry(entry);
51 }
52
53 void DevToolsNetLogObserver::OnAddURLRequestEntry(
54 const net::NetLog::Entry& entry) {
55 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
56
57 bool is_begin = entry.phase() == net::NetLog::PHASE_BEGIN;
58 bool is_end = entry.phase() == net::NetLog::PHASE_END;
59
60 if (entry.type() == net::NetLog::TYPE_URL_REQUEST_START_JOB) {
61 if (is_begin) {
62 int load_flags;
63 scoped_ptr<Value> event_param(entry.ParametersToValue());
64 if (!net::StartEventLoadFlagsFromEventParams(event_param.get(),
65 &load_flags)) {
66 return;
67 }
68
69 if (!(load_flags & net::LOAD_REPORT_RAW_HEADERS))
70 return;
71
72 if (request_to_info_.size() > kMaxNumEntries) {
73 LOG(WARNING) << "The raw headers observer url request count has grown "
74 "larger than expected, resetting";
75 request_to_info_.clear();
76 }
77
78 request_to_info_[entry.source().id] = new ResourceInfo();
79
80 if (request_to_encoded_data_length_.size() > kMaxNumEntries) {
81 LOG(WARNING) << "The encoded data length observer url request count "
82 "has grown larger than expected, resetting";
83 request_to_encoded_data_length_.clear();
84 }
85
86 request_to_encoded_data_length_[entry.source().id] = 0;
87 }
88 return;
89 } else if (entry.type() == net::NetLog::TYPE_REQUEST_ALIVE) {
90 // Cleanup records based on the TYPE_REQUEST_ALIVE entry.
91 if (is_end) {
92 request_to_info_.erase(entry.source().id);
93 request_to_encoded_data_length_.erase(entry.source().id);
94 }
95 return;
96 }
97
98 ResourceInfo* info = GetResourceInfo(entry.source().id);
99 if (!info)
100 return;
101
102 switch (entry.type()) {
103 case net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS: {
104 scoped_ptr<Value> event_params(entry.ParametersToValue());
105 std::string request_line;
106 net::HttpRequestHeaders request_headers;
107
108 if (!net::HttpRequestHeaders::FromNetLogParam(event_params.get(),
109 &request_headers,
110 &request_line)) {
111 NOTREACHED();
112 }
113
114 // We need to clear headers in case the same url_request is reused for
115 // several http requests (e.g. see http://crbug.com/80157).
116 info->request_headers.clear();
117
118 for (net::HttpRequestHeaders::Iterator it(request_headers);
119 it.GetNext();) {
120 info->request_headers.push_back(std::make_pair(it.name(), it.value()));
121 }
122 info->request_headers_text = request_line + request_headers.ToString();
123 break;
124 }
125 case net::NetLog::TYPE_HTTP_TRANSACTION_SPDY_SEND_REQUEST_HEADERS: {
126 scoped_ptr<Value> event_params(entry.ParametersToValue());
127 net::SpdyHeaderBlock request_headers;
128
129 if (!net::SpdyHeaderBlockFromNetLogParam(event_params.get(),
130 &request_headers)) {
131 NOTREACHED();
132 }
133
134 // We need to clear headers in case the same url_request is reused for
135 // several http requests (e.g. see http://crbug.com/80157).
136 info->request_headers.clear();
137
138 for (net::SpdyHeaderBlock::const_iterator it = request_headers.begin();
139 it != request_headers.end(); ++it) {
140 info->request_headers.push_back(std::make_pair(it->first, it->second));
141 }
142 info->request_headers_text = "";
143 break;
144 }
145 case net::NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS: {
146 scoped_ptr<Value> event_params(entry.ParametersToValue());
147
148 scoped_refptr<net::HttpResponseHeaders> response_headers;
149
150 if (!net::HttpResponseHeaders::FromNetLogParam(event_params.get(),
151 &response_headers)) {
152 NOTREACHED();
153 }
154
155 info->http_status_code = response_headers->response_code();
156 info->http_status_text = response_headers->GetStatusText();
157 std::string name, value;
158
159 // We need to clear headers in case the same url_request is reused for
160 // several http requests (e.g. see http://crbug.com/80157).
161 info->response_headers.clear();
162
163 for (void* it = NULL;
164 response_headers->EnumerateHeaderLines(&it, &name, &value); ) {
165 info->response_headers.push_back(std::make_pair(name, value));
166 }
167 info->response_headers_text =
168 net::HttpUtil::ConvertHeadersBackToHTTPResponse(
169 response_headers->raw_headers());
170 break;
171 }
172 case net::NetLog::TYPE_HTTP_STREAM_REQUEST_BOUND_TO_JOB: {
173 scoped_ptr<Value> event_params(entry.ParametersToValue());
174 net::NetLog::Source http_stream_job_source;
175 if (!net::NetLog::Source::FromEventParameters(event_params.get(),
176 &http_stream_job_source)) {
177 NOTREACHED();
178 break;
179 }
180
181 uint32 http_stream_job_id = http_stream_job_source.id;
182 HTTPStreamJobToSocketMap::iterator it =
183 http_stream_job_to_socket_.find(http_stream_job_id);
184 if (it == http_stream_job_to_socket_.end())
185 return;
186 uint32 socket_id = it->second;
187
188 if (socket_to_request_.size() > kMaxNumEntries) {
189 LOG(WARNING) << "The url request observer socket count has grown "
190 "larger than expected, resetting";
191 socket_to_request_.clear();
192 }
193
194 socket_to_request_[socket_id] = entry.source().id;
195 http_stream_job_to_socket_.erase(http_stream_job_id);
196 break;
197 }
198 default:
199 break;
200 }
201 }
202
203 void DevToolsNetLogObserver::OnAddHTTPStreamJobEntry(
204 const net::NetLog::Entry& entry) {
205 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
206
207 if (entry.type() == net::NetLog::TYPE_SOCKET_POOL_BOUND_TO_SOCKET) {
208 scoped_ptr<Value> event_params(entry.ParametersToValue());
209 net::NetLog::Source socket_source;
210 if (!net::NetLog::Source::FromEventParameters(event_params.get(),
211 &socket_source)) {
212 NOTREACHED();
213 return;
214 }
215
216 // Prevents us from passively growing the memory unbounded in
217 // case something went wrong. Should not happen.
218 if (http_stream_job_to_socket_.size() > kMaxNumEntries) {
219 LOG(WARNING) << "The load timing observer http stream job count "
220 "has grown larger than expected, resetting";
221 http_stream_job_to_socket_.clear();
222 }
223 http_stream_job_to_socket_[entry.source().id] = socket_source.id;
224 }
225 }
226
227 void DevToolsNetLogObserver::OnAddSocketEntry(
228 const net::NetLog::Entry& entry) {
229 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
230
231 bool is_end = entry.phase() == net::NetLog::PHASE_END;
232
233 SocketToRequestMap::iterator it =
234 socket_to_request_.find(entry.source().id);
235 if (it == socket_to_request_.end())
236 return;
237 uint32 request_id = it->second;
238
239 if (entry.type() == net::NetLog::TYPE_SOCKET_IN_USE) {
240 if (is_end)
241 socket_to_request_.erase(entry.source().id);
242 return;
243 }
244
245 RequestToEncodedDataLengthMap::iterator encoded_data_length_it =
246 request_to_encoded_data_length_.find(request_id);
247 if (encoded_data_length_it == request_to_encoded_data_length_.end())
248 return;
249
250 if (net::NetLog::TYPE_SOCKET_BYTES_RECEIVED == entry.type()) {
251 int byte_count = 0;
252 scoped_ptr<Value> value(entry.ParametersToValue());
253 if (!value->IsType(Value::TYPE_DICTIONARY))
254 return;
255
256 DictionaryValue* dValue = static_cast<DictionaryValue*>(value.get());
257 if (!dValue->GetInteger("byte_count", &byte_count))
258 return;
259
260 encoded_data_length_it->second += byte_count;
261 }
262 }
263
264 void DevToolsNetLogObserver::Attach() {
265 DCHECK(!instance_);
266 net::NetLog* net_log = GetContentClient()->browser()->GetNetLog();
267 if (net_log) {
268 instance_ = new DevToolsNetLogObserver();
269 net_log->AddThreadSafeObserver(instance_, net::NetLog::LOG_ALL_BUT_BYTES);
270 }
271 }
272
273 void DevToolsNetLogObserver::Detach() {
274 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
275
276 if (instance_) {
277 // Safest not to do this in the destructor to maintain thread safety across
278 // refactorings.
279 instance_->net_log()->RemoveThreadSafeObserver(instance_);
280 delete instance_;
281 instance_ = NULL;
282 }
283 }
284
285 DevToolsNetLogObserver* DevToolsNetLogObserver::GetInstance() {
286 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
287
288 return instance_;
289 }
290
291 // static
292 void DevToolsNetLogObserver::PopulateResponseInfo(
293 net::URLRequest* request,
294 ResourceResponse* response) {
295 if (!(request->load_flags() & net::LOAD_REPORT_RAW_HEADERS))
296 return;
297
298 uint32 source_id = request->net_log().source().id;
299 DevToolsNetLogObserver* dev_tools_net_log_observer =
300 DevToolsNetLogObserver::GetInstance();
301 if (dev_tools_net_log_observer == NULL)
302 return;
303 response->head.devtools_info =
304 dev_tools_net_log_observer->GetResourceInfo(source_id);
305 }
306
307 // static
308 int DevToolsNetLogObserver::GetAndResetEncodedDataLength(
309 net::URLRequest* request) {
310 if (!(request->load_flags() & net::LOAD_REPORT_RAW_HEADERS))
311 return -1;
312
313 uint32 source_id = request->net_log().source().id;
314 DevToolsNetLogObserver* dev_tools_net_log_observer =
315 DevToolsNetLogObserver::GetInstance();
316 if (dev_tools_net_log_observer == NULL)
317 return -1;
318
319 RequestToEncodedDataLengthMap::iterator it =
320 dev_tools_net_log_observer->request_to_encoded_data_length_.find(
321 source_id);
322 if (it == dev_tools_net_log_observer->request_to_encoded_data_length_.end())
323 return -1;
324 int encoded_data_length = it->second;
325 it->second = 0;
326 return encoded_data_length;
327 }
328
329 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/debugger/devtools_netlog_observer.h ('k') | content/browser/debugger/devtools_resources.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698