| 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/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 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(); |
| 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<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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 } |
| OLD | NEW |