| 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 (num_retries_on_network_changes_ < max_retries_on_network_changes_ && |
| 308 FROM_HERE, base::Bind(&URLFetcherCore::StartOnIOThread, this)); | 310 NetworkChangeNotifier::IsOffline()) { |
| 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_; |
| 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 |