OLD | NEW |
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> | 7 #include <string> |
8 | 8 |
9 #include "android_webview/browser/input_stream.h" | 9 #include "android_webview/browser/input_stream.h" |
10 #include "android_webview/browser/net/input_stream_reader.h" | 10 #include "android_webview/browser/net/input_stream_reader.h" |
11 #include "base/android/jni_android.h" | 11 #include "base/android/jni_android.h" |
12 #include "base/android/jni_string.h" | 12 #include "base/android/jni_string.h" |
13 #include "base/bind.h" | 13 #include "base/bind.h" |
14 #include "base/bind_helpers.h" | 14 #include "base/bind_helpers.h" |
15 #include "base/lazy_instance.h" | 15 #include "base/lazy_instance.h" |
16 #include "base/single_thread_task_runner.h" | 16 #include "base/single_thread_task_runner.h" |
17 #include "base/strings/string_number_conversions.h" | 17 #include "base/strings/string_number_conversions.h" |
18 #include "base/task_runner.h" | 18 #include "base/task_runner.h" |
19 #include "base/threading/sequenced_worker_pool.h" | 19 #include "base/threading/sequenced_worker_pool.h" |
20 #include "base/threading/thread.h" | 20 #include "base/threading/thread.h" |
21 #include "content/public/browser/browser_thread.h" | 21 #include "content/public/browser/browser_thread.h" |
22 #include "net/base/io_buffer.h" | 22 #include "net/base/io_buffer.h" |
23 #include "net/base/mime_util.h" | 23 #include "net/base/mime_util.h" |
| 24 #include "net/base/net_errors.h" |
24 #include "net/base/net_util.h" | 25 #include "net/base/net_util.h" |
25 #include "net/http/http_response_headers.h" | 26 #include "net/http/http_response_headers.h" |
26 #include "net/http/http_response_info.h" | 27 #include "net/http/http_response_info.h" |
27 #include "net/http/http_util.h" | 28 #include "net/http/http_util.h" |
28 #include "net/url_request/url_request.h" | 29 #include "net/url_request/url_request.h" |
29 #include "net/url_request/url_request_job_manager.h" | 30 #include "net/url_request/url_request_job_manager.h" |
30 | 31 |
31 using base::android::AttachCurrentThread; | 32 using base::android::AttachCurrentThread; |
32 using base::PostTaskAndReplyWithResult; | 33 using base::PostTaskAndReplyWithResult; |
33 using content::BrowserThread; | 34 using content::BrowserThread; |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
82 scoped_ptr<InputStreamReader> input_stream_reader_; | 83 scoped_ptr<InputStreamReader> input_stream_reader_; |
83 | 84 |
84 DISALLOW_COPY_AND_ASSIGN(InputStreamReaderWrapper); | 85 DISALLOW_COPY_AND_ASSIGN(InputStreamReaderWrapper); |
85 }; | 86 }; |
86 | 87 |
87 AndroidStreamReaderURLRequestJob::AndroidStreamReaderURLRequestJob( | 88 AndroidStreamReaderURLRequestJob::AndroidStreamReaderURLRequestJob( |
88 net::URLRequest* request, | 89 net::URLRequest* request, |
89 net::NetworkDelegate* network_delegate, | 90 net::NetworkDelegate* network_delegate, |
90 scoped_ptr<Delegate> delegate) | 91 scoped_ptr<Delegate> delegate) |
91 : URLRequestJob(request, network_delegate), | 92 : URLRequestJob(request, network_delegate), |
92 range_parse_result_(net::OK), | |
93 delegate_(delegate.Pass()), | 93 delegate_(delegate.Pass()), |
94 weak_factory_(this) { | 94 weak_factory_(this) { |
95 DCHECK(delegate_); | 95 DCHECK(delegate_); |
96 } | 96 } |
97 | 97 |
98 AndroidStreamReaderURLRequestJob::AndroidStreamReaderURLRequestJob( | 98 AndroidStreamReaderURLRequestJob::AndroidStreamReaderURLRequestJob( |
99 net::URLRequest* request, | 99 net::URLRequest* request, |
100 net::NetworkDelegate* network_delegate, | 100 net::NetworkDelegate* network_delegate, |
101 scoped_ptr<DelegateObtainer> delegate_obtainer, | 101 scoped_ptr<DelegateObtainer> delegate_obtainer, |
102 bool) | 102 bool) |
103 : URLRequestJob(request, network_delegate), | 103 : URLRequestJob(request, network_delegate), |
104 range_parse_result_(net::OK), | |
105 delegate_obtainer_(delegate_obtainer.Pass()), | 104 delegate_obtainer_(delegate_obtainer.Pass()), |
106 weak_factory_(this) { | 105 weak_factory_(this) { |
107 DCHECK(delegate_obtainer_); | 106 DCHECK(delegate_obtainer_); |
108 } | 107 } |
109 | 108 |
110 AndroidStreamReaderURLRequestJob::~AndroidStreamReaderURLRequestJob() { | 109 AndroidStreamReaderURLRequestJob::~AndroidStreamReaderURLRequestJob() { |
111 } | 110 } |
112 | 111 |
113 namespace { | 112 namespace { |
114 | 113 |
(...skipping 20 matching lines...) Expand all Loading... |
135 | 134 |
136 void AndroidStreamReaderURLRequestJob::Start() { | 135 void AndroidStreamReaderURLRequestJob::Start() { |
137 DCHECK(thread_checker_.CalledOnValidThread()); | 136 DCHECK(thread_checker_.CalledOnValidThread()); |
138 if (!delegate_) { | 137 if (!delegate_) { |
139 DCHECK(delegate_obtainer_); | 138 DCHECK(delegate_obtainer_); |
140 delegate_obtainer_->ObtainDelegate( | 139 delegate_obtainer_->ObtainDelegate( |
141 request(), | 140 request(), |
142 base::Bind(&AndroidStreamReaderURLRequestJob::DelegateObtained, | 141 base::Bind(&AndroidStreamReaderURLRequestJob::DelegateObtained, |
143 weak_factory_.GetWeakPtr())); | 142 weak_factory_.GetWeakPtr())); |
144 } else { | 143 } else { |
145 // Run DoStart asynchronously to avoid re-entering the delegate. | 144 DoStart(); |
146 base::ThreadTaskRunnerHandle::Get()->PostTask( | |
147 FROM_HERE, base::Bind(&AndroidStreamReaderURLRequestJob::DoStart, | |
148 weak_factory_.GetWeakPtr())); | |
149 } | 145 } |
150 } | 146 } |
151 | 147 |
152 void AndroidStreamReaderURLRequestJob::Kill() { | 148 void AndroidStreamReaderURLRequestJob::Kill() { |
153 DCHECK(thread_checker_.CalledOnValidThread()); | 149 DCHECK(thread_checker_.CalledOnValidThread()); |
154 weak_factory_.InvalidateWeakPtrs(); | 150 weak_factory_.InvalidateWeakPtrs(); |
155 URLRequestJob::Kill(); | 151 URLRequestJob::Kill(); |
156 } | 152 } |
157 | 153 |
158 scoped_ptr<InputStreamReader> | 154 scoped_ptr<InputStreamReader> |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
199 } | 195 } |
200 | 196 |
201 void AndroidStreamReaderURLRequestJob::OnReaderSeekCompleted(int result) { | 197 void AndroidStreamReaderURLRequestJob::OnReaderSeekCompleted(int result) { |
202 DCHECK(thread_checker_.CalledOnValidThread()); | 198 DCHECK(thread_checker_.CalledOnValidThread()); |
203 // Clear the IO_PENDING status set in Start(). | 199 // Clear the IO_PENDING status set in Start(). |
204 SetStatus(net::URLRequestStatus()); | 200 SetStatus(net::URLRequestStatus()); |
205 if (result >= 0) { | 201 if (result >= 0) { |
206 set_expected_content_size(result); | 202 set_expected_content_size(result); |
207 HeadersComplete(kHTTPOk, kHTTPOkText); | 203 HeadersComplete(kHTTPOk, kHTTPOkText); |
208 } else { | 204 } else { |
209 NotifyStartError( | 205 NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, result)); |
210 net::URLRequestStatus(net::URLRequestStatus::FAILED, result)); | |
211 } | 206 } |
212 } | 207 } |
213 | 208 |
214 void AndroidStreamReaderURLRequestJob::OnReaderReadCompleted(int result) { | 209 void AndroidStreamReaderURLRequestJob::OnReaderReadCompleted(int result) { |
215 DCHECK(thread_checker_.CalledOnValidThread()); | 210 DCHECK(thread_checker_.CalledOnValidThread()); |
216 | 211 // The URLRequest API contract requires that: |
217 ReadRawDataComplete(result); | 212 // * NotifyDone be called once, to set the status code, indicate the job is |
| 213 // finished (there will be no further IO), |
| 214 // * NotifyReadComplete be called if false is returned from ReadRawData to |
| 215 // indicate that the IOBuffer will not be used by the job anymore. |
| 216 // There might be multiple calls to ReadRawData (and thus multiple calls to |
| 217 // NotifyReadComplete), which is why NotifyDone is called only on errors |
| 218 // (result < 0) and end of data (result == 0). |
| 219 if (result == 0) { |
| 220 NotifyDone(net::URLRequestStatus()); |
| 221 } else if (result < 0) { |
| 222 NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, result)); |
| 223 } else { |
| 224 // Clear the IO_PENDING status. |
| 225 SetStatus(net::URLRequestStatus()); |
| 226 } |
| 227 NotifyReadComplete(result); |
218 } | 228 } |
219 | 229 |
220 base::TaskRunner* AndroidStreamReaderURLRequestJob::GetWorkerThreadRunner() { | 230 base::TaskRunner* AndroidStreamReaderURLRequestJob::GetWorkerThreadRunner() { |
221 return static_cast<base::TaskRunner*>(BrowserThread::GetBlockingPool()); | 231 return static_cast<base::TaskRunner*>(BrowserThread::GetBlockingPool()); |
222 } | 232 } |
223 | 233 |
224 int AndroidStreamReaderURLRequestJob::ReadRawData(net::IOBuffer* dest, | 234 bool AndroidStreamReaderURLRequestJob::ReadRawData(net::IOBuffer* dest, |
225 int dest_size) { | 235 int dest_size, |
| 236 int* bytes_read) { |
226 DCHECK(thread_checker_.CalledOnValidThread()); | 237 DCHECK(thread_checker_.CalledOnValidThread()); |
227 if (!input_stream_reader_wrapper_.get()) { | 238 if (!input_stream_reader_wrapper_.get()) { |
228 // This will happen if opening the InputStream fails in which case the | 239 // This will happen if opening the InputStream fails in which case the |
229 // error is communicated by setting the HTTP response status header rather | 240 // error is communicated by setting the HTTP response status header rather |
230 // than failing the request during the header fetch phase. | 241 // than failing the request during the header fetch phase. |
231 return 0; | 242 *bytes_read = 0; |
| 243 return true; |
232 } | 244 } |
233 | 245 |
234 PostTaskAndReplyWithResult( | 246 PostTaskAndReplyWithResult( |
235 GetWorkerThreadRunner(), FROM_HERE, | 247 GetWorkerThreadRunner(), FROM_HERE, |
236 base::Bind(&InputStreamReaderWrapper::ReadRawData, | 248 base::Bind(&InputStreamReaderWrapper::ReadRawData, |
237 input_stream_reader_wrapper_, make_scoped_refptr(dest), | 249 input_stream_reader_wrapper_, make_scoped_refptr(dest), |
238 dest_size), | 250 dest_size), |
239 base::Bind(&AndroidStreamReaderURLRequestJob::OnReaderReadCompleted, | 251 base::Bind(&AndroidStreamReaderURLRequestJob::OnReaderReadCompleted, |
240 weak_factory_.GetWeakPtr())); | 252 weak_factory_.GetWeakPtr())); |
241 | 253 |
242 return net::ERR_IO_PENDING; | 254 SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, |
| 255 net::ERR_IO_PENDING)); |
| 256 return false; |
243 } | 257 } |
244 | 258 |
245 bool AndroidStreamReaderURLRequestJob::GetMimeType( | 259 bool AndroidStreamReaderURLRequestJob::GetMimeType( |
246 std::string* mime_type) const { | 260 std::string* mime_type) const { |
247 DCHECK(thread_checker_.CalledOnValidThread()); | 261 DCHECK(thread_checker_.CalledOnValidThread()); |
248 JNIEnv* env = AttachCurrentThread(); | 262 JNIEnv* env = AttachCurrentThread(); |
249 DCHECK(env); | 263 DCHECK(env); |
250 | 264 |
251 if (!input_stream_reader_wrapper_.get()) | 265 if (!input_stream_reader_wrapper_.get()) |
252 return false; | 266 return false; |
(...skipping 29 matching lines...) Expand all Loading... |
282 if (delegate) { | 296 if (delegate) { |
283 delegate_.swap(delegate); | 297 delegate_.swap(delegate); |
284 DoStart(); | 298 DoStart(); |
285 } else { | 299 } else { |
286 NotifyRestartRequired(); | 300 NotifyRestartRequired(); |
287 } | 301 } |
288 } | 302 } |
289 | 303 |
290 void AndroidStreamReaderURLRequestJob::DoStart() { | 304 void AndroidStreamReaderURLRequestJob::DoStart() { |
291 DCHECK(thread_checker_.CalledOnValidThread()); | 305 DCHECK(thread_checker_.CalledOnValidThread()); |
292 if (range_parse_result_ != net::OK) { | |
293 NotifyStartError(net::URLRequestStatus(net::URLRequestStatus::FAILED, | |
294 range_parse_result_)); | |
295 return; | |
296 } | |
297 // Start reading asynchronously so that all error reporting and data | 306 // Start reading asynchronously so that all error reporting and data |
298 // callbacks happen as they would for network requests. | 307 // callbacks happen as they would for network requests. |
299 SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, | 308 SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, |
300 net::ERR_IO_PENDING)); | 309 net::ERR_IO_PENDING)); |
301 | 310 |
302 // This could be done in the InputStreamReader but would force more | 311 // This could be done in the InputStreamReader but would force more |
303 // complex synchronization in the delegate. | 312 // complex synchronization in the delegate. |
304 GetWorkerThreadRunner()->PostTask( | 313 GetWorkerThreadRunner()->PostTask( |
305 FROM_HERE, | 314 FROM_HERE, |
306 base::Bind( | 315 base::Bind( |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
367 void AndroidStreamReaderURLRequestJob::GetResponseInfo( | 376 void AndroidStreamReaderURLRequestJob::GetResponseInfo( |
368 net::HttpResponseInfo* info) { | 377 net::HttpResponseInfo* info) { |
369 if (response_info_) | 378 if (response_info_) |
370 *info = *response_info_; | 379 *info = *response_info_; |
371 } | 380 } |
372 | 381 |
373 void AndroidStreamReaderURLRequestJob::SetExtraRequestHeaders( | 382 void AndroidStreamReaderURLRequestJob::SetExtraRequestHeaders( |
374 const net::HttpRequestHeaders& headers) { | 383 const net::HttpRequestHeaders& headers) { |
375 std::string range_header; | 384 std::string range_header; |
376 if (headers.GetHeader(net::HttpRequestHeaders::kRange, &range_header)) { | 385 if (headers.GetHeader(net::HttpRequestHeaders::kRange, &range_header)) { |
377 // This job only cares about the Range header so that we know how many bytes | 386 // We only extract the "Range" header so that we know how many bytes in the |
378 // in the stream to skip and how many to read after that. Note that | 387 // stream to skip and how many to read after that. |
379 // validation is deferred to DoStart(), because NotifyStartError() is not | |
380 // legal to call since the job has not started. | |
381 std::vector<net::HttpByteRange> ranges; | 388 std::vector<net::HttpByteRange> ranges; |
382 if (net::HttpUtil::ParseRangeHeader(range_header, &ranges)) { | 389 if (net::HttpUtil::ParseRangeHeader(range_header, &ranges)) { |
383 if (ranges.size() == 1) | 390 if (ranges.size() == 1) { |
384 byte_range_ = ranges[0]; | 391 byte_range_ = ranges[0]; |
385 } else { | 392 } else { |
386 // We don't support multiple range requests in one single URL request, | 393 // We don't support multiple range requests in one single URL request, |
387 // because we need to do multipart encoding here. | 394 // because we need to do multipart encoding here. |
388 range_parse_result_ = net::ERR_REQUEST_RANGE_NOT_SATISFIABLE; | 395 NotifyDone( |
| 396 net::URLRequestStatus(net::URLRequestStatus::FAILED, |
| 397 net::ERR_REQUEST_RANGE_NOT_SATISFIABLE)); |
| 398 } |
389 } | 399 } |
390 } | 400 } |
391 } | 401 } |
392 | 402 |
393 } // namespace android_webview | 403 } // namespace android_webview |
OLD | NEW |