[refactor] More post-NSS WebCrypto cleanups (utility functions).
[chromium-blink-merge.git] / content / browser / devtools / devtools_netlog_observer.cc
blob6da15c16b1fbb087633eca0631f813b9cfdb0ed6
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.
5 #include "content/browser/devtools/devtools_netlog_observer.h"
7 #include "base/strings/string_util.h"
8 #include "base/values.h"
9 #include "content/browser/loader/resource_request_info_impl.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"
20 namespace content {
21 const size_t kMaxNumEntries = 1000;
23 DevToolsNetLogObserver* DevToolsNetLogObserver::instance_ = NULL;
25 DevToolsNetLogObserver::DevToolsNetLogObserver() {
28 DevToolsNetLogObserver::~DevToolsNetLogObserver() {
31 DevToolsNetLogObserver::ResourceInfo*
32 DevToolsNetLogObserver::GetResourceInfo(uint32 id) {
33 RequestToInfoMap::iterator it = request_to_info_.find(id);
34 if (it != request_to_info_.end())
35 return it->second.get();
36 return NULL;
39 void DevToolsNetLogObserver::OnAddEntry(const net::NetLog::Entry& entry) {
40 // The events that the Observer is interested in only occur on the IO thread.
41 if (!BrowserThread::CurrentlyOn(BrowserThread::IO))
42 return;
44 if (entry.source().type == net::NetLog::SOURCE_URL_REQUEST)
45 OnAddURLRequestEntry(entry);
48 void DevToolsNetLogObserver::OnAddURLRequestEntry(
49 const net::NetLog::Entry& entry) {
50 DCHECK_CURRENTLY_ON(BrowserThread::IO);
52 bool is_begin = entry.phase() == net::NetLog::PHASE_BEGIN;
53 bool is_end = entry.phase() == net::NetLog::PHASE_END;
55 if (entry.type() == net::NetLog::TYPE_URL_REQUEST_START_JOB) {
56 if (is_begin) {
57 if (request_to_info_.size() > kMaxNumEntries) {
58 LOG(WARNING) << "The raw headers observer url request count has grown "
59 "larger than expected, resetting";
60 request_to_info_.clear();
63 request_to_info_[entry.source().id] = new ResourceInfo();
65 return;
66 } else if (entry.type() == net::NetLog::TYPE_REQUEST_ALIVE) {
67 // Cleanup records based on the TYPE_REQUEST_ALIVE entry.
68 if (is_end)
69 request_to_info_.erase(entry.source().id);
70 return;
73 ResourceInfo* info = GetResourceInfo(entry.source().id);
74 if (!info)
75 return;
77 switch (entry.type()) {
78 case net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS: {
79 scoped_ptr<base::Value> event_params(entry.ParametersToValue());
80 std::string request_line;
81 net::HttpRequestHeaders request_headers;
83 if (!net::HttpRequestHeaders::FromNetLogParam(event_params.get(),
84 &request_headers,
85 &request_line)) {
86 NOTREACHED();
89 // We need to clear headers in case the same url_request is reused for
90 // several http requests (e.g. see http://crbug.com/80157).
91 info->request_headers.clear();
93 for (net::HttpRequestHeaders::Iterator it(request_headers);
94 it.GetNext();) {
95 info->request_headers.push_back(std::make_pair(it.name(), it.value()));
97 info->request_headers_text = request_line + request_headers.ToString();
98 break;
100 case net::NetLog::TYPE_HTTP_TRANSACTION_HTTP2_SEND_REQUEST_HEADERS: {
101 scoped_ptr<base::Value> event_params(entry.ParametersToValue());
102 net::SpdyHeaderBlock request_headers;
104 if (!net::SpdyHeaderBlockFromNetLogParam(event_params.get(),
105 &request_headers)) {
106 NOTREACHED();
109 // We need to clear headers in case the same url_request is reused for
110 // several http requests (e.g. see http://crbug.com/80157).
111 info->request_headers.clear();
113 for (net::SpdyHeaderBlock::const_iterator it = request_headers.begin();
114 it != request_headers.end(); ++it) {
115 info->request_headers.push_back(std::make_pair(it->first, it->second));
117 info->request_headers_text = "";
118 break;
120 case net::NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS: {
121 scoped_ptr<base::Value> event_params(entry.ParametersToValue());
123 scoped_refptr<net::HttpResponseHeaders> response_headers;
125 if (!net::HttpResponseHeaders::FromNetLogParam(event_params.get(),
126 &response_headers)) {
127 NOTREACHED();
130 info->http_status_code = response_headers->response_code();
131 info->http_status_text = response_headers->GetStatusText();
132 std::string name, value;
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->response_headers.clear();
138 for (void* it = NULL;
139 response_headers->EnumerateHeaderLines(&it, &name, &value); ) {
140 info->response_headers.push_back(std::make_pair(name, value));
143 if (!info->request_headers_text.empty()) {
144 info->response_headers_text =
145 net::HttpUtil::ConvertHeadersBackToHTTPResponse(
146 response_headers->raw_headers());
147 } else {
148 // SPDY request.
149 info->response_headers_text = "";
151 break;
153 default:
154 break;
158 void DevToolsNetLogObserver::Attach() {
159 DCHECK(!instance_);
160 net::NetLog* net_log = GetContentClient()->browser()->GetNetLog();
161 if (net_log) {
162 instance_ = new DevToolsNetLogObserver();
163 net_log->DeprecatedAddObserver(
164 instance_, net::NetLogCaptureMode::IncludeCookiesAndCredentials());
168 void DevToolsNetLogObserver::Detach() {
169 DCHECK_CURRENTLY_ON(BrowserThread::IO);
171 if (instance_) {
172 // Safest not to do this in the destructor to maintain thread safety across
173 // refactorings.
174 instance_->net_log()->DeprecatedRemoveObserver(instance_);
175 delete instance_;
176 instance_ = NULL;
180 DevToolsNetLogObserver* DevToolsNetLogObserver::GetInstance() {
181 DCHECK_CURRENTLY_ON(BrowserThread::IO);
183 return instance_;
186 // static
187 void DevToolsNetLogObserver::PopulateResponseInfo(
188 net::URLRequest* request,
189 ResourceResponse* response) {
190 const ResourceRequestInfoImpl* request_info =
191 ResourceRequestInfoImpl::ForRequest(request);
192 if (!request_info || !request_info->ShouldReportRawHeaders())
193 return;
195 uint32 source_id = request->net_log().source().id;
196 DevToolsNetLogObserver* dev_tools_net_log_observer =
197 DevToolsNetLogObserver::GetInstance();
198 if (dev_tools_net_log_observer == NULL)
199 return;
200 response->head.devtools_info =
201 dev_tools_net_log_observer->GetResourceInfo(source_id);
204 } // namespace content