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

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 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
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/request_throttler_manager.h"
24 #include "net/url_request/url_request.h" 25 #include "net/url_request/url_request.h"
25 #include "net/url_request/url_request_context.h" 26 #include "net/url_request/url_request_context.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 {
(...skipping 12 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();
willchan no longer on Chromium 2010/11/24 00:23:07 Is this new functionality? I don't see any mentio
yzshen 2010/11/24 09:42:08 This is not some new functionality, it is in the t
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<RequestThrottlerEntryInterface> original_url_throttler_entry_;
139 scoped_refptr<RequestThrottlerEntryInterface> url_throttler_entry_;
140
125 // |num_retries_| indicates how many times we've failed to successfully 141 // |num_retries_| indicates how many times we've failed to successfully
126 // fetch this URL. Once this value exceeds the maximum number of retries 142 // fetch this URL. Once this value exceeds the maximum number of retries
127 // specified by the protection manager, we'll give up. 143 // specified by the owner URLFetcher instance, we'll give up.
128 int num_retries_; 144 int num_retries_;
129 145
130 // True if the URLFetcher has been cancelled. 146 // True if the URLFetcher has been cancelled.
131 bool was_cancelled_; 147 bool was_cancelled_;
132 148
149 // Since GetBackoffReleaseTime() can only be called on the IO thread, we cache
150 // its value to be used by OnCompletedURLRequest on the creating thread.
151 base::TimeTicks backoff_release_time_;
152
133 static base::LazyInstance<Registry> g_registry; 153 static base::LazyInstance<Registry> g_registry;
134 154
135 friend class URLFetcher; 155 friend class URLFetcher;
136 DISALLOW_COPY_AND_ASSIGN(Core); 156 DISALLOW_COPY_AND_ASSIGN(Core);
137 }; 157 };
138 158
139 URLFetcher::Core::Registry::Registry() {} 159 URLFetcher::Core::Registry::Registry() {}
140 URLFetcher::Core::Registry::~Registry() {} 160 URLFetcher::Core::Registry::~Registry() {}
141 161
142 void URLFetcher::Core::Registry::AddURLFetcherCore(Core* core) { 162 void URLFetcher::Core::Registry::AddURLFetcherCore(Core* core) {
(...skipping 20 matching lines...) Expand all
163 URLFetcher::Core::g_registry(base::LINKER_INITIALIZED); 183 URLFetcher::Core::g_registry(base::LINKER_INITIALIZED);
164 184
165 // static 185 // static
166 URLFetcher::Factory* URLFetcher::factory_ = NULL; 186 URLFetcher::Factory* URLFetcher::factory_ = NULL;
167 187
168 URLFetcher::URLFetcher(const GURL& url, 188 URLFetcher::URLFetcher(const GURL& url,
169 RequestType request_type, 189 RequestType request_type,
170 Delegate* d) 190 Delegate* d)
171 : ALLOW_THIS_IN_INITIALIZER_LIST( 191 : ALLOW_THIS_IN_INITIALIZER_LIST(
172 core_(new Core(this, url, request_type, d))), 192 core_(new Core(this, url, request_type, d))),
173 automatically_retry_on_5xx_(true) { 193 automatically_retry_on_5xx_(true),
194 max_retries_(0) {
174 } 195 }
175 196
176 URLFetcher::~URLFetcher() { 197 URLFetcher::~URLFetcher() {
177 core_->Stop(); 198 core_->Stop();
178 } 199 }
179 200
180 // static 201 // static
181 URLFetcher* URLFetcher::Create(int id, const GURL& url, 202 URLFetcher* URLFetcher::Create(int id, const GURL& url,
182 RequestType request_type, Delegate* d) { 203 RequestType request_type, Delegate* d) {
183 return factory_ ? factory_->CreateURLFetcher(id, url, request_type, d) : 204 return factory_ ? factory_->CreateURLFetcher(id, url, request_type, d) :
184 new URLFetcher(url, request_type, d); 205 new URLFetcher(url, request_type, d);
185 } 206 }
186 207
187 URLFetcher::Core::Core(URLFetcher* fetcher, 208 URLFetcher::Core::Core(URLFetcher* fetcher,
188 const GURL& original_url, 209 const GURL& original_url,
189 RequestType request_type, 210 RequestType request_type,
190 URLFetcher::Delegate* d) 211 URLFetcher::Delegate* d)
191 : fetcher_(fetcher), 212 : fetcher_(fetcher),
192 original_url_(original_url), 213 original_url_(original_url),
193 request_type_(request_type), 214 request_type_(request_type),
194 delegate_(d), 215 delegate_(d),
195 delegate_loop_(MessageLoop::current()), 216 delegate_loop_(MessageLoop::current()),
196 request_(NULL), 217 request_(NULL),
197 load_flags_(net::LOAD_NORMAL), 218 load_flags_(net::LOAD_NORMAL),
198 response_code_(-1), 219 response_code_(-1),
199 buffer_(new net::IOBuffer(kBufferSize)), 220 buffer_(new net::IOBuffer(kBufferSize)),
200 protect_entry_(URLFetcherProtectManager::GetInstance()->Register(
201 original_url_.host())),
202 num_retries_(0), 221 num_retries_(0),
203 was_cancelled_(false) { 222 was_cancelled_(false) {
204 } 223 }
205 224
206 URLFetcher::Core::~Core() { 225 URLFetcher::Core::~Core() {
207 // |request_| should be NULL. If not, it's unsafe to delete it here since we 226 // |request_| should be NULL. If not, it's unsafe to delete it here since we
208 // may not be on the IO thread. 227 // may not be on the IO thread.
209 DCHECK(!request_.get()); 228 DCHECK(!request_.get());
210 } 229 }
211 230
212 void URLFetcher::Core::Start() { 231 void URLFetcher::Core::Start() {
213 DCHECK(delegate_loop_); 232 DCHECK(delegate_loop_);
214 CHECK(request_context_getter_) << "We need an URLRequestContext!"; 233 CHECK(request_context_getter_) << "We need an URLRequestContext!";
215 io_message_loop_proxy_ = request_context_getter_->GetIOMessageLoopProxy(); 234 io_message_loop_proxy_ = request_context_getter_->GetIOMessageLoopProxy();
216 CHECK(io_message_loop_proxy_.get()) << "We need an IO message loop proxy"; 235 CHECK(io_message_loop_proxy_.get()) << "We need an IO message loop proxy";
217 io_message_loop_proxy_->PostDelayedTask( 236
237 io_message_loop_proxy_->PostTask(
218 FROM_HERE, 238 FROM_HERE,
219 NewRunnableMethod(this, &Core::StartURLRequest), 239 NewRunnableMethod(this, &Core::StartURLRequestWhenAppropriate));
220 protect_entry_->UpdateBackoff(URLFetcherProtectEntry::SEND));
221 } 240 }
222 241
223 void URLFetcher::Core::Stop() { 242 void URLFetcher::Core::Stop() {
224 DCHECK_EQ(MessageLoop::current(), delegate_loop_); 243 DCHECK_EQ(MessageLoop::current(), delegate_loop_);
225 delegate_ = NULL; 244 delegate_ = NULL;
226 fetcher_ = NULL; 245 fetcher_ = NULL;
227 if (io_message_loop_proxy_.get()) { 246 if (io_message_loop_proxy_.get()) {
228 io_message_loop_proxy_->PostTask( 247 io_message_loop_proxy_->PostTask(
229 FROM_HERE, NewRunnableMethod(this, &Core::CancelURLRequest)); 248 FROM_HERE, NewRunnableMethod(this, &Core::CancelURLRequest));
230 } 249 }
231 } 250 }
232 251
252 void URLFetcher::Core::ReceivedContentWasMalformed() {
253 DCHECK_EQ(MessageLoop::current(), delegate_loop_);
254 if (io_message_loop_proxy_.get()) {
255 io_message_loop_proxy_->PostTask(
256 FROM_HERE, NewRunnableMethod(this, &Core::NotifyMalformedContent));
257 }
258 }
259
233 void URLFetcher::Core::CancelAll() { 260 void URLFetcher::Core::CancelAll() {
234 g_registry.Get().CancelAll(); 261 g_registry.Get().CancelAll();
235 } 262 }
236 263
237 void URLFetcher::Core::OnResponseStarted(URLRequest* request) { 264 void URLFetcher::Core::OnResponseStarted(URLRequest* request) {
238 DCHECK_EQ(request, request_.get()); 265 DCHECK_EQ(request, request_.get());
239 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); 266 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
240 if (request_->status().is_success()) { 267 if (request_->status().is_success()) {
241 response_code_ = request_->GetResponseCode(); 268 response_code_ = request_->GetResponseCode();
242 response_headers_ = request_->response_headers(); 269 response_headers_ = request_->response_headers();
243 } 270 }
244 271
245 int bytes_read = 0; 272 int bytes_read = 0;
246 // Some servers may treat HEAD requests as GET requests. To free up the 273 // 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 274 // network connection as soon as possible, signal that the request has
248 // completed immediately, without trying to read any data back (all we care 275 // completed immediately, without trying to read any data back (all we care
249 // about is the response code and headers, which we already have). 276 // about is the response code and headers, which we already have).
250 if (request_->status().is_success() && (request_type_ != HEAD)) 277 if (request_->status().is_success() && (request_type_ != HEAD))
251 request_->Read(buffer_, kBufferSize, &bytes_read); 278 request_->Read(buffer_, kBufferSize, &bytes_read);
252 OnReadCompleted(request_.get(), bytes_read); 279 OnReadCompleted(request_.get(), bytes_read);
253 } 280 }
254 281
255 void URLFetcher::Core::OnReadCompleted(URLRequest* request, int bytes_read) { 282 void URLFetcher::Core::OnReadCompleted(URLRequest* request, int bytes_read) {
256 DCHECK(request == request_); 283 DCHECK(request == request_);
257 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); 284 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
258 285
259 url_ = request->url(); 286 url_ = request->url();
287 url_throttler_entry_ =
288 RequestThrottlerManager::GetInstance()->RegisterRequestUrl(url_);
260 289
261 do { 290 do {
262 if (!request_->status().is_success() || bytes_read <= 0) 291 if (!request_->status().is_success() || bytes_read <= 0)
263 break; 292 break;
264 data_.append(buffer_->data(), bytes_read); 293 data_.append(buffer_->data(), bytes_read);
265 } while (request_->Read(buffer_, kBufferSize, &bytes_read)); 294 } while (request_->Read(buffer_, kBufferSize, &bytes_read));
266 295
267 if (request_->status().is_success()) 296 if (request_->status().is_success())
268 request_->GetResponseCookies(&cookies_); 297 request_->GetResponseCookies(&cookies_);
269 298
270 // See comments re: HEAD requests in OnResponseStarted(). 299 // See comments re: HEAD requests in OnResponseStarted().
271 if (!request_->status().is_io_pending() || (request_type_ == HEAD)) { 300 if (!request_->status().is_io_pending() || (request_type_ == HEAD)) {
301 backoff_release_time_ = GetBackoffReleaseTime();
302
272 delegate_loop_->PostTask(FROM_HERE, NewRunnableMethod( 303 delegate_loop_->PostTask(FROM_HERE, NewRunnableMethod(
273 this, &Core::OnCompletedURLRequest, request_->status())); 304 this, &Core::OnCompletedURLRequest, request_->status()));
274 ReleaseRequest(); 305 ReleaseRequest();
275 } 306 }
276 } 307 }
277 308
278 void URLFetcher::Core::StartURLRequest() { 309 void URLFetcher::Core::StartURLRequest() {
279 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); 310 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
280 311
281 if (was_cancelled_) { 312 if (was_cancelled_) {
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
318 default: 349 default:
319 NOTREACHED(); 350 NOTREACHED();
320 } 351 }
321 352
322 if (!extra_request_headers_.IsEmpty()) 353 if (!extra_request_headers_.IsEmpty())
323 request_->SetExtraRequestHeaders(extra_request_headers_); 354 request_->SetExtraRequestHeaders(extra_request_headers_);
324 355
325 request_->Start(); 356 request_->Start();
326 } 357 }
327 358
359 void URLFetcher::Core::StartURLRequestWhenAppropriate() {
360 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
361
362 if (was_cancelled_)
363 return;
364
365 if (original_url_throttler_entry_ == NULL) {
366 original_url_throttler_entry_ =
367 RequestThrottlerManager::GetInstance()->RegisterRequestUrl(
368 original_url_);
369 }
370
371 int64 delay = original_url_throttler_entry_->ReserveSendingTimeForNextRequest(
372 GetBackoffReleaseTime());
373 if (delay == 0) {
374 StartURLRequest();
375 } else {
376 MessageLoop::current()->PostDelayedTask(
377 FROM_HERE,
378 NewRunnableMethod(this, &Core::StartURLRequest),
379 delay);
380 }
381 }
382
328 void URLFetcher::Core::CancelURLRequest() { 383 void URLFetcher::Core::CancelURLRequest() {
329 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); 384 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
330 385
331 if (request_.get()) { 386 if (request_.get()) {
332 request_->Cancel(); 387 request_->Cancel();
333 ReleaseRequest(); 388 ReleaseRequest();
334 } 389 }
335 // Release the reference to the request context. There could be multiple 390 // 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 391 // 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 392 // delete the object, but we cannot delay the destruction of the request
338 // context. 393 // context.
339 request_context_getter_ = NULL; 394 request_context_getter_ = NULL;
340 was_cancelled_ = true; 395 was_cancelled_ = true;
341 } 396 }
342 397
343 void URLFetcher::Core::OnCompletedURLRequest(const URLRequestStatus& status) { 398 void URLFetcher::Core::OnCompletedURLRequest(const URLRequestStatus& status) {
344 DCHECK(MessageLoop::current() == delegate_loop_); 399 DCHECK(MessageLoop::current() == delegate_loop_);
345 400
346 // Checks the response from server. 401 // Checks the response from server.
347 if (response_code_ >= 500) { 402 if (response_code_ >= 500 ||
willchan no longer on Chromium 2010/11/24 00:23:07 Can you explain why this checking happens on the d
yzshen 2010/11/24 09:42:08 This is the original logic, I haven't changed it.
403 status.os_error() == net::ERR_TEMPORARILY_THROTTLED_BY_DDOS) {
willchan no longer on Chromium 2010/11/24 00:23:07 I think I'd rather this error be called ERR_TEMPOR
yzshen 2010/11/24 09:42:08 Done.
348 // When encountering a server error, we will send the request again 404 // When encountering a server error, we will send the request again
349 // after backoff time. 405 // 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_; 406 ++num_retries_;
357 // Restarts the request if we still need to notify the delegate. 407 // Restarts the request if we still need to notify the delegate.
358 if (delegate_) { 408 if (delegate_) {
409 fetcher_->backoff_delay_ = backoff_release_time_ - base::TimeTicks::Now();
410 if (fetcher_->backoff_delay_ < base::TimeDelta())
411 fetcher_->backoff_delay_ = base::TimeDelta();
412
359 if (fetcher_->automatically_retry_on_5xx_ && 413 if (fetcher_->automatically_retry_on_5xx_ &&
360 num_retries_ <= protect_entry_->max_retries()) { 414 num_retries_ <= fetcher_->max_retries()) {
361 io_message_loop_proxy_->PostDelayedTask( 415 io_message_loop_proxy_->PostTask(
362 FROM_HERE, 416 FROM_HERE,
363 NewRunnableMethod(this, &Core::StartURLRequest), back_off_time); 417 NewRunnableMethod(this, &Core::StartURLRequestWhenAppropriate));
364 } else { 418 } else {
365 delegate_->OnURLFetchComplete(fetcher_, url_, status, response_code_, 419 delegate_->OnURLFetchComplete(fetcher_, url_, status, response_code_,
366 cookies_, data_); 420 cookies_, data_);
367 } 421 }
368 } 422 }
369 } else { 423 } else {
370 protect_entry_->UpdateBackoff(URLFetcherProtectEntry::SUCCESS);
371 if (delegate_) { 424 if (delegate_) {
372 fetcher_->backoff_delay_ = base::TimeDelta(); 425 fetcher_->backoff_delay_ = base::TimeDelta();
373 delegate_->OnURLFetchComplete(fetcher_, url_, status, response_code_, 426 delegate_->OnURLFetchComplete(fetcher_, url_, status, response_code_,
374 cookies_, data_); 427 cookies_, data_);
375 } 428 }
376 } 429 }
377 } 430 }
378 431
432 void URLFetcher::Core::NotifyMalformedContent() {
433 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
434 if (url_throttler_entry_ != NULL)
435 url_throttler_entry_->ReceivedContentWasMalformed();
436 }
437
379 void URLFetcher::Core::ReleaseRequest() { 438 void URLFetcher::Core::ReleaseRequest() {
380 request_.reset(); 439 request_.reset();
381 g_registry.Get().RemoveURLFetcherCore(this); 440 g_registry.Get().RemoveURLFetcherCore(this);
382 } 441 }
383 442
443 base::TimeTicks URLFetcher::Core::GetBackoffReleaseTime() {
444 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
445 DCHECK(original_url_throttler_entry_ != NULL);
446
447 base::TimeTicks original_url_backoff =
448 original_url_throttler_entry_->GetExponentialBackoffReleaseTime();
449 base::TimeTicks destination_url_backoff;
450 if (url_throttler_entry_ != NULL &&
451 original_url_throttler_entry_ != url_throttler_entry_) {
452 destination_url_backoff =
453 url_throttler_entry_->GetExponentialBackoffReleaseTime();
454 }
455
456 return original_url_backoff > destination_url_backoff ?
457 original_url_backoff : destination_url_backoff;
458 }
459
384 void URLFetcher::set_upload_data(const std::string& upload_content_type, 460 void URLFetcher::set_upload_data(const std::string& upload_content_type,
385 const std::string& upload_content) { 461 const std::string& upload_content) {
386 core_->upload_content_type_ = upload_content_type; 462 core_->upload_content_type_ = upload_content_type;
387 core_->upload_content_ = upload_content; 463 core_->upload_content_ = upload_content;
388 } 464 }
389 465
390 const std::string& URLFetcher::upload_data() const { 466 const std::string& URLFetcher::upload_data() const {
391 return core_->upload_content_; 467 return core_->upload_content_;
392 } 468 }
393 469
394 void URLFetcher::set_load_flags(int load_flags) { 470 void URLFetcher::set_load_flags(int load_flags) {
395 core_->load_flags_ = load_flags; 471 core_->load_flags_ = load_flags;
(...skipping 23 matching lines...) Expand all
419 } 495 }
420 496
421 void URLFetcher::Start() { 497 void URLFetcher::Start() {
422 core_->Start(); 498 core_->Start();
423 } 499 }
424 500
425 const GURL& URLFetcher::url() const { 501 const GURL& URLFetcher::url() const {
426 return core_->url_; 502 return core_->url_;
427 } 503 }
428 504
505 void URLFetcher::ReceivedContentWasMalformed() {
506 core_->ReceivedContentWasMalformed();
507 }
508
429 // static 509 // static
430 void URLFetcher::CancelAll() { 510 void URLFetcher::CancelAll() {
431 Core::CancelAll(); 511 Core::CancelAll();
432 } 512 }
433 513
434 URLFetcher::Delegate* URLFetcher::delegate() const { 514 URLFetcher::Delegate* URLFetcher::delegate() const {
435 return core_->delegate(); 515 return core_->delegate();
436 } 516 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698