Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 } |
| OLD | NEW |