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"
16 const char kDevToolsRequestInitiator
[] = "X-DevTools-Request-Initiator";
17 const char kDevToolsEmulateNetworkConditionsClientId
[] =
18 "X-DevTools-Emulate-Network-Conditions-Client-Id";
22 DevToolsNetworkTransaction::DevToolsNetworkTransaction(
23 DevToolsNetworkController
* controller
,
24 scoped_ptr
<net::HttpTransaction
> network_transaction
)
25 : controller_(controller
),
26 network_transaction_(network_transaction
.Pass()),
29 throttled_byte_count_(0),
31 proxy_callback_(base::Bind(&DevToolsNetworkTransaction::OnCallback
,
32 base::Unretained(this))) {
36 DevToolsNetworkTransaction::~DevToolsNetworkTransaction() {
38 interceptor_
->RemoveTransaction(this);
41 void DevToolsNetworkTransaction::Throttle(int result
) {
42 throttled_result_
= result
;
44 if (callback_type_
== START
)
45 throttled_byte_count_
+= network_transaction_
->GetTotalReceivedBytes();
47 throttled_byte_count_
+= result
;
50 interceptor_
->ThrottleTransaction(this, callback_type_
== START
);
53 void DevToolsNetworkTransaction::OnCallback(int rv
) {
56 DCHECK(!callback_
.is_null());
57 if (callback_type_
== START
|| callback_type_
== READ
) {
58 if (interceptor_
&& interceptor_
->ShouldThrottle(this)) {
63 net::CompletionCallback callback
= callback_
;
65 callback_type_
= NONE
;
69 int DevToolsNetworkTransaction::SetupCallback(
70 net::CompletionCallback callback
,
72 CallbackType callback_type
) {
73 DCHECK(callback_type_
== NONE
);
75 if (result
== net::ERR_IO_PENDING
) {
76 callback_type_
= callback_type
;
81 if (!interceptor_
|| !interceptor_
->ShouldThrottle(this))
84 // Only START and READ operation throttling is supported.
85 if (callback_type
!= START
&& callback_type
!= READ
)
88 // In case of error |throttled_byte_count_| is unknown.
92 // URLRequestJob relies on synchronous end-of-stream notification.
93 if (callback_type
== READ
&& result
== 0)
96 callback_type_
= callback_type
;
99 return net::ERR_IO_PENDING
;
102 void DevToolsNetworkTransaction::Fail() {
106 network_transaction_
->SetBeforeNetworkStartCallback(
107 BeforeNetworkStartCallback());
108 if (callback_
.is_null())
110 net::CompletionCallback callback
= callback_
;
112 callback_type_
= NONE
;
113 callback
.Run(net::ERR_INTERNET_DISCONNECTED
);
116 int DevToolsNetworkTransaction::Start(
117 const net::HttpRequestInfo
* request
,
118 const net::CompletionCallback
& callback
,
119 const net::BoundNetLog
& net_log
) {
122 interceptor_
= controller_
->GetInterceptor(this);
123 interceptor_
->AddTransaction(this);
125 if (interceptor_
->ShouldFail(this)) {
127 network_transaction_
->SetBeforeNetworkStartCallback(
128 BeforeNetworkStartCallback());
129 return net::ERR_INTERNET_DISCONNECTED
;
131 int rv
= network_transaction_
->Start(request_
, proxy_callback_
, net_log
);
132 return SetupCallback(callback
, rv
, START
);
135 void DevToolsNetworkTransaction::ProcessRequest() {
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
)
144 custom_request_
.reset(new net::HttpRequestInfo(*request_
));
146 if (has_devtools_client_id
) {
147 custom_request_
->extra_headers
.GetHeader(
148 kDevToolsEmulateNetworkConditionsClientId
, &client_id_
);
149 custom_request_
->extra_headers
.RemoveHeader(
150 kDevToolsEmulateNetworkConditionsClientId
);
153 if (has_devtools_request_initiator
) {
154 custom_request_
->extra_headers
.GetHeader(
155 kDevToolsRequestInitiator
, &request_initiator_
);
156 custom_request_
->extra_headers
.RemoveHeader(kDevToolsRequestInitiator
);
159 request_
= custom_request_
.get();
162 int DevToolsNetworkTransaction::RestartIgnoringLastError(
163 const net::CompletionCallback
& callback
) {
165 return net::ERR_INTERNET_DISCONNECTED
;
166 int rv
= network_transaction_
->RestartIgnoringLastError(proxy_callback_
);
167 return SetupCallback(callback
, rv
, RESTART_IGNORING_LAST_ERROR
);
170 int DevToolsNetworkTransaction::RestartWithCertificate(
171 net::X509Certificate
* client_cert
,
172 const net::CompletionCallback
& callback
) {
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
);
180 int DevToolsNetworkTransaction::RestartWithAuth(
181 const net::AuthCredentials
& credentials
,
182 const net::CompletionCallback
& callback
) {
184 return net::ERR_INTERNET_DISCONNECTED
;
185 int rv
= network_transaction_
->RestartWithAuth(credentials
, proxy_callback_
);
186 return SetupCallback(callback
, rv
, RESTART_WITH_AUTH
);
189 bool DevToolsNetworkTransaction::IsReadyToRestartForAuth() {
190 return network_transaction_
->IsReadyToRestartForAuth();
193 int DevToolsNetworkTransaction::Read(
196 const net::CompletionCallback
& callback
) {
198 return net::ERR_INTERNET_DISCONNECTED
;
199 int rv
= network_transaction_
->Read(buf
, buf_len
, proxy_callback_
);
200 return SetupCallback(callback
, rv
, READ
);
203 void DevToolsNetworkTransaction::StopCaching() {
204 network_transaction_
->StopCaching();
207 bool DevToolsNetworkTransaction::GetFullRequestHeaders(
208 net::HttpRequestHeaders
* headers
) const {
209 return network_transaction_
->GetFullRequestHeaders(headers
);
212 int64
DevToolsNetworkTransaction::GetTotalReceivedBytes() const {
213 return network_transaction_
->GetTotalReceivedBytes();
216 void DevToolsNetworkTransaction::DoneReading() {
217 network_transaction_
->DoneReading();
220 const net::HttpResponseInfo
*
221 DevToolsNetworkTransaction::GetResponseInfo() const {
222 return network_transaction_
->GetResponseInfo();
225 net::LoadState
DevToolsNetworkTransaction::GetLoadState() const {
226 return network_transaction_
->GetLoadState();
229 net::UploadProgress
DevToolsNetworkTransaction::GetUploadProgress() const {
230 return network_transaction_
->GetUploadProgress();
233 void DevToolsNetworkTransaction::SetQuicServerInfo(
234 net::QuicServerInfo
* quic_server_info
) {
235 network_transaction_
->SetQuicServerInfo(quic_server_info
);
238 bool DevToolsNetworkTransaction::GetLoadTimingInfo(
239 net::LoadTimingInfo
* load_timing_info
) const {
240 return network_transaction_
->GetLoadTimingInfo(load_timing_info
);
243 void DevToolsNetworkTransaction::SetPriority(net::RequestPriority priority
) {
244 network_transaction_
->SetPriority(priority
);
247 void DevToolsNetworkTransaction::SetWebSocketHandshakeStreamCreateHelper(
248 net::WebSocketHandshakeStreamBase::CreateHelper
* create_helper
) {
249 network_transaction_
->SetWebSocketHandshakeStreamCreateHelper(create_helper
);
252 void DevToolsNetworkTransaction::SetBeforeNetworkStartCallback(
253 const BeforeNetworkStartCallback
& callback
) {
254 network_transaction_
->SetBeforeNetworkStartCallback(callback
);
257 void DevToolsNetworkTransaction::SetBeforeProxyHeadersSentCallback(
258 const BeforeProxyHeadersSentCallback
& callback
) {
259 network_transaction_
->SetBeforeProxyHeadersSentCallback(callback
);
262 int DevToolsNetworkTransaction::ResumeNetworkStart() {
264 return net::ERR_INTERNET_DISCONNECTED
;
265 return network_transaction_
->ResumeNetworkStart();
268 void DevToolsNetworkTransaction::FireThrottledCallback() {
269 DCHECK(!callback_
.is_null());
270 DCHECK(callback_type_
== READ
|| callback_type_
== START
);
271 net::CompletionCallback callback
= callback_
;
273 callback_type_
= NONE
;
274 callback
.Run(throttled_result_
);