Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(588)

Side by Side Diff: chrome/common/net/url_fetcher.cc

Issue 4194001: Implement exponential back-off mechanism and enforce it at the URLRequestHttpJob level. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 10 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/common/net/url_fetcher.h ('k') | chrome/common/net/url_fetcher_protect.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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 "chrome/common/net/url_fetcher.h" 5 #include "chrome/common/net/url_fetcher.h"
6 6
7 #include <set> 7 #include <set>
8 8
9 #include "base/compiler_specific.h" 9 #include "base/compiler_specific.h"
10 #include "base/lazy_instance.h" 10 #include "base/lazy_instance.h"
11 #include "base/lock.h" 11 #include "base/lock.h"
12 #include "base/message_loop_proxy.h" 12 #include "base/message_loop_proxy.h"
13 #include "base/scoped_ptr.h" 13 #include "base/scoped_ptr.h"
14 #include "base/stl_util-inl.h" 14 #include "base/stl_util-inl.h"
15 #include "base/string_util.h" 15 #include "base/string_util.h"
16 #include "base/thread.h" 16 #include "base/thread.h"
17 #include "chrome/common/net/url_fetcher_protect.h"
18 #include "chrome/common/net/url_request_context_getter.h" 17 #include "chrome/common/net/url_request_context_getter.h"
19 #include "googleurl/src/gurl.h" 18 #include "googleurl/src/gurl.h"
20 #include "net/base/load_flags.h" 19 #include "net/base/load_flags.h"
21 #include "net/base/io_buffer.h" 20 #include "net/base/io_buffer.h"
21 #include "net/base/net_errors.h"
22 #include "net/http/http_request_headers.h" 22 #include "net/http/http_request_headers.h"
23 #include "net/http/http_response_headers.h" 23 #include "net/http/http_response_headers.h"
24 #include "net/url_request/url_request.h" 24 #include "net/url_request/url_request.h"
25 #include "net/url_request/url_request_context.h" 25 #include "net/url_request/url_request_context.h"
26 #include "net/url_request/url_request_throttler_manager.h"
26 27
27 static const int kBufferSize = 4096; 28 static const int kBufferSize = 4096;
28 29
29 bool URLFetcher::g_interception_enabled = false; 30 bool URLFetcher::g_interception_enabled = false;
30 31
31 class URLFetcher::Core 32 class URLFetcher::Core
32 : public base::RefCountedThreadSafe<URLFetcher::Core>, 33 : public base::RefCountedThreadSafe<URLFetcher::Core>,
33 public URLRequest::Delegate { 34 public URLRequest::Delegate {
34 public: 35 public:
35 // For POST requests, set |content_type| to the MIME type of the content 36 // For POST requests, set |content_type| to the MIME type of the content
(...skipping 10 matching lines...) Expand all
46 // us. If our caller hasn't had time to fully construct us and take a 47 // us. If our caller hasn't had time to fully construct us and take a
47 // reference, the IO thread could interrupt things, run a task, Release() 48 // reference, the IO thread could interrupt things, run a task, Release()
48 // us, and destroy us, leaving the caller with an already-destroyed object 49 // us, and destroy us, leaving the caller with an already-destroyed object
49 // when construction finishes. 50 // when construction finishes.
50 void Start(); 51 void Start();
51 52
52 // Stops any in-progress load and ensures no callback will happen. It is 53 // Stops any in-progress load and ensures no callback will happen. It is
53 // safe to call this multiple times. 54 // safe to call this multiple times.
54 void Stop(); 55 void Stop();
55 56
57 // Reports that the received content was malformed.
58 void ReceivedContentWasMalformed();
59
56 // URLRequest::Delegate implementation. 60 // URLRequest::Delegate implementation.
57 virtual void OnResponseStarted(URLRequest* request); 61 virtual void OnResponseStarted(URLRequest* request);
58 virtual void OnReadCompleted(URLRequest* request, int bytes_read); 62 virtual void OnReadCompleted(URLRequest* request, int bytes_read);
59 63
60 URLFetcher::Delegate* delegate() const { return delegate_; } 64 URLFetcher::Delegate* delegate() const { return delegate_; }
61 65
62 static void CancelAll(); 66 static void CancelAll();
63 67
64 private: 68 private:
65 friend class base::RefCountedThreadSafe<URLFetcher::Core>; 69 friend class base::RefCountedThreadSafe<URLFetcher::Core>;
(...skipping 12 matching lines...) Expand all
78 std::set<Core*> fetchers_; 82 std::set<Core*> fetchers_;
79 83
80 DISALLOW_COPY_AND_ASSIGN(Registry); 84 DISALLOW_COPY_AND_ASSIGN(Registry);
81 }; 85 };
82 86
83 ~Core(); 87 ~Core();
84 88
85 // Wrapper functions that allow us to ensure actions happen on the right 89 // Wrapper functions that allow us to ensure actions happen on the right
86 // thread. 90 // thread.
87 void StartURLRequest(); 91 void StartURLRequest();
92 void StartURLRequestWhenAppropriate();
88 void CancelURLRequest(); 93 void CancelURLRequest();
89 void OnCompletedURLRequest(const URLRequestStatus& status); 94 void OnCompletedURLRequest(const URLRequestStatus& status);
95 void NotifyMalformedContent();
90 96
91 // Deletes the request, removes it from the registry, and removes the 97 // Deletes the request, removes it from the registry, and removes the
92 // destruction observer. 98 // destruction observer.
93 void ReleaseRequest(); 99 void ReleaseRequest();
94 100
101 // Returns the max value of exponential back-off release time for
102 // |original_url_| and |url_|.
103 base::TimeTicks GetBackoffReleaseTime();
104
95 URLFetcher* fetcher_; // Corresponding fetcher object 105 URLFetcher* fetcher_; // Corresponding fetcher object
96 GURL original_url_; // The URL we were asked to fetch 106 GURL original_url_; // The URL we were asked to fetch
97 GURL url_; // The URL we eventually wound up at 107 GURL url_; // The URL we eventually wound up at
98 RequestType request_type_; // What type of request is this? 108 RequestType request_type_; // What type of request is this?
99 URLFetcher::Delegate* delegate_; // Object to notify on completion 109 URLFetcher::Delegate* delegate_; // Object to notify on completion
100 MessageLoop* delegate_loop_; // Message loop of the creating thread 110 MessageLoop* delegate_loop_; // Message loop of the creating thread
101 scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy_; 111 scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy_;
102 // The message loop proxy for the thread 112 // The message loop proxy for the thread
103 // on which the request IO happens. 113 // on which the request IO happens.
104 scoped_ptr<URLRequest> request_; // The actual request this wraps 114 scoped_ptr<URLRequest> request_; // The actual request this wraps
105 int load_flags_; // Flags for the load operation 115 int load_flags_; // Flags for the load operation
106 int response_code_; // HTTP status code for the request 116 int response_code_; // HTTP status code for the request
107 std::string data_; // Results of the request 117 std::string data_; // Results of the request
108 scoped_refptr<net::IOBuffer> buffer_; 118 scoped_refptr<net::IOBuffer> buffer_;
109 // Read buffer 119 // Read buffer
110 scoped_refptr<URLRequestContextGetter> request_context_getter_; 120 scoped_refptr<URLRequestContextGetter> request_context_getter_;
111 // Cookie/cache info for the request 121 // Cookie/cache info for the request
112 ResponseCookies cookies_; // Response cookies 122 ResponseCookies cookies_; // Response cookies
113 net::HttpRequestHeaders extra_request_headers_; 123 net::HttpRequestHeaders extra_request_headers_;
114 scoped_refptr<net::HttpResponseHeaders> response_headers_; 124 scoped_refptr<net::HttpResponseHeaders> response_headers_;
115 125
116 std::string upload_content_; // HTTP POST payload 126 std::string upload_content_; // HTTP POST payload
117 std::string upload_content_type_; // MIME type of POST payload 127 std::string upload_content_type_; // MIME type of POST payload
118 128
119 // The overload protection entry for this URL. This is used to 129 // Used to determine how long to wait before making a request or doing a
120 // incrementally back off how rapidly we'll send requests to a particular 130 // retry.
121 // URL, to avoid placing too much demand on the remote resource. We update 131 // Both of them can only be accessed on the IO thread.
122 // this with the status of all requests as they return, and in turn use it 132 // We need not only the throttler entry for |original_URL|, but also the one
123 // to determine how long to wait before making another request. 133 // for |url|. For example, consider the case that URL A redirects to URL B,
124 URLFetcherProtectEntry* protect_entry_; 134 // for which the server returns a 500 response. In this case, the exponential
135 // back-off release time of URL A won't increase. If we retry without
136 // considering the back-off constraint of URL B, we may send out too many
137 // requests for URL A in a short period of time.
138 scoped_refptr<net::URLRequestThrottlerEntryInterface>
139 original_url_throttler_entry_;
140 scoped_refptr<net::URLRequestThrottlerEntryInterface> url_throttler_entry_;
141
125 // |num_retries_| indicates how many times we've failed to successfully 142 // |num_retries_| indicates how many times we've failed to successfully
126 // fetch this URL. Once this value exceeds the maximum number of retries 143 // fetch this URL. Once this value exceeds the maximum number of retries
127 // specified by the protection manager, we'll give up. 144 // specified by the owner URLFetcher instance, we'll give up.
128 int num_retries_; 145 int num_retries_;
129 146
130 // True if the URLFetcher has been cancelled. 147 // True if the URLFetcher has been cancelled.
131 bool was_cancelled_; 148 bool was_cancelled_;
132 149
150 // Since GetBackoffReleaseTime() can only be called on the IO thread, we cache
151 // its value to be used by OnCompletedURLRequest on the creating thread.
152 base::TimeTicks backoff_release_time_;
153
133 static base::LazyInstance<Registry> g_registry; 154 static base::LazyInstance<Registry> g_registry;
134 155
135 friend class URLFetcher; 156 friend class URLFetcher;
136 DISALLOW_COPY_AND_ASSIGN(Core); 157 DISALLOW_COPY_AND_ASSIGN(Core);
137 }; 158 };
138 159
139 URLFetcher::Core::Registry::Registry() {} 160 URLFetcher::Core::Registry::Registry() {}
140 URLFetcher::Core::Registry::~Registry() {} 161 URLFetcher::Core::Registry::~Registry() {}
141 162
142 void URLFetcher::Core::Registry::AddURLFetcherCore(Core* core) { 163 void URLFetcher::Core::Registry::AddURLFetcherCore(Core* core) {
(...skipping 20 matching lines...) Expand all
163 URLFetcher::Core::g_registry(base::LINKER_INITIALIZED); 184 URLFetcher::Core::g_registry(base::LINKER_INITIALIZED);
164 185
165 // static 186 // static
166 URLFetcher::Factory* URLFetcher::factory_ = NULL; 187 URLFetcher::Factory* URLFetcher::factory_ = NULL;
167 188
168 URLFetcher::URLFetcher(const GURL& url, 189 URLFetcher::URLFetcher(const GURL& url,
169 RequestType request_type, 190 RequestType request_type,
170 Delegate* d) 191 Delegate* d)
171 : ALLOW_THIS_IN_INITIALIZER_LIST( 192 : ALLOW_THIS_IN_INITIALIZER_LIST(
172 core_(new Core(this, url, request_type, d))), 193 core_(new Core(this, url, request_type, d))),
173 automatically_retry_on_5xx_(true) { 194 automatically_retry_on_5xx_(true),
195 max_retries_(0) {
174 } 196 }
175 197
176 URLFetcher::~URLFetcher() { 198 URLFetcher::~URLFetcher() {
177 core_->Stop(); 199 core_->Stop();
178 } 200 }
179 201
180 // static 202 // static
181 URLFetcher* URLFetcher::Create(int id, const GURL& url, 203 URLFetcher* URLFetcher::Create(int id, const GURL& url,
182 RequestType request_type, Delegate* d) { 204 RequestType request_type, Delegate* d) {
183 return factory_ ? factory_->CreateURLFetcher(id, url, request_type, d) : 205 return factory_ ? factory_->CreateURLFetcher(id, url, request_type, d) :
184 new URLFetcher(url, request_type, d); 206 new URLFetcher(url, request_type, d);
185 } 207 }
186 208
187 URLFetcher::Core::Core(URLFetcher* fetcher, 209 URLFetcher::Core::Core(URLFetcher* fetcher,
188 const GURL& original_url, 210 const GURL& original_url,
189 RequestType request_type, 211 RequestType request_type,
190 URLFetcher::Delegate* d) 212 URLFetcher::Delegate* d)
191 : fetcher_(fetcher), 213 : fetcher_(fetcher),
192 original_url_(original_url), 214 original_url_(original_url),
193 request_type_(request_type), 215 request_type_(request_type),
194 delegate_(d), 216 delegate_(d),
195 delegate_loop_(MessageLoop::current()), 217 delegate_loop_(MessageLoop::current()),
196 request_(NULL), 218 request_(NULL),
197 load_flags_(net::LOAD_NORMAL), 219 load_flags_(net::LOAD_NORMAL),
198 response_code_(-1), 220 response_code_(-1),
199 buffer_(new net::IOBuffer(kBufferSize)), 221 buffer_(new net::IOBuffer(kBufferSize)),
200 protect_entry_(URLFetcherProtectManager::GetInstance()->Register(
201 original_url_.host())),
202 num_retries_(0), 222 num_retries_(0),
203 was_cancelled_(false) { 223 was_cancelled_(false) {
204 } 224 }
205 225
206 URLFetcher::Core::~Core() { 226 URLFetcher::Core::~Core() {
207 // |request_| should be NULL. If not, it's unsafe to delete it here since we 227 // |request_| should be NULL. If not, it's unsafe to delete it here since we
208 // may not be on the IO thread. 228 // may not be on the IO thread.
209 DCHECK(!request_.get()); 229 DCHECK(!request_.get());
210 } 230 }
211 231
212 void URLFetcher::Core::Start() { 232 void URLFetcher::Core::Start() {
213 DCHECK(delegate_loop_); 233 DCHECK(delegate_loop_);
214 CHECK(request_context_getter_) << "We need an URLRequestContext!"; 234 CHECK(request_context_getter_) << "We need an URLRequestContext!";
215 io_message_loop_proxy_ = request_context_getter_->GetIOMessageLoopProxy(); 235 io_message_loop_proxy_ = request_context_getter_->GetIOMessageLoopProxy();
216 CHECK(io_message_loop_proxy_.get()) << "We need an IO message loop proxy"; 236 CHECK(io_message_loop_proxy_.get()) << "We need an IO message loop proxy";
217 io_message_loop_proxy_->PostDelayedTask( 237
238 io_message_loop_proxy_->PostTask(
218 FROM_HERE, 239 FROM_HERE,
219 NewRunnableMethod(this, &Core::StartURLRequest), 240 NewRunnableMethod(this, &Core::StartURLRequestWhenAppropriate));
220 protect_entry_->UpdateBackoff(URLFetcherProtectEntry::SEND));
221 } 241 }
222 242
223 void URLFetcher::Core::Stop() { 243 void URLFetcher::Core::Stop() {
224 DCHECK_EQ(MessageLoop::current(), delegate_loop_); 244 DCHECK_EQ(MessageLoop::current(), delegate_loop_);
225 delegate_ = NULL; 245 delegate_ = NULL;
226 fetcher_ = NULL; 246 fetcher_ = NULL;
227 if (io_message_loop_proxy_.get()) { 247 if (io_message_loop_proxy_.get()) {
228 io_message_loop_proxy_->PostTask( 248 io_message_loop_proxy_->PostTask(
229 FROM_HERE, NewRunnableMethod(this, &Core::CancelURLRequest)); 249 FROM_HERE, NewRunnableMethod(this, &Core::CancelURLRequest));
230 } 250 }
231 } 251 }
232 252
253 void URLFetcher::Core::ReceivedContentWasMalformed() {
254 DCHECK_EQ(MessageLoop::current(), delegate_loop_);
255 if (io_message_loop_proxy_.get()) {
256 io_message_loop_proxy_->PostTask(
257 FROM_HERE, NewRunnableMethod(this, &Core::NotifyMalformedContent));
258 }
259 }
260
233 void URLFetcher::Core::CancelAll() { 261 void URLFetcher::Core::CancelAll() {
234 g_registry.Get().CancelAll(); 262 g_registry.Get().CancelAll();
235 } 263 }
236 264
237 void URLFetcher::Core::OnResponseStarted(URLRequest* request) { 265 void URLFetcher::Core::OnResponseStarted(URLRequest* request) {
238 DCHECK_EQ(request, request_.get()); 266 DCHECK_EQ(request, request_.get());
239 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); 267 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
240 if (request_->status().is_success()) { 268 if (request_->status().is_success()) {
241 response_code_ = request_->GetResponseCode(); 269 response_code_ = request_->GetResponseCode();
242 response_headers_ = request_->response_headers(); 270 response_headers_ = request_->response_headers();
243 } 271 }
244 272
245 int bytes_read = 0; 273 int bytes_read = 0;
246 // Some servers may treat HEAD requests as GET requests. To free up the 274 // Some servers may treat HEAD requests as GET requests. To free up the
247 // network connection as soon as possible, signal that the request has 275 // network connection as soon as possible, signal that the request has
248 // completed immediately, without trying to read any data back (all we care 276 // completed immediately, without trying to read any data back (all we care
249 // about is the response code and headers, which we already have). 277 // about is the response code and headers, which we already have).
250 if (request_->status().is_success() && (request_type_ != HEAD)) 278 if (request_->status().is_success() && (request_type_ != HEAD))
251 request_->Read(buffer_, kBufferSize, &bytes_read); 279 request_->Read(buffer_, kBufferSize, &bytes_read);
252 OnReadCompleted(request_.get(), bytes_read); 280 OnReadCompleted(request_.get(), bytes_read);
253 } 281 }
254 282
255 void URLFetcher::Core::OnReadCompleted(URLRequest* request, int bytes_read) { 283 void URLFetcher::Core::OnReadCompleted(URLRequest* request, int bytes_read) {
256 DCHECK(request == request_); 284 DCHECK(request == request_);
257 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); 285 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
258 286
259 url_ = request->url(); 287 url_ = request->url();
288 url_throttler_entry_ =
289 net::URLRequestThrottlerManager::GetInstance()->RegisterRequestUrl(url_);
260 290
261 do { 291 do {
262 if (!request_->status().is_success() || bytes_read <= 0) 292 if (!request_->status().is_success() || bytes_read <= 0)
263 break; 293 break;
264 data_.append(buffer_->data(), bytes_read); 294 data_.append(buffer_->data(), bytes_read);
265 } while (request_->Read(buffer_, kBufferSize, &bytes_read)); 295 } while (request_->Read(buffer_, kBufferSize, &bytes_read));
266 296
267 if (request_->status().is_success()) 297 if (request_->status().is_success())
268 request_->GetResponseCookies(&cookies_); 298 request_->GetResponseCookies(&cookies_);
269 299
270 // See comments re: HEAD requests in OnResponseStarted(). 300 // See comments re: HEAD requests in OnResponseStarted().
271 if (!request_->status().is_io_pending() || (request_type_ == HEAD)) { 301 if (!request_->status().is_io_pending() || (request_type_ == HEAD)) {
302 backoff_release_time_ = GetBackoffReleaseTime();
303
272 delegate_loop_->PostTask(FROM_HERE, NewRunnableMethod( 304 delegate_loop_->PostTask(FROM_HERE, NewRunnableMethod(
273 this, &Core::OnCompletedURLRequest, request_->status())); 305 this, &Core::OnCompletedURLRequest, request_->status()));
274 ReleaseRequest(); 306 ReleaseRequest();
275 } 307 }
276 } 308 }
277 309
278 void URLFetcher::Core::StartURLRequest() { 310 void URLFetcher::Core::StartURLRequest() {
279 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); 311 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
280 312
281 if (was_cancelled_) { 313 if (was_cancelled_) {
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
318 default: 350 default:
319 NOTREACHED(); 351 NOTREACHED();
320 } 352 }
321 353
322 if (!extra_request_headers_.IsEmpty()) 354 if (!extra_request_headers_.IsEmpty())
323 request_->SetExtraRequestHeaders(extra_request_headers_); 355 request_->SetExtraRequestHeaders(extra_request_headers_);
324 356
325 request_->Start(); 357 request_->Start();
326 } 358 }
327 359
360 void URLFetcher::Core::StartURLRequestWhenAppropriate() {
361 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
362
363 if (was_cancelled_)
364 return;
365
366 if (original_url_throttler_entry_ == NULL) {
367 original_url_throttler_entry_ =
368 net::URLRequestThrottlerManager::GetInstance()->RegisterRequestUrl(
369 original_url_);
370 }
371
372 int64 delay = original_url_throttler_entry_->ReserveSendingTimeForNextRequest(
373 GetBackoffReleaseTime());
374 if (delay == 0) {
375 StartURLRequest();
376 } else {
377 MessageLoop::current()->PostDelayedTask(
378 FROM_HERE,
379 NewRunnableMethod(this, &Core::StartURLRequest),
380 delay);
381 }
382 }
383
328 void URLFetcher::Core::CancelURLRequest() { 384 void URLFetcher::Core::CancelURLRequest() {
329 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); 385 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
330 386
331 if (request_.get()) { 387 if (request_.get()) {
332 request_->Cancel(); 388 request_->Cancel();
333 ReleaseRequest(); 389 ReleaseRequest();
334 } 390 }
335 // Release the reference to the request context. There could be multiple 391 // Release the reference to the request context. There could be multiple
336 // references to URLFetcher::Core at this point so it may take a while to 392 // references to URLFetcher::Core at this point so it may take a while to
337 // delete the object, but we cannot delay the destruction of the request 393 // delete the object, but we cannot delay the destruction of the request
338 // context. 394 // context.
339 request_context_getter_ = NULL; 395 request_context_getter_ = NULL;
340 was_cancelled_ = true; 396 was_cancelled_ = true;
341 } 397 }
342 398
343 void URLFetcher::Core::OnCompletedURLRequest(const URLRequestStatus& status) { 399 void URLFetcher::Core::OnCompletedURLRequest(const URLRequestStatus& status) {
344 DCHECK(MessageLoop::current() == delegate_loop_); 400 DCHECK(MessageLoop::current() == delegate_loop_);
345 401
346 // Checks the response from server. 402 // Checks the response from server.
347 if (response_code_ >= 500) { 403 if (response_code_ >= 500 ||
404 status.os_error() == net::ERR_TEMPORARILY_THROTTLED) {
348 // When encountering a server error, we will send the request again 405 // When encountering a server error, we will send the request again
349 // after backoff time. 406 // after backoff time.
350 int64 back_off_time =
351 protect_entry_->UpdateBackoff(URLFetcherProtectEntry::FAILURE);
352 if (delegate_) {
353 fetcher_->backoff_delay_ =
354 base::TimeDelta::FromMilliseconds(back_off_time);
355 }
356 ++num_retries_; 407 ++num_retries_;
357 // Restarts the request if we still need to notify the delegate. 408 // Restarts the request if we still need to notify the delegate.
358 if (delegate_) { 409 if (delegate_) {
410 fetcher_->backoff_delay_ = backoff_release_time_ - base::TimeTicks::Now();
411 if (fetcher_->backoff_delay_ < base::TimeDelta())
412 fetcher_->backoff_delay_ = base::TimeDelta();
413
359 if (fetcher_->automatically_retry_on_5xx_ && 414 if (fetcher_->automatically_retry_on_5xx_ &&
360 num_retries_ <= protect_entry_->max_retries()) { 415 num_retries_ <= fetcher_->max_retries()) {
361 io_message_loop_proxy_->PostDelayedTask( 416 io_message_loop_proxy_->PostTask(
362 FROM_HERE, 417 FROM_HERE,
363 NewRunnableMethod(this, &Core::StartURLRequest), back_off_time); 418 NewRunnableMethod(this, &Core::StartURLRequestWhenAppropriate));
364 } else { 419 } else {
365 delegate_->OnURLFetchComplete(fetcher_, url_, status, response_code_, 420 delegate_->OnURLFetchComplete(fetcher_, url_, status, response_code_,
366 cookies_, data_); 421 cookies_, data_);
367 } 422 }
368 } 423 }
369 } else { 424 } else {
370 protect_entry_->UpdateBackoff(URLFetcherProtectEntry::SUCCESS);
371 if (delegate_) { 425 if (delegate_) {
372 fetcher_->backoff_delay_ = base::TimeDelta(); 426 fetcher_->backoff_delay_ = base::TimeDelta();
373 delegate_->OnURLFetchComplete(fetcher_, url_, status, response_code_, 427 delegate_->OnURLFetchComplete(fetcher_, url_, status, response_code_,
374 cookies_, data_); 428 cookies_, data_);
375 } 429 }
376 } 430 }
377 } 431 }
378 432
433 void URLFetcher::Core::NotifyMalformedContent() {
434 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
435 if (url_throttler_entry_ != NULL)
436 url_throttler_entry_->ReceivedContentWasMalformed();
437 }
438
379 void URLFetcher::Core::ReleaseRequest() { 439 void URLFetcher::Core::ReleaseRequest() {
380 request_.reset(); 440 request_.reset();
381 g_registry.Get().RemoveURLFetcherCore(this); 441 g_registry.Get().RemoveURLFetcherCore(this);
382 } 442 }
383 443
444 base::TimeTicks URLFetcher::Core::GetBackoffReleaseTime() {
445 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
446 DCHECK(original_url_throttler_entry_ != NULL);
447
448 base::TimeTicks original_url_backoff =
449 original_url_throttler_entry_->GetExponentialBackoffReleaseTime();
450 base::TimeTicks destination_url_backoff;
451 if (url_throttler_entry_ != NULL &&
452 original_url_throttler_entry_ != url_throttler_entry_) {
453 destination_url_backoff =
454 url_throttler_entry_->GetExponentialBackoffReleaseTime();
455 }
456
457 return original_url_backoff > destination_url_backoff ?
458 original_url_backoff : destination_url_backoff;
459 }
460
384 void URLFetcher::set_upload_data(const std::string& upload_content_type, 461 void URLFetcher::set_upload_data(const std::string& upload_content_type,
385 const std::string& upload_content) { 462 const std::string& upload_content) {
386 core_->upload_content_type_ = upload_content_type; 463 core_->upload_content_type_ = upload_content_type;
387 core_->upload_content_ = upload_content; 464 core_->upload_content_ = upload_content;
388 } 465 }
389 466
390 const std::string& URLFetcher::upload_data() const { 467 const std::string& URLFetcher::upload_data() const {
391 return core_->upload_content_; 468 return core_->upload_content_;
392 } 469 }
393 470
394 void URLFetcher::set_load_flags(int load_flags) { 471 void URLFetcher::set_load_flags(int load_flags) {
395 core_->load_flags_ = load_flags; 472 core_->load_flags_ = load_flags;
(...skipping 23 matching lines...) Expand all
419 } 496 }
420 497
421 void URLFetcher::Start() { 498 void URLFetcher::Start() {
422 core_->Start(); 499 core_->Start();
423 } 500 }
424 501
425 const GURL& URLFetcher::url() const { 502 const GURL& URLFetcher::url() const {
426 return core_->url_; 503 return core_->url_;
427 } 504 }
428 505
506 void URLFetcher::ReceivedContentWasMalformed() {
507 core_->ReceivedContentWasMalformed();
508 }
509
429 // static 510 // static
430 void URLFetcher::CancelAll() { 511 void URLFetcher::CancelAll() {
431 Core::CancelAll(); 512 Core::CancelAll();
432 } 513 }
433 514
434 URLFetcher::Delegate* URLFetcher::delegate() const { 515 URLFetcher::Delegate* URLFetcher::delegate() const {
435 return core_->delegate(); 516 return core_->delegate();
436 } 517 }
OLDNEW
« no previous file with comments | « chrome/common/net/url_fetcher.h ('k') | chrome/common/net/url_fetcher_protect.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698