Explicitly add python-numpy dependency to install-build-deps.
[chromium-blink-merge.git] / components / cronet / android / url_request_adapter.cc
blob5d8f84965fc9c59dc616399aa77d4637234728f8
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 <string.h>
9 #include "base/bind.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"
23 namespace cronet {
25 static const size_t kBufferSizeIncrement = 8192;
27 URLRequestAdapter::URLRequestAdapter(URLRequestContextAdapter* context,
28 URLRequestAdapterDelegate* delegate,
29 GURL url,
30 net::RequestPriority priority)
31 : method_("GET"),
32 read_buffer_(new net::GrowableIOBuffer()),
33 bytes_read_(0),
34 total_bytes_read_(0),
35 error_code_(0),
36 http_status_code_(0),
37 canceled_(false),
38 expected_size_(0),
39 chunked_upload_(false),
40 disable_redirect_(false) {
41 context_ = context;
42 delegate_ = delegate;
43 url_ = url;
44 priority_ = priority;
47 URLRequestAdapter::~URLRequestAdapter() {
48 DCHECK(OnNetworkThread());
49 CHECK(url_request_ == NULL);
52 void URLRequestAdapter::SetMethod(const std::string& method) {
53 method_ = 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));
65 upload_data_stream_ =
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));
72 upload_data_stream_ =
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,
85 bool is_last_chunk) {
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(
90 FROM_HERE,
91 base::Bind(&URLRequestAdapter::OnAppendChunk,
92 base::Unretained(this),
93 Passed(buf.Pass()),
94 bytes_len,
95 is_last_chunk));
98 std::string URLRequestAdapter::GetHeader(const std::string& name) const {
99 std::string value;
100 if (url_request_ != NULL) {
101 url_request_->GetResponseHeaderByName(name, &value);
103 return value;
106 net::HttpResponseHeaders* URLRequestAdapter::GetResponseHeaders() const {
107 if (url_request_ == NULL) {
108 return 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(
121 FROM_HERE,
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.
131 if (!url_request_) {
132 VLOG(1) << "Cannot append chunk to destroyed request: "
133 << url_.possibly_invalid_spec().c_str();
134 return;
136 url_request_->AppendChunkToUpload(bytes.get(), bytes_len, is_last_chunk);
139 void URLRequestAdapter::OnInitiateConnection() {
140 DCHECK(OnNetworkThread());
141 if (canceled_) {
142 return;
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() {
174 if (canceled_) {
175 return;
178 canceled_ = true;
180 context_->PostTaskToNetworkThread(
181 FROM_HERE,
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();
193 OnRequestCanceled();
196 void URLRequestAdapter::Destroy() {
197 context_->PostTaskToNetworkThread(
198 FROM_HERE, base::Bind(&URLRequestAdapter::OnDestroyRequest, this));
201 // static
202 void URLRequestAdapter::OnDestroyRequest(URLRequestAdapter* self) {
203 DCHECK(self->OnNetworkThread());
204 VLOG(1) << "Destroying chromium request: "
205 << self->url_.possibly_invalid_spec();
206 delete self;
209 // static
210 void URLRequestAdapter::OnResponseStarted(net::URLRequest* request) {
211 DCHECK(OnNetworkThread());
212 if (request->status().status() != net::URLRequestStatus::SUCCESS) {
213 OnRequestFailed();
214 return;
217 http_status_code_ = request->GetResponseCode();
218 VLOG(1) << "Response started with status: " << http_status_code_;
220 net::HttpResponseHeaders* headers = request->response_headers();
221 if (headers)
222 http_status_text_ = headers->GetStatusText();
224 request->GetResponseHeaderByName("Content-Type", &content_type_);
225 expected_size_ = request->GetExpectedContentSize();
226 delegate_->OnResponseStarted(this);
228 Read();
231 // Reads all available data or starts an asynchronous read.
232 void URLRequestAdapter::Read() {
233 DCHECK(OnNetworkThread());
234 while (true) {
235 if (read_buffer_->RemainingCapacity() == 0) {
236 int new_capacity = read_buffer_->capacity() + kBufferSizeIncrement;
237 read_buffer_->SetCapacity(new_capacity);
240 int bytes_read;
241 if (url_request_->Read(read_buffer_.get(),
242 read_buffer_->RemainingCapacity(),
243 &bytes_read)) {
244 if (bytes_read == 0) {
245 OnRequestSucceeded();
246 break;
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);
258 bytes_read_ = 0;
260 VLOG(1) << "Started async read";
261 break;
262 } else {
263 OnRequestFailed();
264 break;
269 void URLRequestAdapter::OnReadCompleted(net::URLRequest* request,
270 int bytes_read) {
271 DCHECK(OnNetworkThread());
272 VLOG(1) << "Asynchronously read: " << bytes_read << " bytes";
273 if (bytes_read < 0) {
274 OnRequestFailed();
275 return;
276 } else if (bytes_read == 0) {
277 OnRequestSucceeded();
278 return;
281 OnBytesRead(bytes_read);
282 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;
293 canceled_ = true;
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());
308 if (canceled_) {
309 return;
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());
320 if (canceled_) {
321 return;
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