Chromium Code Reviews| Index: net/cronet/android/url_request_peer.cc |
| diff --git a/net/cronet/android/url_request_peer.cc b/net/cronet/android/url_request_peer.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..4f1bba11e9502c7fa51a548b63ab7a0cfcc391f0 |
| --- /dev/null |
| +++ b/net/cronet/android/url_request_peer.cc |
| @@ -0,0 +1,322 @@ |
| +// Copyright 2014 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "url_request_peer.h" |
| + |
| +#include "base/strings/string_number_conversions.h" |
| +#include "net/base/load_flags.h" |
| +#include "net/http/http_status_code.h" |
| + |
| +static const size_t kBufferSizeIncrement = 8192; |
| + |
| +// Fragment automatically inserted in the User-Agent header to indicate |
| +// that the request is coming from this network stack. |
| +static const char kUserAgentFragment[] = "; ChromiumJNI/"; |
| + |
| +URLRequestPeer::URLRequestPeer(URLRequestContextPeer *context, |
| + URLRequestPeerDelegate *delegate, GURL url, |
| + net::RequestPriority priority) |
| + : method_("GET"), |
| + url_request_(NULL), |
| + read_buffer_(new net::GrowableIOBuffer()), |
| + bytes_read_(0), |
| + total_bytes_read_(0), |
| + error_code_(0), |
| + http_status_code_(0), |
| + canceled_(false), |
| + expected_size_(0), |
| + streaming_upload_(false) { |
| + context_ = context; |
| + delegate_ = delegate; |
| + url_ = url; |
| + priority_ = priority; |
| +} |
| + |
| +URLRequestPeer::~URLRequestPeer() { |
| + CHECK(url_request_ == NULL); |
| +} |
| + |
| +void URLRequestPeer::SetMethod(const std::string &method) { |
| + method_ = method; |
| +} |
| + |
| +void URLRequestPeer::AddHeader(const std::string &name, |
| + const std::string &value) { |
| + headers_.SetHeader(name, value); |
| +} |
| + |
| +void URLRequestPeer::SetPostContent(const char *bytes, int bytes_len) { |
| + if (!upload_data_stream_) { |
| + upload_data_stream_.reset( |
| + new net::UploadDataStream(net::UploadDataStream::CHUNKED, 0)); |
| + } |
| + upload_data_stream_->AppendChunk(bytes, bytes_len, true /* is_last_chunk */); |
| +} |
| + |
| +void URLRequestPeer::EnableStreamingUpload() { |
| + streaming_upload_ = true; |
| +} |
| + |
| +void URLRequestPeer::AppendChunk(const char *bytes, int bytes_len, |
| + bool is_last_chunk) { |
| + VLOG(context_->logging_level()) |
| + << "AppendChunk, len: " << bytes_len << ", last: " << is_last_chunk; |
| + |
| + context_->GetNetworkTaskRunner()->PostTask( |
| + FROM_HERE, base::Bind(&URLRequestPeer::OnAppendChunkWrapper, this, |
| + bytes, bytes_len, is_last_chunk)); |
| +} |
| + |
| +GURL URLRequestPeer::url() const { |
| + return url_; |
| +} |
| + |
| +int URLRequestPeer::error_code() const { |
| + return error_code_; |
| +} |
| + |
| +int URLRequestPeer::http_status_code() const { |
| + return http_status_code_; |
| +} |
| + |
| +int64 URLRequestPeer::content_length() const { |
| + return expected_size_; |
| +} |
| + |
| +std::string URLRequestPeer::content_type() const { |
| + return content_type_; |
| +} |
| + |
| +void URLRequestPeer::Start() { |
| + context_->GetNetworkTaskRunner()->PostTask( |
| + FROM_HERE, |
| + base::Bind(&URLRequestPeer::OnInitiateConnectionWrapper, this)); |
| +} |
| + |
| +/* static */ |
|
mmenke
2014/02/27 23:06:02
C++-style comments
mef
2014/03/03 19:15:13
Done.
|
| +void URLRequestPeer::OnAppendChunkWrapper(URLRequestPeer *self, |
| + const char *bytes, |
| + int bytes_len, |
| + bool is_last_chunk) { |
| + self->OnAppendChunk(bytes, bytes_len, is_last_chunk); |
| +} |
| + |
| +void URLRequestPeer::OnAppendChunk(const char *bytes, int bytes_len, |
| + bool is_last_chunk) { |
| + if (url_request_ != NULL) { |
| + url_request_->AppendChunkToUpload(bytes, bytes_len, is_last_chunk); |
| + delegate_->OnAppendChunkCompleted(this); |
| + } |
| +} |
| + |
| +/* static */ |
|
mmenke
2014/02/27 23:06:02
C++-style comments
mef
2014/03/03 19:15:13
Done.
|
| +void URLRequestPeer::OnInitiateConnectionWrapper(URLRequestPeer *self) { |
| + self->OnInitiateConnection(); |
| +} |
| + |
| +void URLRequestPeer::OnInitiateConnection() { |
| + if (canceled_) { |
| + return; |
| + } |
| + |
| + VLOG(context_->logging_level()) |
| + << "Starting chromium request: " << url_.possibly_invalid_spec().c_str() |
| + << " priority: " << RequestPriorityToString(priority_); |
| + url_request_ = |
| + new net::URLRequest(url_, |
| + net::DEFAULT_PRIORITY, |
| + this, |
| + context_->GetURLRequestContext()); |
| + url_request_->SetLoadFlags(net::LOAD_DISABLE_CACHE | |
| + net::LOAD_DO_NOT_SAVE_COOKIES | |
| + net::LOAD_DO_NOT_SEND_COOKIES); |
| + url_request_->set_method(method_); |
| + url_request_->SetExtraRequestHeaders(headers_); |
| + std::string user_agent; |
| + if (headers_.HasHeader(net::HttpRequestHeaders::kUserAgent)) { |
| + headers_.GetHeader(net::HttpRequestHeaders::kUserAgent, &user_agent); |
| + } else { |
| + user_agent = context_->GetUserAgent(url_); |
| + } |
| + size_t pos = user_agent.find(')'); |
| + if (pos != std::string::npos) { |
| + user_agent.insert(pos, context_->version()); |
| + user_agent.insert(pos, kUserAgentFragment); |
| + } |
| + url_request_->SetExtraRequestHeaderByName(net::HttpRequestHeaders::kUserAgent, |
| + user_agent, true /* override */); |
| + |
| + VLOG(context_->logging_level()) << "User agent: " << user_agent; |
| + |
| + if (upload_data_stream_) { |
| + url_request_->set_upload(make_scoped_ptr(upload_data_stream_.release())); |
| + } else if (streaming_upload_) { |
| + url_request_->EnableChunkedUpload(); |
| + } |
| + |
| + url_request_->SetPriority(priority_); |
| + |
| + url_request_->Start(); |
| +} |
| + |
| +void URLRequestPeer::Cancel() { |
| + if (canceled_) { |
| + return; |
| + } |
| + |
| + canceled_ = true; |
| + |
| + context_->GetNetworkTaskRunner()->PostTask( |
| + FROM_HERE, base::Bind(&URLRequestPeer::OnCancelRequestWrapper, this)); |
| +} |
| + |
| +/* static */ |
| +void URLRequestPeer::OnCancelRequestWrapper(URLRequestPeer *self) { |
|
mmenke
2014/02/27 23:06:02
URLRequestPeer* self
mef
2014/03/03 19:15:13
Done.
|
| + self->OnCancelRequest(); |
| +} |
| + |
| +void URLRequestPeer::OnCancelRequest() { |
| + VLOG(context_->logging_level()) |
| + << "Canceling chromium request: " << url_.possibly_invalid_spec(); |
| + |
| + if (url_request_ != NULL) { |
| + url_request_->Cancel(); |
| + } |
| + |
| + OnRequestCanceled(); |
| +} |
| + |
| +void URLRequestPeer::Destroy() { |
| + context_->GetNetworkTaskRunner()->PostTask( |
| + FROM_HERE, base::Bind(&URLRequestPeer::OnDestroyRequest, this)); |
| +} |
| + |
| +/* static */ |
| +void URLRequestPeer::OnDestroyRequest(URLRequestPeer *self) { |
|
mmenke
2014/02/27 23:06:02
URLRequestPeer* self
mef
2014/03/03 19:15:13
Done.
|
| + VLOG(self->context_->logging_level()) |
| + << "Destroying chromium request: " << self->url_.possibly_invalid_spec(); |
| + delete self; |
| +} |
| + |
| +void URLRequestPeer::OnResponseStarted(net::URLRequest *request) { |
|
mmenke
2014/02/27 23:06:02
net::URLRequest* request
mef
2014/03/03 19:15:13
Done.
|
| + if (request->status().status() != net::URLRequestStatus::SUCCESS) { |
| + OnRequestFailed(); |
| + return; |
| + } |
| + |
| + http_status_code_ = request->GetResponseCode(); |
| + VLOG(context_->logging_level()) |
| + << "Response started with status: " << http_status_code_; |
| + |
| + request->GetResponseHeaderByName("Content-Type", &content_type_); |
| + expected_size_ = request->GetExpectedContentSize(); |
| + delegate_->OnResponseStarted(this); |
| + |
| + Read(); |
| +} |
| + |
| +/* |
| + * Reads all available data or starts an asynchronous read. |
| + */ |
|
mmenke
2014/02/27 23:06:02
C++ style comments
mef
2014/03/03 19:15:13
Done.
|
| +void URLRequestPeer::Read() { |
| + while (1) { |
|
mmenke
2014/02/27 23:06:02
while (true)
mef
2014/03/03 19:15:13
Done.
|
| + if (read_buffer_->RemainingCapacity() == 0) { |
| + int new_capacity = read_buffer_->capacity() + kBufferSizeIncrement; |
| + read_buffer_->SetCapacity(new_capacity); |
| + } |
| + |
| + int bytes_read; |
| + if (url_request_->Read(read_buffer_, read_buffer_->RemainingCapacity(), |
| + &bytes_read)) { |
| + if (bytes_read == 0) { |
| + OnRequestSucceeded(); |
| + break; |
| + } |
| + |
| + VLOG(context_->logging_level()) |
| + << "Synchronously read: " << bytes_read << " bytes"; |
| + OnBytesRead(bytes_read); |
| + } else if (url_request_->status().status() == |
| + net::URLRequestStatus::IO_PENDING) { |
| + if (bytes_read_ != 0) { |
| + VLOG(context_->logging_level()) |
| + << "Flushing buffer: " << bytes_read_ << " bytes"; |
| + |
| + delegate_->OnBytesRead(this); |
| + read_buffer_->set_offset(0); |
| + bytes_read_ = 0; |
| + } |
| + VLOG(context_->logging_level()) << "Started async read" ; |
| + break; |
| + } else { |
| + OnRequestFailed(); |
| + break; |
| + } |
| + } |
| +} |
| + |
| +void URLRequestPeer::OnReadCompleted(net::URLRequest *request, int bytes_read) { |
| + VLOG(context_->logging_level()) |
| + << "Asynchronously read: " << bytes_read << " bytes"; |
| + if (bytes_read < 0) { |
| + OnRequestFailed(); |
| + return; |
| + } else if (bytes_read == 0) { |
| + OnRequestSucceeded(); |
| + return; |
| + } |
| + |
| + OnBytesRead(bytes_read); |
| + Read(); |
| +} |
| + |
| +void URLRequestPeer::OnBytesRead(int bytes_read) { |
| + read_buffer_->set_offset(read_buffer_->offset() + bytes_read); |
| + bytes_read_ += bytes_read; |
| + total_bytes_read_ += bytes_read; |
| +} |
| + |
| +void URLRequestPeer::OnRequestSucceeded() { |
| + if (canceled_) { |
| + return; |
| + } |
| + |
| + VLOG(context_->logging_level()) |
| + << "Request completed with HTTP status: " << http_status_code_ |
| + << ". Total bytes read: " << total_bytes_read_; |
| + |
| + OnRequestCompleted(); |
| +} |
| + |
| +void URLRequestPeer::OnRequestFailed() { |
| + if (canceled_) { |
| + return; |
| + } |
| + |
| + error_code_ = url_request_->status().error(); |
| + VLOG(context_->logging_level()) |
| + << "Request failed with status: " << url_request_->status().status() |
| + << " and error: " << net::ErrorToString(error_code_); |
| + OnRequestCompleted(); |
| +} |
| + |
| +void URLRequestPeer::OnRequestCanceled() { OnRequestCompleted(); } |
| + |
| +void URLRequestPeer::OnRequestCompleted() { |
| + VLOG(context_->logging_level()) |
| + << "Completed: " << url_.possibly_invalid_spec(); |
| + if (url_request_ != NULL) { |
| + delete url_request_; |
| + url_request_ = NULL; |
| + } |
| + |
| + delegate_->OnBytesRead(this); |
| + delegate_->OnRequestFinished(this); |
| +} |
| + |
| +size_t URLRequestPeer::BytesRead() const { return bytes_read_; } |
|
mmenke
2014/02/27 23:06:02
Inline and rename to bytes_read?
mef
2014/03/03 19:15:13
Done.
|
| + |
| +unsigned char *URLRequestPeer::Data() const { |
| + return reinterpret_cast<unsigned char *>(read_buffer_->StartOfBuffer()); |
|
mmenke
2014/02/27 23:06:02
<unsigned char*>
mef
2014/03/03 19:15:13
Done.
|
| +} |