| Index: net/url_request/url_fetcher_core.cc
|
| diff --git a/net/url_request/url_fetcher_core.cc b/net/url_request/url_fetcher_core.cc
|
| index 00aa56f5cdd5b4e8c6ffa7adaceaca765f261c8d..b0a6c65f9fedb6240115dae635e5ad328dedf066 100644
|
| --- a/net/url_request/url_fetcher_core.cc
|
| +++ b/net/url_request/url_fetcher_core.cc
|
| @@ -280,13 +280,15 @@ URLFetcherCore::URLFetcherCore(URLFetcher* fetcher,
|
| url_request_data_key_(NULL),
|
| was_fetched_via_proxy_(false),
|
| is_chunked_upload_(false),
|
| - num_retries_(0),
|
| was_cancelled_(false),
|
| response_destination_(STRING),
|
| stop_on_redirect_(false),
|
| stopped_on_redirect_(false),
|
| automatically_retry_on_5xx_(true),
|
| - max_retries_(0),
|
| + num_retries_on_5xx_(0),
|
| + max_retries_on_5xx_(0),
|
| + num_retries_on_network_changes_(0),
|
| + max_retries_on_network_changes_(0),
|
| current_upload_bytes_(-1),
|
| current_response_bytes_(0),
|
| total_response_bytes_(-1) {
|
| @@ -304,8 +306,17 @@ void URLFetcherCore::Start() {
|
| }
|
| DCHECK(network_task_runner_.get()) << "We need an IO task runner";
|
|
|
| - network_task_runner_->PostTask(
|
| - FROM_HERE, base::Bind(&URLFetcherCore::StartOnIOThread, this));
|
| + if (num_retries_on_network_changes_ < max_retries_on_network_changes_ &&
|
| + NetworkChangeNotifier::IsOffline()) {
|
| + // We're currently offline and this request will immediately fail. Try to
|
| + // start later if |max_retries_on_network_changes_| is set, indicating that
|
| + // our owner wants the fetcher to automatically retry on network changes.
|
| + ++num_retries_on_network_changes_;
|
| + NetworkChangeNotifier::AddConnectionTypeObserver(this);
|
| + } else {
|
| + network_task_runner_->PostTask(
|
| + FROM_HERE, base::Bind(&URLFetcherCore::StartOnIOThread, this));
|
| + }
|
| }
|
|
|
| void URLFetcherCore::Stop() {
|
| @@ -407,18 +418,22 @@ void URLFetcherCore::SetAutomaticallyRetryOn5xx(bool retry) {
|
| automatically_retry_on_5xx_ = retry;
|
| }
|
|
|
| -void URLFetcherCore::SetMaxRetries(int max_retries) {
|
| - max_retries_ = max_retries;
|
| +void URLFetcherCore::SetMaxRetriesOn5xx(int max_retries) {
|
| + max_retries_on_5xx_ = max_retries;
|
| }
|
|
|
| -int URLFetcherCore::GetMaxRetries() const {
|
| - return max_retries_;
|
| +int URLFetcherCore::GetMaxRetriesOn5xx() const {
|
| + return max_retries_on_5xx_;
|
| }
|
|
|
| base::TimeDelta URLFetcherCore::GetBackoffDelay() const {
|
| return backoff_delay_;
|
| }
|
|
|
| +void URLFetcherCore::SetAutomaticallyRetryOnNetworkChanges(int max_retries) {
|
| + max_retries_on_network_changes_ = max_retries;
|
| +}
|
| +
|
| void URLFetcherCore::SaveResponseToFileAtPath(
|
| const FilePath& file_path,
|
| scoped_refptr<base::TaskRunner> file_task_runner) {
|
| @@ -606,6 +621,20 @@ void URLFetcherCore::OnReadCompleted(URLRequest* request,
|
| }
|
| }
|
|
|
| +void URLFetcherCore::OnConnectionTypeChanged(
|
| + NetworkChangeNotifier::ConnectionType type) {
|
| + DCHECK_GT(num_retries_on_network_changes_, 0);
|
| + if (type == NetworkChangeNotifier::CONNECTION_NONE) {
|
| + // Keep waiting.
|
| + return;
|
| + }
|
| +
|
| + // Stop observing and try again now.
|
| + NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
|
| + network_task_runner_->PostTask(
|
| + FROM_HERE, base::Bind(&URLFetcherCore::StartOnIOThread, this));
|
| +}
|
| +
|
| void URLFetcherCore::CancelAll() {
|
| g_registry.Get().CancelAll();
|
| }
|
| @@ -838,7 +867,7 @@ void URLFetcherCore::RetryOrCompleteUrlFetch() {
|
| status_.error() == ERR_TEMPORARILY_THROTTLED) {
|
| // When encountering a server error, we will send the request again
|
| // after backoff time.
|
| - ++num_retries_;
|
| + ++num_retries_on_5xx_;
|
|
|
| // Note that backoff_delay may be 0 because (a) the
|
| // URLRequestThrottlerManager and related code does not
|
| @@ -850,13 +879,32 @@ void URLFetcherCore::RetryOrCompleteUrlFetch() {
|
| if (backoff_delay < base::TimeDelta())
|
| backoff_delay = base::TimeDelta();
|
|
|
| - if (automatically_retry_on_5xx_ && num_retries_ <= max_retries_) {
|
| + if (automatically_retry_on_5xx_ &&
|
| + num_retries_on_5xx_ <= max_retries_on_5xx_) {
|
| StartOnIOThread();
|
| return;
|
| }
|
| } else {
|
| backoff_delay = base::TimeDelta();
|
| }
|
| +
|
| + // Retry if the request failed due to network changes.
|
| + if (status_.error() == ERR_NETWORK_CHANGED &&
|
| + num_retries_on_network_changes_ < max_retries_on_network_changes_) {
|
| + ++num_retries_on_network_changes_;
|
| +
|
| + if (NetworkChangeNotifier::IsOffline()) {
|
| + // Retry once we're back online.
|
| + NetworkChangeNotifier::AddConnectionTypeObserver(this);
|
| + } else {
|
| + // Retry soon, after flushing all the current tasks which may include
|
| + // further network change observers.
|
| + network_task_runner_->PostTask(
|
| + FROM_HERE, base::Bind(&URLFetcherCore::StartOnIOThread, this));
|
| + }
|
| + return;
|
| + }
|
| +
|
| request_context_getter_ = NULL;
|
| first_party_for_cookies_ = GURL();
|
| url_request_data_key_ = NULL;
|
| @@ -871,6 +919,8 @@ void URLFetcherCore::RetryOrCompleteUrlFetch() {
|
| }
|
|
|
| void URLFetcherCore::ReleaseRequest() {
|
| + if (num_retries_on_network_changes_ > 0)
|
| + NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
|
| upload_progress_checker_timer_.reset();
|
| request_.reset();
|
| g_registry.Get().RemoveURLFetcherCore(this);
|
|
|