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"
7 #include "base/strings/string_number_conversions.h"
8 #include "components/cronet/android/url_request_context_adapter.h"
9 #include "components/cronet/android/wrapped_channel_upload_element_reader.h"
10 #include "net/base/load_flags.h"
11 #include "net/base/upload_bytes_element_reader.h"
12 #include "net/http/http_status_code.h"
16 static const size_t kBufferSizeIncrement
= 8192;
18 URLRequestAdapter::URLRequestAdapter(URLRequestContextAdapter
* context
,
19 URLRequestAdapterDelegate
* delegate
,
21 net::RequestPriority priority
)
24 read_buffer_(new net::GrowableIOBuffer()),
37 URLRequestAdapter::~URLRequestAdapter() {
38 CHECK(url_request_
== NULL
);
41 void URLRequestAdapter::SetMethod(const std::string
& method
) {
45 void URLRequestAdapter::AddHeader(const std::string
& name
,
46 const std::string
& value
) {
47 headers_
.SetHeader(name
, value
);
50 void URLRequestAdapter::SetUploadContent(const char* bytes
, int bytes_len
) {
51 std::vector
<char> data(bytes
, bytes
+ bytes_len
);
52 scoped_ptr
<net::UploadElementReader
> reader(
53 new net::UploadOwnedBytesElementReader(&data
));
54 upload_data_stream_
.reset(
55 net::UploadDataStream::CreateWithReader(reader
.Pass(), 0));
58 void URLRequestAdapter::SetUploadChannel(JNIEnv
* env
, int64 content_length
) {
59 scoped_ptr
<net::UploadElementReader
> reader(
60 new WrappedChannelElementReader(delegate_
, content_length
));
61 upload_data_stream_
.reset(
62 net::UploadDataStream::CreateWithReader(reader
.Pass(), 0));
65 std::string
URLRequestAdapter::GetHeader(const std::string
& name
) const {
67 if (url_request_
!= NULL
) {
68 url_request_
->GetResponseHeaderByName(name
, &value
);
73 net::HttpResponseHeaders
* URLRequestAdapter::GetResponseHeaders() const {
74 if (url_request_
== NULL
) {
77 return url_request_
->response_headers();
80 void URLRequestAdapter::Start() {
81 context_
->GetNetworkTaskRunner()->PostTask(
83 base::Bind(&URLRequestAdapter::OnInitiateConnection
,
84 base::Unretained(this)));
87 void URLRequestAdapter::OnInitiateConnection() {
92 VLOG(1) << "Starting chromium request: "
93 << url_
.possibly_invalid_spec().c_str()
94 << " priority: " << RequestPriorityToString(priority_
);
95 url_request_
= new net::URLRequest(
96 url_
, net::DEFAULT_PRIORITY
, this, context_
->GetURLRequestContext());
97 url_request_
->SetLoadFlags(net::LOAD_DISABLE_CACHE
|
98 net::LOAD_DO_NOT_SAVE_COOKIES
|
99 net::LOAD_DO_NOT_SEND_COOKIES
);
100 url_request_
->set_method(method_
);
101 url_request_
->SetExtraRequestHeaders(headers_
);
102 if (!headers_
.HasHeader(net::HttpRequestHeaders::kUserAgent
)) {
103 std::string user_agent
;
104 user_agent
= context_
->GetUserAgent(url_
);
105 url_request_
->SetExtraRequestHeaderByName(
106 net::HttpRequestHeaders::kUserAgent
, user_agent
, true /* override */);
109 if (upload_data_stream_
)
110 url_request_
->set_upload(upload_data_stream_
.Pass());
112 url_request_
->SetPriority(priority_
);
114 url_request_
->Start();
117 void URLRequestAdapter::Cancel() {
124 context_
->GetNetworkTaskRunner()->PostTask(
126 base::Bind(&URLRequestAdapter::OnCancelRequest
, base::Unretained(this)));
129 void URLRequestAdapter::OnCancelRequest() {
130 VLOG(1) << "Canceling chromium request: " << url_
.possibly_invalid_spec();
132 if (url_request_
!= NULL
) {
133 url_request_
->Cancel();
139 void URLRequestAdapter::Destroy() {
140 context_
->GetNetworkTaskRunner()->PostTask(
141 FROM_HERE
, base::Bind(&URLRequestAdapter::OnDestroyRequest
, this));
145 void URLRequestAdapter::OnDestroyRequest(URLRequestAdapter
* self
) {
146 VLOG(1) << "Destroying chromium request: "
147 << self
->url_
.possibly_invalid_spec();
151 void URLRequestAdapter::OnResponseStarted(net::URLRequest
* request
) {
152 if (request
->status().status() != net::URLRequestStatus::SUCCESS
) {
157 http_status_code_
= request
->GetResponseCode();
158 VLOG(1) << "Response started with status: " << http_status_code_
;
160 request
->GetResponseHeaderByName("Content-Type", &content_type_
);
161 expected_size_
= request
->GetExpectedContentSize();
162 delegate_
->OnResponseStarted(this);
167 // Reads all available data or starts an asynchronous read.
168 void URLRequestAdapter::Read() {
170 if (read_buffer_
->RemainingCapacity() == 0) {
171 int new_capacity
= read_buffer_
->capacity() + kBufferSizeIncrement
;
172 read_buffer_
->SetCapacity(new_capacity
);
176 if (url_request_
->Read(
177 read_buffer_
, read_buffer_
->RemainingCapacity(), &bytes_read
)) {
178 if (bytes_read
== 0) {
179 OnRequestSucceeded();
183 VLOG(1) << "Synchronously read: " << bytes_read
<< " bytes";
184 OnBytesRead(bytes_read
);
185 } else if (url_request_
->status().status() ==
186 net::URLRequestStatus::IO_PENDING
) {
187 if (bytes_read_
!= 0) {
188 VLOG(1) << "Flushing buffer: " << bytes_read_
<< " bytes";
190 delegate_
->OnBytesRead(this);
191 read_buffer_
->set_offset(0);
194 VLOG(1) << "Started async read";
203 void URLRequestAdapter::OnReadCompleted(net::URLRequest
* request
,
205 VLOG(1) << "Asynchronously read: " << bytes_read
<< " bytes";
206 if (bytes_read
< 0) {
209 } else if (bytes_read
== 0) {
210 OnRequestSucceeded();
214 OnBytesRead(bytes_read
);
218 void URLRequestAdapter::OnBytesRead(int bytes_read
) {
219 read_buffer_
->set_offset(read_buffer_
->offset() + bytes_read
);
220 bytes_read_
+= bytes_read
;
221 total_bytes_read_
+= bytes_read
;
224 void URLRequestAdapter::OnRequestSucceeded() {
229 VLOG(1) << "Request completed with HTTP status: " << http_status_code_
230 << ". Total bytes read: " << total_bytes_read_
;
232 OnRequestCompleted();
235 void URLRequestAdapter::OnRequestFailed() {
240 error_code_
= url_request_
->status().error();
241 VLOG(1) << "Request failed with status: " << url_request_
->status().status()
242 << " and error: " << net::ErrorToString(error_code_
);
243 OnRequestCompleted();
246 void URLRequestAdapter::OnRequestCanceled() {
247 OnRequestCompleted();
250 void URLRequestAdapter::OnRequestCompleted() {
251 VLOG(1) << "Completed: " << url_
.possibly_invalid_spec();
252 if (url_request_
!= NULL
) {
257 delegate_
->OnBytesRead(this);
258 delegate_
->OnRequestFinished(this);
261 unsigned char* URLRequestAdapter::Data() const {
262 return reinterpret_cast<unsigned char*>(read_buffer_
->StartOfBuffer());
265 } // namespace cronet