devtools_netlog_observer.cc revision 201ade2fbba22bfb27ae029f4d23fca6ded109a0
1// Copyright (c) 2010 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 "chrome/browser/debugger/devtools_netlog_observer.h" 6 7#include "base/string_util.h" 8#include "chrome/browser/io_thread.h" 9#include "chrome/common/resource_response.h" 10#include "net/base/load_flags.h" 11#include "net/http/http_net_log_params.h" 12#include "net/http/http_response_headers.h" 13#include "net/url_request/url_request.h" 14#include "net/url_request/url_request_netlog_params.h" 15#include "webkit/glue/resource_loader_bridge.h" 16 17const size_t kMaxNumEntries = 1000; 18 19DevToolsNetLogObserver* DevToolsNetLogObserver::instance_ = NULL; 20 21DevToolsNetLogObserver::DevToolsNetLogObserver(ChromeNetLog* chrome_net_log) 22 : ChromeNetLog::Observer(net::NetLog::LOG_ALL_BUT_BYTES), 23 chrome_net_log_(chrome_net_log) { 24 chrome_net_log_->AddObserver(this); 25} 26 27DevToolsNetLogObserver::~DevToolsNetLogObserver() { 28 chrome_net_log_->RemoveObserver(this); 29} 30 31DevToolsNetLogObserver::ResourceInfo* 32DevToolsNetLogObserver::GetResourceInfo(uint32 id) { 33 RequestToInfoMap::iterator it = request_to_info_.find(id); 34 if (it != request_to_info_.end()) 35 return it->second; 36 return NULL; 37} 38 39void DevToolsNetLogObserver::OnAddEntry(net::NetLog::EventType type, 40 const base::TimeTicks& time, 41 const net::NetLog::Source& source, 42 net::NetLog::EventPhase phase, 43 net::NetLog::EventParameters* params) { 44 if (type == net::NetLog::TYPE_URL_REQUEST_START_JOB) { 45 if (phase != net::NetLog::PHASE_BEGIN) 46 return; 47 int load_flags = static_cast<URLRequestStartEventParameters*>(params)-> 48 load_flags(); 49 if (!(load_flags & net::LOAD_REPORT_RAW_HEADERS)) 50 return; 51 if (request_to_info_.size() > kMaxNumEntries) { 52 LOG(WARNING) << "The raw headers observer url request count has grown " 53 "larger than expected, resetting"; 54 request_to_info_.clear(); 55 } 56 scoped_refptr<ResourceInfo> new_record(new ResourceInfo()); 57 // We may encounter multiple PHASE_BEGIN for same resource in case of 58 // redirect -- if so, replace the old record to avoid keeping headers 59 // from different requests. 60 std::pair<RequestToInfoMap::iterator, bool> inserted = 61 request_to_info_.insert(std::make_pair(source.id, new_record)); 62 if (!inserted.second) 63 inserted.first->second = new_record; 64 return; 65 } 66 if (type == net::NetLog::TYPE_REQUEST_ALIVE && 67 phase == net::NetLog::PHASE_END) { 68 request_to_info_.erase(source.id); 69 return; 70 } 71 if (type != net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS && 72 type != net::NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS) 73 return; 74 75 ResourceInfo* info = GetResourceInfo(source.id); 76 if (!info) 77 return; 78 79 switch (type) { 80 case net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS: { 81 const net::HttpRequestHeaders &request_headers = 82 static_cast<net::NetLogHttpRequestParameter*>(params)->GetHeaders(); 83 for (net::HttpRequestHeaders::Iterator it(request_headers); 84 it.GetNext();) { 85 info->request_headers.push_back(std::make_pair(it.name(), 86 it.value())); 87 } 88 break; 89 } 90 case net::NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS: { 91 const net::HttpResponseHeaders& response_headers = 92 static_cast<net::NetLogHttpResponseParameter*>(params)->GetHeaders(); 93 info->http_status_code = response_headers.response_code(); 94 info->http_status_text = response_headers.GetStatusText(); 95 std::string name, value; 96 for (void* it = NULL; 97 response_headers.EnumerateHeaderLines(&it, &name, &value); ) { 98 info->response_headers.push_back(std::make_pair(name, value)); 99 } 100 break; 101 } 102 default: 103 break; 104 } 105} 106 107void DevToolsNetLogObserver::Attach(IOThread* io_thread) { 108 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 109 DCHECK(!instance_); 110 111 instance_ = new DevToolsNetLogObserver(io_thread->globals()->net_log.get()); 112} 113 114void DevToolsNetLogObserver::Detach() { 115 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 116 DCHECK(instance_); 117 118 delete instance_; 119 instance_ = NULL; 120} 121 122DevToolsNetLogObserver* DevToolsNetLogObserver::GetInstance() { 123 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 124 125 return instance_; 126} 127 128// static 129void DevToolsNetLogObserver::PopulateResponseInfo(URLRequest* request, 130 ResourceResponse* response) { 131 if (!(request->load_flags() & net::LOAD_REPORT_RAW_HEADERS)) 132 return; 133 134 uint32 source_id = request->net_log().source().id; 135 DevToolsNetLogObserver* dev_tools_net_log_observer = 136 DevToolsNetLogObserver::GetInstance(); 137 if (!dev_tools_net_log_observer) 138 return; 139 response->response_head.devtools_info = 140 dev_tools_net_log_observer->GetResourceInfo(source_id); 141} 142