Index: chrome/common/net/url_fetcher.cc |
diff --git a/chrome/common/net/url_fetcher.cc b/chrome/common/net/url_fetcher.cc |
index ddccff1a347c486de39ade641f527c75be371d28..30c18fbbd6d5227900a5356d79f93c8dbc51e76c 100644 |
--- a/chrome/common/net/url_fetcher.cc |
+++ b/chrome/common/net/url_fetcher.cc |
@@ -101,6 +101,12 @@ class URLFetcher::Core |
// |original_url_| and |url_|. |
base::TimeTicks GetBackoffReleaseTime(); |
+ void CompleteAddingUploadDataChunk(const std::string& data); |
+ |
+ // Adds a block of data to be uploaded in a POST body. This can only be called |
+ // after Start(). |
+ void AppendChunkToUpload(const std::string& data); |
+ |
URLFetcher* fetcher_; // Corresponding fetcher object |
GURL original_url_; // The URL we were asked to fetch |
GURL url_; // The URL we eventually wound up at |
@@ -127,6 +133,7 @@ class URLFetcher::Core |
std::string upload_content_; // HTTP POST payload |
std::string upload_content_type_; // MIME type of POST payload |
std::string referrer_; // HTTP Referer header value |
+ bool is_chunked_upload_; // True if using chunked transfer encoding |
// Used to determine how long to wait before making a request or doing a |
// retry. |
@@ -221,6 +228,7 @@ URLFetcher::Core::Core(URLFetcher* fetcher, |
load_flags_(net::LOAD_NORMAL), |
response_code_(-1), |
buffer_(new net::IOBuffer(kBufferSize)), |
+ is_chunked_upload_(false), |
num_retries_(0), |
was_cancelled_(false) { |
} |
@@ -282,6 +290,26 @@ void URLFetcher::Core::OnResponseStarted(net::URLRequest* request) { |
OnReadCompleted(request_.get(), bytes_read); |
} |
+void URLFetcher::Core::CompleteAddingUploadDataChunk( |
+ const std::string& content) { |
+ DCHECK(is_chunked_upload_); |
+ DCHECK(request_.get()); |
+ if (content.length()) { |
+ request_->AppendChunkToUpload(content.data(), |
+ static_cast<int>(content.length())); |
+ } else { |
+ request_->MarkEndOfChunks(); |
+ } |
+} |
+ |
+void URLFetcher::Core::AppendChunkToUpload(const std::string& content) { |
+ DCHECK(delegate_loop_proxy_); |
+ CHECK(io_message_loop_proxy_.get()); |
+ io_message_loop_proxy_->PostTask( |
+ FROM_HERE, |
+ NewRunnableMethod(this, &Core::CompleteAddingUploadDataChunk, content)); |
+} |
+ |
void URLFetcher::Core::OnReadCompleted(net::URLRequest* request, |
int bytes_read) { |
DCHECK(request == request_); |
@@ -334,6 +362,8 @@ void URLFetcher::Core::StartURLRequest() { |
if (!g_interception_enabled) { |
flags = flags | net::LOAD_DISABLE_INTERCEPT; |
} |
+ if (is_chunked_upload_) |
+ request_->EnableChunkedUpload(); |
request_->set_load_flags(flags); |
request_->set_context(request_context_getter_->GetURLRequestContext()); |
request_->set_referrer(referrer_); |
@@ -343,14 +373,16 @@ void URLFetcher::Core::StartURLRequest() { |
break; |
case POST: |
- DCHECK(!upload_content_.empty()); |
+ DCHECK(!upload_content_.empty() || is_chunked_upload_); |
DCHECK(!upload_content_type_.empty()); |
request_->set_method("POST"); |
extra_request_headers_.SetHeader(net::HttpRequestHeaders::kContentType, |
upload_content_type_); |
- request_->AppendBytesToUpload(upload_content_.data(), |
- static_cast<int>(upload_content_.size())); |
+ if (!upload_content_.empty()) { |
+ request_->AppendBytesToUpload( |
+ upload_content_.data(), static_cast<int>(upload_content_.length())); |
+ } |
break; |
case HEAD: |
@@ -474,10 +506,29 @@ base::TimeTicks URLFetcher::Core::GetBackoffReleaseTime() { |
void URLFetcher::set_upload_data(const std::string& upload_content_type, |
const std::string& upload_content) { |
+ DCHECK(!core_->is_chunked_upload_); |
core_->upload_content_type_ = upload_content_type; |
core_->upload_content_ = upload_content; |
} |
+void URLFetcher::set_chunked_upload(const std::string& content_type) { |
+ DCHECK(core_->is_chunked_upload_ || |
+ (core_->upload_content_type_.empty() && |
+ core_->upload_content_.empty())); |
+ core_->upload_content_type_ = content_type; |
+ core_->upload_content_.clear(); |
+ core_->is_chunked_upload_ = true; |
+} |
+ |
+void URLFetcher::AppendChunkToUpload(const std::string& data) { |
+ DCHECK(data.length()); |
+ core_->AppendChunkToUpload(data); |
+} |
+ |
+void URLFetcher::MarkEndOfChunks() { |
+ core_->AppendChunkToUpload(std::string()); |
+} |
+ |
const std::string& URLFetcher::upload_data() const { |
return core_->upload_content_; |
} |