Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(117)

Side by Side Diff: android_webview/browser/net/android_stream_reader_url_request_job.cc

Issue 12531002: [android_webview] Make intercepted URLRequests have status codes. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix unit test Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "android_webview/browser/net/android_stream_reader_url_request_job.h" 5 #include "android_webview/browser/net/android_stream_reader_url_request_job.h"
6 6
7 #include <string>
8
7 #include "android_webview/browser/input_stream.h" 9 #include "android_webview/browser/input_stream.h"
8 #include "android_webview/browser/net/input_stream_reader.h" 10 #include "android_webview/browser/net/input_stream_reader.h"
9 #include "base/android/jni_android.h" 11 #include "base/android/jni_android.h"
10 #include "base/android/jni_string.h" 12 #include "base/android/jni_string.h"
11 #include "base/bind.h" 13 #include "base/bind.h"
12 #include "base/bind_helpers.h" 14 #include "base/bind_helpers.h"
13 #include "base/lazy_instance.h" 15 #include "base/lazy_instance.h"
14 #include "base/message_loop.h" 16 #include "base/message_loop.h"
15 #include "base/message_loop_proxy.h" 17 #include "base/message_loop_proxy.h"
18 #include "base/strings/string_number_conversions.h"
16 #include "base/task_runner.h" 19 #include "base/task_runner.h"
17 #include "base/threading/sequenced_worker_pool.h" 20 #include "base/threading/sequenced_worker_pool.h"
18 #include "base/threading/thread.h" 21 #include "base/threading/thread.h"
19 #include "content/public/browser/browser_thread.h" 22 #include "content/public/browser/browser_thread.h"
20 #include "net/base/io_buffer.h" 23 #include "net/base/io_buffer.h"
21 #include "net/base/mime_util.h" 24 #include "net/base/mime_util.h"
22 #include "net/base/net_errors.h" 25 #include "net/base/net_errors.h"
23 #include "net/base/net_util.h" 26 #include "net/base/net_util.h"
27 #include "net/http/http_response_headers.h"
28 #include "net/http/http_response_info.h"
24 #include "net/http/http_util.h" 29 #include "net/http/http_util.h"
25 #include "net/url_request/url_request.h" 30 #include "net/url_request/url_request.h"
26 #include "net/url_request/url_request_job_manager.h" 31 #include "net/url_request/url_request_job_manager.h"
27 32
28 using android_webview::InputStream; 33 using android_webview::InputStream;
29 using android_webview::InputStreamReader; 34 using android_webview::InputStreamReader;
30 using base::android::AttachCurrentThread; 35 using base::android::AttachCurrentThread;
31 using base::PostTaskAndReplyWithResult; 36 using base::PostTaskAndReplyWithResult;
32 using content::BrowserThread; 37 using content::BrowserThread;
33 38
39 namespace {
40
41 const int kHTTPOk = 200;
42 const int kHTTPNotFound = 404;
43
44 const char kHTTPOkText[] = "OK";
45 const char kHTTPNotFoundText[] = "Not Found";
46
47 } // namespace
48
34 // The requests posted to the worker thread might outlive the job. Thread-safe 49 // The requests posted to the worker thread might outlive the job. Thread-safe
35 // ref counting is used to ensure that the InputStream and InputStreamReader 50 // ref counting is used to ensure that the InputStream and InputStreamReader
36 // members of this class are still there when the closure is run on the worker 51 // members of this class are still there when the closure is run on the worker
37 // thread. 52 // thread.
38 class InputStreamReaderWrapper : 53 class InputStreamReaderWrapper :
39 public base::RefCountedThreadSafe<InputStreamReaderWrapper> { 54 public base::RefCountedThreadSafe<InputStreamReaderWrapper> {
40 public: 55 public:
41 InputStreamReaderWrapper( 56 InputStreamReaderWrapper(
42 scoped_ptr<InputStream> input_stream, 57 scoped_ptr<InputStream> input_stream,
43 scoped_ptr<InputStreamReader> input_stream_reader) 58 scoped_ptr<InputStreamReader> input_stream_reader)
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
148 DCHECK(thread_checker_.CalledOnValidThread()); 163 DCHECK(thread_checker_.CalledOnValidThread());
149 DCHECK(returned_delegate); 164 DCHECK(returned_delegate);
150 delegate_ = returned_delegate.Pass(); 165 delegate_ = returned_delegate.Pass();
151 166
152 if (!input_stream) { 167 if (!input_stream) {
153 bool restart_required = false; 168 bool restart_required = false;
154 delegate_->OnInputStreamOpenFailed(request(), &restart_required); 169 delegate_->OnInputStreamOpenFailed(request(), &restart_required);
155 if (restart_required) { 170 if (restart_required) {
156 NotifyRestartRequired(); 171 NotifyRestartRequired();
157 } else { 172 } else {
158 NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, 173 // Clear the IO_PENDING status set in Start().
159 net::ERR_FAILED)); 174 SetStatus(net::URLRequestStatus());
175 HeadersComplete(kHTTPNotFound, kHTTPNotFoundText);
160 } 176 }
161 return; 177 return;
162 } 178 }
163 179
164 scoped_ptr<InputStreamReader> input_stream_reader( 180 scoped_ptr<InputStreamReader> input_stream_reader(
165 CreateStreamReader(input_stream.get())); 181 CreateStreamReader(input_stream.get()));
166 DCHECK(input_stream_reader); 182 DCHECK(input_stream_reader);
167 183
168 DCHECK(!input_stream_reader_wrapper_); 184 DCHECK(!input_stream_reader_wrapper_);
169 input_stream_reader_wrapper_ = new InputStreamReaderWrapper( 185 input_stream_reader_wrapper_ = new InputStreamReaderWrapper(
170 input_stream.Pass(), input_stream_reader.Pass()); 186 input_stream.Pass(), input_stream_reader.Pass());
171 187
172 PostTaskAndReplyWithResult( 188 PostTaskAndReplyWithResult(
173 GetWorkerThreadRunner(), 189 GetWorkerThreadRunner(),
174 FROM_HERE, 190 FROM_HERE,
175 base::Bind(&InputStreamReaderWrapper::Seek, 191 base::Bind(&InputStreamReaderWrapper::Seek,
176 input_stream_reader_wrapper_, 192 input_stream_reader_wrapper_,
177 byte_range_), 193 byte_range_),
178 base::Bind(&AndroidStreamReaderURLRequestJob::OnReaderSeekCompleted, 194 base::Bind(&AndroidStreamReaderURLRequestJob::OnReaderSeekCompleted,
179 weak_factory_.GetWeakPtr())); 195 weak_factory_.GetWeakPtr()));
180 } 196 }
181 197
182 void AndroidStreamReaderURLRequestJob::OnReaderSeekCompleted(int result) { 198 void AndroidStreamReaderURLRequestJob::OnReaderSeekCompleted(int result) {
183 DCHECK(thread_checker_.CalledOnValidThread()); 199 DCHECK(thread_checker_.CalledOnValidThread());
184 // Clear the IO_PENDING status set in Start(). 200 // Clear the IO_PENDING status set in Start().
185 SetStatus(net::URLRequestStatus()); 201 SetStatus(net::URLRequestStatus());
186 if (result >= 0) { 202 if (result >= 0) {
187 set_expected_content_size(result); 203 set_expected_content_size(result);
188 NotifyHeadersComplete(); 204 HeadersComplete(kHTTPOk, kHTTPOkText);
189 } else { 205 } else {
190 NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, result)); 206 NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, result));
191 } 207 }
192 } 208 }
193 209
194 void AndroidStreamReaderURLRequestJob::OnReaderReadCompleted(int result) { 210 void AndroidStreamReaderURLRequestJob::OnReaderReadCompleted(int result) {
195 DCHECK(thread_checker_.CalledOnValidThread()); 211 DCHECK(thread_checker_.CalledOnValidThread());
196 // The URLRequest API contract requires that: 212 // The URLRequest API contract requires that:
197 // * NotifyDone be called once, to set the status code, indicate the job is 213 // * NotifyDone be called once, to set the status code, indicate the job is
198 // finished (there will be no further IO), 214 // finished (there will be no further IO),
(...skipping 14 matching lines...) Expand all
213 } 229 }
214 230
215 base::TaskRunner* AndroidStreamReaderURLRequestJob::GetWorkerThreadRunner() { 231 base::TaskRunner* AndroidStreamReaderURLRequestJob::GetWorkerThreadRunner() {
216 return static_cast<base::TaskRunner*>(BrowserThread::GetBlockingPool()); 232 return static_cast<base::TaskRunner*>(BrowserThread::GetBlockingPool());
217 } 233 }
218 234
219 bool AndroidStreamReaderURLRequestJob::ReadRawData(net::IOBuffer* dest, 235 bool AndroidStreamReaderURLRequestJob::ReadRawData(net::IOBuffer* dest,
220 int dest_size, 236 int dest_size,
221 int* bytes_read) { 237 int* bytes_read) {
222 DCHECK(thread_checker_.CalledOnValidThread()); 238 DCHECK(thread_checker_.CalledOnValidThread());
223 DCHECK(input_stream_reader_wrapper_); 239 if (!input_stream_reader_wrapper_) {
240 // This will happen if opening the InputStream fails in which case the
241 // error is communicated by setting the HTTP response status header rather
242 // than failing the request during the header fetch phase.
243 *bytes_read = 0;
244 return true;
245 }
224 246
225 PostTaskAndReplyWithResult( 247 PostTaskAndReplyWithResult(
226 GetWorkerThreadRunner(), 248 GetWorkerThreadRunner(),
227 FROM_HERE, 249 FROM_HERE,
228 base::Bind(&InputStreamReaderWrapper::ReadRawData, 250 base::Bind(&InputStreamReaderWrapper::ReadRawData,
229 input_stream_reader_wrapper_, 251 input_stream_reader_wrapper_,
230 make_scoped_refptr(dest), 252 make_scoped_refptr(dest),
231 dest_size), 253 dest_size),
232 base::Bind(&AndroidStreamReaderURLRequestJob::OnReaderReadCompleted, 254 base::Bind(&AndroidStreamReaderURLRequestJob::OnReaderReadCompleted,
233 weak_factory_.GetWeakPtr())); 255 weak_factory_.GetWeakPtr()));
(...skipping 29 matching lines...) Expand all
263 return false; 285 return false;
264 286
265 // Since it's possible for this call to alter the InputStream a 287 // Since it's possible for this call to alter the InputStream a
266 // Seek or ReadRawData operation running in the background is not permitted. 288 // Seek or ReadRawData operation running in the background is not permitted.
267 DCHECK(!request_->status().is_io_pending()); 289 DCHECK(!request_->status().is_io_pending());
268 290
269 return delegate_->GetCharset( 291 return delegate_->GetCharset(
270 env, request(), input_stream_reader_wrapper_->input_stream(), charset); 292 env, request(), input_stream_reader_wrapper_->input_stream(), charset);
271 } 293 }
272 294
295 void AndroidStreamReaderURLRequestJob::HeadersComplete(
296 int status_code,
297 const std::string& status_text) {
298 std::string status("HTTP/1.1 ");
299 status.append(base::IntToString(status_code));
300 status.append(" ");
301 status.append(status_text);
302 // HttpResponseHeaders expects its input string to be terminated by two NULs.
303 status.append("\0\0", 2);
304 net::HttpResponseHeaders* headers = new net::HttpResponseHeaders(status);
305
306 if (status_code == kHTTPOk) {
307 if (expected_content_size() != -1) {
308 std::string content_length_header(
309 net::HttpRequestHeaders::kContentLength);
310 content_length_header.append(": ");
311 content_length_header.append(
312 base::Int64ToString(expected_content_size()));
313 headers->AddHeader(content_length_header);
314 }
315
316 std::string mime_type;
317 if (GetMimeType(&mime_type) && !mime_type.empty()) {
318 std::string content_type_header(net::HttpRequestHeaders::kContentType);
319 content_type_header.append(": ");
320 content_type_header.append(mime_type);
321 headers->AddHeader(content_type_header);
322 }
323 }
324
325 response_info_.reset(new net::HttpResponseInfo());
326 response_info_->headers = headers;
327
328 NotifyHeadersComplete();
329 }
330
331 int AndroidStreamReaderURLRequestJob::GetResponseCode() const {
332 if (response_info_)
333 return response_info_->headers->response_code();
334 return URLRequestJob::GetResponseCode();
335 }
336
337 void AndroidStreamReaderURLRequestJob::GetResponseInfo(
338 net::HttpResponseInfo* info) {
339 if (response_info_)
340 *info = *response_info_;
341 }
342
273 void AndroidStreamReaderURLRequestJob::SetExtraRequestHeaders( 343 void AndroidStreamReaderURLRequestJob::SetExtraRequestHeaders(
274 const net::HttpRequestHeaders& headers) { 344 const net::HttpRequestHeaders& headers) {
275 std::string range_header; 345 std::string range_header;
276 if (headers.GetHeader(net::HttpRequestHeaders::kRange, &range_header)) { 346 if (headers.GetHeader(net::HttpRequestHeaders::kRange, &range_header)) {
277 // We only extract the "Range" header so that we know how many bytes in the 347 // We only extract the "Range" header so that we know how many bytes in the
278 // stream to skip and how many to read after that. 348 // stream to skip and how many to read after that.
279 std::vector<net::HttpByteRange> ranges; 349 std::vector<net::HttpByteRange> ranges;
280 if (net::HttpUtil::ParseRangeHeader(range_header, &ranges)) { 350 if (net::HttpUtil::ParseRangeHeader(range_header, &ranges)) {
281 if (ranges.size() == 1) { 351 if (ranges.size() == 1) {
282 byte_range_ = ranges[0]; 352 byte_range_ = ranges[0];
283 } else { 353 } else {
284 // We don't support multiple range requests in one single URL request, 354 // We don't support multiple range requests in one single URL request,
285 // because we need to do multipart encoding here. 355 // because we need to do multipart encoding here.
286 NotifyDone(net::URLRequestStatus( 356 NotifyDone(net::URLRequestStatus(
287 net::URLRequestStatus::FAILED, 357 net::URLRequestStatus::FAILED,
288 net::ERR_REQUEST_RANGE_NOT_SATISFIABLE)); 358 net::ERR_REQUEST_RANGE_NOT_SATISFIABLE));
289 } 359 }
290 } 360 }
291 } 361 }
292 } 362 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698