| 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 |