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