devtools_network_transaction.cc revision f8ee788a64d60abd8f2d742a5fdedde054ecd910
1600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang// Copyright 2014 The Chromium Authors. All rights reserved. 2600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang// Use of this source code is governed by a BSD-style license that can be 3600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang// found in the LICENSE file. 4600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 5600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang#include "chrome/browser/devtools/devtools_network_transaction.h" 6600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 7600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang#include "chrome/browser/devtools/devtools_network_controller.h" 8600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang#include "chrome/browser/devtools/devtools_network_interceptor.h" 9600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang#include "net/base/net_errors.h" 10600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang#include "net/base/upload_progress.h" 11600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang#include "net/http/http_network_transaction.h" 12600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang#include "net/http/http_request_info.h" 13600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 14600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangnamespace { 15600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 16600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangconst char kDevToolsRequestInitiator[] = "X-DevTools-Request-Initiator"; 17600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangconst char kDevToolsEmulateNetworkConditionsClientId[] = 18600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "X-DevTools-Emulate-Network-Conditions-Client-Id"; 19600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 20600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang} // namespace 21600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 22600c7a4bbc7348167293eac928192e695b4ad5baChung-yih WangDevToolsNetworkTransaction::DevToolsNetworkTransaction( 23600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang DevToolsNetworkController* controller, 24600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang scoped_ptr<net::HttpTransaction> network_transaction) 25600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang : controller_(controller), 26600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang network_transaction_(network_transaction.Pass()), 27600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang request_(NULL), 28600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang failed_(false), 29600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throttled_byte_count_(0), 30600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang callback_type_(NONE), 31600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang proxy_callback_(base::Bind(&DevToolsNetworkTransaction::OnCallback, 32600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang base::Unretained(this))) { 33600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang DCHECK(controller); 34600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang} 35600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 36600c7a4bbc7348167293eac928192e695b4ad5baChung-yih WangDevToolsNetworkTransaction::~DevToolsNetworkTransaction() { 37600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (interceptor_) 38600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang interceptor_->RemoveTransaction(this); 39600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang} 40600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 41600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangvoid DevToolsNetworkTransaction::Throttle(int result) { 42600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throttled_result_ = result; 43600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 44600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (callback_type_ == START) 45600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throttled_byte_count_ += network_transaction_->GetTotalReceivedBytes(); 46600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (result > 0) 47600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throttled_byte_count_ += result; 48600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 49600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (interceptor_) 50600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang interceptor_->ThrottleTransaction(this); 51} 52 53void DevToolsNetworkTransaction::OnCallback(int rv) { 54 if (failed_) 55 return; 56 DCHECK(!callback_.is_null()); 57 if (callback_type_ == START || callback_type_ == READ) { 58 if (interceptor_ && interceptor_->ShouldThrottle(this)) { 59 Throttle(rv); 60 return; 61 } 62 } 63 net::CompletionCallback callback = callback_; 64 callback_.Reset(); 65 callback_type_ = NONE; 66 callback.Run(rv); 67} 68 69int DevToolsNetworkTransaction::SetupCallback( 70 net::CompletionCallback callback, 71 int result, 72 CallbackType callback_type) { 73 DCHECK(callback_type_ == NONE); 74 75 if (result == net::ERR_IO_PENDING) { 76 callback_type_ = callback_type; 77 callback_ = callback; 78 return result; 79 } 80 81 if (!interceptor_ || !interceptor_->ShouldThrottle(this)) 82 return result; 83 84 // Only START and READ operation throttling is supported. 85 if (callback_type != START && callback_type != READ) 86 return result; 87 88 // In case of error |throttled_byte_count_| is unknown. 89 if (result < 0) 90 return result; 91 92 // URLRequestJob relies on synchronous end-of-stream notification. 93 if (callback_type == READ && result == 0) 94 return result; 95 96 callback_type_ = callback_type; 97 callback_ = callback; 98 Throttle(result); 99 return net::ERR_IO_PENDING; 100} 101 102void DevToolsNetworkTransaction::Fail() { 103 DCHECK(request_); 104 DCHECK(!failed_); 105 failed_ = true; 106 network_transaction_->SetBeforeNetworkStartCallback( 107 BeforeNetworkStartCallback()); 108 if (callback_.is_null()) 109 return; 110 net::CompletionCallback callback = callback_; 111 callback_.Reset(); 112 callback_type_ = NONE; 113 callback.Run(net::ERR_INTERNET_DISCONNECTED); 114} 115 116int DevToolsNetworkTransaction::Start( 117 const net::HttpRequestInfo* request, 118 const net::CompletionCallback& callback, 119 const net::BoundNetLog& net_log) { 120 DCHECK(request); 121 request_ = request; 122 interceptor_ = controller_->GetInterceptor(this); 123 interceptor_->AddTransaction(this); 124 125 if (interceptor_->ShouldFail(this)) { 126 failed_ = true; 127 network_transaction_->SetBeforeNetworkStartCallback( 128 BeforeNetworkStartCallback()); 129 return net::ERR_INTERNET_DISCONNECTED; 130 } 131 int rv = network_transaction_->Start(request_, proxy_callback_, net_log); 132 return SetupCallback(callback, rv, START); 133} 134 135void DevToolsNetworkTransaction::ProcessRequest() { 136 DCHECK(request_); 137 bool has_devtools_client_id = request_->extra_headers.HasHeader( 138 kDevToolsEmulateNetworkConditionsClientId); 139 bool has_devtools_request_initiator = request_->extra_headers.HasHeader( 140 kDevToolsRequestInitiator); 141 if (!has_devtools_client_id && !has_devtools_request_initiator) 142 return; 143 144 custom_request_.reset(new net::HttpRequestInfo(*request_)); 145 146 if (has_devtools_client_id) { 147 custom_request_->extra_headers.GetHeader( 148 kDevToolsEmulateNetworkConditionsClientId, &client_id_); 149 custom_request_->extra_headers.RemoveHeader( 150 kDevToolsEmulateNetworkConditionsClientId); 151 } 152 153 if (has_devtools_request_initiator) { 154 custom_request_->extra_headers.GetHeader( 155 kDevToolsRequestInitiator, &request_initiator_); 156 custom_request_->extra_headers.RemoveHeader(kDevToolsRequestInitiator); 157 } 158 159 request_ = custom_request_.get(); 160} 161 162int DevToolsNetworkTransaction::RestartIgnoringLastError( 163 const net::CompletionCallback& callback) { 164 if (failed_) 165 return net::ERR_INTERNET_DISCONNECTED; 166 int rv = network_transaction_->RestartIgnoringLastError(proxy_callback_); 167 return SetupCallback(callback, rv, RESTART_IGNORING_LAST_ERROR); 168} 169 170int DevToolsNetworkTransaction::RestartWithCertificate( 171 net::X509Certificate* client_cert, 172 const net::CompletionCallback& callback) { 173 if (failed_) 174 return net::ERR_INTERNET_DISCONNECTED; 175 int rv = network_transaction_->RestartWithCertificate( 176 client_cert, proxy_callback_); 177 return SetupCallback(callback, rv, RESTART_WITH_CERTIFICATE); 178} 179 180int DevToolsNetworkTransaction::RestartWithAuth( 181 const net::AuthCredentials& credentials, 182 const net::CompletionCallback& callback) { 183 if (failed_) 184 return net::ERR_INTERNET_DISCONNECTED; 185 int rv = network_transaction_->RestartWithAuth(credentials, proxy_callback_); 186 return SetupCallback(callback, rv, RESTART_WITH_AUTH); 187} 188 189bool DevToolsNetworkTransaction::IsReadyToRestartForAuth() { 190 return network_transaction_->IsReadyToRestartForAuth(); 191} 192 193int DevToolsNetworkTransaction::Read( 194 net::IOBuffer* buf, 195 int buf_len, 196 const net::CompletionCallback& callback) { 197 if (failed_) 198 return net::ERR_INTERNET_DISCONNECTED; 199 int rv = network_transaction_->Read(buf, buf_len, proxy_callback_); 200 return SetupCallback(callback, rv, READ); 201} 202 203void DevToolsNetworkTransaction::StopCaching() { 204 network_transaction_->StopCaching(); 205} 206 207bool DevToolsNetworkTransaction::GetFullRequestHeaders( 208 net::HttpRequestHeaders* headers) const { 209 return network_transaction_->GetFullRequestHeaders(headers); 210} 211 212int64 DevToolsNetworkTransaction::GetTotalReceivedBytes() const { 213 return network_transaction_->GetTotalReceivedBytes(); 214} 215 216void DevToolsNetworkTransaction::DoneReading() { 217 network_transaction_->DoneReading(); 218} 219 220const net::HttpResponseInfo* 221DevToolsNetworkTransaction::GetResponseInfo() const { 222 return network_transaction_->GetResponseInfo(); 223} 224 225net::LoadState DevToolsNetworkTransaction::GetLoadState() const { 226 return network_transaction_->GetLoadState(); 227} 228 229net::UploadProgress DevToolsNetworkTransaction::GetUploadProgress() const { 230 return network_transaction_->GetUploadProgress(); 231} 232 233void DevToolsNetworkTransaction::SetQuicServerInfo( 234 net::QuicServerInfo* quic_server_info) { 235 network_transaction_->SetQuicServerInfo(quic_server_info); 236} 237 238bool DevToolsNetworkTransaction::GetLoadTimingInfo( 239 net::LoadTimingInfo* load_timing_info) const { 240 return network_transaction_->GetLoadTimingInfo(load_timing_info); 241} 242 243void DevToolsNetworkTransaction::SetPriority(net::RequestPriority priority) { 244 network_transaction_->SetPriority(priority); 245} 246 247void DevToolsNetworkTransaction::SetWebSocketHandshakeStreamCreateHelper( 248 net::WebSocketHandshakeStreamBase::CreateHelper* create_helper) { 249 network_transaction_->SetWebSocketHandshakeStreamCreateHelper(create_helper); 250} 251 252void DevToolsNetworkTransaction::SetBeforeNetworkStartCallback( 253 const BeforeNetworkStartCallback& callback) { 254 network_transaction_->SetBeforeNetworkStartCallback(callback); 255} 256 257int DevToolsNetworkTransaction::ResumeNetworkStart() { 258 if (failed_) 259 return net::ERR_INTERNET_DISCONNECTED; 260 return network_transaction_->ResumeNetworkStart(); 261} 262 263void DevToolsNetworkTransaction::FireThrottledCallback() { 264 DCHECK(!callback_.is_null()); 265 DCHECK(callback_type_ == READ || callback_type_ == START); 266 net::CompletionCallback callback = callback_; 267 callback_.Reset(); 268 callback_type_ = NONE; 269 callback.Run(throttled_result_); 270} 271