Home | History | Annotate | Download | only in android
      1 // Copyright 2014 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 "url_request_adapter.h"
      6 
      7 #include <string.h>
      8 
      9 #include "base/bind.h"
     10 #include "base/location.h"
     11 #include "base/logging.h"
     12 #include "base/strings/string_number_conversions.h"
     13 #include "components/cronet/android/url_request_context_adapter.h"
     14 #include "components/cronet/android/wrapped_channel_upload_element_reader.h"
     15 #include "net/base/load_flags.h"
     16 #include "net/base/upload_bytes_element_reader.h"
     17 #include "net/http/http_status_code.h"
     18 
     19 namespace cronet {
     20 
     21 static const size_t kBufferSizeIncrement = 8192;
     22 
     23 URLRequestAdapter::URLRequestAdapter(URLRequestContextAdapter* context,
     24                                      URLRequestAdapterDelegate* delegate,
     25                                      GURL url,
     26                                      net::RequestPriority priority)
     27     : method_("GET"),
     28       read_buffer_(new net::GrowableIOBuffer()),
     29       bytes_read_(0),
     30       total_bytes_read_(0),
     31       error_code_(0),
     32       http_status_code_(0),
     33       canceled_(false),
     34       expected_size_(0),
     35       chunked_upload_(false) {
     36   context_ = context;
     37   delegate_ = delegate;
     38   url_ = url;
     39   priority_ = priority;
     40 }
     41 
     42 URLRequestAdapter::~URLRequestAdapter() {
     43   CHECK(url_request_ == NULL);
     44 }
     45 
     46 void URLRequestAdapter::SetMethod(const std::string& method) {
     47   method_ = method;
     48 }
     49 
     50 void URLRequestAdapter::AddHeader(const std::string& name,
     51                                   const std::string& value) {
     52   headers_.SetHeader(name, value);
     53 }
     54 
     55 void URLRequestAdapter::SetUploadContent(const char* bytes, int bytes_len) {
     56   std::vector<char> data(bytes, bytes + bytes_len);
     57   scoped_ptr<net::UploadElementReader> reader(
     58       new net::UploadOwnedBytesElementReader(&data));
     59   upload_data_stream_.reset(
     60       net::UploadDataStream::CreateWithReader(reader.Pass(), 0));
     61 }
     62 
     63 void URLRequestAdapter::SetUploadChannel(JNIEnv* env, int64 content_length) {
     64   scoped_ptr<net::UploadElementReader> reader(
     65       new WrappedChannelElementReader(delegate_, content_length));
     66   upload_data_stream_.reset(
     67       net::UploadDataStream::CreateWithReader(reader.Pass(), 0));
     68 }
     69 
     70 void URLRequestAdapter::EnableChunkedUpload() {
     71   chunked_upload_ = true;
     72 }
     73 
     74 void URLRequestAdapter::AppendChunk(const char* bytes, int bytes_len,
     75                                     bool is_last_chunk) {
     76   VLOG(1) << "AppendChunk, len: " << bytes_len << ", last: " << is_last_chunk;
     77   scoped_ptr<char[]> buf(new char[bytes_len]);
     78   memcpy(buf.get(), bytes, bytes_len);
     79   context_->GetNetworkTaskRunner()->PostTask(
     80       FROM_HERE,
     81       base::Bind(&URLRequestAdapter::OnAppendChunk,
     82                  base::Unretained(this),
     83                  Passed(buf.Pass()),
     84                  bytes_len,
     85                  is_last_chunk));
     86 }
     87 
     88 std::string URLRequestAdapter::GetHeader(const std::string& name) const {
     89   std::string value;
     90   if (url_request_ != NULL) {
     91     url_request_->GetResponseHeaderByName(name, &value);
     92   }
     93   return value;
     94 }
     95 
     96 net::HttpResponseHeaders* URLRequestAdapter::GetResponseHeaders() const {
     97   if (url_request_ == NULL) {
     98     return NULL;
     99   }
    100   return url_request_->response_headers();
    101 }
    102 
    103 std::string URLRequestAdapter::GetNegotiatedProtocol() const {
    104   if (url_request_ == NULL)
    105     return std::string();
    106   return url_request_->response_info().npn_negotiated_protocol;
    107 }
    108 
    109 void URLRequestAdapter::Start() {
    110   context_->GetNetworkTaskRunner()->PostTask(
    111       FROM_HERE,
    112       base::Bind(&URLRequestAdapter::OnInitiateConnection,
    113                  base::Unretained(this)));
    114 }
    115 
    116 void URLRequestAdapter::OnAppendChunk(const scoped_ptr<char[]> bytes,
    117                                       int bytes_len, bool is_last_chunk) {
    118   url_request_->AppendChunkToUpload(bytes.get(), bytes_len, is_last_chunk);
    119 }
    120 
    121 void URLRequestAdapter::OnInitiateConnection() {
    122   if (canceled_) {
    123     return;
    124   }
    125 
    126   VLOG(1) << "Starting chromium request: "
    127           << url_.possibly_invalid_spec().c_str()
    128           << " priority: " << RequestPriorityToString(priority_);
    129   url_request_ = context_->GetURLRequestContext()->CreateRequest(
    130       url_, net::DEFAULT_PRIORITY, this, NULL);
    131   url_request_->SetLoadFlags(net::LOAD_DISABLE_CACHE |
    132                              net::LOAD_DO_NOT_SAVE_COOKIES |
    133                              net::LOAD_DO_NOT_SEND_COOKIES);
    134   url_request_->set_method(method_);
    135   url_request_->SetExtraRequestHeaders(headers_);
    136   if (!headers_.HasHeader(net::HttpRequestHeaders::kUserAgent)) {
    137     std::string user_agent;
    138     user_agent = context_->GetUserAgent(url_);
    139     url_request_->SetExtraRequestHeaderByName(
    140         net::HttpRequestHeaders::kUserAgent, user_agent, true /* override */);
    141   }
    142 
    143   if (upload_data_stream_) {
    144     url_request_->set_upload(upload_data_stream_.Pass());
    145   } else if (chunked_upload_) {
    146     url_request_->EnableChunkedUpload();
    147   }
    148 
    149   url_request_->SetPriority(priority_);
    150 
    151   url_request_->Start();
    152 }
    153 
    154 void URLRequestAdapter::Cancel() {
    155   if (canceled_) {
    156     return;
    157   }
    158 
    159   canceled_ = true;
    160 
    161   context_->GetNetworkTaskRunner()->PostTask(
    162       FROM_HERE,
    163       base::Bind(&URLRequestAdapter::OnCancelRequest, base::Unretained(this)));
    164 }
    165 
    166 void URLRequestAdapter::OnCancelRequest() {
    167   VLOG(1) << "Canceling chromium request: " << url_.possibly_invalid_spec();
    168 
    169   if (url_request_ != NULL) {
    170     url_request_->Cancel();
    171   }
    172 
    173   OnRequestCanceled();
    174 }
    175 
    176 void URLRequestAdapter::Destroy() {
    177   context_->GetNetworkTaskRunner()->PostTask(
    178       FROM_HERE, base::Bind(&URLRequestAdapter::OnDestroyRequest, this));
    179 }
    180 
    181 // static
    182 void URLRequestAdapter::OnDestroyRequest(URLRequestAdapter* self) {
    183   VLOG(1) << "Destroying chromium request: "
    184           << self->url_.possibly_invalid_spec();
    185   delete self;
    186 }
    187 
    188 void URLRequestAdapter::OnResponseStarted(net::URLRequest* request) {
    189   if (request->status().status() != net::URLRequestStatus::SUCCESS) {
    190     OnRequestFailed();
    191     return;
    192   }
    193 
    194   http_status_code_ = request->GetResponseCode();
    195   VLOG(1) << "Response started with status: " << http_status_code_;
    196 
    197   request->GetResponseHeaderByName("Content-Type", &content_type_);
    198   expected_size_ = request->GetExpectedContentSize();
    199   delegate_->OnResponseStarted(this);
    200 
    201   Read();
    202 }
    203 
    204 // Reads all available data or starts an asynchronous read.
    205 void URLRequestAdapter::Read() {
    206   while (true) {
    207     if (read_buffer_->RemainingCapacity() == 0) {
    208       int new_capacity = read_buffer_->capacity() + kBufferSizeIncrement;
    209       read_buffer_->SetCapacity(new_capacity);
    210     }
    211 
    212     int bytes_read;
    213     if (url_request_->Read(
    214             read_buffer_, read_buffer_->RemainingCapacity(), &bytes_read)) {
    215       if (bytes_read == 0) {
    216         OnRequestSucceeded();
    217         break;
    218       }
    219 
    220       VLOG(1) << "Synchronously read: " << bytes_read << " bytes";
    221       OnBytesRead(bytes_read);
    222     } else if (url_request_->status().status() ==
    223                net::URLRequestStatus::IO_PENDING) {
    224       if (bytes_read_ != 0) {
    225         VLOG(1) << "Flushing buffer: " << bytes_read_ << " bytes";
    226 
    227         delegate_->OnBytesRead(this);
    228         read_buffer_->set_offset(0);
    229         bytes_read_ = 0;
    230       }
    231       VLOG(1) << "Started async read";
    232       break;
    233     } else {
    234       OnRequestFailed();
    235       break;
    236     }
    237   }
    238 }
    239 
    240 void URLRequestAdapter::OnReadCompleted(net::URLRequest* request,
    241                                         int bytes_read) {
    242   VLOG(1) << "Asynchronously read: " << bytes_read << " bytes";
    243   if (bytes_read < 0) {
    244     OnRequestFailed();
    245     return;
    246   } else if (bytes_read == 0) {
    247     OnRequestSucceeded();
    248     return;
    249   }
    250 
    251   OnBytesRead(bytes_read);
    252   Read();
    253 }
    254 
    255 void URLRequestAdapter::OnBytesRead(int bytes_read) {
    256   read_buffer_->set_offset(read_buffer_->offset() + bytes_read);
    257   bytes_read_ += bytes_read;
    258   total_bytes_read_ += bytes_read;
    259 }
    260 
    261 void URLRequestAdapter::OnRequestSucceeded() {
    262   if (canceled_) {
    263     return;
    264   }
    265 
    266   VLOG(1) << "Request completed with HTTP status: " << http_status_code_
    267           << ". Total bytes read: " << total_bytes_read_;
    268 
    269   OnRequestCompleted();
    270 }
    271 
    272 void URLRequestAdapter::OnRequestFailed() {
    273   if (canceled_) {
    274     return;
    275   }
    276 
    277   error_code_ = url_request_->status().error();
    278   VLOG(1) << "Request failed with status: " << url_request_->status().status()
    279           << " and error: " << net::ErrorToString(error_code_);
    280   OnRequestCompleted();
    281 }
    282 
    283 void URLRequestAdapter::OnRequestCanceled() {
    284   OnRequestCompleted();
    285 }
    286 
    287 void URLRequestAdapter::OnRequestCompleted() {
    288   VLOG(1) << "Completed: " << url_.possibly_invalid_spec();
    289   url_request_.reset();
    290 
    291   delegate_->OnBytesRead(this);
    292   delegate_->OnRequestFinished(this);
    293 }
    294 
    295 unsigned char* URLRequestAdapter::Data() const {
    296   return reinterpret_cast<unsigned char*>(read_buffer_->StartOfBuffer());
    297 }
    298 
    299 }  // namespace cronet
    300