Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 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/memory/scoped_ptr.h" | 11 #include "base/memory/scoped_ptr.h" |
| 12 #include "base/message_loop_proxy.h" | 12 #include "base/message_loop_proxy.h" |
| 13 #include "base/stl_util-inl.h" | 13 #include "base/stl_util-inl.h" |
| 14 #include "base/string_util.h" | 14 #include "base/string_util.h" |
| 15 #include "base/threading/thread.h" | 15 #include "base/threading/thread.h" |
| 16 #include "googleurl/src/gurl.h" | 16 #include "googleurl/src/gurl.h" |
| 17 #include "net/base/load_flags.h" | 17 #include "net/base/load_flags.h" |
| 18 #include "net/base/io_buffer.h" | 18 #include "net/base/io_buffer.h" |
| 19 #include "net/base/net_errors.h" | 19 #include "net/base/net_errors.h" |
| 20 #include "net/http/http_request_headers.h" | 20 #include "net/http/http_request_headers.h" |
| 21 #include "net/http/http_response_headers.h" | 21 #include "net/http/http_response_headers.h" |
| 22 #include "net/url_request/url_request.h" | 22 #include "net/url_request/url_request.h" |
| 23 #include "net/url_request/url_request_context.h" | 23 #include "net/url_request/url_request_context.h" |
| 24 #include "net/url_request/url_request_context_getter.h" | 24 #include "net/url_request/url_request_context_getter.h" |
| 25 #include "net/url_request/url_request_throttler_manager.h" | 25 #include "net/url_request/url_request_throttler_manager.h" |
| 26 | 26 |
| 27 static const int kBufferSize = 4096; | 27 static const int kBufferSize = 4096; |
| 28 | 28 |
| 29 // Hold the body of a response to a URL fetch in a std::string. | |
| 30 class StringResponseBodyContainer | |
| 31 : public URLFetcher::ResponseBodyContainerInterface { | |
| 32 public: | |
| 33 StringResponseBodyContainer() {} | |
| 34 | |
| 35 virtual void Append(char* data, int data_length) { | |
|
darin (slow to review)
2011/04/28 03:25:17
if the goal is to have an alternative implementati
Sam Kerner (Chrome)
2011/04/28 04:24:58
My plan was to have each call to Append() send a m
| |
| 36 data_.append(data, data_length); | |
| 37 } | |
| 38 | |
| 39 virtual bool GetAsString(std::string* out_body) const { | |
| 40 *out_body = data_; | |
| 41 return true; | |
| 42 } | |
| 43 | |
| 44 private: | |
| 45 std::string data_; | |
| 46 }; | |
| 47 | |
| 48 // Default implementation of OnURLFetchCompleteNew() takes the response | |
| 49 // body, makes it into a string, and calls the old callback. | |
| 50 void URLFetcher::Delegate::OnURLFetchCompleteNew( | |
| 51 const URLFetcher* source, | |
| 52 const GURL& url, | |
| 53 const net::URLRequestStatus& status, | |
| 54 int response_code, | |
| 55 const ResponseCookies& cookies, | |
| 56 const ResponseBodyContainerInterface& response_body) { | |
| 57 | |
| 58 std::string response_data; | |
| 59 | |
| 60 // If the response container doesn't support getting the response as | |
| 61 // a string, then it is not the default string container. The delegate that | |
| 62 // passed in its wn container should have overriden this method and | |
| 63 // dealt with the container itself. | |
| 64 CHECK(response_body.GetAsString(&response_data)); | |
| 65 | |
| 66 // To avoid changing existing code, call the old callback with a string | |
| 67 // holding the response. | |
| 68 OnURLFetchComplete( | |
| 69 source, url, status, response_code, cookies, response_data); | |
| 70 } | |
| 71 | |
| 72 URLFetcher::ResponseBodyContainerInterface* | |
| 73 URLFetcher::Delegate::CreateResponseBodyContainer() { | |
| 74 // If subclass does not override, use a string. | |
| 75 return new StringResponseBodyContainer; | |
| 76 } | |
| 77 | |
| 29 class URLFetcher::Core | 78 class URLFetcher::Core |
| 30 : public base::RefCountedThreadSafe<URLFetcher::Core>, | 79 : public base::RefCountedThreadSafe<URLFetcher::Core>, |
| 31 public net::URLRequest::Delegate { | 80 public net::URLRequest::Delegate { |
| 32 public: | 81 public: |
| 33 // For POST requests, set |content_type| to the MIME type of the content | 82 // For POST requests, set |content_type| to the MIME type of the content |
| 34 // and set |content| to the data to upload. |flags| are flags to apply to | 83 // and set |content| to the data to upload. |flags| are flags to apply to |
| 35 // the load operation--these should be one or more of the LOAD_* flags | 84 // the load operation--these should be one or more of the LOAD_* flags |
| 36 // defined in net/base/load_flags.h. | 85 // defined in net/base/load_flags.h. |
| 37 Core(URLFetcher* fetcher, | 86 Core(URLFetcher* fetcher, |
| 38 const GURL& original_url, | 87 const GURL& original_url, |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 117 URLFetcher::Delegate* delegate_; // Object to notify on completion | 166 URLFetcher::Delegate* delegate_; // Object to notify on completion |
| 118 scoped_refptr<base::MessageLoopProxy> delegate_loop_proxy_; | 167 scoped_refptr<base::MessageLoopProxy> delegate_loop_proxy_; |
| 119 // Message loop proxy of the creating | 168 // Message loop proxy of the creating |
| 120 // thread. | 169 // thread. |
| 121 scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy_; | 170 scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy_; |
| 122 // The message loop proxy for the thread | 171 // The message loop proxy for the thread |
| 123 // on which the request IO happens. | 172 // on which the request IO happens. |
| 124 scoped_ptr<net::URLRequest> request_; // The actual request this wraps | 173 scoped_ptr<net::URLRequest> request_; // The actual request this wraps |
| 125 int load_flags_; // Flags for the load operation | 174 int load_flags_; // Flags for the load operation |
| 126 int response_code_; // HTTP status code for the request | 175 int response_code_; // HTTP status code for the request |
| 127 std::string data_; // Results of the request | 176 scoped_ptr<ResponseBodyContainerInterface> response_body_; |
| 177 // Results of the request | |
| 128 scoped_refptr<net::IOBuffer> buffer_; | 178 scoped_refptr<net::IOBuffer> buffer_; |
| 129 // Read buffer | 179 // Read buffer |
| 130 scoped_refptr<net::URLRequestContextGetter> request_context_getter_; | 180 scoped_refptr<net::URLRequestContextGetter> request_context_getter_; |
| 131 // Cookie/cache info for the request | 181 // Cookie/cache info for the request |
| 132 ResponseCookies cookies_; // Response cookies | 182 ResponseCookies cookies_; // Response cookies |
| 133 net::HttpRequestHeaders extra_request_headers_; | 183 net::HttpRequestHeaders extra_request_headers_; |
| 134 scoped_refptr<net::HttpResponseHeaders> response_headers_; | 184 scoped_refptr<net::HttpResponseHeaders> response_headers_; |
| 135 | 185 |
| 136 std::string upload_content_; // HTTP POST payload | 186 std::string upload_content_; // HTTP POST payload |
| 137 std::string upload_content_type_; // MIME type of POST payload | 187 std::string upload_content_type_; // MIME type of POST payload |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 317 DCHECK(request == request_); | 367 DCHECK(request == request_); |
| 318 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); | 368 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); |
| 319 | 369 |
| 320 url_ = request->url(); | 370 url_ = request->url(); |
| 321 url_throttler_entry_ = | 371 url_throttler_entry_ = |
| 322 net::URLRequestThrottlerManager::GetInstance()->RegisterRequestUrl(url_); | 372 net::URLRequestThrottlerManager::GetInstance()->RegisterRequestUrl(url_); |
| 323 | 373 |
| 324 do { | 374 do { |
| 325 if (!request_->status().is_success() || bytes_read <= 0) | 375 if (!request_->status().is_success() || bytes_read <= 0) |
| 326 break; | 376 break; |
| 327 data_.append(buffer_->data(), bytes_read); | 377 response_body_->Append(buffer_->data(), bytes_read); |
| 328 } while (request_->Read(buffer_, kBufferSize, &bytes_read)); | 378 } while (request_->Read(buffer_, kBufferSize, &bytes_read)); |
| 329 | 379 |
| 330 if (request_->status().is_success()) | 380 if (request_->status().is_success()) |
| 331 request_->GetResponseCookies(&cookies_); | 381 request_->GetResponseCookies(&cookies_); |
| 332 | 382 |
| 333 // See comments re: HEAD requests in OnResponseStarted(). | 383 // See comments re: HEAD requests in OnResponseStarted(). |
| 334 if (!request_->status().is_io_pending() || (request_type_ == HEAD)) { | 384 if (!request_->status().is_io_pending() || (request_type_ == HEAD)) { |
| 335 backoff_release_time_ = GetBackoffReleaseTime(); | 385 backoff_release_time_ = GetBackoffReleaseTime(); |
| 336 | 386 |
| 337 bool posted = delegate_loop_proxy_->PostTask( | 387 bool posted = delegate_loop_proxy_->PostTask( |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 392 break; | 442 break; |
| 393 | 443 |
| 394 default: | 444 default: |
| 395 NOTREACHED(); | 445 NOTREACHED(); |
| 396 } | 446 } |
| 397 | 447 |
| 398 if (!extra_request_headers_.IsEmpty()) | 448 if (!extra_request_headers_.IsEmpty()) |
| 399 request_->SetExtraRequestHeaders(extra_request_headers_); | 449 request_->SetExtraRequestHeaders(extra_request_headers_); |
| 400 | 450 |
| 401 // There might be data left over from a previous request attempt. | 451 // There might be data left over from a previous request attempt. |
| 402 data_.clear(); | 452 response_body_.reset(delegate_->CreateResponseBodyContainer()); |
| 403 | 453 |
| 404 request_->Start(); | 454 request_->Start(); |
| 405 } | 455 } |
| 406 | 456 |
| 407 void URLFetcher::Core::StartURLRequestWhenAppropriate() { | 457 void URLFetcher::Core::StartURLRequestWhenAppropriate() { |
| 408 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); | 458 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); |
| 409 | 459 |
| 410 if (was_cancelled_) | 460 if (was_cancelled_) |
| 411 return; | 461 return; |
| 412 | 462 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 458 fetcher_->backoff_delay_ = backoff_release_time_ - base::TimeTicks::Now(); | 508 fetcher_->backoff_delay_ = backoff_release_time_ - base::TimeTicks::Now(); |
| 459 if (fetcher_->backoff_delay_ < base::TimeDelta()) | 509 if (fetcher_->backoff_delay_ < base::TimeDelta()) |
| 460 fetcher_->backoff_delay_ = base::TimeDelta(); | 510 fetcher_->backoff_delay_ = base::TimeDelta(); |
| 461 | 511 |
| 462 if (fetcher_->automatically_retry_on_5xx_ && | 512 if (fetcher_->automatically_retry_on_5xx_ && |
| 463 num_retries_ <= fetcher_->max_retries()) { | 513 num_retries_ <= fetcher_->max_retries()) { |
| 464 io_message_loop_proxy_->PostTask( | 514 io_message_loop_proxy_->PostTask( |
| 465 FROM_HERE, | 515 FROM_HERE, |
| 466 NewRunnableMethod(this, &Core::StartURLRequestWhenAppropriate)); | 516 NewRunnableMethod(this, &Core::StartURLRequestWhenAppropriate)); |
| 467 } else { | 517 } else { |
| 468 delegate_->OnURLFetchComplete(fetcher_, url_, status, response_code_, | 518 delegate_->OnURLFetchCompleteNew(fetcher_, url_, status, response_code_, |
| 469 cookies_, data_); | 519 cookies_, *response_body_); |
| 470 } | 520 } |
| 471 } | 521 } |
| 472 } else { | 522 } else { |
| 473 if (delegate_) { | 523 if (delegate_) { |
| 474 fetcher_->backoff_delay_ = base::TimeDelta(); | 524 fetcher_->backoff_delay_ = base::TimeDelta(); |
| 475 delegate_->OnURLFetchComplete(fetcher_, url_, status, response_code_, | 525 delegate_->OnURLFetchCompleteNew(fetcher_, url_, status, response_code_, |
| 476 cookies_, data_); | 526 cookies_, *response_body_); |
| 477 } | 527 } |
| 478 } | 528 } |
| 479 } | 529 } |
| 480 | 530 |
| 481 void URLFetcher::Core::NotifyMalformedContent() { | 531 void URLFetcher::Core::NotifyMalformedContent() { |
| 482 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); | 532 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); |
| 483 if (url_throttler_entry_ != NULL) | 533 if (url_throttler_entry_ != NULL) |
| 484 url_throttler_entry_->ReceivedContentWasMalformed(); | 534 url_throttler_entry_->ReceivedContentWasMalformed(); |
| 485 } | 535 } |
| 486 | 536 |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 581 } | 631 } |
| 582 | 632 |
| 583 // static | 633 // static |
| 584 int URLFetcher::GetNumFetcherCores() { | 634 int URLFetcher::GetNumFetcherCores() { |
| 585 return Core::g_registry.Get().size(); | 635 return Core::g_registry.Get().size(); |
| 586 } | 636 } |
| 587 | 637 |
| 588 URLFetcher::Delegate* URLFetcher::delegate() const { | 638 URLFetcher::Delegate* URLFetcher::delegate() const { |
| 589 return core_->delegate(); | 639 return core_->delegate(); |
| 590 } | 640 } |
| OLD | NEW |