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 "services/network/throttling/throttling_network_transaction.h"
6 
7 #include <utility>
8 
9 #include "base/bind.h"
10 #include "base/callback_helpers.h"
11 #include "net/base/load_timing_info.h"
12 #include "net/base/net_errors.h"
13 #include "net/http/http_network_transaction.h"
14 #include "net/http/http_request_info.h"
15 #include "net/socket/connection_attempts.h"
16 #include "services/network/throttling/throttling_controller.h"
17 #include "services/network/throttling/throttling_network_interceptor.h"
18 #include "services/network/throttling/throttling_upload_data_stream.h"
19 
20 namespace network {
21 
ThrottlingNetworkTransaction(std::unique_ptr<net::HttpTransaction> network_transaction)22 ThrottlingNetworkTransaction::ThrottlingNetworkTransaction(
23     std::unique_ptr<net::HttpTransaction> network_transaction)
24     : throttled_byte_count_(0),
25       network_transaction_(std::move(network_transaction)),
26       request_(nullptr),
27       failed_(false) {}
28 
~ThrottlingNetworkTransaction()29 ThrottlingNetworkTransaction::~ThrottlingNetworkTransaction() {
30   if (interceptor_ && !throttle_callback_.is_null())
31     interceptor_->StopThrottle(throttle_callback_);
32 }
33 
IOCallback(bool start,int result)34 void ThrottlingNetworkTransaction::IOCallback(
35     bool start,
36     int result) {
37   DCHECK(callback_);
38   result = Throttle(start, result);
39   if (result != net::ERR_IO_PENDING)
40     std::move(callback_).Run(result);
41 }
42 
Throttle(bool start,int result)43 int ThrottlingNetworkTransaction::Throttle(
44     bool start,
45     int result) {
46   if (failed_)
47     return net::ERR_INTERNET_DISCONNECTED;
48   if (!interceptor_ || result < 0)
49     return result;
50 
51   base::TimeTicks send_end;
52   if (start) {
53     throttled_byte_count_ += network_transaction_->GetTotalReceivedBytes();
54     net::LoadTimingInfo load_timing_info;
55     if (GetLoadTimingInfo(&load_timing_info)) {
56       send_end = load_timing_info.send_end;
57       if (!load_timing_info.push_start.is_null())
58         start = false;
59     }
60     if (send_end.is_null())
61       send_end = base::TimeTicks::Now();
62   }
63   if (result > 0)
64     throttled_byte_count_ += result;
65 
66   throttle_callback_ = base::BindRepeating(
67       &ThrottlingNetworkTransaction::ThrottleCallback, base::Unretained(this));
68   int rv = interceptor_->StartThrottle(result, throttled_byte_count_, send_end,
69                                        start, false, throttle_callback_);
70   if (rv != net::ERR_IO_PENDING)
71     throttle_callback_.Reset();
72   if (rv == net::ERR_INTERNET_DISCONNECTED)
73     Fail();
74   return rv;
75 }
76 
ThrottleCallback(int result,int64_t bytes)77 void ThrottlingNetworkTransaction::ThrottleCallback(
78     int result,
79     int64_t bytes) {
80   DCHECK(callback_);
81   DCHECK(!throttle_callback_.is_null());
82 
83   throttle_callback_.Reset();
84   if (result == net::ERR_INTERNET_DISCONNECTED)
85     Fail();
86   throttled_byte_count_ = bytes;
87   std::move(callback_).Run(result);
88 }
89 
Fail()90 void ThrottlingNetworkTransaction::Fail() {
91   DCHECK(request_);
92   DCHECK(!failed_);
93   failed_ = true;
94   network_transaction_->SetBeforeNetworkStartCallback(
95       BeforeNetworkStartCallback());
96   if (interceptor_)
97     interceptor_.reset();
98 }
99 
CheckFailed()100 bool ThrottlingNetworkTransaction::CheckFailed() {
101   if (failed_)
102     return true;
103   if (interceptor_ && interceptor_->IsOffline()) {
104     Fail();
105     return true;
106   }
107   return false;
108 }
109 
Start(const net::HttpRequestInfo * request,net::CompletionOnceCallback callback,const net::NetLogWithSource & net_log)110 int ThrottlingNetworkTransaction::Start(const net::HttpRequestInfo* request,
111                                         net::CompletionOnceCallback callback,
112                                         const net::NetLogWithSource& net_log) {
113   DCHECK(request);
114   request_ = request;
115 
116   ThrottlingNetworkInterceptor* interceptor =
117       ThrottlingController::GetInterceptor(net_log.source().id);
118 
119   if (interceptor) {
120     custom_request_.reset(new net::HttpRequestInfo(*request_));
121 
122     if (request_->upload_data_stream) {
123       custom_upload_data_stream_.reset(
124           new ThrottlingUploadDataStream(request_->upload_data_stream));
125       custom_request_->upload_data_stream = custom_upload_data_stream_.get();
126     }
127 
128     request_ = custom_request_.get();
129 
130     interceptor_ = interceptor->GetWeakPtr();
131     if (custom_upload_data_stream_)
132       custom_upload_data_stream_->SetInterceptor(interceptor);
133   }
134 
135   if (CheckFailed())
136     return net::ERR_INTERNET_DISCONNECTED;
137 
138   if (!interceptor_)
139     return network_transaction_->Start(request_, std::move(callback), net_log);
140 
141   callback_ = std::move(callback);
142   int result = network_transaction_->Start(
143       request_,
144       base::BindOnce(&ThrottlingNetworkTransaction::IOCallback,
145                      base::Unretained(this), true),
146       net_log);
147   return Throttle(true, result);
148 }
149 
RestartIgnoringLastError(net::CompletionOnceCallback callback)150 int ThrottlingNetworkTransaction::RestartIgnoringLastError(
151     net::CompletionOnceCallback callback) {
152   if (CheckFailed())
153     return net::ERR_INTERNET_DISCONNECTED;
154   if (!interceptor_)
155     return network_transaction_->RestartIgnoringLastError(std::move(callback));
156 
157   callback_ = std::move(callback);
158   int result = network_transaction_->RestartIgnoringLastError(base::BindOnce(
159       &ThrottlingNetworkTransaction::IOCallback, base::Unretained(this), true));
160   return Throttle(true, result);
161 }
162 
RestartWithCertificate(scoped_refptr<net::X509Certificate> client_cert,scoped_refptr<net::SSLPrivateKey> client_private_key,net::CompletionOnceCallback callback)163 int ThrottlingNetworkTransaction::RestartWithCertificate(
164     scoped_refptr<net::X509Certificate> client_cert,
165     scoped_refptr<net::SSLPrivateKey> client_private_key,
166     net::CompletionOnceCallback callback) {
167   if (CheckFailed())
168     return net::ERR_INTERNET_DISCONNECTED;
169   if (!interceptor_) {
170     return network_transaction_->RestartWithCertificate(
171         std::move(client_cert), std::move(client_private_key),
172         std::move(callback));
173   }
174 
175   callback_ = std::move(callback);
176   int result = network_transaction_->RestartWithCertificate(
177       std::move(client_cert), std::move(client_private_key),
178       base::BindOnce(&ThrottlingNetworkTransaction::IOCallback,
179                      base::Unretained(this), true));
180   return Throttle(true, result);
181 }
182 
RestartWithAuth(const net::AuthCredentials & credentials,net::CompletionOnceCallback callback)183 int ThrottlingNetworkTransaction::RestartWithAuth(
184     const net::AuthCredentials& credentials,
185     net::CompletionOnceCallback callback) {
186   if (CheckFailed())
187     return net::ERR_INTERNET_DISCONNECTED;
188   if (!interceptor_)
189     return network_transaction_->RestartWithAuth(credentials,
190                                                  std::move(callback));
191 
192   callback_ = std::move(callback);
193   int result = network_transaction_->RestartWithAuth(
194       credentials, base::BindOnce(&ThrottlingNetworkTransaction::IOCallback,
195                                   base::Unretained(this), true));
196   return Throttle(true, result);
197 }
198 
IsReadyToRestartForAuth()199 bool ThrottlingNetworkTransaction::IsReadyToRestartForAuth() {
200   return network_transaction_->IsReadyToRestartForAuth();
201 }
202 
Read(net::IOBuffer * buf,int buf_len,net::CompletionOnceCallback callback)203 int ThrottlingNetworkTransaction::Read(net::IOBuffer* buf,
204                                        int buf_len,
205                                        net::CompletionOnceCallback callback) {
206   if (CheckFailed())
207     return net::ERR_INTERNET_DISCONNECTED;
208   if (!interceptor_)
209     return network_transaction_->Read(buf, buf_len, std::move(callback));
210 
211   callback_ = std::move(callback);
212   int result = network_transaction_->Read(
213       buf, buf_len,
214       base::BindOnce(&ThrottlingNetworkTransaction::IOCallback,
215                      base::Unretained(this), false));
216   // URLRequestJob relies on synchronous end-of-stream notification.
217   if (result == 0)
218     return result;
219   return Throttle(false, result);
220 }
221 
StopCaching()222 void ThrottlingNetworkTransaction::StopCaching() {
223   network_transaction_->StopCaching();
224 }
225 
GetTotalReceivedBytes() const226 int64_t ThrottlingNetworkTransaction::GetTotalReceivedBytes() const {
227   return network_transaction_->GetTotalReceivedBytes();
228 }
229 
GetTotalSentBytes() const230 int64_t ThrottlingNetworkTransaction::GetTotalSentBytes() const {
231   return network_transaction_->GetTotalSentBytes();
232 }
233 
DoneReading()234 void ThrottlingNetworkTransaction::DoneReading() {
235   network_transaction_->DoneReading();
236 }
237 
GetResponseInfo() const238 const net::HttpResponseInfo* ThrottlingNetworkTransaction::GetResponseInfo()
239     const {
240   return network_transaction_->GetResponseInfo();
241 }
242 
GetLoadState() const243 net::LoadState ThrottlingNetworkTransaction::GetLoadState() const {
244   return network_transaction_->GetLoadState();
245 }
246 
SetQuicServerInfo(net::QuicServerInfo * quic_server_info)247 void ThrottlingNetworkTransaction::SetQuicServerInfo(
248     net::QuicServerInfo* quic_server_info) {
249   network_transaction_->SetQuicServerInfo(quic_server_info);
250 }
251 
GetLoadTimingInfo(net::LoadTimingInfo * load_timing_info) const252 bool ThrottlingNetworkTransaction::GetLoadTimingInfo(
253     net::LoadTimingInfo* load_timing_info) const {
254   return network_transaction_->GetLoadTimingInfo(load_timing_info);
255 }
256 
GetRemoteEndpoint(net::IPEndPoint * endpoint) const257 bool ThrottlingNetworkTransaction::GetRemoteEndpoint(
258     net::IPEndPoint* endpoint) const {
259   return network_transaction_->GetRemoteEndpoint(endpoint);
260 }
261 
PopulateNetErrorDetails(net::NetErrorDetails * details) const262 void ThrottlingNetworkTransaction::PopulateNetErrorDetails(
263     net::NetErrorDetails* details) const {
264   return network_transaction_->PopulateNetErrorDetails(details);
265 }
266 
SetPriority(net::RequestPriority priority)267 void ThrottlingNetworkTransaction::SetPriority(net::RequestPriority priority) {
268   network_transaction_->SetPriority(priority);
269 }
270 
SetWebSocketHandshakeStreamCreateHelper(net::WebSocketHandshakeStreamBase::CreateHelper * create_helper)271 void ThrottlingNetworkTransaction::SetWebSocketHandshakeStreamCreateHelper(
272     net::WebSocketHandshakeStreamBase::CreateHelper* create_helper) {
273   network_transaction_->SetWebSocketHandshakeStreamCreateHelper(create_helper);
274 }
275 
SetBeforeNetworkStartCallback(BeforeNetworkStartCallback callback)276 void ThrottlingNetworkTransaction::SetBeforeNetworkStartCallback(
277     BeforeNetworkStartCallback callback) {
278   network_transaction_->SetBeforeNetworkStartCallback(std::move(callback));
279 }
280 
SetRequestHeadersCallback(net::RequestHeadersCallback callback)281 void ThrottlingNetworkTransaction::SetRequestHeadersCallback(
282     net::RequestHeadersCallback callback) {
283   network_transaction_->SetRequestHeadersCallback(std::move(callback));
284 }
285 
SetResponseHeadersCallback(net::ResponseHeadersCallback callback)286 void ThrottlingNetworkTransaction::SetResponseHeadersCallback(
287     net::ResponseHeadersCallback callback) {
288   network_transaction_->SetResponseHeadersCallback(std::move(callback));
289 }
290 
SetConnectedCallback(const ConnectedCallback & callback)291 void ThrottlingNetworkTransaction::SetConnectedCallback(
292     const ConnectedCallback& callback) {
293   network_transaction_->SetConnectedCallback(callback);
294 }
295 
ResumeNetworkStart()296 int ThrottlingNetworkTransaction::ResumeNetworkStart() {
297   if (CheckFailed())
298     return net::ERR_INTERNET_DISCONNECTED;
299   return network_transaction_->ResumeNetworkStart();
300 }
301 
GetConnectionAttempts(net::ConnectionAttempts * out) const302 void ThrottlingNetworkTransaction::GetConnectionAttempts(
303     net::ConnectionAttempts* out) const {
304   network_transaction_->GetConnectionAttempts(out);
305 }
306 
307 }  // namespace network
308