OLD | NEW |
| (Empty) |
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_peer.h" | |
6 | |
7 #include "base/strings/string_number_conversions.h" | |
8 #include "components/cronet/android/url_request_context_peer.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" | |
13 | |
14 namespace cronet { | |
15 | |
16 static const size_t kBufferSizeIncrement = 8192; | |
17 | |
18 URLRequestPeer::URLRequestPeer(URLRequestContextPeer* context, | |
19 URLRequestPeerDelegate* delegate, | |
20 GURL url, | |
21 net::RequestPriority priority) | |
22 : method_("GET"), | |
23 url_request_(NULL), | |
24 read_buffer_(new net::GrowableIOBuffer()), | |
25 bytes_read_(0), | |
26 total_bytes_read_(0), | |
27 error_code_(0), | |
28 http_status_code_(0), | |
29 canceled_(false), | |
30 expected_size_(0) { | |
31 context_ = context; | |
32 delegate_ = delegate; | |
33 url_ = url; | |
34 priority_ = priority; | |
35 } | |
36 | |
37 URLRequestPeer::~URLRequestPeer() { CHECK(url_request_ == NULL); } | |
38 | |
39 void URLRequestPeer::SetMethod(const std::string& method) { method_ = method; } | |
40 | |
41 void URLRequestPeer::AddHeader(const std::string& name, | |
42 const std::string& value) { | |
43 headers_.SetHeader(name, value); | |
44 } | |
45 | |
46 void URLRequestPeer::SetUploadContent(const char* bytes, int bytes_len) { | |
47 std::vector<char> data(bytes, bytes + bytes_len); | |
48 scoped_ptr<net::UploadElementReader> reader( | |
49 new net::UploadOwnedBytesElementReader(&data)); | |
50 upload_data_stream_.reset(net::UploadDataStream::CreateWithReader( | |
51 reader.Pass(), 0)); | |
52 } | |
53 | |
54 void URLRequestPeer::SetUploadChannel(JNIEnv* env, int64 content_length) { | |
55 scoped_ptr<net::UploadElementReader> reader( | |
56 new WrappedChannelElementReader(delegate_, content_length)); | |
57 upload_data_stream_.reset(net::UploadDataStream::CreateWithReader( | |
58 reader.Pass(), 0)); | |
59 } | |
60 | |
61 std::string URLRequestPeer::GetHeader(const std::string &name) const { | |
62 std::string value; | |
63 if (url_request_ != NULL) { | |
64 url_request_->GetResponseHeaderByName(name, &value); | |
65 } | |
66 return value; | |
67 } | |
68 | |
69 net::HttpResponseHeaders* URLRequestPeer::GetResponseHeaders() const { | |
70 if (url_request_ == NULL) { | |
71 return NULL; | |
72 } | |
73 return url_request_->response_headers(); | |
74 } | |
75 | |
76 void URLRequestPeer::Start() { | |
77 context_->GetNetworkTaskRunner()->PostTask( | |
78 FROM_HERE, | |
79 base::Bind(&URLRequestPeer::OnInitiateConnection, | |
80 base::Unretained(this))); | |
81 } | |
82 | |
83 void URLRequestPeer::OnInitiateConnection() { | |
84 if (canceled_) { | |
85 return; | |
86 } | |
87 | |
88 VLOG(1) << "Starting chromium request: " | |
89 << url_.possibly_invalid_spec().c_str() | |
90 << " priority: " << RequestPriorityToString(priority_); | |
91 url_request_ = new net::URLRequest( | |
92 url_, net::DEFAULT_PRIORITY, this, context_->GetURLRequestContext()); | |
93 url_request_->SetLoadFlags(net::LOAD_DISABLE_CACHE | | |
94 net::LOAD_DO_NOT_SAVE_COOKIES | | |
95 net::LOAD_DO_NOT_SEND_COOKIES); | |
96 url_request_->set_method(method_); | |
97 url_request_->SetExtraRequestHeaders(headers_); | |
98 if (!headers_.HasHeader(net::HttpRequestHeaders::kUserAgent)) { | |
99 std::string user_agent; | |
100 user_agent = context_->GetUserAgent(url_); | |
101 url_request_->SetExtraRequestHeaderByName( | |
102 net::HttpRequestHeaders::kUserAgent, user_agent, true /* override */); | |
103 } | |
104 | |
105 if (upload_data_stream_) | |
106 url_request_->set_upload(upload_data_stream_.Pass()); | |
107 | |
108 url_request_->SetPriority(priority_); | |
109 | |
110 url_request_->Start(); | |
111 } | |
112 | |
113 void URLRequestPeer::Cancel() { | |
114 if (canceled_) { | |
115 return; | |
116 } | |
117 | |
118 canceled_ = true; | |
119 | |
120 context_->GetNetworkTaskRunner()->PostTask( | |
121 FROM_HERE, | |
122 base::Bind(&URLRequestPeer::OnCancelRequest, base::Unretained(this))); | |
123 } | |
124 | |
125 void URLRequestPeer::OnCancelRequest() { | |
126 VLOG(1) << "Canceling chromium request: " << url_.possibly_invalid_spec(); | |
127 | |
128 if (url_request_ != NULL) { | |
129 url_request_->Cancel(); | |
130 } | |
131 | |
132 OnRequestCanceled(); | |
133 } | |
134 | |
135 void URLRequestPeer::Destroy() { | |
136 context_->GetNetworkTaskRunner()->PostTask( | |
137 FROM_HERE, base::Bind(&URLRequestPeer::OnDestroyRequest, this)); | |
138 } | |
139 | |
140 // static | |
141 void URLRequestPeer::OnDestroyRequest(URLRequestPeer* self) { | |
142 VLOG(1) << "Destroying chromium request: " | |
143 << self->url_.possibly_invalid_spec(); | |
144 delete self; | |
145 } | |
146 | |
147 void URLRequestPeer::OnResponseStarted(net::URLRequest* request) { | |
148 if (request->status().status() != net::URLRequestStatus::SUCCESS) { | |
149 OnRequestFailed(); | |
150 return; | |
151 } | |
152 | |
153 http_status_code_ = request->GetResponseCode(); | |
154 VLOG(1) << "Response started with status: " << http_status_code_; | |
155 | |
156 request->GetResponseHeaderByName("Content-Type", &content_type_); | |
157 expected_size_ = request->GetExpectedContentSize(); | |
158 delegate_->OnResponseStarted(this); | |
159 | |
160 Read(); | |
161 } | |
162 | |
163 // Reads all available data or starts an asynchronous read. | |
164 void URLRequestPeer::Read() { | |
165 while (true) { | |
166 if (read_buffer_->RemainingCapacity() == 0) { | |
167 int new_capacity = read_buffer_->capacity() + kBufferSizeIncrement; | |
168 read_buffer_->SetCapacity(new_capacity); | |
169 } | |
170 | |
171 int bytes_read; | |
172 if (url_request_->Read( | |
173 read_buffer_, read_buffer_->RemainingCapacity(), &bytes_read)) { | |
174 if (bytes_read == 0) { | |
175 OnRequestSucceeded(); | |
176 break; | |
177 } | |
178 | |
179 VLOG(1) << "Synchronously read: " << bytes_read << " bytes"; | |
180 OnBytesRead(bytes_read); | |
181 } else if (url_request_->status().status() == | |
182 net::URLRequestStatus::IO_PENDING) { | |
183 if (bytes_read_ != 0) { | |
184 VLOG(1) << "Flushing buffer: " << bytes_read_ << " bytes"; | |
185 | |
186 delegate_->OnBytesRead(this); | |
187 read_buffer_->set_offset(0); | |
188 bytes_read_ = 0; | |
189 } | |
190 VLOG(1) << "Started async read"; | |
191 break; | |
192 } else { | |
193 OnRequestFailed(); | |
194 break; | |
195 } | |
196 } | |
197 } | |
198 | |
199 void URLRequestPeer::OnReadCompleted(net::URLRequest* request, int bytes_read) { | |
200 VLOG(1) << "Asynchronously read: " << bytes_read << " bytes"; | |
201 if (bytes_read < 0) { | |
202 OnRequestFailed(); | |
203 return; | |
204 } else if (bytes_read == 0) { | |
205 OnRequestSucceeded(); | |
206 return; | |
207 } | |
208 | |
209 OnBytesRead(bytes_read); | |
210 Read(); | |
211 } | |
212 | |
213 void URLRequestPeer::OnBytesRead(int bytes_read) { | |
214 read_buffer_->set_offset(read_buffer_->offset() + bytes_read); | |
215 bytes_read_ += bytes_read; | |
216 total_bytes_read_ += bytes_read; | |
217 } | |
218 | |
219 void URLRequestPeer::OnRequestSucceeded() { | |
220 if (canceled_) { | |
221 return; | |
222 } | |
223 | |
224 VLOG(1) << "Request completed with HTTP status: " << http_status_code_ | |
225 << ". Total bytes read: " << total_bytes_read_; | |
226 | |
227 OnRequestCompleted(); | |
228 } | |
229 | |
230 void URLRequestPeer::OnRequestFailed() { | |
231 if (canceled_) { | |
232 return; | |
233 } | |
234 | |
235 error_code_ = url_request_->status().error(); | |
236 VLOG(1) << "Request failed with status: " << url_request_->status().status() | |
237 << " and error: " << net::ErrorToString(error_code_); | |
238 OnRequestCompleted(); | |
239 } | |
240 | |
241 void URLRequestPeer::OnRequestCanceled() { OnRequestCompleted(); } | |
242 | |
243 void URLRequestPeer::OnRequestCompleted() { | |
244 VLOG(1) << "Completed: " << url_.possibly_invalid_spec(); | |
245 if (url_request_ != NULL) { | |
246 delete url_request_; | |
247 url_request_ = NULL; | |
248 } | |
249 | |
250 delegate_->OnBytesRead(this); | |
251 delegate_->OnRequestFinished(this); | |
252 } | |
253 | |
254 unsigned char* URLRequestPeer::Data() const { | |
255 return reinterpret_cast<unsigned char*>(read_buffer_->StartOfBuffer()); | |
256 } | |
257 | |
258 } // namespace cronet | |
OLD | NEW |