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.
5 #include "url_request_adapter.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"
21 static const size_t kBufferSizeIncrement
= 8192;
23 URLRequestAdapter::URLRequestAdapter(URLRequestContextAdapter
* context
,
24 URLRequestAdapterDelegate
* delegate
,
26 net::RequestPriority priority
)
28 read_buffer_(new net::GrowableIOBuffer()),
35 chunked_upload_(false) {
42 URLRequestAdapter::~URLRequestAdapter() {
43 CHECK(url_request_
== NULL
);
46 void URLRequestAdapter::SetMethod(const std::string
& method
) {
50 void URLRequestAdapter::AddHeader(const std::string
& name
,
51 const std::string
& value
) {
52 headers_
.SetHeader(name
, value
);
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));
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));
70 void URLRequestAdapter::EnableChunkedUpload() {
71 chunked_upload_
= true;
74 void URLRequestAdapter::AppendChunk(const char* bytes
, int bytes_len
,
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(
81 base::Bind(&URLRequestAdapter::OnAppendChunk
,
82 base::Unretained(this),
88 std::string
URLRequestAdapter::GetHeader(const std::string
& name
) const {
90 if (url_request_
!= NULL
) {
91 url_request_
->GetResponseHeaderByName(name
, &value
);
96 net::HttpResponseHeaders
* URLRequestAdapter::GetResponseHeaders() const {
97 if (url_request_
== NULL
) {
100 return url_request_
->response_headers();
103 void URLRequestAdapter::Start() {
104 context_
->GetNetworkTaskRunner()->PostTask(
106 base::Bind(&URLRequestAdapter::OnInitiateConnection
,
107 base::Unretained(this)));
110 void URLRequestAdapter::OnAppendChunk(const scoped_ptr
<char[]> bytes
,
111 int bytes_len
, bool is_last_chunk
) {
112 url_request_
->AppendChunkToUpload(bytes
.get(), bytes_len
, is_last_chunk
);
115 void URLRequestAdapter::OnInitiateConnection() {
120 VLOG(1) << "Starting chromium request: "
121 << url_
.possibly_invalid_spec().c_str()
122 << " priority: " << RequestPriorityToString(priority_
);
123 url_request_
= context_
->GetURLRequestContext()->CreateRequest(
124 url_
, net::DEFAULT_PRIORITY
, this, NULL
);
125 url_request_
->SetLoadFlags(net::LOAD_DISABLE_CACHE
|
126 net::LOAD_DO_NOT_SAVE_COOKIES
|
127 net::LOAD_DO_NOT_SEND_COOKIES
);
128 url_request_
->set_method(method_
);
129 url_request_
->SetExtraRequestHeaders(headers_
);
130 if (!headers_
.HasHeader(net::HttpRequestHeaders::kUserAgent
)) {
131 std::string user_agent
;
132 user_agent
= context_
->GetUserAgent(url_
);
133 url_request_
->SetExtraRequestHeaderByName(
134 net::HttpRequestHeaders::kUserAgent
, user_agent
, true /* override */);
137 if (upload_data_stream_
) {
138 url_request_
->set_upload(upload_data_stream_
.Pass());
139 } else if (chunked_upload_
) {
140 url_request_
->EnableChunkedUpload();
143 url_request_
->SetPriority(priority_
);
145 url_request_
->Start();
148 void URLRequestAdapter::Cancel() {
155 context_
->GetNetworkTaskRunner()->PostTask(
157 base::Bind(&URLRequestAdapter::OnCancelRequest
, base::Unretained(this)));
160 void URLRequestAdapter::OnCancelRequest() {
161 VLOG(1) << "Canceling chromium request: " << url_
.possibly_invalid_spec();
163 if (url_request_
!= NULL
) {
164 url_request_
->Cancel();
170 void URLRequestAdapter::Destroy() {
171 context_
->GetNetworkTaskRunner()->PostTask(
172 FROM_HERE
, base::Bind(&URLRequestAdapter::OnDestroyRequest
, this));
176 void URLRequestAdapter::OnDestroyRequest(URLRequestAdapter
* self
) {
177 VLOG(1) << "Destroying chromium request: "
178 << self
->url_
.possibly_invalid_spec();
182 void URLRequestAdapter::OnResponseStarted(net::URLRequest
* request
) {
183 if (request
->status().status() != net::URLRequestStatus::SUCCESS
) {
188 http_status_code_
= request
->GetResponseCode();
189 VLOG(1) << "Response started with status: " << http_status_code_
;
191 request
->GetResponseHeaderByName("Content-Type", &content_type_
);
192 expected_size_
= request
->GetExpectedContentSize();
193 delegate_
->OnResponseStarted(this);
198 // Reads all available data or starts an asynchronous read.
199 void URLRequestAdapter::Read() {
201 if (read_buffer_
->RemainingCapacity() == 0) {
202 int new_capacity
= read_buffer_
->capacity() + kBufferSizeIncrement
;
203 read_buffer_
->SetCapacity(new_capacity
);
207 if (url_request_
->Read(
208 read_buffer_
, read_buffer_
->RemainingCapacity(), &bytes_read
)) {
209 if (bytes_read
== 0) {
210 OnRequestSucceeded();
214 VLOG(1) << "Synchronously read: " << bytes_read
<< " bytes";
215 OnBytesRead(bytes_read
);
216 } else if (url_request_
->status().status() ==
217 net::URLRequestStatus::IO_PENDING
) {
218 if (bytes_read_
!= 0) {
219 VLOG(1) << "Flushing buffer: " << bytes_read_
<< " bytes";
221 delegate_
->OnBytesRead(this);
222 read_buffer_
->set_offset(0);
225 VLOG(1) << "Started async read";
234 void URLRequestAdapter::OnReadCompleted(net::URLRequest
* request
,
236 VLOG(1) << "Asynchronously read: " << bytes_read
<< " bytes";
237 if (bytes_read
< 0) {
240 } else if (bytes_read
== 0) {
241 OnRequestSucceeded();
245 OnBytesRead(bytes_read
);
249 void URLRequestAdapter::OnBytesRead(int bytes_read
) {
250 read_buffer_
->set_offset(read_buffer_
->offset() + bytes_read
);
251 bytes_read_
+= bytes_read
;
252 total_bytes_read_
+= bytes_read
;
255 void URLRequestAdapter::OnRequestSucceeded() {
260 VLOG(1) << "Request completed with HTTP status: " << http_status_code_
261 << ". Total bytes read: " << total_bytes_read_
;
263 OnRequestCompleted();
266 void URLRequestAdapter::OnRequestFailed() {
271 error_code_
= url_request_
->status().error();
272 VLOG(1) << "Request failed with status: " << url_request_
->status().status()
273 << " and error: " << net::ErrorToString(error_code_
);
274 OnRequestCompleted();
277 void URLRequestAdapter::OnRequestCanceled() {
278 OnRequestCompleted();
281 void URLRequestAdapter::OnRequestCompleted() {
282 VLOG(1) << "Completed: " << url_
.possibly_invalid_spec();
283 url_request_
.reset();
285 delegate_
->OnBytesRead(this);
286 delegate_
->OnRequestFinished(this);
289 unsigned char* URLRequestAdapter::Data() const {
290 return reinterpret_cast<unsigned char*>(read_buffer_
->StartOfBuffer());
293 } // namespace cronet