| 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 "android_webview/browser/input_stream.h" | 7 #include "android_webview/browser/input_stream.h" |
| 8 #include "android_webview/browser/net/input_stream_reader.h" | 8 #include "android_webview/browser/net/input_stream_reader.h" |
| 9 #include "base/android/jni_android.h" | 9 #include "base/android/jni_android.h" |
| 10 #include "base/android/jni_string.h" | 10 #include "base/android/jni_string.h" |
| 11 #include "base/bind.h" | 11 #include "base/bind.h" |
| 12 #include "base/bind_helpers.h" | 12 #include "base/bind_helpers.h" |
| 13 #include "base/lazy_instance.h" | 13 #include "base/lazy_instance.h" |
| 14 #include "base/message_loop.h" | 14 #include "base/message_loop.h" |
| 15 #include "base/message_loop_proxy.h" |
| 15 #include "base/task_runner.h" | 16 #include "base/task_runner.h" |
| 16 #include "base/threading/sequenced_worker_pool.h" | 17 #include "base/threading/sequenced_worker_pool.h" |
| 17 #include "base/threading/thread.h" | 18 #include "base/threading/thread.h" |
| 18 #include "content/public/browser/browser_thread.h" | 19 #include "content/public/browser/browser_thread.h" |
| 19 #include "net/base/io_buffer.h" | 20 #include "net/base/io_buffer.h" |
| 20 #include "net/base/mime_util.h" | 21 #include "net/base/mime_util.h" |
| 21 #include "net/base/net_errors.h" | 22 #include "net/base/net_errors.h" |
| 22 #include "net/base/net_util.h" | 23 #include "net/base/net_util.h" |
| 23 #include "net/http/http_util.h" | 24 #include "net/http/http_util.h" |
| 24 #include "net/url_request/url_request.h" | 25 #include "net/url_request/url_request.h" |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 74 scoped_ptr<Delegate> delegate) | 75 scoped_ptr<Delegate> delegate) |
| 75 : URLRequestJob(request, network_delegate), | 76 : URLRequestJob(request, network_delegate), |
| 76 delegate_(delegate.Pass()), | 77 delegate_(delegate.Pass()), |
| 77 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) { | 78 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) { |
| 78 DCHECK(delegate_); | 79 DCHECK(delegate_); |
| 79 } | 80 } |
| 80 | 81 |
| 81 AndroidStreamReaderURLRequestJob::~AndroidStreamReaderURLRequestJob() { | 82 AndroidStreamReaderURLRequestJob::~AndroidStreamReaderURLRequestJob() { |
| 82 } | 83 } |
| 83 | 84 |
| 85 namespace { |
| 86 |
| 87 typedef base::Callback< |
| 88 void(scoped_ptr<AndroidStreamReaderURLRequestJob::Delegate>, |
| 89 scoped_ptr<InputStream>)> OnInputStreamOpenedCallback; |
| 90 |
| 91 // static |
| 92 void OpenInputStreamOnWorkerThread( |
| 93 scoped_refptr<base::MessageLoopProxy> job_thread_proxy, |
| 94 scoped_ptr<AndroidStreamReaderURLRequestJob::Delegate> delegate, |
| 95 const GURL& url, |
| 96 OnInputStreamOpenedCallback callback) { |
| 97 |
| 98 JNIEnv* env = AttachCurrentThread(); |
| 99 DCHECK(env); |
| 100 |
| 101 scoped_ptr<InputStream> input_stream = delegate->OpenInputStream(env, url); |
| 102 job_thread_proxy->PostTask(FROM_HERE, |
| 103 base::Bind(callback, |
| 104 base::Passed(delegate.Pass()), |
| 105 base::Passed(input_stream.Pass()))); |
| 106 } |
| 107 |
| 108 } // namespace |
| 109 |
| 84 void AndroidStreamReaderURLRequestJob::Start() { | 110 void AndroidStreamReaderURLRequestJob::Start() { |
| 111 DCHECK(thread_checker_.CalledOnValidThread()); |
| 85 // Start reading asynchronously so that all error reporting and data | 112 // Start reading asynchronously so that all error reporting and data |
| 86 // callbacks happen as they would for network requests. | 113 // callbacks happen as they would for network requests. |
| 87 SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, | 114 SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, |
| 88 net::ERR_IO_PENDING)); | 115 net::ERR_IO_PENDING)); |
| 89 MessageLoop::current()->PostTask( | 116 |
| 117 // This could be done in the InputStreamReader but would force more |
| 118 // complex synchronization in the delegate. |
| 119 GetWorkerThreadRunner()->PostTask( |
| 90 FROM_HERE, | 120 FROM_HERE, |
| 91 base::Bind( | 121 base::Bind( |
| 92 &AndroidStreamReaderURLRequestJob::StartAsync, | 122 &OpenInputStreamOnWorkerThread, |
| 93 weak_factory_.GetWeakPtr())); | 123 MessageLoop::current()->message_loop_proxy(), |
| 124 // This is intentional - the job could be deleted while the callback |
| 125 // is executing on the background thread. |
| 126 // The delegate will be "returned" to the job once the InputStream |
| 127 // open attempt is completed. |
| 128 base::Passed(&delegate_), |
| 129 request()->url(), |
| 130 base::Bind(&AndroidStreamReaderURLRequestJob::OnInputStreamOpened, |
| 131 weak_factory_.GetWeakPtr()))); |
| 94 } | 132 } |
| 95 | 133 |
| 96 void AndroidStreamReaderURLRequestJob::Kill() { | 134 void AndroidStreamReaderURLRequestJob::Kill() { |
| 135 DCHECK(thread_checker_.CalledOnValidThread()); |
| 97 weak_factory_.InvalidateWeakPtrs(); | 136 weak_factory_.InvalidateWeakPtrs(); |
| 98 URLRequestJob::Kill(); | 137 URLRequestJob::Kill(); |
| 99 } | 138 } |
| 100 | 139 |
| 101 scoped_ptr<InputStreamReader> | 140 scoped_ptr<InputStreamReader> |
| 102 AndroidStreamReaderURLRequestJob::CreateStreamReader(InputStream* stream) { | 141 AndroidStreamReaderURLRequestJob::CreateStreamReader(InputStream* stream) { |
| 103 return make_scoped_ptr(new InputStreamReader(stream)); | 142 return make_scoped_ptr(new InputStreamReader(stream)); |
| 104 } | 143 } |
| 105 | 144 |
| 106 void AndroidStreamReaderURLRequestJob::StartAsync() { | 145 void AndroidStreamReaderURLRequestJob::OnInputStreamOpened( |
| 107 JNIEnv* env = AttachCurrentThread(); | 146 scoped_ptr<Delegate> returned_delegate, |
| 108 DCHECK(env); | 147 scoped_ptr<android_webview::InputStream> input_stream) { |
| 148 DCHECK(thread_checker_.CalledOnValidThread()); |
| 149 DCHECK(returned_delegate); |
| 150 delegate_ = returned_delegate.Pass(); |
| 109 | 151 |
| 110 // This could be done in the InputStreamReader but would force more | 152 if (!input_stream) { |
| 111 // complex synchronization in the delegate. | 153 bool restart_required = false; |
| 112 scoped_ptr<android_webview::InputStream> stream( | 154 delegate_->OnInputStreamOpenFailed(request(), &restart_required); |
| 113 delegate_->OpenInputStream(env, request())); | 155 if (restart_required) { |
| 114 | 156 NotifyRestartRequired(); |
| 115 if (!stream) { | 157 } else { |
| 116 NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, | 158 NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, |
| 117 net::ERR_FAILED)); | 159 net::ERR_FAILED)); |
| 160 } |
| 118 return; | 161 return; |
| 119 } | 162 } |
| 120 | 163 |
| 121 scoped_ptr<InputStreamReader> input_stream_reader( | 164 scoped_ptr<InputStreamReader> input_stream_reader( |
| 122 CreateStreamReader(stream.get())); | 165 CreateStreamReader(input_stream.get())); |
| 123 DCHECK(input_stream_reader); | 166 DCHECK(input_stream_reader); |
| 124 | 167 |
| 125 DCHECK(!input_stream_reader_wrapper_); | 168 DCHECK(!input_stream_reader_wrapper_); |
| 126 input_stream_reader_wrapper_ = | 169 input_stream_reader_wrapper_ = new InputStreamReaderWrapper( |
| 127 new InputStreamReaderWrapper(stream.Pass(), input_stream_reader.Pass()); | 170 input_stream.Pass(), input_stream_reader.Pass()); |
| 128 | 171 |
| 129 PostTaskAndReplyWithResult( | 172 PostTaskAndReplyWithResult( |
| 130 GetWorkerThreadRunner(), | 173 GetWorkerThreadRunner(), |
| 131 FROM_HERE, | 174 FROM_HERE, |
| 132 base::Bind(&InputStreamReaderWrapper::Seek, | 175 base::Bind(&InputStreamReaderWrapper::Seek, |
| 133 input_stream_reader_wrapper_, | 176 input_stream_reader_wrapper_, |
| 134 byte_range_), | 177 byte_range_), |
| 135 base::Bind(&AndroidStreamReaderURLRequestJob::OnReaderSeekCompleted, | 178 base::Bind(&AndroidStreamReaderURLRequestJob::OnReaderSeekCompleted, |
| 136 weak_factory_.GetWeakPtr())); | 179 weak_factory_.GetWeakPtr())); |
| 137 } | 180 } |
| 138 | 181 |
| 139 void AndroidStreamReaderURLRequestJob::OnReaderSeekCompleted(int result) { | 182 void AndroidStreamReaderURLRequestJob::OnReaderSeekCompleted(int result) { |
| 183 DCHECK(thread_checker_.CalledOnValidThread()); |
| 140 // Clear the IO_PENDING status set in Start(). | 184 // Clear the IO_PENDING status set in Start(). |
| 141 SetStatus(net::URLRequestStatus()); | 185 SetStatus(net::URLRequestStatus()); |
| 142 if (result >= 0) { | 186 if (result >= 0) { |
| 143 set_expected_content_size(result); | 187 set_expected_content_size(result); |
| 144 NotifyHeadersComplete(); | 188 NotifyHeadersComplete(); |
| 145 } else { | 189 } else { |
| 146 NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, result)); | 190 NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, result)); |
| 147 } | 191 } |
| 148 } | 192 } |
| 149 | 193 |
| 150 void AndroidStreamReaderURLRequestJob::OnReaderReadCompleted(int result) { | 194 void AndroidStreamReaderURLRequestJob::OnReaderReadCompleted(int result) { |
| 195 DCHECK(thread_checker_.CalledOnValidThread()); |
| 151 // The URLRequest API contract requires that: | 196 // The URLRequest API contract requires that: |
| 152 // * NotifyDone be called once, to set the status code, indicate the job is | 197 // * NotifyDone be called once, to set the status code, indicate the job is |
| 153 // finished (there will be no further IO), | 198 // finished (there will be no further IO), |
| 154 // * NotifyReadComplete be called if false is returned from ReadRawData to | 199 // * NotifyReadComplete be called if false is returned from ReadRawData to |
| 155 // indicate that the IOBuffer will not be used by the job anymore. | 200 // indicate that the IOBuffer will not be used by the job anymore. |
| 156 // There might be multiple calls to ReadRawData (and thus multiple calls to | 201 // There might be multiple calls to ReadRawData (and thus multiple calls to |
| 157 // NotifyReadComplete), which is why NotifyDone is called only on errors | 202 // NotifyReadComplete), which is why NotifyDone is called only on errors |
| 158 // (result < 0) and end of data (result == 0). | 203 // (result < 0) and end of data (result == 0). |
| 159 if (result == 0) { | 204 if (result == 0) { |
| 160 NotifyDone(net::URLRequestStatus()); | 205 NotifyDone(net::URLRequestStatus()); |
| 161 } else if (result < 0) { | 206 } else if (result < 0) { |
| 162 NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, result)); | 207 NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, result)); |
| 163 } else { | 208 } else { |
| 164 // Clear the IO_PENDING status. | 209 // Clear the IO_PENDING status. |
| 165 SetStatus(net::URLRequestStatus()); | 210 SetStatus(net::URLRequestStatus()); |
| 166 } | 211 } |
| 167 NotifyReadComplete(result); | 212 NotifyReadComplete(result); |
| 168 } | 213 } |
| 169 | 214 |
| 170 base::TaskRunner* AndroidStreamReaderURLRequestJob::GetWorkerThreadRunner() { | 215 base::TaskRunner* AndroidStreamReaderURLRequestJob::GetWorkerThreadRunner() { |
| 171 return static_cast<base::TaskRunner*>(BrowserThread::GetBlockingPool()); | 216 return static_cast<base::TaskRunner*>(BrowserThread::GetBlockingPool()); |
| 172 } | 217 } |
| 173 | 218 |
| 174 bool AndroidStreamReaderURLRequestJob::ReadRawData(net::IOBuffer* dest, | 219 bool AndroidStreamReaderURLRequestJob::ReadRawData(net::IOBuffer* dest, |
| 175 int dest_size, | 220 int dest_size, |
| 176 int* bytes_read) { | 221 int* bytes_read) { |
| 222 DCHECK(thread_checker_.CalledOnValidThread()); |
| 177 DCHECK(input_stream_reader_wrapper_); | 223 DCHECK(input_stream_reader_wrapper_); |
| 178 | 224 |
| 179 PostTaskAndReplyWithResult( | 225 PostTaskAndReplyWithResult( |
| 180 GetWorkerThreadRunner(), | 226 GetWorkerThreadRunner(), |
| 181 FROM_HERE, | 227 FROM_HERE, |
| 182 base::Bind(&InputStreamReaderWrapper::ReadRawData, | 228 base::Bind(&InputStreamReaderWrapper::ReadRawData, |
| 183 input_stream_reader_wrapper_, | 229 input_stream_reader_wrapper_, |
| 184 make_scoped_refptr(dest), | 230 make_scoped_refptr(dest), |
| 185 dest_size), | 231 dest_size), |
| 186 base::Bind(&AndroidStreamReaderURLRequestJob::OnReaderReadCompleted, | 232 base::Bind(&AndroidStreamReaderURLRequestJob::OnReaderReadCompleted, |
| 187 weak_factory_.GetWeakPtr())); | 233 weak_factory_.GetWeakPtr())); |
| 188 | 234 |
| 189 SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, | 235 SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, |
| 190 net::ERR_IO_PENDING)); | 236 net::ERR_IO_PENDING)); |
| 191 return false; | 237 return false; |
| 192 } | 238 } |
| 193 | 239 |
| 194 bool AndroidStreamReaderURLRequestJob::GetMimeType( | 240 bool AndroidStreamReaderURLRequestJob::GetMimeType( |
| 195 std::string* mime_type) const { | 241 std::string* mime_type) const { |
| 242 DCHECK(thread_checker_.CalledOnValidThread()); |
| 196 JNIEnv* env = AttachCurrentThread(); | 243 JNIEnv* env = AttachCurrentThread(); |
| 197 DCHECK(env); | 244 DCHECK(env); |
| 198 | 245 |
| 199 if (!input_stream_reader_wrapper_) | 246 if (!input_stream_reader_wrapper_) |
| 200 return false; | 247 return false; |
| 201 | 248 |
| 202 // Since it's possible for this call to alter the InputStream a | 249 // Since it's possible for this call to alter the InputStream a |
| 203 // Seek or ReadRawData operation running in the background is not permitted. | 250 // Seek or ReadRawData operation running in the background is not permitted. |
| 204 DCHECK(!request_->status().is_io_pending()); | 251 DCHECK(!request_->status().is_io_pending()); |
| 205 | 252 |
| 206 return delegate_->GetMimeType( | 253 return delegate_->GetMimeType( |
| 207 env, request(), input_stream_reader_wrapper_->input_stream(), mime_type); | 254 env, request(), input_stream_reader_wrapper_->input_stream(), mime_type); |
| 208 } | 255 } |
| 209 | 256 |
| 210 bool AndroidStreamReaderURLRequestJob::GetCharset(std::string* charset) { | 257 bool AndroidStreamReaderURLRequestJob::GetCharset(std::string* charset) { |
| 258 DCHECK(thread_checker_.CalledOnValidThread()); |
| 211 JNIEnv* env = AttachCurrentThread(); | 259 JNIEnv* env = AttachCurrentThread(); |
| 212 DCHECK(env); | 260 DCHECK(env); |
| 213 | 261 |
| 214 if (!input_stream_reader_wrapper_) | 262 if (!input_stream_reader_wrapper_) |
| 215 return false; | 263 return false; |
| 216 | 264 |
| 217 // Since it's possible for this call to alter the InputStream a | 265 // Since it's possible for this call to alter the InputStream a |
| 218 // Seek or ReadRawData operation running in the background is not permitted. | 266 // Seek or ReadRawData operation running in the background is not permitted. |
| 219 DCHECK(!request_->status().is_io_pending()); | 267 DCHECK(!request_->status().is_io_pending()); |
| 220 | 268 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 235 } else { | 283 } else { |
| 236 // We don't support multiple range requests in one single URL request, | 284 // We don't support multiple range requests in one single URL request, |
| 237 // because we need to do multipart encoding here. | 285 // because we need to do multipart encoding here. |
| 238 NotifyDone(net::URLRequestStatus( | 286 NotifyDone(net::URLRequestStatus( |
| 239 net::URLRequestStatus::FAILED, | 287 net::URLRequestStatus::FAILED, |
| 240 net::ERR_REQUEST_RANGE_NOT_SATISFIABLE)); | 288 net::ERR_REQUEST_RANGE_NOT_SATISFIABLE)); |
| 241 } | 289 } |
| 242 } | 290 } |
| 243 } | 291 } |
| 244 } | 292 } |
| OLD | NEW |