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 "base/profiler/scoped_tracker.h"
8 #include "chrome/browser/devtools/devtools_network_controller.h"
9 #include "chrome/browser/devtools/devtools_network_interceptor.h"
10 #include "net/base/net_errors.h"
11 #include "net/base/upload_progress.h"
12 #include "net/http/http_network_transaction.h"
13 #include "net/http/http_request_info.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
) {
56 // TODO(vadimt): Remove ScopedTracker below once crbug.com/424359 is fixed.
57 tracked_objects::ScopedTracker
tracking_profile(
58 FROM_HERE_WITH_EXPLICIT_FUNCTION(
59 "424359 DevToolsNetworkTransaction::OnCallback"));
63 DCHECK(!callback_
.is_null());
64 if (callback_type_
== START
|| callback_type_
== READ
) {
65 if (interceptor_
&& interceptor_
->ShouldThrottle(this)) {
70 net::CompletionCallback callback
= callback_
;
72 callback_type_
= NONE
;
76 int DevToolsNetworkTransaction::SetupCallback(
77 net::CompletionCallback callback
,
79 CallbackType callback_type
) {
80 DCHECK(callback_type_
== NONE
);
82 if (result
== net::ERR_IO_PENDING
) {
83 callback_type_
= callback_type
;
88 if (!interceptor_
|| !interceptor_
->ShouldThrottle(this))
91 // Only START and READ operation throttling is supported.
92 if (callback_type
!= START
&& callback_type
!= READ
)
95 // In case of error |throttled_byte_count_| is unknown.
99 // URLRequestJob relies on synchronous end-of-stream notification.
100 if (callback_type
== READ
&& result
== 0)
103 callback_type_
= callback_type
;
104 callback_
= callback
;
106 return net::ERR_IO_PENDING
;
109 void DevToolsNetworkTransaction::Fail() {
113 network_transaction_
->SetBeforeNetworkStartCallback(
114 BeforeNetworkStartCallback());
115 if (callback_
.is_null())
117 net::CompletionCallback callback
= callback_
;
119 callback_type_
= NONE
;
120 callback
.Run(net::ERR_INTERNET_DISCONNECTED
);
123 int DevToolsNetworkTransaction::Start(
124 const net::HttpRequestInfo
* request
,
125 const net::CompletionCallback
& callback
,
126 const net::BoundNetLog
& net_log
) {
129 interceptor_
= controller_
->GetInterceptor(this);
130 interceptor_
->AddTransaction(this);
132 if (interceptor_
->ShouldFail(this)) {
134 network_transaction_
->SetBeforeNetworkStartCallback(
135 BeforeNetworkStartCallback());
136 return net::ERR_INTERNET_DISCONNECTED
;
138 int rv
= network_transaction_
->Start(request_
, proxy_callback_
, net_log
);
139 return SetupCallback(callback
, rv
, START
);
142 void DevToolsNetworkTransaction::ProcessRequest() {
144 bool has_devtools_client_id
= request_
->extra_headers
.HasHeader(
145 kDevToolsEmulateNetworkConditionsClientId
);
146 bool has_devtools_request_initiator
= request_
->extra_headers
.HasHeader(
147 kDevToolsRequestInitiator
);
148 if (!has_devtools_client_id
&& !has_devtools_request_initiator
)
151 custom_request_
.reset(new net::HttpRequestInfo(*request_
));
153 if (has_devtools_client_id
) {
154 custom_request_
->extra_headers
.GetHeader(
155 kDevToolsEmulateNetworkConditionsClientId
, &client_id_
);
156 custom_request_
->extra_headers
.RemoveHeader(
157 kDevToolsEmulateNetworkConditionsClientId
);
160 if (has_devtools_request_initiator
) {
161 custom_request_
->extra_headers
.GetHeader(
162 kDevToolsRequestInitiator
, &request_initiator_
);
163 custom_request_
->extra_headers
.RemoveHeader(kDevToolsRequestInitiator
);
166 request_
= custom_request_
.get();
169 int DevToolsNetworkTransaction::RestartIgnoringLastError(
170 const net::CompletionCallback
& callback
) {
172 return net::ERR_INTERNET_DISCONNECTED
;
173 int rv
= network_transaction_
->RestartIgnoringLastError(proxy_callback_
);
174 return SetupCallback(callback
, rv
, RESTART_IGNORING_LAST_ERROR
);
177 int DevToolsNetworkTransaction::RestartWithCertificate(
178 net::X509Certificate
* client_cert
,
179 const net::CompletionCallback
& callback
) {
181 return net::ERR_INTERNET_DISCONNECTED
;
182 int rv
= network_transaction_
->RestartWithCertificate(
183 client_cert
, proxy_callback_
);
184 return SetupCallback(callback
, rv
, RESTART_WITH_CERTIFICATE
);
187 int DevToolsNetworkTransaction::RestartWithAuth(
188 const net::AuthCredentials
& credentials
,
189 const net::CompletionCallback
& callback
) {
191 return net::ERR_INTERNET_DISCONNECTED
;
192 int rv
= network_transaction_
->RestartWithAuth(credentials
, proxy_callback_
);
193 return SetupCallback(callback
, rv
, RESTART_WITH_AUTH
);
196 bool DevToolsNetworkTransaction::IsReadyToRestartForAuth() {
197 return network_transaction_
->IsReadyToRestartForAuth();
200 int DevToolsNetworkTransaction::Read(
203 const net::CompletionCallback
& callback
) {
205 return net::ERR_INTERNET_DISCONNECTED
;
206 int rv
= network_transaction_
->Read(buf
, buf_len
, proxy_callback_
);
207 return SetupCallback(callback
, rv
, READ
);
210 void DevToolsNetworkTransaction::StopCaching() {
211 network_transaction_
->StopCaching();
214 bool DevToolsNetworkTransaction::GetFullRequestHeaders(
215 net::HttpRequestHeaders
* headers
) const {
216 return network_transaction_
->GetFullRequestHeaders(headers
);
219 int64
DevToolsNetworkTransaction::GetTotalReceivedBytes() const {
220 return network_transaction_
->GetTotalReceivedBytes();
223 void DevToolsNetworkTransaction::DoneReading() {
224 network_transaction_
->DoneReading();
227 const net::HttpResponseInfo
*
228 DevToolsNetworkTransaction::GetResponseInfo() const {
229 return network_transaction_
->GetResponseInfo();
232 net::LoadState
DevToolsNetworkTransaction::GetLoadState() const {
233 return network_transaction_
->GetLoadState();
236 net::UploadProgress
DevToolsNetworkTransaction::GetUploadProgress() const {
237 return network_transaction_
->GetUploadProgress();
240 void DevToolsNetworkTransaction::SetQuicServerInfo(
241 net::QuicServerInfo
* quic_server_info
) {
242 network_transaction_
->SetQuicServerInfo(quic_server_info
);
245 bool DevToolsNetworkTransaction::GetLoadTimingInfo(
246 net::LoadTimingInfo
* load_timing_info
) const {
247 return network_transaction_
->GetLoadTimingInfo(load_timing_info
);
250 void DevToolsNetworkTransaction::SetPriority(net::RequestPriority priority
) {
251 network_transaction_
->SetPriority(priority
);
254 void DevToolsNetworkTransaction::SetWebSocketHandshakeStreamCreateHelper(
255 net::WebSocketHandshakeStreamBase::CreateHelper
* create_helper
) {
256 network_transaction_
->SetWebSocketHandshakeStreamCreateHelper(create_helper
);
259 void DevToolsNetworkTransaction::SetBeforeNetworkStartCallback(
260 const BeforeNetworkStartCallback
& callback
) {
261 network_transaction_
->SetBeforeNetworkStartCallback(callback
);
264 void DevToolsNetworkTransaction::SetBeforeProxyHeadersSentCallback(
265 const BeforeProxyHeadersSentCallback
& callback
) {
266 network_transaction_
->SetBeforeProxyHeadersSentCallback(callback
);
269 int DevToolsNetworkTransaction::ResumeNetworkStart() {
271 return net::ERR_INTERNET_DISCONNECTED
;
272 return network_transaction_
->ResumeNetworkStart();
275 void DevToolsNetworkTransaction::FireThrottledCallback() {
276 DCHECK(!callback_
.is_null());
277 DCHECK(callback_type_
== READ
|| callback_type_
== START
);
278 net::CompletionCallback callback
= callback_
;
280 callback_type_
= NONE
;
281 callback
.Run(throttled_result_
);