OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "content/common/net/url_fetcher.h" | 5 #include "content/common/net/url_fetcher.h" |
6 | 6 |
7 #include <set> | 7 #include <set> |
8 | 8 |
| 9 #include "base/bind.h" |
| 10 #include "base/bind_helpers.h" |
9 #include "base/compiler_specific.h" | 11 #include "base/compiler_specific.h" |
10 #include "base/file_path.h" | 12 #include "base/file_path.h" |
11 #include "base/file_util_proxy.h" | 13 #include "base/file_util_proxy.h" |
12 #include "base/lazy_instance.h" | 14 #include "base/lazy_instance.h" |
13 #include "base/memory/scoped_callback_factory.h" | |
14 #include "base/memory/scoped_ptr.h" | 15 #include "base/memory/scoped_ptr.h" |
| 16 #include "base/memory/weak_ptr.h" |
15 #include "base/message_loop_proxy.h" | 17 #include "base/message_loop_proxy.h" |
16 #include "base/platform_file.h" | 18 #include "base/platform_file.h" |
17 #include "base/stl_util.h" | 19 #include "base/stl_util.h" |
18 #include "base/string_util.h" | 20 #include "base/string_util.h" |
19 #include "base/threading/thread.h" | 21 #include "base/threading/thread.h" |
20 #include "googleurl/src/gurl.h" | 22 #include "googleurl/src/gurl.h" |
21 #include "net/base/host_port_pair.h" | 23 #include "net/base/host_port_pair.h" |
22 #include "net/base/io_buffer.h" | 24 #include "net/base/io_buffer.h" |
23 #include "net/base/load_flags.h" | 25 #include "net/base/load_flags.h" |
24 #include "net/base/net_errors.h" | 26 #include "net/base/net_errors.h" |
25 #include "net/http/http_request_headers.h" | 27 #include "net/http/http_request_headers.h" |
26 #include "net/http/http_response_headers.h" | 28 #include "net/http/http_response_headers.h" |
27 #include "net/url_request/url_request.h" | 29 #include "net/url_request/url_request.h" |
28 #include "net/url_request/url_request_context.h" | 30 #include "net/url_request/url_request_context.h" |
29 #include "net/url_request/url_request_context_getter.h" | 31 #include "net/url_request/url_request_context_getter.h" |
30 #include "net/url_request/url_request_throttler_manager.h" | 32 #include "net/url_request/url_request_throttler_manager.h" |
31 | 33 |
32 static const int kBufferSize = 4096; | 34 static const int kBufferSize = 4096; |
33 const int URLFetcher::kInvalidHttpResponseCode = -1; | 35 const int URLFetcher::kInvalidHttpResponseCode = -1; |
34 | 36 |
| 37 using base::FileUtilProxy; |
| 38 using base::PlatformFileError; |
| 39 |
35 class URLFetcher::Core | 40 class URLFetcher::Core |
36 : public base::RefCountedThreadSafe<URLFetcher::Core>, | 41 : public base::RefCountedThreadSafe<URLFetcher::Core>, |
37 public net::URLRequest::Delegate { | 42 public net::URLRequest::Delegate { |
38 public: | 43 public: |
39 // For POST requests, set |content_type| to the MIME type of the content | 44 // For POST requests, set |content_type| to the MIME type of the content |
40 // and set |content| to the data to upload. |flags| are flags to apply to | 45 // and set |content| to the data to upload. |flags| are flags to apply to |
41 // the load operation--these should be one or more of the LOAD_* flags | 46 // the load operation--these should be one or more of the LOAD_* flags |
42 // defined in net/base/load_flags.h. | 47 // defined in net/base/load_flags.h. |
43 Core(URLFetcher* fetcher, | 48 Core(URLFetcher* fetcher, |
44 const GURL& original_url, | 49 const GURL& original_url, |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
139 // Callback which gets the result of closing the temp file. | 144 // Callback which gets the result of closing the temp file. |
140 void DidCloseTempFile(base::PlatformFileError error); | 145 void DidCloseTempFile(base::PlatformFileError error); |
141 | 146 |
142 // The URLFetcher::Core which instantiated this class. | 147 // The URLFetcher::Core which instantiated this class. |
143 URLFetcher::Core* core_; | 148 URLFetcher::Core* core_; |
144 | 149 |
145 // The last error encountered on a file operation. base::PLATFORM_FILE_OK | 150 // The last error encountered on a file operation. base::PLATFORM_FILE_OK |
146 // if no error occurred. | 151 // if no error occurred. |
147 base::PlatformFileError error_code_; | 152 base::PlatformFileError error_code_; |
148 | 153 |
149 // Callbacks are created for use with base::FileUtilProxy. | 154 // For file_util calls on the FileThread. |
150 base::ScopedCallbackFactory<URLFetcher::Core::TempFileWriter> | 155 base::WeakPtrFactory<URLFetcher::Core::TempFileWriter> |
151 callback_factory_; | 156 weak_factory_; |
152 | 157 |
153 // Message loop on which file opperations should happen. | 158 // Message loop on which file opperations should happen. |
154 scoped_refptr<base::MessageLoopProxy> file_message_loop_proxy_; | 159 scoped_refptr<base::MessageLoopProxy> file_message_loop_proxy_; |
155 | 160 |
156 // Path to the temporary file. This path is empty when there | 161 // Path to the temporary file. This path is empty when there |
157 // is no temp file. | 162 // is no temp file. |
158 FilePath temp_file_; | 163 FilePath temp_file_; |
159 | 164 |
160 // Handle to the temp file. | 165 // Handle to the temp file. |
161 base::PlatformFile temp_file_handle_; | 166 base::PlatformFile temp_file_handle_; |
162 | 167 |
| 168 // Bytes written by the last ContinueWrite. |
| 169 int bytes_written_; |
| 170 |
163 // We always append to the file. Track the total number of bytes | 171 // We always append to the file. Track the total number of bytes |
164 // written, so that writes know the offset to give. | 172 // written, so that writes know the offset to give. |
165 int64 total_bytes_written_; | 173 int64 total_bytes_written_; |
166 | 174 |
167 // How many bytes did the last Write() try to write? Needed so | 175 // How many bytes did the last Write() try to write? Needed so |
168 // that if not all the bytes get written on a Write(), we can | 176 // that if not all the bytes get written on a Write(), we can |
169 // call Write() again with the rest. | 177 // call Write() again with the rest. |
170 int pending_bytes_; | 178 int pending_bytes_; |
171 | 179 |
172 // When writing, how many bytes from the buffer have been successfully | 180 // When writing, how many bytes from the buffer have been successfully |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
312 | 320 |
313 // static | 321 // static |
314 base::LazyInstance<URLFetcher::Core::Registry> | 322 base::LazyInstance<URLFetcher::Core::Registry> |
315 URLFetcher::Core::g_registry(base::LINKER_INITIALIZED); | 323 URLFetcher::Core::g_registry(base::LINKER_INITIALIZED); |
316 | 324 |
317 URLFetcher::Core::TempFileWriter::TempFileWriter( | 325 URLFetcher::Core::TempFileWriter::TempFileWriter( |
318 URLFetcher::Core* core, | 326 URLFetcher::Core* core, |
319 scoped_refptr<base::MessageLoopProxy> file_message_loop_proxy) | 327 scoped_refptr<base::MessageLoopProxy> file_message_loop_proxy) |
320 : core_(core), | 328 : core_(core), |
321 error_code_(base::PLATFORM_FILE_OK), | 329 error_code_(base::PLATFORM_FILE_OK), |
322 callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), | 330 weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), |
323 file_message_loop_proxy_(file_message_loop_proxy), | 331 file_message_loop_proxy_(file_message_loop_proxy), |
324 temp_file_handle_(base::kInvalidPlatformFileValue) { | 332 temp_file_handle_(base::kInvalidPlatformFileValue) { |
325 } | 333 } |
326 | 334 |
327 URLFetcher::Core::TempFileWriter::~TempFileWriter() { | 335 URLFetcher::Core::TempFileWriter::~TempFileWriter() { |
328 RemoveTempFile(); | 336 RemoveTempFile(); |
329 } | 337 } |
330 | 338 |
331 void URLFetcher::Core::TempFileWriter::CreateTempFile() { | 339 void URLFetcher::Core::TempFileWriter::CreateTempFile() { |
332 DCHECK(core_->io_message_loop_proxy_->BelongsToCurrentThread()); | 340 DCHECK(core_->io_message_loop_proxy_->BelongsToCurrentThread()); |
333 CHECK(file_message_loop_proxy_.get()); | 341 CHECK(file_message_loop_proxy_.get()); |
334 base::FileUtilProxy::CreateTemporary( | 342 FileUtilProxy::CreateTemporary( |
335 file_message_loop_proxy_, | 343 file_message_loop_proxy_, |
336 0, // No additional file flags. | 344 0, // No additional file flags. |
337 callback_factory_.NewCallback( | 345 base::Bind(&URLFetcher::Core::TempFileWriter::DidCreateTempFile, |
338 &URLFetcher::Core::TempFileWriter::DidCreateTempFile)); | 346 weak_factory_.GetWeakPtr())); |
339 } | 347 } |
340 | 348 |
341 void URLFetcher::Core::TempFileWriter::DidCreateTempFile( | 349 void URLFetcher::Core::TempFileWriter::DidCreateTempFile( |
342 base::PlatformFileError error_code, | 350 base::PlatformFileError error_code, |
343 base::PassPlatformFile file_handle, | 351 base::PassPlatformFile file_handle, |
344 FilePath file_path) { | 352 FilePath file_path) { |
345 DCHECK(core_->io_message_loop_proxy_->BelongsToCurrentThread()); | 353 DCHECK(core_->io_message_loop_proxy_->BelongsToCurrentThread()); |
346 | 354 |
347 if (base::PLATFORM_FILE_OK != error_code) { | 355 if (base::PLATFORM_FILE_OK != error_code) { |
348 error_code_ = error_code; | 356 error_code_ = error_code; |
349 RemoveTempFile(); | 357 RemoveTempFile(); |
350 core_->delegate_loop_proxy_->PostTask( | 358 core_->delegate_loop_proxy_->PostTask( |
351 FROM_HERE, | 359 FROM_HERE, |
352 NewRunnableMethod(core_, &Core::InformDelegateFetchIsComplete)); | 360 base::Bind(&Core::InformDelegateFetchIsComplete, core_)); |
353 return; | 361 return; |
354 } | 362 } |
355 | 363 |
356 temp_file_ = file_path; | 364 temp_file_ = file_path; |
357 temp_file_handle_ = file_handle.ReleaseValue(); | 365 temp_file_handle_ = file_handle.ReleaseValue(); |
358 total_bytes_written_ = 0; | 366 total_bytes_written_ = 0; |
359 | 367 |
360 core_->io_message_loop_proxy_->PostTask( | 368 core_->io_message_loop_proxy_->PostTask( |
361 FROM_HERE, | 369 FROM_HERE, |
362 NewRunnableMethod(core_, &Core::StartURLRequestWhenAppropriate)); | 370 base::Bind(&Core::StartURLRequestWhenAppropriate, core_)); |
363 } | 371 } |
364 | 372 |
365 void URLFetcher::Core::TempFileWriter::WriteBuffer(int num_bytes) { | 373 void URLFetcher::Core::TempFileWriter::WriteBuffer(int num_bytes) { |
366 DCHECK(core_->io_message_loop_proxy_->BelongsToCurrentThread()); | 374 DCHECK(core_->io_message_loop_proxy_->BelongsToCurrentThread()); |
367 | 375 |
368 // Start writing to the temp file by setting the initial state | 376 // Start writing to the temp file by setting the initial state |
369 // of |pending_bytes_| and |buffer_offset_| to indicate that the | 377 // of |pending_bytes_| and |buffer_offset_| to indicate that the |
370 // entire buffer has not yet been written. | 378 // entire buffer has not yet been written. |
371 pending_bytes_ = num_bytes; | 379 pending_bytes_ = num_bytes; |
372 buffer_offset_ = 0; | 380 buffer_offset_ = 0; |
373 ContinueWrite(base::PLATFORM_FILE_OK, 0); | 381 ContinueWrite(base::PLATFORM_FILE_OK, 0); |
374 } | 382 } |
375 | 383 |
376 void URLFetcher::Core::TempFileWriter::ContinueWrite( | 384 void URLFetcher::Core::TempFileWriter::ContinueWrite( |
377 base::PlatformFileError error_code, | 385 base::PlatformFileError error_code, |
378 int bytes_written) { | 386 int bytes_written) { |
379 DCHECK(core_->io_message_loop_proxy_->BelongsToCurrentThread()); | 387 DCHECK(core_->io_message_loop_proxy_->BelongsToCurrentThread()); |
380 | 388 |
381 if (base::PLATFORM_FILE_OK != error_code) { | 389 if (base::PLATFORM_FILE_OK != error_code) { |
382 error_code_ = error_code; | 390 error_code_ = error_code; |
383 RemoveTempFile(); | 391 RemoveTempFile(); |
384 core_->delegate_loop_proxy_->PostTask( | 392 core_->delegate_loop_proxy_->PostTask( |
385 FROM_HERE, | 393 FROM_HERE, |
386 NewRunnableMethod(core_, &Core::InformDelegateFetchIsComplete)); | 394 base::Bind(&Core::InformDelegateFetchIsComplete, core_)); |
387 return; | 395 return; |
388 } | 396 } |
389 | 397 |
390 total_bytes_written_ += bytes_written; | 398 total_bytes_written_ += bytes_written; |
391 buffer_offset_ += bytes_written; | 399 buffer_offset_ += bytes_written; |
392 pending_bytes_ -= bytes_written; | 400 pending_bytes_ -= bytes_written; |
393 | 401 |
394 if (pending_bytes_ > 0) { | 402 if (pending_bytes_ > 0) { |
395 base::FileUtilProxy::Write( | 403 FileUtilProxy::Write( |
396 file_message_loop_proxy_, | 404 file_message_loop_proxy_, |
397 temp_file_handle_, | 405 temp_file_handle_, |
398 total_bytes_written_, // Append to the end | 406 total_bytes_written_, // Append to the end |
399 (core_->buffer_->data() + buffer_offset_), | 407 (core_->buffer_->data() + buffer_offset_), |
400 pending_bytes_, | 408 pending_bytes_, |
401 callback_factory_.NewCallback( | 409 base::Bind(&URLFetcher::Core::TempFileWriter::ContinueWrite, |
402 &URLFetcher::Core::TempFileWriter::ContinueWrite)); | 410 weak_factory_.GetWeakPtr())); |
403 } else { | 411 } else { |
404 // Finished writing core_->buffer_ to the file. Read some more. | 412 // Finished writing core_->buffer_ to the file. Read some more. |
405 core_->ReadResponse(); | 413 core_->ReadResponse(); |
406 } | 414 } |
407 } | 415 } |
408 | 416 |
409 void URLFetcher::Core::TempFileWriter::DisownTempFile() { | 417 void URLFetcher::Core::TempFileWriter::DisownTempFile() { |
410 DCHECK(core_->io_message_loop_proxy_->BelongsToCurrentThread()); | 418 DCHECK(core_->io_message_loop_proxy_->BelongsToCurrentThread()); |
411 | 419 |
412 // Disowning is done by the delegate's OnURLFetchComplete method. | 420 // Disowning is done by the delegate's OnURLFetchComplete method. |
413 // The temp file should be closed by the time that method is called. | 421 // The temp file should be closed by the time that method is called. |
414 DCHECK(temp_file_handle_ == base::kInvalidPlatformFileValue); | 422 DCHECK(temp_file_handle_ == base::kInvalidPlatformFileValue); |
415 | 423 |
416 // Forget about any temp file by reseting the path. | 424 // Forget about any temp file by reseting the path. |
417 temp_file_ = FilePath(); | 425 temp_file_ = FilePath(); |
418 } | 426 } |
419 | 427 |
420 void URLFetcher::Core::TempFileWriter::CloseTempFileAndCompleteRequest() { | 428 void URLFetcher::Core::TempFileWriter::CloseTempFileAndCompleteRequest() { |
421 DCHECK(core_->io_message_loop_proxy_->BelongsToCurrentThread()); | 429 DCHECK(core_->io_message_loop_proxy_->BelongsToCurrentThread()); |
422 | 430 |
423 if (temp_file_handle_ != base::kInvalidPlatformFileValue) { | 431 if (temp_file_handle_ != base::kInvalidPlatformFileValue) { |
424 base::FileUtilProxy::Close( | 432 FileUtilProxy::PostFileTaskAndReplyStatus<bool, PlatformFileError>( |
425 file_message_loop_proxy_, | 433 file_message_loop_proxy_, |
426 temp_file_handle_, | 434 FROM_HERE, |
427 callback_factory_.NewCallback( | 435 base::Bind(&base::ClosePlatformFile, temp_file_handle_), |
428 &URLFetcher::Core::TempFileWriter::DidCloseTempFile)); | 436 base::Bind(&URLFetcher::Core::TempFileWriter::DidCloseTempFile, |
| 437 weak_factory_.GetWeakPtr())); |
429 temp_file_handle_ = base::kInvalidPlatformFileValue; | 438 temp_file_handle_ = base::kInvalidPlatformFileValue; |
430 } | 439 } |
431 } | 440 } |
432 | 441 |
433 void URLFetcher::Core::TempFileWriter::DidCloseTempFile( | 442 void URLFetcher::Core::TempFileWriter::DidCloseTempFile( |
434 base::PlatformFileError error_code) { | 443 base::PlatformFileError error_code) { |
435 DCHECK(core_->io_message_loop_proxy_->BelongsToCurrentThread()); | 444 DCHECK(core_->io_message_loop_proxy_->BelongsToCurrentThread()); |
436 | 445 |
437 if (base::PLATFORM_FILE_OK != error_code) { | 446 if (base::PLATFORM_FILE_OK != error_code) { |
438 error_code_ = error_code; | 447 error_code_ = error_code; |
439 RemoveTempFile(); | 448 RemoveTempFile(); |
440 core_->delegate_loop_proxy_->PostTask( | 449 core_->delegate_loop_proxy_->PostTask( |
441 FROM_HERE, | 450 FROM_HERE, |
442 NewRunnableMethod(core_, &Core::InformDelegateFetchIsComplete)); | 451 base::Bind(&Core::InformDelegateFetchIsComplete, core_)); |
443 return; | 452 return; |
444 } | 453 } |
445 | 454 |
446 // If the file was successfully closed, then the URL request is complete. | 455 // If the file was successfully closed, then the URL request is complete. |
447 core_->RetryOrCompleteUrlFetch(); | 456 core_->RetryOrCompleteUrlFetch(); |
448 } | 457 } |
449 | 458 |
450 void URLFetcher::Core::TempFileWriter::RemoveTempFile() { | 459 void URLFetcher::Core::TempFileWriter::RemoveTempFile() { |
451 DCHECK(core_->io_message_loop_proxy_->BelongsToCurrentThread()); | 460 DCHECK(core_->io_message_loop_proxy_->BelongsToCurrentThread()); |
452 | 461 |
453 // Close the temp file if it is open. | 462 // Close the temp file if it is open. |
454 if (temp_file_handle_ != base::kInvalidPlatformFileValue) { | 463 if (temp_file_handle_ != base::kInvalidPlatformFileValue) { |
455 base::FileUtilProxy::Close( | 464 file_message_loop_proxy_->PostTask( |
456 file_message_loop_proxy_, | 465 FROM_HERE, |
457 temp_file_handle_, | 466 base::IgnoreReturn(base::Callback<bool(void)>( |
458 NULL); // No callback: Ignore errors. | 467 base::Bind(&base::ClosePlatformFile, temp_file_handle_)))); |
459 temp_file_handle_ = base::kInvalidPlatformFileValue; | 468 temp_file_handle_ = base::kInvalidPlatformFileValue; |
460 } | 469 } |
461 | 470 |
462 if (!temp_file_.empty()) { | 471 if (!temp_file_.empty()) { |
463 base::FileUtilProxy::Delete( | 472 file_message_loop_proxy_->PostTask( |
464 file_message_loop_proxy_, | 473 FROM_HERE, |
465 temp_file_, | 474 base::IgnoreReturn(base::Callback<bool(void)>( |
466 false, // No need to recurse, as the path is to a file. | 475 base::Bind(&file_util::Delete, temp_file_, |
467 NULL); // No callback: Ignore errors. | 476 false /* recursive */)))); |
468 DisownTempFile(); | 477 DisownTempFile(); |
469 } | 478 } |
470 } | 479 } |
471 | 480 |
472 // static | 481 // static |
473 URLFetcher::Factory* URLFetcher::factory_ = NULL; | 482 URLFetcher::Factory* URLFetcher::factory_ = NULL; |
474 | 483 |
475 void URLFetcher::Delegate::OnURLFetchComplete( | 484 void URLFetcher::Delegate::OnURLFetchComplete( |
476 const URLFetcher* source, | 485 const URLFetcher* source, |
477 const GURL& url, | 486 const GURL& url, |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
559 if (io_message_loop_proxy_) { | 568 if (io_message_loop_proxy_) { |
560 DCHECK_EQ(io_message_loop_proxy_, | 569 DCHECK_EQ(io_message_loop_proxy_, |
561 request_context_getter_->GetIOMessageLoopProxy()); | 570 request_context_getter_->GetIOMessageLoopProxy()); |
562 } else { | 571 } else { |
563 io_message_loop_proxy_ = request_context_getter_->GetIOMessageLoopProxy(); | 572 io_message_loop_proxy_ = request_context_getter_->GetIOMessageLoopProxy(); |
564 } | 573 } |
565 CHECK(io_message_loop_proxy_.get()) << "We need an IO message loop proxy"; | 574 CHECK(io_message_loop_proxy_.get()) << "We need an IO message loop proxy"; |
566 | 575 |
567 io_message_loop_proxy_->PostTask( | 576 io_message_loop_proxy_->PostTask( |
568 FROM_HERE, | 577 FROM_HERE, |
569 NewRunnableMethod(this, &Core::StartOnIOThread)); | 578 base::Bind(&Core::StartOnIOThread, this)); |
570 } | 579 } |
571 | 580 |
572 void URLFetcher::Core::StartOnIOThread() { | 581 void URLFetcher::Core::StartOnIOThread() { |
573 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); | 582 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); |
574 | 583 |
575 switch (response_destination_) { | 584 switch (response_destination_) { |
576 case STRING: | 585 case STRING: |
577 StartURLRequestWhenAppropriate(); | 586 StartURLRequestWhenAppropriate(); |
578 break; | 587 break; |
579 | 588 |
(...skipping 543 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1123 } | 1132 } |
1124 | 1133 |
1125 // static | 1134 // static |
1126 int URLFetcher::GetNumFetcherCores() { | 1135 int URLFetcher::GetNumFetcherCores() { |
1127 return Core::g_registry.Get().size(); | 1136 return Core::g_registry.Get().size(); |
1128 } | 1137 } |
1129 | 1138 |
1130 URLFetcher::Delegate* URLFetcher::delegate() const { | 1139 URLFetcher::Delegate* URLFetcher::delegate() const { |
1131 return core_->delegate(); | 1140 return core_->delegate(); |
1132 } | 1141 } |
OLD | NEW |