Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(86)

Side by Side Diff: components/cronet/android/url_request_adapter.cc

Issue 743713002: Cronet Fix Channel Write after Close when request is canceled after success. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Split out change to net::IOBufferWithSize. Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "url_request_adapter.h" 5 #include "url_request_adapter.h"
6 6
7 #include <string.h> 7 #include <string.h>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/location.h" 10 #include "base/location.h"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/single_thread_task_runner.h" 12 #include "base/single_thread_task_runner.h"
13 #include "base/strings/string_number_conversions.h" 13 #include "base/strings/string_number_conversions.h"
14 #include "components/cronet/android/url_request_context_adapter.h" 14 #include "components/cronet/android/url_request_context_adapter.h"
15 #include "components/cronet/android/wrapped_channel_upload_element_reader.h" 15 #include "components/cronet/android/wrapped_channel_upload_element_reader.h"
16 #include "net/base/elements_upload_data_stream.h" 16 #include "net/base/elements_upload_data_stream.h"
17 #include "net/base/load_flags.h" 17 #include "net/base/load_flags.h"
18 #include "net/base/net_errors.h" 18 #include "net/base/net_errors.h"
19 #include "net/base/upload_bytes_element_reader.h" 19 #include "net/base/upload_bytes_element_reader.h"
20 #include "net/http/http_response_headers.h" 20 #include "net/http/http_response_headers.h"
21 #include "net/http/http_status_code.h" 21 #include "net/http/http_status_code.h"
22 22
23 namespace cronet { 23 namespace cronet {
24 24
25 static const size_t kBufferSizeIncrement = 8192; 25 static const size_t kBufferSizeIncrement = 32768;
26 26
27 URLRequestAdapter::URLRequestAdapter(URLRequestContextAdapter* context, 27 URLRequestAdapter::URLRequestAdapter(URLRequestContextAdapter* context,
28 URLRequestAdapterDelegate* delegate, 28 URLRequestAdapterDelegate* delegate,
29 GURL url, 29 GURL url,
30 net::RequestPriority priority) 30 net::RequestPriority priority)
31 : method_("GET"), 31 : method_("GET"),
32 read_buffer_(new net::GrowableIOBuffer()), 32 read_buffer_(new net::GrowableIOBuffer()),
33 bytes_read_(0), 33 bytes_read_(0),
34 total_bytes_read_(0), 34 total_bytes_read_(0),
35 error_code_(0), 35 error_code_(0),
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
164 } else if (chunked_upload_) { 164 } else if (chunked_upload_) {
165 url_request_->EnableChunkedUpload(); 165 url_request_->EnableChunkedUpload();
166 } 166 }
167 167
168 url_request_->SetPriority(priority_); 168 url_request_->SetPriority(priority_);
169 169
170 url_request_->Start(); 170 url_request_->Start();
171 } 171 }
172 172
173 void URLRequestAdapter::Cancel() { 173 void URLRequestAdapter::Cancel() {
174 if (canceled_) {
175 return;
176 }
177
178 canceled_ = true;
179
180 context_->PostTaskToNetworkThread( 174 context_->PostTaskToNetworkThread(
181 FROM_HERE, 175 FROM_HERE,
182 base::Bind(&URLRequestAdapter::OnCancelRequest, base::Unretained(this))); 176 base::Bind(&URLRequestAdapter::OnCancelRequest, base::Unretained(this)));
183 } 177 }
184 178
185 void URLRequestAdapter::OnCancelRequest() { 179 void URLRequestAdapter::OnCancelRequest() {
186 DCHECK(OnNetworkThread()); 180 DCHECK(OnNetworkThread());
187 VLOG(1) << "Canceling chromium request: " << url_.possibly_invalid_spec(); 181 VLOG(1) << "Canceling chromium request: " << url_.possibly_invalid_spec();
188 182 if (canceled_) {
183 return;
184 }
mmenke 2014/12/02 17:10:24 nit: Shouldn't use braces on single line if's (Ye
mef 2014/12/02 19:41:40 Done.
185 canceled_ = true;
189 if (url_request_ != NULL) { 186 if (url_request_ != NULL) {
190 url_request_->Cancel(); 187 url_request_->Cancel();
191 } 188 }
192 189
193 OnRequestCanceled(); 190 OnRequestCanceled();
194 } 191 }
195 192
196 void URLRequestAdapter::Destroy() { 193 void URLRequestAdapter::Destroy() {
197 context_->PostTaskToNetworkThread( 194 context_->PostTaskToNetworkThread(
198 FROM_HERE, base::Bind(&URLRequestAdapter::OnDestroyRequest, this)); 195 FROM_HERE, base::Bind(&URLRequestAdapter::OnDestroyRequest, this));
(...skipping 23 matching lines...) Expand all
222 http_status_text_ = headers->GetStatusText(); 219 http_status_text_ = headers->GetStatusText();
223 220
224 request->GetResponseHeaderByName("Content-Type", &content_type_); 221 request->GetResponseHeaderByName("Content-Type", &content_type_);
225 expected_size_ = request->GetExpectedContentSize(); 222 expected_size_ = request->GetExpectedContentSize();
226 delegate_->OnResponseStarted(this); 223 delegate_->OnResponseStarted(this);
227 224
228 Read(); 225 Read();
229 } 226 }
230 227
231 // Reads all available data or starts an asynchronous read. 228 // Reads all available data or starts an asynchronous read.
232 void URLRequestAdapter::Read() { 229 void URLRequestAdapter::Read() {
mmenke 2014/12/02 17:10:24 Why does all this stuff here need to be a part of
mef 2014/12/02 19:41:40 Discussed. :)
233 DCHECK(OnNetworkThread()); 230 DCHECK(OnNetworkThread());
234 while (true) { 231 if (read_buffer_->RemainingCapacity() == 0) {
235 if (read_buffer_->RemainingCapacity() == 0) { 232 int new_capacity = read_buffer_->capacity() + kBufferSizeIncrement;
236 int new_capacity = read_buffer_->capacity() + kBufferSizeIncrement; 233 read_buffer_->SetCapacity(new_capacity);
237 read_buffer_->SetCapacity(new_capacity); 234 }
238 }
239 235
240 int bytes_read; 236 int bytes_read = 0;
241 if (url_request_->Read(read_buffer_.get(), 237 url_request_->Read(
242 read_buffer_->RemainingCapacity(), 238 read_buffer_.get(), read_buffer_->RemainingCapacity(), &bytes_read);
243 &bytes_read)) { 239 // If IO is pending, wait for the URLRequest to call OnReadCompleted.
244 if (bytes_read == 0) { 240 if (url_request_->status().is_io_pending())
245 OnRequestSucceeded(); 241 return;
246 break;
247 }
248 242
249 VLOG(1) << "Synchronously read: " << bytes_read << " bytes"; 243 VLOG(1) << "Synchronously read: " << bytes_read << " bytes";
250 OnBytesRead(bytes_read); 244 OnReadCompleted(url_request_.get(), bytes_read);
251 } else if (url_request_->status().status() ==
252 net::URLRequestStatus::IO_PENDING) {
253 if (bytes_read_ != 0) {
254 VLOG(1) << "Flushing buffer: " << bytes_read_ << " bytes";
255
256 delegate_->OnBytesRead(this);
257 read_buffer_->set_offset(0);
258 bytes_read_ = 0;
259 }
260 VLOG(1) << "Started async read";
261 break;
262 } else {
263 OnRequestFailed();
264 break;
265 }
266 }
267 } 245 }
268 246
269 void URLRequestAdapter::OnReadCompleted(net::URLRequest* request, 247 void URLRequestAdapter::OnReadCompleted(net::URLRequest* request,
270 int bytes_read) { 248 int bytes_read) {
271 DCHECK(OnNetworkThread()); 249 DCHECK(OnNetworkThread());
272 VLOG(1) << "Asynchronously read: " << bytes_read << " bytes"; 250 VLOG(1) << "Completed read: " << bytes_read << " bytes";
273 if (bytes_read < 0) { 251 if (!url_request_->status().is_success()) {
274 OnRequestFailed(); 252 OnRequestFailed();
275 return; 253 return;
276 } else if (bytes_read == 0) { 254 } else if (bytes_read == 0) {
277 OnRequestSucceeded(); 255 OnRequestSucceeded();
278 return; 256 return;
279 } 257 }
280 258
281 OnBytesRead(bytes_read); 259 OnBytesRead(bytes_read);
282 Read(); 260 Read();
mmenke 2014/12/02 18:15:12 Recommend against tail recursion here. Ideally sh
mef 2014/12/02 19:41:39 Ack. I've tried to post the read to network thread
mmenke 2014/12/02 20:33:47 I'd suggest splitting the logic into 3 methods: R
mef 2014/12/03 20:29:54 Done.
283 } 261 }
284 262
285 void URLRequestAdapter::OnReceivedRedirect(net::URLRequest* request, 263 void URLRequestAdapter::OnReceivedRedirect(net::URLRequest* request,
286 const net::RedirectInfo& info, 264 const net::RedirectInfo& info,
287 bool* defer_redirect) { 265 bool* defer_redirect) {
288 DCHECK(OnNetworkThread()); 266 DCHECK(OnNetworkThread());
289 if (disable_redirect_) { 267 if (disable_redirect_) {
290 http_status_code_ = request->GetResponseCode(); 268 http_status_code_ = request->GetResponseCode();
291 request->CancelWithError(net::ERR_TOO_MANY_REDIRECTS); 269 request->CancelWithError(net::ERR_TOO_MANY_REDIRECTS);
292 error_code_ = net::ERR_TOO_MANY_REDIRECTS; 270 error_code_ = net::ERR_TOO_MANY_REDIRECTS;
293 canceled_ = true; 271 canceled_ = true;
294 *defer_redirect = false; 272 *defer_redirect = false;
295 OnRequestCompleted(); 273 OnRequestCompleted();
296 } 274 }
297 } 275 }
298 276
299 void URLRequestAdapter::OnBytesRead(int bytes_read) { 277 void URLRequestAdapter::OnBytesRead(int bytes_read) {
mmenke 2014/12/02 18:15:12 Suggest just inlining this.
mef 2014/12/02 19:41:39 Done.
300 DCHECK(OnNetworkThread()); 278 DCHECK(OnNetworkThread());
301 read_buffer_->set_offset(read_buffer_->offset() + bytes_read); 279 bytes_read_ = bytes_read;
302 bytes_read_ += bytes_read;
303 total_bytes_read_ += bytes_read; 280 total_bytes_read_ += bytes_read;
281 delegate_->OnBytesRead(this);
282 read_buffer_->set_offset(0);
283 bytes_read_ = 0;
mmenke 2014/12/02 18:15:12 If we're going to refactor this logic here, should
mef 2014/12/02 19:41:40 Done.
304 } 284 }
305 285
306 void URLRequestAdapter::OnRequestSucceeded() { 286 void URLRequestAdapter::OnRequestSucceeded() {
307 DCHECK(OnNetworkThread()); 287 DCHECK(OnNetworkThread());
308 if (canceled_) { 288 if (canceled_) {
309 return; 289 return;
310 } 290 }
311 291
312 VLOG(1) << "Request completed with HTTP status: " << http_status_code_ 292 VLOG(1) << "Request completed with HTTP status: " << http_status_code_
313 << ". Total bytes read: " << total_bytes_read_; 293 << ". Total bytes read: " << total_bytes_read_;
314 294
315 OnRequestCompleted(); 295 OnRequestCompleted();
316 } 296 }
317 297
318 void URLRequestAdapter::OnRequestFailed() { 298 void URLRequestAdapter::OnRequestFailed() {
319 DCHECK(OnNetworkThread()); 299 DCHECK(OnNetworkThread());
320 if (canceled_) { 300 if (canceled_) {
321 return; 301 return;
322 } 302 }
323 303
324 error_code_ = url_request_->status().error(); 304 error_code_ = url_request_->status().error();
325 VLOG(1) << "Request failed with status: " << url_request_->status().status() 305 VLOG(1) << "Request failed with status: " << url_request_->status().status()
326 << " and error: " << net::ErrorToString(error_code_); 306 << " and error: " << net::ErrorToString(error_code_);
327 OnRequestCompleted(); 307 OnRequestCompleted();
328 } 308 }
329 309
330 void URLRequestAdapter::OnRequestCanceled() { 310 void URLRequestAdapter::OnRequestCanceled() {
mmenke 2014/12/02 18:15:12 Having OnCancelRequest and OnRequestCanceled seems
mef 2014/12/02 19:41:39 Done.
331 DCHECK(OnNetworkThread()); 311 DCHECK(OnNetworkThread());
332 OnRequestCompleted(); 312 OnRequestCompleted();
333 } 313 }
334 314
335 void URLRequestAdapter::OnRequestCompleted() { 315 void URLRequestAdapter::OnRequestCompleted() {
336 DCHECK(OnNetworkThread()); 316 DCHECK(OnNetworkThread());
337 VLOG(1) << "Completed: " << url_.possibly_invalid_spec(); 317 VLOG(1) << "Completed: " << url_.possibly_invalid_spec();
338 318
339 delegate_->OnBytesRead(this); 319 if (url_request_ == nullptr)
mmenke 2014/12/02 18:15:12 This handles the cancel after complete case? If y
mef 2014/12/02 19:41:39 I think it also handles complete after cancel, doe
mmenke 2014/12/02 20:33:47 Don't think so. Cancel calls into OnRequestComple
mef 2014/12/03 20:29:54 Done.
320 return;
321
340 delegate_->OnRequestFinished(this); 322 delegate_->OnRequestFinished(this);
341 url_request_.reset(); 323 url_request_.reset();
342 } 324 }
343 325
344 unsigned char* URLRequestAdapter::Data() const { 326 unsigned char* URLRequestAdapter::Data() const {
345 DCHECK(OnNetworkThread()); 327 DCHECK(OnNetworkThread());
346 return reinterpret_cast<unsigned char*>(read_buffer_->StartOfBuffer()); 328 return reinterpret_cast<unsigned char*>(read_buffer_->StartOfBuffer());
347 } 329 }
348 330
349 bool URLRequestAdapter::OnNetworkThread() const { 331 bool URLRequestAdapter::OnNetworkThread() const {
350 return context_->GetNetworkTaskRunner()->BelongsToCurrentThread(); 332 return context_->GetNetworkTaskRunner()->BelongsToCurrentThread();
351 } 333 }
352 334
353 } // namespace cronet 335 } // namespace cronet
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698