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