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

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

Powered by Google App Engine
This is Rietveld 408576698