1 // Copyright 2014 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 "chrome/browser/devtools/devtools_network_transaction.h"
7 #include "chrome/browser/devtools/devtools_network_controller.h"
8 #include "chrome/browser/devtools/devtools_network_interceptor.h"
9 #include "net/base/net_errors.h"
10 #include "net/base/upload_progress.h"
11 #include "net/http/http_network_transaction.h"
12 #include "net/http/http_request_info.h"
13 #include "net/socket/connection_attempts.h"
15 // Keep in sync with kDevToolsRequestInitiator and
16 // kDevToolsEmulateNetworkConditionsClientId defined in
17 // InspectorResourceAgent.cpp.
18 const char DevToolsNetworkTransaction::kDevToolsRequestInitiator
[] =
19 "X-DevTools-Request-Initiator";
21 DevToolsNetworkTransaction::kDevToolsEmulateNetworkConditionsClientId
[] =
22 "X-DevTools-Emulate-Network-Conditions-Client-Id";
24 DevToolsNetworkTransaction::DevToolsNetworkTransaction(
25 DevToolsNetworkController
* controller
,
26 scoped_ptr
<net::HttpTransaction
> network_transaction
)
27 : controller_(controller
),
28 network_transaction_(network_transaction
.Pass()),
31 throttled_byte_count_(0),
33 proxy_callback_(base::Bind(&DevToolsNetworkTransaction::OnCallback
,
34 base::Unretained(this))) {
38 DevToolsNetworkTransaction::~DevToolsNetworkTransaction() {
40 interceptor_
->RemoveTransaction(this);
43 void DevToolsNetworkTransaction::Throttle(int result
) {
44 throttled_result_
= result
;
46 if (callback_type_
== START
)
47 throttled_byte_count_
+= network_transaction_
->GetTotalReceivedBytes();
49 throttled_byte_count_
+= result
;
52 interceptor_
->ThrottleTransaction(this, callback_type_
== START
);
55 void DevToolsNetworkTransaction::OnCallback(int rv
) {
58 DCHECK(!callback_
.is_null());
59 if (callback_type_
== START
|| callback_type_
== READ
) {
60 if (interceptor_
&& interceptor_
->ShouldThrottle(this)) {
65 net::CompletionCallback callback
= callback_
;
67 callback_type_
= NONE
;
71 int DevToolsNetworkTransaction::SetupCallback(
72 net::CompletionCallback callback
,
74 CallbackType callback_type
) {
75 DCHECK(callback_type_
== NONE
);
77 if (result
== net::ERR_IO_PENDING
) {
78 callback_type_
= callback_type
;
83 if (!interceptor_
|| !interceptor_
->ShouldThrottle(this))
86 // Only START and READ operation throttling is supported.
87 if (callback_type
!= START
&& callback_type
!= READ
)
90 // In case of error |throttled_byte_count_| is unknown.
94 // URLRequestJob relies on synchronous end-of-stream notification.
95 if (callback_type
== READ
&& result
== 0)
98 callback_type_
= callback_type
;
101 return net::ERR_IO_PENDING
;
104 void DevToolsNetworkTransaction::Fail() {
108 network_transaction_
->SetBeforeNetworkStartCallback(
109 BeforeNetworkStartCallback());
110 if (callback_
.is_null())
112 net::CompletionCallback callback
= callback_
;
114 callback_type_
= NONE
;
115 callback
.Run(net::ERR_INTERNET_DISCONNECTED
);
118 int DevToolsNetworkTransaction::Start(
119 const net::HttpRequestInfo
* request
,
120 const net::CompletionCallback
& callback
,
121 const net::BoundNetLog
& net_log
) {
124 interceptor_
= controller_
->GetInterceptor(this);
125 interceptor_
->AddTransaction(this);
127 if (interceptor_
->ShouldFail(this)) {
129 network_transaction_
->SetBeforeNetworkStartCallback(
130 BeforeNetworkStartCallback());
131 return net::ERR_INTERNET_DISCONNECTED
;
133 int rv
= network_transaction_
->Start(request_
, proxy_callback_
, net_log
);
134 return SetupCallback(callback
, rv
, START
);
137 void DevToolsNetworkTransaction::ProcessRequest() {
139 bool has_devtools_client_id
= request_
->extra_headers
.HasHeader(
140 kDevToolsEmulateNetworkConditionsClientId
);
141 bool has_devtools_request_initiator
= request_
->extra_headers
.HasHeader(
142 kDevToolsRequestInitiator
);
143 if (!has_devtools_client_id
&& !has_devtools_request_initiator
)
146 custom_request_
.reset(new net::HttpRequestInfo(*request_
));
148 if (has_devtools_client_id
) {
149 custom_request_
->extra_headers
.GetHeader(
150 kDevToolsEmulateNetworkConditionsClientId
, &client_id_
);
151 custom_request_
->extra_headers
.RemoveHeader(
152 kDevToolsEmulateNetworkConditionsClientId
);
155 if (has_devtools_request_initiator
) {
156 custom_request_
->extra_headers
.GetHeader(
157 kDevToolsRequestInitiator
, &request_initiator_
);
158 custom_request_
->extra_headers
.RemoveHeader(kDevToolsRequestInitiator
);
161 request_
= custom_request_
.get();
164 int DevToolsNetworkTransaction::RestartIgnoringLastError(
165 const net::CompletionCallback
& callback
) {
167 return net::ERR_INTERNET_DISCONNECTED
;
168 int rv
= network_transaction_
->RestartIgnoringLastError(proxy_callback_
);
169 return SetupCallback(callback
, rv
, RESTART_IGNORING_LAST_ERROR
);
172 int DevToolsNetworkTransaction::RestartWithCertificate(
173 net::X509Certificate
* client_cert
,
174 const net::CompletionCallback
& callback
) {
176 return net::ERR_INTERNET_DISCONNECTED
;
177 int rv
= network_transaction_
->RestartWithCertificate(
178 client_cert
, proxy_callback_
);
179 return SetupCallback(callback
, rv
, RESTART_WITH_CERTIFICATE
);
182 int DevToolsNetworkTransaction::RestartWithAuth(
183 const net::AuthCredentials
& credentials
,
184 const net::CompletionCallback
& callback
) {
186 return net::ERR_INTERNET_DISCONNECTED
;
187 int rv
= network_transaction_
->RestartWithAuth(credentials
, proxy_callback_
);
188 return SetupCallback(callback
, rv
, RESTART_WITH_AUTH
);
191 bool DevToolsNetworkTransaction::IsReadyToRestartForAuth() {
192 return network_transaction_
->IsReadyToRestartForAuth();
195 int DevToolsNetworkTransaction::Read(
198 const net::CompletionCallback
& callback
) {
200 return net::ERR_INTERNET_DISCONNECTED
;
201 int rv
= network_transaction_
->Read(buf
, buf_len
, proxy_callback_
);
202 return SetupCallback(callback
, rv
, READ
);
205 void DevToolsNetworkTransaction::StopCaching() {
206 network_transaction_
->StopCaching();
209 bool DevToolsNetworkTransaction::GetFullRequestHeaders(
210 net::HttpRequestHeaders
* headers
) const {
211 return network_transaction_
->GetFullRequestHeaders(headers
);
214 int64
DevToolsNetworkTransaction::GetTotalReceivedBytes() const {
215 return network_transaction_
->GetTotalReceivedBytes();
218 void DevToolsNetworkTransaction::DoneReading() {
219 network_transaction_
->DoneReading();
222 const net::HttpResponseInfo
*
223 DevToolsNetworkTransaction::GetResponseInfo() const {
224 return network_transaction_
->GetResponseInfo();
227 net::LoadState
DevToolsNetworkTransaction::GetLoadState() const {
228 return network_transaction_
->GetLoadState();
231 net::UploadProgress
DevToolsNetworkTransaction::GetUploadProgress() const {
232 return network_transaction_
->GetUploadProgress();
235 void DevToolsNetworkTransaction::SetQuicServerInfo(
236 net::QuicServerInfo
* quic_server_info
) {
237 network_transaction_
->SetQuicServerInfo(quic_server_info
);
240 bool DevToolsNetworkTransaction::GetLoadTimingInfo(
241 net::LoadTimingInfo
* load_timing_info
) const {
242 return network_transaction_
->GetLoadTimingInfo(load_timing_info
);
245 void DevToolsNetworkTransaction::SetPriority(net::RequestPriority priority
) {
246 network_transaction_
->SetPriority(priority
);
249 void DevToolsNetworkTransaction::SetWebSocketHandshakeStreamCreateHelper(
250 net::WebSocketHandshakeStreamBase::CreateHelper
* create_helper
) {
251 network_transaction_
->SetWebSocketHandshakeStreamCreateHelper(create_helper
);
254 void DevToolsNetworkTransaction::SetBeforeNetworkStartCallback(
255 const BeforeNetworkStartCallback
& callback
) {
256 network_transaction_
->SetBeforeNetworkStartCallback(callback
);
259 void DevToolsNetworkTransaction::SetBeforeProxyHeadersSentCallback(
260 const BeforeProxyHeadersSentCallback
& callback
) {
261 network_transaction_
->SetBeforeProxyHeadersSentCallback(callback
);
264 int DevToolsNetworkTransaction::ResumeNetworkStart() {
266 return net::ERR_INTERNET_DISCONNECTED
;
267 return network_transaction_
->ResumeNetworkStart();
271 DevToolsNetworkTransaction::GetConnectionAttempts(net::ConnectionAttempts
* out
)
273 network_transaction_
->GetConnectionAttempts(out
);
276 void DevToolsNetworkTransaction::FireThrottledCallback() {
277 DCHECK(!callback_
.is_null());
278 DCHECK(callback_type_
== READ
|| callback_type_
== START
);
279 net::CompletionCallback callback
= callback_
;
281 callback_type_
= NONE
;
282 callback
.Run(throttled_result_
);