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/single_thread_task_runner.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "components/cronet/android/url_request_context_adapter.h"
15 #include "components/cronet/android/wrapped_channel_upload_element_reader.h"
16 #include "net/base/elements_upload_data_stream.h"
17 #include "net/base/load_flags.h"
18 #include "net/base/net_errors.h"
19 #include "net/base/upload_bytes_element_reader.h"
20 #include "net/http/http_response_headers.h"
21 #include "net/http/http_status_code.h"
25 static const size_t kBufferSizeIncrement
= 8192;
27 URLRequestAdapter::URLRequestAdapter(URLRequestContextAdapter
* context
,
28 URLRequestAdapterDelegate
* delegate
,
30 net::RequestPriority priority
)
32 read_buffer_(new net::GrowableIOBuffer()),
39 chunked_upload_(false),
40 disable_redirect_(false) {
47 URLRequestAdapter::~URLRequestAdapter() {
48 DCHECK(OnNetworkThread());
49 CHECK(url_request_
== NULL
);
52 void URLRequestAdapter::SetMethod(const std::string
& method
) {
56 void URLRequestAdapter::AddHeader(const std::string
& name
,
57 const std::string
& value
) {
58 headers_
.SetHeader(name
, value
);
61 void URLRequestAdapter::SetUploadContent(const char* bytes
, int bytes_len
) {
62 std::vector
<char> data(bytes
, bytes
+ bytes_len
);
63 scoped_ptr
<net::UploadElementReader
> reader(
64 new net::UploadOwnedBytesElementReader(&data
));
66 net::ElementsUploadDataStream::CreateWithReader(reader
.Pass(), 0);
69 void URLRequestAdapter::SetUploadChannel(JNIEnv
* env
, int64 content_length
) {
70 scoped_ptr
<net::UploadElementReader
> reader(
71 new WrappedChannelElementReader(delegate_
, content_length
));
73 net::ElementsUploadDataStream::CreateWithReader(reader
.Pass(), 0);
76 void URLRequestAdapter::DisableRedirects() {
77 disable_redirect_
= true;
80 void URLRequestAdapter::EnableChunkedUpload() {
81 chunked_upload_
= true;
84 void URLRequestAdapter::AppendChunk(const char* bytes
, int bytes_len
,
86 VLOG(1) << "AppendChunk, len: " << bytes_len
<< ", last: " << is_last_chunk
;
87 scoped_ptr
<char[]> buf(new char[bytes_len
]);
88 memcpy(buf
.get(), bytes
, bytes_len
);
89 context_
->PostTaskToNetworkThread(
91 base::Bind(&URLRequestAdapter::OnAppendChunk
,
92 base::Unretained(this),
98 std::string
URLRequestAdapter::GetHeader(const std::string
& name
) const {
100 if (url_request_
!= NULL
) {
101 url_request_
->GetResponseHeaderByName(name
, &value
);
106 net::HttpResponseHeaders
* URLRequestAdapter::GetResponseHeaders() const {
107 if (url_request_
== NULL
) {
110 return url_request_
->response_headers();
113 std::string
URLRequestAdapter::GetNegotiatedProtocol() const {
114 if (url_request_
== NULL
)
115 return std::string();
116 return url_request_
->response_info().npn_negotiated_protocol
;
119 void URLRequestAdapter::Start() {
120 context_
->PostTaskToNetworkThread(
122 base::Bind(&URLRequestAdapter::OnInitiateConnection
,
123 base::Unretained(this)));
126 void URLRequestAdapter::OnAppendChunk(const scoped_ptr
<char[]> bytes
,
127 int bytes_len
, bool is_last_chunk
) {
128 DCHECK(OnNetworkThread());
129 // Request could have completed and been destroyed on the network thread
130 // while appendChunk was posting the task from an application thread.
132 VLOG(1) << "Cannot append chunk to destroyed request: "
133 << url_
.possibly_invalid_spec().c_str();
136 url_request_
->AppendChunkToUpload(bytes
.get(), bytes_len
, is_last_chunk
);
139 void URLRequestAdapter::OnInitiateConnection() {
140 DCHECK(OnNetworkThread());
145 VLOG(1) << "Starting chromium request: "
146 << url_
.possibly_invalid_spec().c_str()
147 << " priority: " << RequestPriorityToString(priority_
);
148 url_request_
= context_
->GetURLRequestContext()->CreateRequest(
149 url_
, net::DEFAULT_PRIORITY
, this, NULL
);
150 url_request_
->SetLoadFlags(net::LOAD_DISABLE_CACHE
|
151 net::LOAD_DO_NOT_SAVE_COOKIES
|
152 net::LOAD_DO_NOT_SEND_COOKIES
);
153 url_request_
->set_method(method_
);
154 url_request_
->SetExtraRequestHeaders(headers_
);
155 if (!headers_
.HasHeader(net::HttpRequestHeaders::kUserAgent
)) {
156 std::string user_agent
;
157 user_agent
= context_
->GetUserAgent(url_
);
158 url_request_
->SetExtraRequestHeaderByName(
159 net::HttpRequestHeaders::kUserAgent
, user_agent
, true /* override */);
162 if (upload_data_stream_
) {
163 url_request_
->set_upload(upload_data_stream_
.Pass());
164 } else if (chunked_upload_
) {
165 url_request_
->EnableChunkedUpload();
168 url_request_
->SetPriority(priority_
);
170 url_request_
->Start();
173 void URLRequestAdapter::Cancel() {
180 context_
->PostTaskToNetworkThread(
182 base::Bind(&URLRequestAdapter::OnCancelRequest
, base::Unretained(this)));
185 void URLRequestAdapter::OnCancelRequest() {
186 DCHECK(OnNetworkThread());
187 VLOG(1) << "Canceling chromium request: " << url_
.possibly_invalid_spec();
189 if (url_request_
!= NULL
) {
190 url_request_
->Cancel();
196 void URLRequestAdapter::Destroy() {
197 context_
->PostTaskToNetworkThread(
198 FROM_HERE
, base::Bind(&URLRequestAdapter::OnDestroyRequest
, this));
202 void URLRequestAdapter::OnDestroyRequest(URLRequestAdapter
* self
) {
203 DCHECK(self
->OnNetworkThread());
204 VLOG(1) << "Destroying chromium request: "
205 << self
->url_
.possibly_invalid_spec();
210 void URLRequestAdapter::OnResponseStarted(net::URLRequest
* request
) {
211 DCHECK(OnNetworkThread());
212 if (request
->status().status() != net::URLRequestStatus::SUCCESS
) {
217 http_status_code_
= request
->GetResponseCode();
218 VLOG(1) << "Response started with status: " << http_status_code_
;
220 net::HttpResponseHeaders
* headers
= request
->response_headers();
222 http_status_text_
= headers
->GetStatusText();
224 request
->GetResponseHeaderByName("Content-Type", &content_type_
);
225 expected_size_
= request
->GetExpectedContentSize();
226 delegate_
->OnResponseStarted(this);
231 // Reads all available data or starts an asynchronous read.
232 void URLRequestAdapter::Read() {
233 DCHECK(OnNetworkThread());
235 if (read_buffer_
->RemainingCapacity() == 0) {
236 int new_capacity
= read_buffer_
->capacity() + kBufferSizeIncrement
;
237 read_buffer_
->SetCapacity(new_capacity
);
241 if (url_request_
->Read(read_buffer_
.get(),
242 read_buffer_
->RemainingCapacity(),
244 if (bytes_read
== 0) {
245 OnRequestSucceeded();
249 VLOG(1) << "Synchronously read: " << bytes_read
<< " bytes";
250 OnBytesRead(bytes_read
);
251 } else if (url_request_
->status().status() ==
252 net::URLRequestStatus::IO_PENDING
) {
253 if (bytes_read_
!= 0) {
254 VLOG(1) << "Flushing buffer: " << bytes_read_
<< " bytes";
256 delegate_
->OnBytesRead(this);
257 read_buffer_
->set_offset(0);
260 VLOG(1) << "Started async read";
269 void URLRequestAdapter::OnReadCompleted(net::URLRequest
* request
,
271 DCHECK(OnNetworkThread());
272 VLOG(1) << "Asynchronously read: " << bytes_read
<< " bytes";
273 if (bytes_read
< 0) {
276 } else if (bytes_read
== 0) {
277 OnRequestSucceeded();
281 OnBytesRead(bytes_read
);
285 void URLRequestAdapter::OnReceivedRedirect(net::URLRequest
* request
,
286 const net::RedirectInfo
& info
,
287 bool* defer_redirect
) {
288 DCHECK(OnNetworkThread());
289 if (disable_redirect_
) {
290 http_status_code_
= request
->GetResponseCode();
291 request
->CancelWithError(net::ERR_TOO_MANY_REDIRECTS
);
292 error_code_
= net::ERR_TOO_MANY_REDIRECTS
;
294 *defer_redirect
= false;
295 OnRequestCompleted();
299 void URLRequestAdapter::OnBytesRead(int bytes_read
) {
300 DCHECK(OnNetworkThread());
301 read_buffer_
->set_offset(read_buffer_
->offset() + bytes_read
);
302 bytes_read_
+= bytes_read
;
303 total_bytes_read_
+= bytes_read
;
306 void URLRequestAdapter::OnRequestSucceeded() {
307 DCHECK(OnNetworkThread());
312 VLOG(1) << "Request completed with HTTP status: " << http_status_code_
313 << ". Total bytes read: " << total_bytes_read_
;
315 OnRequestCompleted();
318 void URLRequestAdapter::OnRequestFailed() {
319 DCHECK(OnNetworkThread());
324 error_code_
= url_request_
->status().error();
325 VLOG(1) << "Request failed with status: " << url_request_
->status().status()
326 << " and error: " << net::ErrorToString(error_code_
);
327 OnRequestCompleted();
330 void URLRequestAdapter::OnRequestCanceled() {
331 DCHECK(OnNetworkThread());
332 OnRequestCompleted();
335 void URLRequestAdapter::OnRequestCompleted() {
336 DCHECK(OnNetworkThread());
337 VLOG(1) << "Completed: " << url_
.possibly_invalid_spec();
339 delegate_
->OnBytesRead(this);
340 delegate_
->OnRequestFinished(this);
341 url_request_
.reset();
344 unsigned char* URLRequestAdapter::Data() const {
345 DCHECK(OnNetworkThread());
346 return reinterpret_cast<unsigned char*>(read_buffer_
->StartOfBuffer());
349 bool URLRequestAdapter::OnNetworkThread() const {
350 return context_
->GetNetworkTaskRunner()->BelongsToCurrentThread();
353 } // namespace cronet