| 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" |
| 22 #include "net/http/http_request_headers.h" | 21 #include "net/http/http_request_headers.h" |
| 23 #include "net/http/http_response_headers.h" | 22 #include "net/http/http_response_headers.h" |
| 23 #include "net/request_throttler/request_throttler_manager.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 | 26 |
| 27 static const int kBufferSize = 4096; | 27 static const int kBufferSize = 4096; |
| 28 | 28 |
| 29 bool URLFetcher::g_interception_enabled = false; | 29 bool URLFetcher::g_interception_enabled = false; |
| 30 | 30 |
| 31 class URLFetcher::Core | 31 class URLFetcher::Core |
| 32 : public base::RefCountedThreadSafe<URLFetcher::Core>, | 32 : public base::RefCountedThreadSafe<URLFetcher::Core>, |
| 33 public URLRequest::Delegate { | 33 public URLRequest::Delegate { |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 109 // Read buffer | 109 // Read buffer |
| 110 scoped_refptr<URLRequestContextGetter> request_context_getter_; | 110 scoped_refptr<URLRequestContextGetter> request_context_getter_; |
| 111 // Cookie/cache info for the request | 111 // Cookie/cache info for the request |
| 112 ResponseCookies cookies_; // Response cookies | 112 ResponseCookies cookies_; // Response cookies |
| 113 net::HttpRequestHeaders extra_request_headers_; | 113 net::HttpRequestHeaders extra_request_headers_; |
| 114 scoped_refptr<net::HttpResponseHeaders> response_headers_; | 114 scoped_refptr<net::HttpResponseHeaders> response_headers_; |
| 115 | 115 |
| 116 std::string upload_content_; // HTTP POST payload | 116 std::string upload_content_; // HTTP POST payload |
| 117 std::string upload_content_type_; // MIME type of POST payload | 117 std::string upload_content_type_; // MIME type of POST payload |
| 118 | 118 |
| 119 // The overload protection entry for this URL. This is used to | |
| 120 // incrementally back off how rapidly we'll send requests to a particular | |
| 121 // URL, to avoid placing too much demand on the remote resource. We update | |
| 122 // this with the status of all requests as they return, and in turn use it | |
| 123 // to determine how long to wait before making another request. | |
| 124 URLFetcherProtectEntry* protect_entry_; | |
| 125 // |num_retries_| indicates how many times we've failed to successfully | 119 // |num_retries_| indicates how many times we've failed to successfully |
| 126 // fetch this URL. Once this value exceeds the maximum number of retries | 120 // fetch this URL. Once this value exceeds the maximum number of retries |
| 127 // specified by the protection manager, we'll give up. | 121 // specified by the owner URLFetcher instance, we'll give up. |
| 128 int num_retries_; | 122 int num_retries_; |
| 129 | 123 |
| 124 // Cache the pointer to the singleton object of RequestThrottlerManager. |
| 125 // This is used to determine how long to wait before making a request or doing |
| 126 // a retry. |
| 127 RequestThrottlerManager* request_throttler_manager_; |
| 128 |
| 130 // True if the URLFetcher has been cancelled. | 129 // True if the URLFetcher has been cancelled. |
| 131 bool was_cancelled_; | 130 bool was_cancelled_; |
| 132 | 131 |
| 133 static base::LazyInstance<Registry> g_registry; | 132 static base::LazyInstance<Registry> g_registry; |
| 134 | 133 |
| 135 friend class URLFetcher; | 134 friend class URLFetcher; |
| 136 DISALLOW_COPY_AND_ASSIGN(Core); | 135 DISALLOW_COPY_AND_ASSIGN(Core); |
| 137 }; | 136 }; |
| 138 | 137 |
| 139 URLFetcher::Core::Registry::Registry() {} | 138 URLFetcher::Core::Registry::Registry() {} |
| (...skipping 23 matching lines...) Expand all Loading... |
| 163 URLFetcher::Core::g_registry(base::LINKER_INITIALIZED); | 162 URLFetcher::Core::g_registry(base::LINKER_INITIALIZED); |
| 164 | 163 |
| 165 // static | 164 // static |
| 166 URLFetcher::Factory* URLFetcher::factory_ = NULL; | 165 URLFetcher::Factory* URLFetcher::factory_ = NULL; |
| 167 | 166 |
| 168 URLFetcher::URLFetcher(const GURL& url, | 167 URLFetcher::URLFetcher(const GURL& url, |
| 169 RequestType request_type, | 168 RequestType request_type, |
| 170 Delegate* d) | 169 Delegate* d) |
| 171 : ALLOW_THIS_IN_INITIALIZER_LIST( | 170 : ALLOW_THIS_IN_INITIALIZER_LIST( |
| 172 core_(new Core(this, url, request_type, d))), | 171 core_(new Core(this, url, request_type, d))), |
| 173 automatically_retry_on_5xx_(true) { | 172 automatically_retry_on_5xx_(true), |
| 173 max_retries_(0) { |
| 174 } | 174 } |
| 175 | 175 |
| 176 URLFetcher::~URLFetcher() { | 176 URLFetcher::~URLFetcher() { |
| 177 core_->Stop(); | 177 core_->Stop(); |
| 178 } | 178 } |
| 179 | 179 |
| 180 // static | 180 // static |
| 181 URLFetcher* URLFetcher::Create(int id, const GURL& url, | 181 URLFetcher* URLFetcher::Create(int id, const GURL& url, |
| 182 RequestType request_type, Delegate* d) { | 182 RequestType request_type, Delegate* d) { |
| 183 return factory_ ? factory_->CreateURLFetcher(id, url, request_type, d) : | 183 return factory_ ? factory_->CreateURLFetcher(id, url, request_type, d) : |
| 184 new URLFetcher(url, request_type, d); | 184 new URLFetcher(url, request_type, d); |
| 185 } | 185 } |
| 186 | 186 |
| 187 URLFetcher::Core::Core(URLFetcher* fetcher, | 187 URLFetcher::Core::Core(URLFetcher* fetcher, |
| 188 const GURL& original_url, | 188 const GURL& original_url, |
| 189 RequestType request_type, | 189 RequestType request_type, |
| 190 URLFetcher::Delegate* d) | 190 URLFetcher::Delegate* d) |
| 191 : fetcher_(fetcher), | 191 : fetcher_(fetcher), |
| 192 original_url_(original_url), | 192 original_url_(original_url), |
| 193 request_type_(request_type), | 193 request_type_(request_type), |
| 194 delegate_(d), | 194 delegate_(d), |
| 195 delegate_loop_(MessageLoop::current()), | 195 delegate_loop_(MessageLoop::current()), |
| 196 request_(NULL), | 196 request_(NULL), |
| 197 load_flags_(net::LOAD_NORMAL), | 197 load_flags_(net::LOAD_NORMAL), |
| 198 response_code_(-1), | 198 response_code_(-1), |
| 199 buffer_(new net::IOBuffer(kBufferSize)), | 199 buffer_(new net::IOBuffer(kBufferSize)), |
| 200 protect_entry_(URLFetcherProtectManager::GetInstance()->Register( | |
| 201 original_url_.host())), | |
| 202 num_retries_(0), | 200 num_retries_(0), |
| 201 request_throttler_manager_(Singleton<RequestThrottlerManager>::get()), |
| 203 was_cancelled_(false) { | 202 was_cancelled_(false) { |
| 204 } | 203 } |
| 205 | 204 |
| 206 URLFetcher::Core::~Core() { | 205 URLFetcher::Core::~Core() { |
| 207 // |request_| should be NULL. If not, it's unsafe to delete it here since we | 206 // |request_| should be NULL. If not, it's unsafe to delete it here since we |
| 208 // may not be on the IO thread. | 207 // may not be on the IO thread. |
| 209 DCHECK(!request_.get()); | 208 DCHECK(!request_.get()); |
| 210 } | 209 } |
| 211 | 210 |
| 212 void URLFetcher::Core::Start() { | 211 void URLFetcher::Core::Start() { |
| 213 DCHECK(delegate_loop_); | 212 DCHECK(delegate_loop_); |
| 214 CHECK(request_context_getter_) << "We need an URLRequestContext!"; | 213 CHECK(request_context_getter_) << "We need an URLRequestContext!"; |
| 215 io_message_loop_proxy_ = request_context_getter_->GetIOMessageLoopProxy(); | 214 io_message_loop_proxy_ = request_context_getter_->GetIOMessageLoopProxy(); |
| 216 CHECK(io_message_loop_proxy_.get()) << "We need an IO message loop proxy"; | 215 CHECK(io_message_loop_proxy_.get()) << "We need an IO message loop proxy"; |
| 216 |
| 217 io_message_loop_proxy_->PostDelayedTask( | 217 io_message_loop_proxy_->PostDelayedTask( |
| 218 FROM_HERE, | 218 FROM_HERE, |
| 219 NewRunnableMethod(this, &Core::StartURLRequest), | 219 NewRunnableMethod(this, &Core::StartURLRequest), |
| 220 protect_entry_->UpdateBackoff(URLFetcherProtectEntry::SEND)); | 220 request_throttler_manager_->GetBackoffDelayInMilliseconds(original_url_)); |
| 221 } | 221 } |
| 222 | 222 |
| 223 void URLFetcher::Core::Stop() { | 223 void URLFetcher::Core::Stop() { |
| 224 DCHECK_EQ(MessageLoop::current(), delegate_loop_); | 224 DCHECK_EQ(MessageLoop::current(), delegate_loop_); |
| 225 delegate_ = NULL; | 225 delegate_ = NULL; |
| 226 fetcher_ = NULL; | 226 fetcher_ = NULL; |
| 227 if (io_message_loop_proxy_.get()) { | 227 if (io_message_loop_proxy_.get()) { |
| 228 io_message_loop_proxy_->PostTask( | 228 io_message_loop_proxy_->PostTask( |
| 229 FROM_HERE, NewRunnableMethod(this, &Core::CancelURLRequest)); | 229 FROM_HERE, NewRunnableMethod(this, &Core::CancelURLRequest)); |
| 230 } | 230 } |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 341 } | 341 } |
| 342 | 342 |
| 343 void URLFetcher::Core::OnCompletedURLRequest(const URLRequestStatus& status) { | 343 void URLFetcher::Core::OnCompletedURLRequest(const URLRequestStatus& status) { |
| 344 DCHECK(MessageLoop::current() == delegate_loop_); | 344 DCHECK(MessageLoop::current() == delegate_loop_); |
| 345 | 345 |
| 346 // Checks the response from server. | 346 // Checks the response from server. |
| 347 if (response_code_ >= 500) { | 347 if (response_code_ >= 500) { |
| 348 // When encountering a server error, we will send the request again | 348 // When encountering a server error, we will send the request again |
| 349 // after backoff time. | 349 // after backoff time. |
| 350 int64 back_off_time = | 350 int64 back_off_time = |
| 351 protect_entry_->UpdateBackoff(URLFetcherProtectEntry::FAILURE); | 351 request_throttler_manager_->GetBackoffDelayInMilliseconds(url_); |
| 352 if (delegate_) { | 352 if (delegate_) { |
| 353 fetcher_->backoff_delay_ = | 353 fetcher_->backoff_delay_ = |
| 354 base::TimeDelta::FromMilliseconds(back_off_time); | 354 base::TimeDelta::FromMilliseconds(back_off_time); |
| 355 } | 355 } |
| 356 ++num_retries_; | 356 ++num_retries_; |
| 357 // Restarts the request if we still need to notify the delegate. | 357 // Restarts the request if we still need to notify the delegate. |
| 358 if (delegate_) { | 358 if (delegate_) { |
| 359 if (fetcher_->automatically_retry_on_5xx_ && | 359 if (fetcher_->automatically_retry_on_5xx_ && |
| 360 num_retries_ <= protect_entry_->max_retries()) { | 360 num_retries_ <= fetcher_->max_retries()) { |
| 361 io_message_loop_proxy_->PostDelayedTask( | 361 io_message_loop_proxy_->PostDelayedTask( |
| 362 FROM_HERE, | 362 FROM_HERE, |
| 363 NewRunnableMethod(this, &Core::StartURLRequest), back_off_time); | 363 NewRunnableMethod(this, &Core::StartURLRequest), back_off_time); |
| 364 } else { | 364 } else { |
| 365 delegate_->OnURLFetchComplete(fetcher_, url_, status, response_code_, | 365 delegate_->OnURLFetchComplete(fetcher_, url_, status, response_code_, |
| 366 cookies_, data_); | 366 cookies_, data_); |
| 367 } | 367 } |
| 368 } | 368 } |
| 369 } else { | 369 } else { |
| 370 protect_entry_->UpdateBackoff(URLFetcherProtectEntry::SUCCESS); | |
| 371 if (delegate_) { | 370 if (delegate_) { |
| 372 fetcher_->backoff_delay_ = base::TimeDelta(); | 371 fetcher_->backoff_delay_ = base::TimeDelta(); |
| 373 delegate_->OnURLFetchComplete(fetcher_, url_, status, response_code_, | 372 delegate_->OnURLFetchComplete(fetcher_, url_, status, response_code_, |
| 374 cookies_, data_); | 373 cookies_, data_); |
| 375 } | 374 } |
| 376 } | 375 } |
| 377 } | 376 } |
| 378 | 377 |
| 379 void URLFetcher::Core::ReleaseRequest() { | 378 void URLFetcher::Core::ReleaseRequest() { |
| 380 request_.reset(); | 379 request_.reset(); |
| 381 g_registry.Get().RemoveURLFetcherCore(this); | 380 g_registry.Get().RemoveURLFetcherCore(this); |
| 382 } | 381 } |
| 383 | 382 |
| 384 void URLFetcher::set_upload_data(const std::string& upload_content_type, | 383 void URLFetcher::set_upload_data(const std::string& upload_content_type, |
| 385 const std::string& upload_content) { | 384 const std::string& upload_content) { |
| 386 core_->upload_content_type_ = upload_content_type; | 385 core_->upload_content_type_ = upload_content_type; |
| 387 core_->upload_content_ = upload_content; | 386 core_->upload_content_ = upload_content; |
| 388 } | 387 } |
| 389 | 388 |
| 390 const std::string& URLFetcher::upload_data() const { | 389 const std::string& URLFetcher::upload_data() const { |
| 391 return core_->upload_content_; | 390 return core_->upload_content_; |
| 392 } | 391 } |
| 393 | 392 |
| 394 void URLFetcher::set_load_flags(int load_flags) { | 393 void URLFetcher::set_load_flags(int load_flags) { |
| 395 core_->load_flags_ = load_flags; | 394 core_->load_flags_ = load_flags; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 427 } | 426 } |
| 428 | 427 |
| 429 // static | 428 // static |
| 430 void URLFetcher::CancelAll() { | 429 void URLFetcher::CancelAll() { |
| 431 Core::CancelAll(); | 430 Core::CancelAll(); |
| 432 } | 431 } |
| 433 | 432 |
| 434 URLFetcher::Delegate* URLFetcher::delegate() const { | 433 URLFetcher::Delegate* URLFetcher::delegate() const { |
| 435 return core_->delegate(); | 434 return core_->delegate(); |
| 436 } | 435 } |
| OLD | NEW |