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