OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "net/url_request/url_fetcher_core.h" | 5 #include "net/url_request/url_fetcher_core.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/file_util_proxy.h" | 8 #include "base/file_util_proxy.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/single_thread_task_runner.h" | 10 #include "base/single_thread_task_runner.h" |
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
273 delegate_(d), | 273 delegate_(d), |
274 delegate_task_runner_( | 274 delegate_task_runner_( |
275 base::ThreadTaskRunnerHandle::Get()), | 275 base::ThreadTaskRunnerHandle::Get()), |
276 request_(NULL), | 276 request_(NULL), |
277 load_flags_(LOAD_NORMAL), | 277 load_flags_(LOAD_NORMAL), |
278 response_code_(URLFetcher::RESPONSE_CODE_INVALID), | 278 response_code_(URLFetcher::RESPONSE_CODE_INVALID), |
279 buffer_(new IOBuffer(kBufferSize)), | 279 buffer_(new IOBuffer(kBufferSize)), |
280 url_request_data_key_(NULL), | 280 url_request_data_key_(NULL), |
281 was_fetched_via_proxy_(false), | 281 was_fetched_via_proxy_(false), |
282 is_chunked_upload_(false), | 282 is_chunked_upload_(false), |
283 num_retries_(0), | |
284 was_cancelled_(false), | 283 was_cancelled_(false), |
285 response_destination_(STRING), | 284 response_destination_(STRING), |
286 stop_on_redirect_(false), | 285 stop_on_redirect_(false), |
287 stopped_on_redirect_(false), | 286 stopped_on_redirect_(false), |
288 automatically_retry_on_5xx_(true), | 287 automatically_retry_on_5xx_(true), |
289 max_retries_(0), | 288 num_retries_on_5xx_(0), |
289 max_retries_on_5xx_(0), | |
290 num_retries_on_network_changes_(0), | |
291 max_retries_on_network_changes_(0), | |
290 current_upload_bytes_(-1), | 292 current_upload_bytes_(-1), |
291 current_response_bytes_(0), | 293 current_response_bytes_(0), |
292 total_response_bytes_(-1) { | 294 total_response_bytes_(-1) { |
293 CHECK(original_url_.is_valid()); | 295 CHECK(original_url_.is_valid()); |
294 } | 296 } |
295 | 297 |
296 void URLFetcherCore::Start() { | 298 void URLFetcherCore::Start() { |
297 DCHECK(delegate_task_runner_); | 299 DCHECK(delegate_task_runner_); |
298 DCHECK(request_context_getter_) << "We need an URLRequestContext!"; | 300 DCHECK(request_context_getter_) << "We need an URLRequestContext!"; |
299 if (network_task_runner_) { | 301 if (network_task_runner_) { |
300 DCHECK_EQ(network_task_runner_, | 302 DCHECK_EQ(network_task_runner_, |
301 request_context_getter_->GetNetworkTaskRunner()); | 303 request_context_getter_->GetNetworkTaskRunner()); |
302 } else { | 304 } else { |
303 network_task_runner_ = request_context_getter_->GetNetworkTaskRunner(); | 305 network_task_runner_ = request_context_getter_->GetNetworkTaskRunner(); |
304 } | 306 } |
305 DCHECK(network_task_runner_.get()) << "We need an IO task runner"; | 307 DCHECK(network_task_runner_.get()) << "We need an IO task runner"; |
306 | 308 |
307 network_task_runner_->PostTask( | 309 if (NetworkChangeNotifier::IsOffline() && |
308 FROM_HERE, base::Bind(&URLFetcherCore::StartOnIOThread, this)); | 310 num_retries_on_network_changes_ < max_retries_on_network_changes_) { |
311 // We're currently offline and this request will immediately fail. Try to | |
312 // start later if |max_retries_on_network_changes_| is set, indicating that | |
313 // our owner wants the fetcher to automatically retry on network changes. | |
314 num_retries_on_network_changes_++; | |
315 NetworkChangeNotifier::AddConnectionTypeObserver(this); | |
316 } else { | |
317 network_task_runner_->PostTask( | |
318 FROM_HERE, base::Bind(&URLFetcherCore::StartOnIOThread, this)); | |
319 } | |
309 } | 320 } |
310 | 321 |
311 void URLFetcherCore::Stop() { | 322 void URLFetcherCore::Stop() { |
312 if (delegate_task_runner_) // May be NULL in tests. | 323 if (delegate_task_runner_) // May be NULL in tests. |
313 DCHECK(delegate_task_runner_->BelongsToCurrentThread()); | 324 DCHECK(delegate_task_runner_->BelongsToCurrentThread()); |
314 | 325 |
315 delegate_ = NULL; | 326 delegate_ = NULL; |
316 fetcher_ = NULL; | 327 fetcher_ = NULL; |
317 if (!network_task_runner_.get()) | 328 if (!network_task_runner_.get()) |
318 return; | 329 return; |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
400 } | 411 } |
401 | 412 |
402 void URLFetcherCore::SetStopOnRedirect(bool stop_on_redirect) { | 413 void URLFetcherCore::SetStopOnRedirect(bool stop_on_redirect) { |
403 stop_on_redirect_ = stop_on_redirect; | 414 stop_on_redirect_ = stop_on_redirect; |
404 } | 415 } |
405 | 416 |
406 void URLFetcherCore::SetAutomaticallyRetryOn5xx(bool retry) { | 417 void URLFetcherCore::SetAutomaticallyRetryOn5xx(bool retry) { |
407 automatically_retry_on_5xx_ = retry; | 418 automatically_retry_on_5xx_ = retry; |
408 } | 419 } |
409 | 420 |
410 void URLFetcherCore::SetMaxRetries(int max_retries) { | 421 void URLFetcherCore::SetMaxRetriesOn5xx(int max_retries) { |
411 max_retries_ = max_retries; | 422 max_retries_on_5xx_ = max_retries; |
412 } | 423 } |
413 | 424 |
414 int URLFetcherCore::GetMaxRetries() const { | 425 int URLFetcherCore::GetMaxRetriesOn5xx() const { |
415 return max_retries_; | 426 return max_retries_on_5xx_; |
416 } | 427 } |
417 | 428 |
418 base::TimeDelta URLFetcherCore::GetBackoffDelay() const { | 429 base::TimeDelta URLFetcherCore::GetBackoffDelay() const { |
419 return backoff_delay_; | 430 return backoff_delay_; |
420 } | 431 } |
421 | 432 |
433 void URLFetcherCore::SetAutomaticallyRetryOnNetworkChanges(int max_retries) { | |
434 max_retries_on_network_changes_ = max_retries; | |
435 } | |
436 | |
422 void URLFetcherCore::SaveResponseToFileAtPath( | 437 void URLFetcherCore::SaveResponseToFileAtPath( |
423 const FilePath& file_path, | 438 const FilePath& file_path, |
424 scoped_refptr<base::TaskRunner> file_task_runner) { | 439 scoped_refptr<base::TaskRunner> file_task_runner) { |
425 DCHECK(delegate_task_runner_->BelongsToCurrentThread()); | 440 DCHECK(delegate_task_runner_->BelongsToCurrentThread()); |
426 file_task_runner_ = file_task_runner; | 441 file_task_runner_ = file_task_runner; |
427 response_destination_ = URLFetcherCore::PERMANENT_FILE; | 442 response_destination_ = URLFetcherCore::PERMANENT_FILE; |
428 response_destination_file_path_ = file_path; | 443 response_destination_file_path_ = file_path; |
429 } | 444 } |
430 | 445 |
431 void URLFetcherCore::SaveResponseToTemporaryFile( | 446 void URLFetcherCore::SaveResponseToTemporaryFile( |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
599 // If the file is open, close it. After closing the file, | 614 // If the file is open, close it. After closing the file, |
600 // RetryOrCompleteUrlFetch() will be called. | 615 // RetryOrCompleteUrlFetch() will be called. |
601 file_writer_->CloseFileAndCompleteRequest(); | 616 file_writer_->CloseFileAndCompleteRequest(); |
602 } else { | 617 } else { |
603 // Otherwise, complete or retry the URL request directly. | 618 // Otherwise, complete or retry the URL request directly. |
604 RetryOrCompleteUrlFetch(); | 619 RetryOrCompleteUrlFetch(); |
605 } | 620 } |
606 } | 621 } |
607 } | 622 } |
608 | 623 |
624 void URLFetcherCore::OnConnectionTypeChanged( | |
625 NetworkChangeNotifier::ConnectionType type) { | |
626 DCHECK_GT(num_retries_on_network_changes_, 0); | |
627 if (type == NetworkChangeNotifier::CONNECTION_NONE) { | |
628 // Keep waiting. | |
629 return; | |
630 } | |
631 | |
632 // Stop observing and try again now. | |
633 NetworkChangeNotifier::RemoveConnectionTypeObserver(this); | |
634 network_task_runner_->PostTask( | |
635 FROM_HERE, base::Bind(&URLFetcherCore::StartOnIOThread, this)); | |
636 } | |
637 | |
609 void URLFetcherCore::CancelAll() { | 638 void URLFetcherCore::CancelAll() { |
610 g_registry.Get().CancelAll(); | 639 g_registry.Get().CancelAll(); |
611 } | 640 } |
612 | 641 |
613 int URLFetcherCore::GetNumFetcherCores() { | 642 int URLFetcherCore::GetNumFetcherCores() { |
614 return g_registry.Get().size(); | 643 return g_registry.Get().size(); |
615 } | 644 } |
616 | 645 |
617 void URLFetcherCore::SetEnableInterceptionForTests(bool enabled) { | 646 void URLFetcherCore::SetEnableInterceptionForTests(bool enabled) { |
618 g_interception_enabled = enabled; | 647 g_interception_enabled = enabled; |
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
831 | 860 |
832 void URLFetcherCore::RetryOrCompleteUrlFetch() { | 861 void URLFetcherCore::RetryOrCompleteUrlFetch() { |
833 DCHECK(network_task_runner_->BelongsToCurrentThread()); | 862 DCHECK(network_task_runner_->BelongsToCurrentThread()); |
834 base::TimeDelta backoff_delay; | 863 base::TimeDelta backoff_delay; |
835 | 864 |
836 // Checks the response from server. | 865 // Checks the response from server. |
837 if (response_code_ >= 500 || | 866 if (response_code_ >= 500 || |
838 status_.error() == ERR_TEMPORARILY_THROTTLED) { | 867 status_.error() == ERR_TEMPORARILY_THROTTLED) { |
839 // When encountering a server error, we will send the request again | 868 // When encountering a server error, we will send the request again |
840 // after backoff time. | 869 // after backoff time. |
841 ++num_retries_; | 870 ++num_retries_on_5xx_; |
842 | 871 |
843 // Note that backoff_delay may be 0 because (a) the | 872 // Note that backoff_delay may be 0 because (a) the |
844 // URLRequestThrottlerManager and related code does not | 873 // URLRequestThrottlerManager and related code does not |
845 // necessarily back off on the first error, (b) it only backs off | 874 // necessarily back off on the first error, (b) it only backs off |
846 // on some of the 5xx status codes, (c) not all URLRequestContexts | 875 // on some of the 5xx status codes, (c) not all URLRequestContexts |
847 // have a throttler manager. | 876 // have a throttler manager. |
848 base::TimeTicks backoff_release_time = GetBackoffReleaseTime(); | 877 base::TimeTicks backoff_release_time = GetBackoffReleaseTime(); |
849 backoff_delay = backoff_release_time - base::TimeTicks::Now(); | 878 backoff_delay = backoff_release_time - base::TimeTicks::Now(); |
850 if (backoff_delay < base::TimeDelta()) | 879 if (backoff_delay < base::TimeDelta()) |
851 backoff_delay = base::TimeDelta(); | 880 backoff_delay = base::TimeDelta(); |
852 | 881 |
853 if (automatically_retry_on_5xx_ && num_retries_ <= max_retries_) { | 882 if (automatically_retry_on_5xx_ && |
883 num_retries_on_5xx_ <= max_retries_on_5xx_) { | |
854 StartOnIOThread(); | 884 StartOnIOThread(); |
855 return; | 885 return; |
856 } | 886 } |
857 } else { | 887 } else { |
858 backoff_delay = base::TimeDelta(); | 888 backoff_delay = base::TimeDelta(); |
859 } | 889 } |
890 | |
891 // Retry if the request failed due to network changes. | |
892 if (status_.error() == ERR_NETWORK_CHANGED && | |
893 num_retries_on_network_changes_ < max_retries_on_network_changes_) { | |
894 num_retries_on_network_changes_++; | |
szym
2012/12/10 18:36:31
nit: pre-increment
Joao da Silva
2012/12/11 13:36:43
Done.
| |
895 | |
896 if (NetworkChangeNotifier::IsOffline()) { | |
897 // Retry once we're back online. | |
898 NetworkChangeNotifier::AddConnectionTypeObserver(this); | |
899 } else { | |
900 // Retry soon, after flushing all the current tasks which may include | |
901 // further network change observers. | |
902 network_task_runner_->PostTask( | |
903 FROM_HERE, base::Bind(&URLFetcherCore::StartOnIOThread, this)); | |
904 } | |
905 return; | |
906 } | |
907 | |
860 request_context_getter_ = NULL; | 908 request_context_getter_ = NULL; |
861 first_party_for_cookies_ = GURL(); | 909 first_party_for_cookies_ = GURL(); |
862 url_request_data_key_ = NULL; | 910 url_request_data_key_ = NULL; |
863 url_request_create_data_callback_.Reset(); | 911 url_request_create_data_callback_.Reset(); |
864 bool posted = delegate_task_runner_->PostTask( | 912 bool posted = delegate_task_runner_->PostTask( |
865 FROM_HERE, | 913 FROM_HERE, |
866 base::Bind(&URLFetcherCore::OnCompletedURLRequest, this, backoff_delay)); | 914 base::Bind(&URLFetcherCore::OnCompletedURLRequest, this, backoff_delay)); |
867 | 915 |
868 // If the delegate message loop does not exist any more, then the delegate | 916 // If the delegate message loop does not exist any more, then the delegate |
869 // should be gone too. | 917 // should be gone too. |
870 DCHECK(posted || !delegate_); | 918 DCHECK(posted || !delegate_); |
871 } | 919 } |
872 | 920 |
873 void URLFetcherCore::ReleaseRequest() { | 921 void URLFetcherCore::ReleaseRequest() { |
922 if (num_retries_on_network_changes_ > 0) | |
923 NetworkChangeNotifier::RemoveConnectionTypeObserver(this); | |
874 upload_progress_checker_timer_.reset(); | 924 upload_progress_checker_timer_.reset(); |
875 request_.reset(); | 925 request_.reset(); |
876 g_registry.Get().RemoveURLFetcherCore(this); | 926 g_registry.Get().RemoveURLFetcherCore(this); |
877 } | 927 } |
878 | 928 |
879 base::TimeTicks URLFetcherCore::GetBackoffReleaseTime() { | 929 base::TimeTicks URLFetcherCore::GetBackoffReleaseTime() { |
880 DCHECK(network_task_runner_->BelongsToCurrentThread()); | 930 DCHECK(network_task_runner_->BelongsToCurrentThread()); |
881 | 931 |
882 if (original_url_throttler_entry_) { | 932 if (original_url_throttler_entry_) { |
883 base::TimeTicks original_url_backoff = | 933 base::TimeTicks original_url_backoff = |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1007 } | 1057 } |
1008 | 1058 |
1009 void URLFetcherCore::InformDelegateDownloadDataInDelegateThread( | 1059 void URLFetcherCore::InformDelegateDownloadDataInDelegateThread( |
1010 scoped_ptr<std::string> download_data) { | 1060 scoped_ptr<std::string> download_data) { |
1011 DCHECK(delegate_task_runner_->BelongsToCurrentThread()); | 1061 DCHECK(delegate_task_runner_->BelongsToCurrentThread()); |
1012 if (delegate_) | 1062 if (delegate_) |
1013 delegate_->OnURLFetchDownloadData(fetcher_, download_data.Pass()); | 1063 delegate_->OnURLFetchDownloadData(fetcher_, download_data.Pass()); |
1014 } | 1064 } |
1015 | 1065 |
1016 } // namespace net | 1066 } // namespace net |
OLD | NEW |