1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/common/net/url_fetcher.h" 6 7 #include <set> 8 9 #include "base/compiler_specific.h" 10 #include "base/lazy_instance.h" 11 #include "base/memory/scoped_ptr.h" 12 #include "base/message_loop_proxy.h" 13 #include "base/stl_util-inl.h" 14 #include "base/string_util.h" 15 #include "base/threading/thread.h" 16 #include "googleurl/src/gurl.h" 17 #include "net/base/load_flags.h" 18 #include "net/base/io_buffer.h" 19 #include "net/base/net_errors.h" 20 #include "net/http/http_request_headers.h" 21 #include "net/http/http_response_headers.h" 22 #include "net/url_request/url_request.h" 23 #include "net/url_request/url_request_context.h" 24 #include "net/url_request/url_request_context_getter.h" 25 #include "net/url_request/url_request_throttler_manager.h" 26 27 #ifdef ANDROID 28 #include "android/autofill/url_fetcher_proxy.h" 29 #endif 30 31 static const int kBufferSize = 4096; 32 33 class URLFetcher::Core 34 : public base::RefCountedThreadSafe<URLFetcher::Core>, 35 public net::URLRequest::Delegate { 36 public: 37 // For POST requests, set |content_type| to the MIME type of the content 38 // and set |content| to the data to upload. |flags| are flags to apply to 39 // the load operation--these should be one or more of the LOAD_* flags 40 // defined in net/base/load_flags.h. 41 Core(URLFetcher* fetcher, 42 const GURL& original_url, 43 RequestType request_type, 44 URLFetcher::Delegate* d); 45 46 // Starts the load. It's important that this not happen in the constructor 47 // because it causes the IO thread to begin AddRef()ing and Release()ing 48 // us. If our caller hasn't had time to fully construct us and take a 49 // reference, the IO thread could interrupt things, run a task, Release() 50 // us, and destroy us, leaving the caller with an already-destroyed object 51 // when construction finishes. 52 void Start(); 53 54 // Stops any in-progress load and ensures no callback will happen. It is 55 // safe to call this multiple times. 56 void Stop(); 57 58 // Reports that the received content was malformed. 59 void ReceivedContentWasMalformed(); 60 61 // Overridden from net::URLRequest::Delegate: 62 virtual void OnResponseStarted(net::URLRequest* request); 63 virtual void OnReadCompleted(net::URLRequest* request, int bytes_read); 64 65 URLFetcher::Delegate* delegate() const { return delegate_; } 66 67 static void CancelAll(); 68 69 private: 70 friend class base::RefCountedThreadSafe<URLFetcher::Core>; 71 72 class Registry { 73 public: 74 Registry(); 75 ~Registry(); 76 77 void AddURLFetcherCore(Core* core); 78 void RemoveURLFetcherCore(Core* core); 79 80 void CancelAll(); 81 82 int size() const { 83 return fetchers_.size(); 84 } 85 86 private: 87 std::set<Core*> fetchers_; 88 89 DISALLOW_COPY_AND_ASSIGN(Registry); 90 }; 91 92 virtual ~Core(); 93 94 // Wrapper functions that allow us to ensure actions happen on the right 95 // thread. 96 void StartURLRequest(); 97 void StartURLRequestWhenAppropriate(); 98 void CancelURLRequest(); 99 void OnCompletedURLRequest(const net::URLRequestStatus& status); 100 void NotifyMalformedContent(); 101 102 // Deletes the request, removes it from the registry, and removes the 103 // destruction observer. 104 void ReleaseRequest(); 105 106 // Returns the max value of exponential back-off release time for 107 // |original_url_| and |url_|. 108 base::TimeTicks GetBackoffReleaseTime(); 109 110 void CompleteAddingUploadDataChunk(const std::string& data, 111 bool is_last_chunk); 112 113 // Adds a block of data to be uploaded in a POST body. This can only be called 114 // after Start(). 115 void AppendChunkToUpload(const std::string& data, bool is_last_chunk); 116 117 URLFetcher* fetcher_; // Corresponding fetcher object 118 GURL original_url_; // The URL we were asked to fetch 119 GURL url_; // The URL we eventually wound up at 120 RequestType request_type_; // What type of request is this? 121 URLFetcher::Delegate* delegate_; // Object to notify on completion 122 scoped_refptr<base::MessageLoopProxy> delegate_loop_proxy_; 123 // Message loop proxy of the creating 124 // thread. 125 scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy_; 126 // The message loop proxy for the thread 127 // on which the request IO happens. 128 scoped_ptr<net::URLRequest> request_; // The actual request this wraps 129 int load_flags_; // Flags for the load operation 130 int response_code_; // HTTP status code for the request 131 std::string data_; // Results of the request 132 scoped_refptr<net::IOBuffer> buffer_; 133 // Read buffer 134 scoped_refptr<net::URLRequestContextGetter> request_context_getter_; 135 // Cookie/cache info for the request 136 ResponseCookies cookies_; // Response cookies 137 net::HttpRequestHeaders extra_request_headers_; 138 scoped_refptr<net::HttpResponseHeaders> response_headers_; 139 140 std::string upload_content_; // HTTP POST payload 141 std::string upload_content_type_; // MIME type of POST payload 142 std::string referrer_; // HTTP Referer header value 143 bool is_chunked_upload_; // True if using chunked transfer encoding 144 145 // Used to determine how long to wait before making a request or doing a 146 // retry. 147 // Both of them can only be accessed on the IO thread. 148 // We need not only the throttler entry for |original_URL|, but also the one 149 // for |url|. For example, consider the case that URL A redirects to URL B, 150 // for which the server returns a 500 response. In this case, the exponential 151 // back-off release time of URL A won't increase. If we retry without 152 // considering the back-off constraint of URL B, we may send out too many 153 // requests for URL A in a short period of time. 154 scoped_refptr<net::URLRequestThrottlerEntryInterface> 155 original_url_throttler_entry_; 156 scoped_refptr<net::URLRequestThrottlerEntryInterface> url_throttler_entry_; 157 158 // |num_retries_| indicates how many times we've failed to successfully 159 // fetch this URL. Once this value exceeds the maximum number of retries 160 // specified by the owner URLFetcher instance, we'll give up. 161 int num_retries_; 162 163 // True if the URLFetcher has been cancelled. 164 bool was_cancelled_; 165 166 // Since GetBackoffReleaseTime() can only be called on the IO thread, we cache 167 // its value to be used by OnCompletedURLRequest on the creating thread. 168 base::TimeTicks backoff_release_time_; 169 170 static base::LazyInstance<Registry> g_registry; 171 172 friend class URLFetcher; 173 DISALLOW_COPY_AND_ASSIGN(Core); 174 }; 175 176 URLFetcher::Core::Registry::Registry() {} 177 URLFetcher::Core::Registry::~Registry() {} 178 179 void URLFetcher::Core::Registry::AddURLFetcherCore(Core* core) { 180 DCHECK(!ContainsKey(fetchers_, core)); 181 fetchers_.insert(core); 182 } 183 184 void URLFetcher::Core::Registry::RemoveURLFetcherCore(Core* core) { 185 DCHECK(ContainsKey(fetchers_, core)); 186 fetchers_.erase(core); 187 } 188 189 void URLFetcher::Core::Registry::CancelAll() { 190 while (!fetchers_.empty()) 191 (*fetchers_.begin())->CancelURLRequest(); 192 } 193 194 // static 195 base::LazyInstance<URLFetcher::Core::Registry> 196 URLFetcher::Core::g_registry(base::LINKER_INITIALIZED); 197 198 // static 199 URLFetcher::Factory* URLFetcher::factory_ = NULL; 200 201 // static 202 bool URLFetcher::g_interception_enabled = false; 203 204 URLFetcher::URLFetcher(const GURL& url, 205 RequestType request_type, 206 Delegate* d) 207 : ALLOW_THIS_IN_INITIALIZER_LIST( 208 core_(new Core(this, url, request_type, d))), 209 automatically_retry_on_5xx_(true), 210 max_retries_(0) { 211 } 212 213 URLFetcher::~URLFetcher() { 214 core_->Stop(); 215 } 216 217 // static 218 URLFetcher* URLFetcher::Create(int id, const GURL& url, 219 RequestType request_type, Delegate* d) { 220 #ifdef ANDROID 221 // TODO: Upstream. 222 return new URLFetcherProxy(url, request_type, d); 223 #else 224 return factory_ ? factory_->CreateURLFetcher(id, url, request_type, d) : 225 new URLFetcher(url, request_type, d); 226 #endif 227 } 228 229 URLFetcher::Core::Core(URLFetcher* fetcher, 230 const GURL& original_url, 231 RequestType request_type, 232 URLFetcher::Delegate* d) 233 : fetcher_(fetcher), 234 original_url_(original_url), 235 request_type_(request_type), 236 delegate_(d), 237 delegate_loop_proxy_(base::MessageLoopProxy::CreateForCurrentThread()), 238 request_(NULL), 239 load_flags_(net::LOAD_NORMAL), 240 response_code_(-1), 241 buffer_(new net::IOBuffer(kBufferSize)), 242 is_chunked_upload_(false), 243 num_retries_(0), 244 was_cancelled_(false) { 245 } 246 247 URLFetcher::Core::~Core() { 248 // |request_| should be NULL. If not, it's unsafe to delete it here since we 249 // may not be on the IO thread. 250 DCHECK(!request_.get()); 251 } 252 253 void URLFetcher::Core::Start() { 254 DCHECK(delegate_loop_proxy_); 255 CHECK(request_context_getter_) << "We need an URLRequestContext!"; 256 io_message_loop_proxy_ = request_context_getter_->GetIOMessageLoopProxy(); 257 CHECK(io_message_loop_proxy_.get()) << "We need an IO message loop proxy"; 258 259 io_message_loop_proxy_->PostTask( 260 FROM_HERE, 261 NewRunnableMethod(this, &Core::StartURLRequestWhenAppropriate)); 262 } 263 264 void URLFetcher::Core::Stop() { 265 DCHECK(delegate_loop_proxy_->BelongsToCurrentThread()); 266 delegate_ = NULL; 267 fetcher_ = NULL; 268 if (io_message_loop_proxy_.get()) { 269 io_message_loop_proxy_->PostTask( 270 FROM_HERE, NewRunnableMethod(this, &Core::CancelURLRequest)); 271 } 272 } 273 274 void URLFetcher::Core::ReceivedContentWasMalformed() { 275 DCHECK(delegate_loop_proxy_->BelongsToCurrentThread()); 276 if (io_message_loop_proxy_.get()) { 277 io_message_loop_proxy_->PostTask( 278 FROM_HERE, NewRunnableMethod(this, &Core::NotifyMalformedContent)); 279 } 280 } 281 282 void URLFetcher::Core::CancelAll() { 283 g_registry.Get().CancelAll(); 284 } 285 286 void URLFetcher::Core::OnResponseStarted(net::URLRequest* request) { 287 DCHECK_EQ(request, request_.get()); 288 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); 289 if (request_->status().is_success()) { 290 response_code_ = request_->GetResponseCode(); 291 response_headers_ = request_->response_headers(); 292 } 293 294 int bytes_read = 0; 295 // Some servers may treat HEAD requests as GET requests. To free up the 296 // network connection as soon as possible, signal that the request has 297 // completed immediately, without trying to read any data back (all we care 298 // about is the response code and headers, which we already have). 299 if (request_->status().is_success() && (request_type_ != HEAD)) 300 request_->Read(buffer_, kBufferSize, &bytes_read); 301 OnReadCompleted(request_.get(), bytes_read); 302 } 303 304 void URLFetcher::Core::CompleteAddingUploadDataChunk( 305 const std::string& content, bool is_last_chunk) { 306 DCHECK(is_chunked_upload_); 307 DCHECK(request_.get()); 308 DCHECK(!content.empty()); 309 request_->AppendChunkToUpload(content.data(), 310 static_cast<int>(content.length()), 311 is_last_chunk); 312 } 313 314 void URLFetcher::Core::AppendChunkToUpload(const std::string& content, 315 bool is_last_chunk) { 316 DCHECK(delegate_loop_proxy_); 317 CHECK(io_message_loop_proxy_.get()); 318 io_message_loop_proxy_->PostTask( 319 FROM_HERE, 320 NewRunnableMethod(this, &Core::CompleteAddingUploadDataChunk, content, 321 is_last_chunk)); 322 } 323 324 void URLFetcher::Core::OnReadCompleted(net::URLRequest* request, 325 int bytes_read) { 326 DCHECK(request == request_); 327 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); 328 329 url_ = request->url(); 330 url_throttler_entry_ = 331 net::URLRequestThrottlerManager::GetInstance()->RegisterRequestUrl(url_); 332 333 do { 334 if (!request_->status().is_success() || bytes_read <= 0) 335 break; 336 data_.append(buffer_->data(), bytes_read); 337 } while (request_->Read(buffer_, kBufferSize, &bytes_read)); 338 339 if (request_->status().is_success()) 340 request_->GetResponseCookies(&cookies_); 341 342 // See comments re: HEAD requests in OnResponseStarted(). 343 if (!request_->status().is_io_pending() || (request_type_ == HEAD)) { 344 backoff_release_time_ = GetBackoffReleaseTime(); 345 346 bool posted = delegate_loop_proxy_->PostTask( 347 FROM_HERE, 348 NewRunnableMethod(this, 349 &Core::OnCompletedURLRequest, 350 request_->status())); 351 // If the delegate message loop does not exist any more, then the delegate 352 // should be gone too. 353 DCHECK(posted || !delegate_); 354 ReleaseRequest(); 355 } 356 } 357 358 void URLFetcher::Core::StartURLRequest() { 359 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); 360 361 if (was_cancelled_) { 362 // Since StartURLRequest() is posted as a *delayed* task, it may 363 // run after the URLFetcher was already stopped. 364 return; 365 } 366 367 CHECK(request_context_getter_); 368 DCHECK(!request_.get()); 369 370 g_registry.Get().AddURLFetcherCore(this); 371 request_.reset(new net::URLRequest(original_url_, this)); 372 int flags = request_->load_flags() | load_flags_; 373 if (!g_interception_enabled) { 374 flags = flags | net::LOAD_DISABLE_INTERCEPT; 375 } 376 if (is_chunked_upload_) 377 request_->EnableChunkedUpload(); 378 request_->set_load_flags(flags); 379 request_->set_context(request_context_getter_->GetURLRequestContext()); 380 request_->set_referrer(referrer_); 381 382 switch (request_type_) { 383 case GET: 384 break; 385 386 case POST: 387 DCHECK(!upload_content_.empty() || is_chunked_upload_); 388 DCHECK(!upload_content_type_.empty()); 389 390 request_->set_method("POST"); 391 extra_request_headers_.SetHeader(net::HttpRequestHeaders::kContentType, 392 upload_content_type_); 393 if (!upload_content_.empty()) { 394 request_->AppendBytesToUpload( 395 upload_content_.data(), static_cast<int>(upload_content_.length())); 396 } 397 break; 398 399 case HEAD: 400 request_->set_method("HEAD"); 401 break; 402 403 default: 404 NOTREACHED(); 405 } 406 407 if (!extra_request_headers_.IsEmpty()) 408 request_->SetExtraRequestHeaders(extra_request_headers_); 409 410 // There might be data left over from a previous request attempt. 411 data_.clear(); 412 413 request_->Start(); 414 } 415 416 void URLFetcher::Core::StartURLRequestWhenAppropriate() { 417 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); 418 419 if (was_cancelled_) 420 return; 421 422 if (original_url_throttler_entry_ == NULL) { 423 original_url_throttler_entry_ = 424 net::URLRequestThrottlerManager::GetInstance()->RegisterRequestUrl( 425 original_url_); 426 } 427 428 int64 delay = original_url_throttler_entry_->ReserveSendingTimeForNextRequest( 429 GetBackoffReleaseTime()); 430 if (delay == 0) { 431 StartURLRequest(); 432 } else { 433 MessageLoop::current()->PostDelayedTask( 434 FROM_HERE, 435 NewRunnableMethod(this, &Core::StartURLRequest), 436 delay); 437 } 438 } 439 440 void URLFetcher::Core::CancelURLRequest() { 441 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); 442 443 if (request_.get()) { 444 request_->Cancel(); 445 ReleaseRequest(); 446 } 447 // Release the reference to the request context. There could be multiple 448 // references to URLFetcher::Core at this point so it may take a while to 449 // delete the object, but we cannot delay the destruction of the request 450 // context. 451 request_context_getter_ = NULL; 452 was_cancelled_ = true; 453 } 454 455 void URLFetcher::Core::OnCompletedURLRequest( 456 const net::URLRequestStatus& status) { 457 DCHECK(delegate_loop_proxy_->BelongsToCurrentThread()); 458 459 // Checks the response from server. 460 if (response_code_ >= 500 || 461 status.os_error() == net::ERR_TEMPORARILY_THROTTLED) { 462 // When encountering a server error, we will send the request again 463 // after backoff time. 464 ++num_retries_; 465 // Restarts the request if we still need to notify the delegate. 466 if (delegate_) { 467 fetcher_->backoff_delay_ = backoff_release_time_ - base::TimeTicks::Now(); 468 if (fetcher_->backoff_delay_ < base::TimeDelta()) 469 fetcher_->backoff_delay_ = base::TimeDelta(); 470 471 if (fetcher_->automatically_retry_on_5xx_ && 472 num_retries_ <= fetcher_->max_retries()) { 473 io_message_loop_proxy_->PostTask( 474 FROM_HERE, 475 NewRunnableMethod(this, &Core::StartURLRequestWhenAppropriate)); 476 } else { 477 delegate_->OnURLFetchComplete(fetcher_, url_, status, response_code_, 478 cookies_, data_); 479 } 480 } 481 } else { 482 if (delegate_) { 483 fetcher_->backoff_delay_ = base::TimeDelta(); 484 delegate_->OnURLFetchComplete(fetcher_, url_, status, response_code_, 485 cookies_, data_); 486 } 487 } 488 } 489 490 void URLFetcher::Core::NotifyMalformedContent() { 491 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); 492 if (url_throttler_entry_ != NULL) 493 url_throttler_entry_->ReceivedContentWasMalformed(); 494 } 495 496 void URLFetcher::Core::ReleaseRequest() { 497 request_.reset(); 498 g_registry.Get().RemoveURLFetcherCore(this); 499 } 500 501 base::TimeTicks URLFetcher::Core::GetBackoffReleaseTime() { 502 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); 503 DCHECK(original_url_throttler_entry_ != NULL); 504 505 base::TimeTicks original_url_backoff = 506 original_url_throttler_entry_->GetExponentialBackoffReleaseTime(); 507 base::TimeTicks destination_url_backoff; 508 if (url_throttler_entry_ != NULL && 509 original_url_throttler_entry_ != url_throttler_entry_) { 510 destination_url_backoff = 511 url_throttler_entry_->GetExponentialBackoffReleaseTime(); 512 } 513 514 return original_url_backoff > destination_url_backoff ? 515 original_url_backoff : destination_url_backoff; 516 } 517 518 void URLFetcher::set_upload_data(const std::string& upload_content_type, 519 const std::string& upload_content) { 520 DCHECK(!core_->is_chunked_upload_); 521 core_->upload_content_type_ = upload_content_type; 522 core_->upload_content_ = upload_content; 523 } 524 525 void URLFetcher::set_chunked_upload(const std::string& content_type) { 526 DCHECK(core_->is_chunked_upload_ || 527 (core_->upload_content_type_.empty() && 528 core_->upload_content_.empty())); 529 core_->upload_content_type_ = content_type; 530 core_->upload_content_.clear(); 531 core_->is_chunked_upload_ = true; 532 } 533 534 void URLFetcher::AppendChunkToUpload(const std::string& data, 535 bool is_last_chunk) { 536 DCHECK(data.length()); 537 core_->AppendChunkToUpload(data, is_last_chunk); 538 } 539 540 const std::string& URLFetcher::upload_data() const { 541 return core_->upload_content_; 542 } 543 544 void URLFetcher::set_referrer(const std::string& referrer) { 545 core_->referrer_ = referrer; 546 } 547 548 void URLFetcher::set_load_flags(int load_flags) { 549 core_->load_flags_ = load_flags; 550 } 551 552 int URLFetcher::load_flags() const { 553 return core_->load_flags_; 554 } 555 556 void URLFetcher::set_extra_request_headers( 557 const std::string& extra_request_headers) { 558 core_->extra_request_headers_.Clear(); 559 core_->extra_request_headers_.AddHeadersFromString(extra_request_headers); 560 } 561 562 void URLFetcher::set_request_context( 563 net::URLRequestContextGetter* request_context_getter) { 564 core_->request_context_getter_ = request_context_getter; 565 } 566 567 #ifdef ANDROID 568 net::URLRequestContextGetter* URLFetcher::request_context() { 569 return core_->request_context_getter_; 570 } 571 #endif 572 573 void URLFetcher::set_automatically_retry_on_5xx(bool retry) { 574 automatically_retry_on_5xx_ = retry; 575 } 576 577 net::HttpResponseHeaders* URLFetcher::response_headers() const { 578 return core_->response_headers_; 579 } 580 581 void URLFetcher::Start() { 582 core_->Start(); 583 } 584 585 const GURL& URLFetcher::url() const { 586 return core_->url_; 587 } 588 589 void URLFetcher::ReceivedContentWasMalformed() { 590 core_->ReceivedContentWasMalformed(); 591 } 592 593 // static 594 void URLFetcher::CancelAll() { 595 Core::CancelAll(); 596 } 597 598 // static 599 int URLFetcher::GetNumFetcherCores() { 600 return Core::g_registry.Get().size(); 601 } 602 603 URLFetcher::Delegate* URLFetcher::delegate() const { 604 return core_->delegate(); 605 } 606