| 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_request_throttler_entry.h" | 5 #include "net/url_request/url_request_throttler_entry.h" |
| 6 | 6 |
| 7 #include <cmath> | 7 #include <cmath> |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/metrics/field_trial.h" | 10 #include "base/metrics/field_trial.h" |
| (...skipping 26 matching lines...) Expand all Loading... |
| 37 // | 37 // |
| 38 // Ignoring the first couple of errors is just a conservative measure to | 38 // Ignoring the first couple of errors is just a conservative measure to |
| 39 // avoid false positives. It should help avoid back-off from kicking in e.g. | 39 // avoid false positives. It should help avoid back-off from kicking in e.g. |
| 40 // on flaky connections. | 40 // on flaky connections. |
| 41 const int URLRequestThrottlerEntry::kDefaultNumErrorsToIgnore = 2; | 41 const int URLRequestThrottlerEntry::kDefaultNumErrorsToIgnore = 2; |
| 42 const int URLRequestThrottlerEntry::kDefaultInitialBackoffMs = 700; | 42 const int URLRequestThrottlerEntry::kDefaultInitialBackoffMs = 700; |
| 43 const double URLRequestThrottlerEntry::kDefaultMultiplyFactor = 1.4; | 43 const double URLRequestThrottlerEntry::kDefaultMultiplyFactor = 1.4; |
| 44 const double URLRequestThrottlerEntry::kDefaultJitterFactor = 0.4; | 44 const double URLRequestThrottlerEntry::kDefaultJitterFactor = 0.4; |
| 45 const int URLRequestThrottlerEntry::kDefaultMaximumBackoffMs = 15 * 60 * 1000; | 45 const int URLRequestThrottlerEntry::kDefaultMaximumBackoffMs = 15 * 60 * 1000; |
| 46 const int URLRequestThrottlerEntry::kDefaultEntryLifetimeMs = 2 * 60 * 1000; | 46 const int URLRequestThrottlerEntry::kDefaultEntryLifetimeMs = 2 * 60 * 1000; |
| 47 const char URLRequestThrottlerEntry::kRetryHeaderName[] = "X-Retry-After"; | |
| 48 const char URLRequestThrottlerEntry::kExponentialThrottlingHeader[] = | 47 const char URLRequestThrottlerEntry::kExponentialThrottlingHeader[] = |
| 49 "X-Chrome-Exponential-Throttling"; | 48 "X-Chrome-Exponential-Throttling"; |
| 50 const char URLRequestThrottlerEntry::kExponentialThrottlingDisableValue[] = | 49 const char URLRequestThrottlerEntry::kExponentialThrottlingDisableValue[] = |
| 51 "disable"; | 50 "disable"; |
| 52 | 51 |
| 53 // NetLog parameters when a request is rejected by throttling. | 52 // NetLog parameters when a request is rejected by throttling. |
| 54 class RejectedRequestParameters : public NetLog::EventParameters { | 53 class RejectedRequestParameters : public NetLog::EventParameters { |
| 55 public: | 54 public: |
| 56 RejectedRequestParameters(const std::string& url_id, | 55 RejectedRequestParameters(const std::string& url_id, |
| 57 int num_failures, | 56 int num_failures, |
| (...skipping 10 matching lines...) Expand all Loading... |
| 68 dict->SetInteger("release_after_ms", release_after_ms_); | 67 dict->SetInteger("release_after_ms", release_after_ms_); |
| 69 return dict; | 68 return dict; |
| 70 } | 69 } |
| 71 | 70 |
| 72 private: | 71 private: |
| 73 std::string url_id_; | 72 std::string url_id_; |
| 74 int num_failures_; | 73 int num_failures_; |
| 75 int release_after_ms_; | 74 int release_after_ms_; |
| 76 }; | 75 }; |
| 77 | 76 |
| 78 // NetLog parameters when a response contains an X-Retry-After header. | |
| 79 class RetryAfterParameters : public NetLog::EventParameters { | |
| 80 public: | |
| 81 RetryAfterParameters(const std::string& url_id, | |
| 82 int retry_after_ms) | |
| 83 : url_id_(url_id), | |
| 84 retry_after_ms_(retry_after_ms) { | |
| 85 } | |
| 86 | |
| 87 virtual Value* ToValue() const { | |
| 88 DictionaryValue* dict = new DictionaryValue(); | |
| 89 dict->SetString("url", url_id_); | |
| 90 dict->SetInteger("retry_after_ms", retry_after_ms_); | |
| 91 return dict; | |
| 92 } | |
| 93 | |
| 94 private: | |
| 95 std::string url_id_; | |
| 96 int retry_after_ms_; | |
| 97 }; | |
| 98 | |
| 99 URLRequestThrottlerEntry::URLRequestThrottlerEntry( | 77 URLRequestThrottlerEntry::URLRequestThrottlerEntry( |
| 100 URLRequestThrottlerManager* manager, | 78 URLRequestThrottlerManager* manager, |
| 101 const std::string& url_id) | 79 const std::string& url_id) |
| 102 : sliding_window_period_( | 80 : sliding_window_period_( |
| 103 base::TimeDelta::FromMilliseconds(kDefaultSlidingWindowPeriodMs)), | 81 base::TimeDelta::FromMilliseconds(kDefaultSlidingWindowPeriodMs)), |
| 104 max_send_threshold_(kDefaultMaxSendThreshold), | 82 max_send_threshold_(kDefaultMaxSendThreshold), |
| 105 is_backoff_disabled_(false), | 83 is_backoff_disabled_(false), |
| 106 backoff_entry_(&backoff_policy_), | 84 backoff_entry_(&backoff_policy_), |
| 107 manager_(manager), | 85 manager_(manager), |
| 108 url_id_(url_id), | 86 url_id_(url_id), |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 257 const std::string& host, | 235 const std::string& host, |
| 258 const URLRequestThrottlerHeaderInterface* response) { | 236 const URLRequestThrottlerHeaderInterface* response) { |
| 259 int response_code = response->GetResponseCode(); | 237 int response_code = response->GetResponseCode(); |
| 260 HandleMetricsTracking(response_code); | 238 HandleMetricsTracking(response_code); |
| 261 | 239 |
| 262 if (IsConsideredError(response_code)) { | 240 if (IsConsideredError(response_code)) { |
| 263 GetBackoffEntry()->InformOfRequest(false); | 241 GetBackoffEntry()->InformOfRequest(false); |
| 264 } else { | 242 } else { |
| 265 GetBackoffEntry()->InformOfRequest(true); | 243 GetBackoffEntry()->InformOfRequest(true); |
| 266 | 244 |
| 267 std::string retry_header = response->GetNormalizedValue(kRetryHeaderName); | |
| 268 if (!retry_header.empty()) | |
| 269 HandleCustomRetryAfter(retry_header); | |
| 270 | |
| 271 std::string throttling_header = response->GetNormalizedValue( | 245 std::string throttling_header = response->GetNormalizedValue( |
| 272 kExponentialThrottlingHeader); | 246 kExponentialThrottlingHeader); |
| 273 if (!throttling_header.empty()) | 247 if (!throttling_header.empty()) |
| 274 HandleThrottlingHeader(throttling_header, host); | 248 HandleThrottlingHeader(throttling_header, host); |
| 275 } | 249 } |
| 276 } | 250 } |
| 277 | 251 |
| 278 void URLRequestThrottlerEntry::ReceivedContentWasMalformed(int response_code) { | 252 void URLRequestThrottlerEntry::ReceivedContentWasMalformed(int response_code) { |
| 279 // A malformed body can only occur when the request to fetch a resource | 253 // A malformed body can only occur when the request to fetch a resource |
| 280 // was successful. Therefore, in such a situation, we will receive one | 254 // was successful. Therefore, in such a situation, we will receive one |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 330 // localhost, where you are not actually connected to the network. | 304 // localhost, where you are not actually connected to the network. |
| 331 return (response_code == 500 || | 305 return (response_code == 500 || |
| 332 response_code == 503 || | 306 response_code == 503 || |
| 333 response_code == 509); | 307 response_code == 509); |
| 334 } | 308 } |
| 335 | 309 |
| 336 base::TimeTicks URLRequestThrottlerEntry::ImplGetTimeNow() const { | 310 base::TimeTicks URLRequestThrottlerEntry::ImplGetTimeNow() const { |
| 337 return base::TimeTicks::Now(); | 311 return base::TimeTicks::Now(); |
| 338 } | 312 } |
| 339 | 313 |
| 340 void URLRequestThrottlerEntry::HandleCustomRetryAfter( | |
| 341 const std::string& header_value) { | |
| 342 // Input parameter is the number of seconds to wait in a floating point value. | |
| 343 double time_in_sec = 0; | |
| 344 bool conversion_is_ok = base::StringToDouble(header_value, &time_in_sec); | |
| 345 | |
| 346 // Conversion of custom retry-after header value failed. | |
| 347 if (!conversion_is_ok) | |
| 348 return; | |
| 349 | |
| 350 // We must use an int value later so we transform this in milliseconds. | |
| 351 int64 value_ms = static_cast<int64>(0.5 + time_in_sec * 1000); | |
| 352 | |
| 353 // We do not check for an upper bound; the server can set any Retry-After it | |
| 354 // desires. Recovery from error would involve restarting the browser. | |
| 355 if (value_ms < 0) | |
| 356 return; | |
| 357 | |
| 358 net_log_.AddEvent( | |
| 359 NetLog::TYPE_THROTTLING_GOT_CUSTOM_RETRY_AFTER, | |
| 360 make_scoped_refptr(new RetryAfterParameters(url_id_, value_ms))); | |
| 361 | |
| 362 base::TimeDelta value = base::TimeDelta::FromMilliseconds(value_ms); | |
| 363 GetBackoffEntry()->SetCustomReleaseTime(ImplGetTimeNow() + value); | |
| 364 | |
| 365 UMA_HISTOGRAM_CUSTOM_TIMES( | |
| 366 "Throttling.CustomRetryAfterMs", value, | |
| 367 base::TimeDelta::FromSeconds(1), base::TimeDelta::FromHours(12), 50); | |
| 368 } | |
| 369 | |
| 370 void URLRequestThrottlerEntry::HandleThrottlingHeader( | 314 void URLRequestThrottlerEntry::HandleThrottlingHeader( |
| 371 const std::string& header_value, | 315 const std::string& header_value, |
| 372 const std::string& host) { | 316 const std::string& host) { |
| 373 if (header_value == kExponentialThrottlingDisableValue) { | 317 if (header_value == kExponentialThrottlingDisableValue) { |
| 374 DisableBackoffThrottling(); | 318 DisableBackoffThrottling(); |
| 375 if (manager_) | 319 if (manager_) |
| 376 manager_->AddToOptOutList(host); | 320 manager_->AddToOptOutList(host); |
| 377 } else { | 321 } else { |
| 378 // TODO(joi): Log this. | 322 // TODO(joi): Log this. |
| 379 } | 323 } |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 412 BackoffEntry* URLRequestThrottlerEntry::GetBackoffEntry() { | 356 BackoffEntry* URLRequestThrottlerEntry::GetBackoffEntry() { |
| 413 return &backoff_entry_; | 357 return &backoff_entry_; |
| 414 } | 358 } |
| 415 | 359 |
| 416 // static | 360 // static |
| 417 bool URLRequestThrottlerEntry::ExplicitUserRequest(const int load_flags) { | 361 bool URLRequestThrottlerEntry::ExplicitUserRequest(const int load_flags) { |
| 418 return (load_flags & LOAD_MAYBE_USER_GESTURE) != 0; | 362 return (load_flags & LOAD_MAYBE_USER_GESTURE) != 0; |
| 419 } | 363 } |
| 420 | 364 |
| 421 } // namespace net | 365 } // namespace net |
| OLD | NEW |