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 |