Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / devtools / devtools_network_transaction.cc
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.
4
5 #include "chrome/browser/devtools/devtools_network_transaction.h"
6
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
14 namespace {
15
16 const char kDevToolsRequestInitiator[] = "X-DevTools-Request-Initiator";
17 const char kDevToolsEmulateNetworkConditionsClientId[] =
18     "X-DevTools-Emulate-Network-Conditions-Client-Id";
19
20 }  // namespace
21
22 DevToolsNetworkTransaction::DevToolsNetworkTransaction(
23     DevToolsNetworkController* controller,
24     scoped_ptr<net::HttpTransaction> network_transaction)
25     : controller_(controller),
26       network_transaction_(network_transaction.Pass()),
27       request_(NULL),
28       failed_(false),
29       throttled_byte_count_(0),
30       callback_type_(NONE),
31       proxy_callback_(base::Bind(&DevToolsNetworkTransaction::OnCallback,
32                                  base::Unretained(this))) {
33   DCHECK(controller);
34 }
35
36 DevToolsNetworkTransaction::~DevToolsNetworkTransaction() {
37   if (interceptor_)
38     interceptor_->RemoveTransaction(this);
39 }
40
41 void DevToolsNetworkTransaction::Throttle(int result) {
42   throttled_result_ = result;
43
44   if (callback_type_ == START)
45     throttled_byte_count_ += network_transaction_->GetTotalReceivedBytes();
46   if (result > 0)
47     throttled_byte_count_ += result;
48
49   if (interceptor_)
50     interceptor_->ThrottleTransaction(this, callback_type_ == START);
51 }
52
53 void 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
69 int 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
102 void 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
116 int 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
135 void 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
162 int 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
170 int 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
180 int 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
189 bool DevToolsNetworkTransaction::IsReadyToRestartForAuth() {
190   return network_transaction_->IsReadyToRestartForAuth();
191 }
192
193 int 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
203 void DevToolsNetworkTransaction::StopCaching() {
204   network_transaction_->StopCaching();
205 }
206
207 bool DevToolsNetworkTransaction::GetFullRequestHeaders(
208     net::HttpRequestHeaders* headers) const {
209   return network_transaction_->GetFullRequestHeaders(headers);
210 }
211
212 int64 DevToolsNetworkTransaction::GetTotalReceivedBytes() const {
213   return network_transaction_->GetTotalReceivedBytes();
214 }
215
216 void DevToolsNetworkTransaction::DoneReading() {
217   network_transaction_->DoneReading();
218 }
219
220 const net::HttpResponseInfo*
221 DevToolsNetworkTransaction::GetResponseInfo() const {
222   return network_transaction_->GetResponseInfo();
223 }
224
225 net::LoadState DevToolsNetworkTransaction::GetLoadState() const {
226   return network_transaction_->GetLoadState();
227 }
228
229 net::UploadProgress DevToolsNetworkTransaction::GetUploadProgress() const {
230   return network_transaction_->GetUploadProgress();
231 }
232
233 void DevToolsNetworkTransaction::SetQuicServerInfo(
234     net::QuicServerInfo* quic_server_info) {
235   network_transaction_->SetQuicServerInfo(quic_server_info);
236 }
237
238 bool DevToolsNetworkTransaction::GetLoadTimingInfo(
239     net::LoadTimingInfo* load_timing_info) const {
240   return network_transaction_->GetLoadTimingInfo(load_timing_info);
241 }
242
243 void DevToolsNetworkTransaction::SetPriority(net::RequestPriority priority) {
244   network_transaction_->SetPriority(priority);
245 }
246
247 void DevToolsNetworkTransaction::SetWebSocketHandshakeStreamCreateHelper(
248     net::WebSocketHandshakeStreamBase::CreateHelper* create_helper) {
249   network_transaction_->SetWebSocketHandshakeStreamCreateHelper(create_helper);
250 }
251
252 void DevToolsNetworkTransaction::SetBeforeNetworkStartCallback(
253     const BeforeNetworkStartCallback& callback) {
254   network_transaction_->SetBeforeNetworkStartCallback(callback);
255 }
256
257 void DevToolsNetworkTransaction::SetBeforeProxyHeadersSentCallback(
258     const BeforeProxyHeadersSentCallback& callback) {
259   network_transaction_->SetBeforeProxyHeadersSentCallback(callback);
260 }
261
262 int DevToolsNetworkTransaction::ResumeNetworkStart() {
263   if (failed_)
264     return net::ERR_INTERNET_DISCONNECTED;
265   return network_transaction_->ResumeNetworkStart();
266 }
267
268 void DevToolsNetworkTransaction::FireThrottledCallback() {
269   DCHECK(!callback_.is_null());
270   DCHECK(callback_type_ == READ || callback_type_ == START);
271   net::CompletionCallback callback = callback_;
272   callback_.Reset();
273   callback_type_ = NONE;
274   callback.Run(throttled_result_);
275 }