| 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(), | 235 GetWorkerThreadRunner(), FROM_HERE, |
| 248 FROM_HERE, | |
| 249 base::Bind(&InputStreamReaderWrapper::ReadRawData, | 236 base::Bind(&InputStreamReaderWrapper::ReadRawData, |
| 250 input_stream_reader_wrapper_, | 237 input_stream_reader_wrapper_, make_scoped_refptr(dest), |
| 251 make_scoped_refptr(dest), | |
| 252 dest_size), | 238 dest_size), |
| 253 base::Bind(&AndroidStreamReaderURLRequestJob::OnReaderReadCompleted, | 239 base::Bind(&AndroidStreamReaderURLRequestJob::OnReaderReadCompleted, |
| 254 weak_factory_.GetWeakPtr())); | 240 weak_factory_.GetWeakPtr())); |
| 255 | 241 |
| 256 SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, | 242 return net::ERR_IO_PENDING; |
| 257 net::ERR_IO_PENDING)); | |
| 258 return false; | |
| 259 } | 243 } |
| 260 | 244 |
| 261 bool AndroidStreamReaderURLRequestJob::GetMimeType( | 245 bool AndroidStreamReaderURLRequestJob::GetMimeType( |
| 262 std::string* mime_type) const { | 246 std::string* mime_type) const { |
| 263 DCHECK(thread_checker_.CalledOnValidThread()); | 247 DCHECK(thread_checker_.CalledOnValidThread()); |
| 264 JNIEnv* env = AttachCurrentThread(); | 248 JNIEnv* env = AttachCurrentThread(); |
| 265 DCHECK(env); | 249 DCHECK(env); |
| 266 | 250 |
| 267 if (!input_stream_reader_wrapper_.get()) | 251 if (!input_stream_reader_wrapper_.get()) |
| 268 return false; | 252 return false; |
| (...skipping 29 matching lines...) Expand all Loading... |
| 298 if (delegate) { | 282 if (delegate) { |
| 299 delegate_.swap(delegate); | 283 delegate_.swap(delegate); |
| 300 DoStart(); | 284 DoStart(); |
| 301 } else { | 285 } else { |
| 302 NotifyRestartRequired(); | 286 NotifyRestartRequired(); |
| 303 } | 287 } |
| 304 } | 288 } |
| 305 | 289 |
| 306 void AndroidStreamReaderURLRequestJob::DoStart() { | 290 void AndroidStreamReaderURLRequestJob::DoStart() { |
| 307 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 } |
| 308 // Start reading asynchronously so that all error reporting and data | 297 // Start reading asynchronously so that all error reporting and data |
| 309 // callbacks happen as they would for network requests. | 298 // callbacks happen as they would for network requests. |
| 310 SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, | 299 SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, |
| 311 net::ERR_IO_PENDING)); | 300 net::ERR_IO_PENDING)); |
| 312 | 301 |
| 313 // This could be done in the InputStreamReader but would force more | 302 // This could be done in the InputStreamReader but would force more |
| 314 // complex synchronization in the delegate. | 303 // complex synchronization in the delegate. |
| 315 GetWorkerThreadRunner()->PostTask( | 304 GetWorkerThreadRunner()->PostTask( |
| 316 FROM_HERE, | 305 FROM_HERE, |
| 317 base::Bind( | 306 base::Bind( |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 378 void AndroidStreamReaderURLRequestJob::GetResponseInfo( | 367 void AndroidStreamReaderURLRequestJob::GetResponseInfo( |
| 379 net::HttpResponseInfo* info) { | 368 net::HttpResponseInfo* info) { |
| 380 if (response_info_) | 369 if (response_info_) |
| 381 *info = *response_info_; | 370 *info = *response_info_; |
| 382 } | 371 } |
| 383 | 372 |
| 384 void AndroidStreamReaderURLRequestJob::SetExtraRequestHeaders( | 373 void AndroidStreamReaderURLRequestJob::SetExtraRequestHeaders( |
| 385 const net::HttpRequestHeaders& headers) { | 374 const net::HttpRequestHeaders& headers) { |
| 386 std::string range_header; | 375 std::string range_header; |
| 387 if (headers.GetHeader(net::HttpRequestHeaders::kRange, &range_header)) { | 376 if (headers.GetHeader(net::HttpRequestHeaders::kRange, &range_header)) { |
| 388 // 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 |
| 389 // 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. |
| 390 std::vector<net::HttpByteRange> ranges; | 381 std::vector<net::HttpByteRange> ranges; |
| 391 if (net::HttpUtil::ParseRangeHeader(range_header, &ranges)) { | 382 if (net::HttpUtil::ParseRangeHeader(range_header, &ranges)) { |
| 392 if (ranges.size() == 1) { | 383 if (ranges.size() == 1) |
| 393 byte_range_ = ranges[0]; | 384 byte_range_ = ranges[0]; |
| 394 } else { | 385 } else { |
| 395 // 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, |
| 396 // because we need to do multipart encoding here. | 387 // because we need to do multipart encoding here. |
| 397 NotifyDone(net::URLRequestStatus( | 388 range_parse_result_ = net::ERR_REQUEST_RANGE_NOT_SATISFIABLE; |
| 398 net::URLRequestStatus::FAILED, | |
| 399 net::ERR_REQUEST_RANGE_NOT_SATISFIABLE)); | |
| 400 } | |
| 401 } | 389 } |
| 402 } | 390 } |
| 403 } | 391 } |
| 404 | 392 |
| 405 } // namespace android_webview | 393 } // namespace android_webview |
| OLD | NEW |