Chromium Code Reviews| 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" |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 61 private: | 61 private: |
| 62 friend class base::RefCountedThreadSafe<InputStreamReaderWrapper>; | 62 friend class base::RefCountedThreadSafe<InputStreamReaderWrapper>; |
| 63 ~InputStreamReaderWrapper() {} | 63 ~InputStreamReaderWrapper() {} |
| 64 | 64 |
| 65 scoped_ptr<android_webview::InputStream> input_stream_; | 65 scoped_ptr<android_webview::InputStream> input_stream_; |
| 66 scoped_ptr<android_webview::InputStreamReader> input_stream_reader_; | 66 scoped_ptr<android_webview::InputStreamReader> input_stream_reader_; |
| 67 | 67 |
| 68 DISALLOW_COPY_AND_ASSIGN(InputStreamReaderWrapper); | 68 DISALLOW_COPY_AND_ASSIGN(InputStreamReaderWrapper); |
| 69 }; | 69 }; |
| 70 | 70 |
| 71 // In unittests the Job isn't created on the IO thread making it slightly | |
| 72 // harder to post back to the job's thread. We use a helper data structure to | |
| 73 // be able to use PostTaskAndReplyWithResult with OpenInputStreamOnWorkerThread | |
| 74 // which will take care of posting back to the Job's thread. | |
| 75 struct AndroidStreamReaderURLRequestJob::OpenInputStreamResult { | |
|
mnaganov (inactive)
2013/03/06 09:26:47
Is this about C++ or Java unittests? If C++, perha
mkosiba (inactive)
2013/03/06 19:05:27
C++ unittests. So it looks all of the remaining jo
| |
| 76 scoped_ptr<InputStream> input_stream; | |
| 77 scoped_ptr<AndroidStreamReaderURLRequestJob::Delegate> delegate; | |
| 78 }; | |
| 79 | |
| 71 AndroidStreamReaderURLRequestJob::AndroidStreamReaderURLRequestJob( | 80 AndroidStreamReaderURLRequestJob::AndroidStreamReaderURLRequestJob( |
| 72 net::URLRequest* request, | 81 net::URLRequest* request, |
| 73 net::NetworkDelegate* network_delegate, | 82 net::NetworkDelegate* network_delegate, |
| 74 scoped_ptr<Delegate> delegate) | 83 scoped_ptr<Delegate> delegate) |
| 75 : URLRequestJob(request, network_delegate), | 84 : URLRequestJob(request, network_delegate), |
| 76 delegate_(delegate.Pass()), | 85 delegate_(delegate.Pass()), |
| 77 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) { | 86 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) { |
| 78 DCHECK(delegate_); | 87 DCHECK(delegate_); |
| 79 } | 88 } |
| 80 | 89 |
| 81 AndroidStreamReaderURLRequestJob::~AndroidStreamReaderURLRequestJob() { | 90 AndroidStreamReaderURLRequestJob::~AndroidStreamReaderURLRequestJob() { |
| 82 } | 91 } |
| 83 | 92 |
| 93 // static | |
| 94 scoped_ptr<AndroidStreamReaderURLRequestJob::OpenInputStreamResult> | |
| 95 AndroidStreamReaderURLRequestJob::OpenInputStreamOnWorkerThread( | |
| 96 scoped_ptr<AndroidStreamReaderURLRequestJob::Delegate> delegate, | |
| 97 const GURL& url) { | |
| 98 JNIEnv* env = AttachCurrentThread(); | |
| 99 DCHECK(env); | |
| 100 | |
| 101 scoped_ptr<AndroidStreamReaderURLRequestJob::OpenInputStreamResult> result( | |
| 102 new AndroidStreamReaderURLRequestJob::OpenInputStreamResult()); | |
| 103 result->input_stream = delegate->OpenInputStream(env, url); | |
| 104 result->delegate = delegate.Pass(); | |
| 105 return result.Pass(); | |
| 106 } | |
| 107 | |
| 84 void AndroidStreamReaderURLRequestJob::Start() { | 108 void AndroidStreamReaderURLRequestJob::Start() { |
| 109 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 85 // Start reading asynchronously so that all error reporting and data | 110 // Start reading asynchronously so that all error reporting and data |
| 86 // callbacks happen as they would for network requests. | 111 // callbacks happen as they would for network requests. |
| 87 SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, | 112 SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, |
| 88 net::ERR_IO_PENDING)); | 113 net::ERR_IO_PENDING)); |
| 89 MessageLoop::current()->PostTask( | 114 |
| 115 // This could be done in the InputStreamReader but would force more | |
| 116 // complex synchronization in the delegate. | |
| 117 PostTaskAndReplyWithResult( | |
| 118 GetWorkerThreadRunner(), | |
| 90 FROM_HERE, | 119 FROM_HERE, |
| 91 base::Bind( | 120 base::Bind( |
| 92 &AndroidStreamReaderURLRequestJob::StartAsync, | 121 &OpenInputStreamOnWorkerThread, |
| 93 weak_factory_.GetWeakPtr())); | 122 // This is intentional - the job could be deleted while the callback |
| 123 // is executing on the background thread. | |
| 124 // The delegate will be "returned" to the job once the InputStream | |
| 125 // open attempt is completed. | |
| 126 base::Passed(&delegate_), | |
|
boliu
2013/03/06 02:30:18
How bad is it to make delegate RefCountedThreadSaf
mkosiba (inactive)
2013/03/06 19:05:27
but the delegate _isn't_ thread safe. I actually l
| |
| 127 request()->url()), | |
| 128 base::Bind(&AndroidStreamReaderURLRequestJob::OnInputStreamOpened, | |
| 129 weak_factory_.GetWeakPtr())); | |
| 94 } | 130 } |
| 95 | 131 |
| 96 void AndroidStreamReaderURLRequestJob::Kill() { | 132 void AndroidStreamReaderURLRequestJob::Kill() { |
| 133 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 97 weak_factory_.InvalidateWeakPtrs(); | 134 weak_factory_.InvalidateWeakPtrs(); |
| 98 URLRequestJob::Kill(); | 135 URLRequestJob::Kill(); |
| 99 } | 136 } |
| 100 | 137 |
| 101 scoped_ptr<InputStreamReader> | 138 scoped_ptr<InputStreamReader> |
| 102 AndroidStreamReaderURLRequestJob::CreateStreamReader(InputStream* stream) { | 139 AndroidStreamReaderURLRequestJob::CreateStreamReader(InputStream* stream) { |
| 103 return make_scoped_ptr(new InputStreamReader(stream)); | 140 return make_scoped_ptr(new InputStreamReader(stream)); |
| 104 } | 141 } |
| 105 | 142 |
| 106 void AndroidStreamReaderURLRequestJob::StartAsync() { | 143 void AndroidStreamReaderURLRequestJob::OnInputStreamOpened( |
| 107 JNIEnv* env = AttachCurrentThread(); | 144 scoped_ptr<OpenInputStreamResult> result) { |
| 108 DCHECK(env); | 145 DCHECK(thread_checker_.CalledOnValidThread()); |
| 146 DCHECK(result->delegate); | |
| 147 delegate_ = result->delegate.Pass(); | |
| 148 scoped_ptr<InputStream> input_stream = result->input_stream.Pass(); | |
| 109 | 149 |
| 110 // This could be done in the InputStreamReader but would force more | 150 if (!input_stream) { |
| 111 // complex synchronization in the delegate. | 151 bool restart_required = false; |
| 112 scoped_ptr<android_webview::InputStream> stream( | 152 delegate_->OnInputStreamOpenFailed(request(), &restart_required); |
| 113 delegate_->OpenInputStream(env, request())); | 153 if (restart_required) { |
| 114 | 154 NotifyRestartRequired(); |
| 115 if (!stream) { | 155 } else { |
| 116 NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, | 156 NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, |
| 117 net::ERR_FAILED)); | 157 net::ERR_FAILED)); |
| 158 } | |
| 118 return; | 159 return; |
| 119 } | 160 } |
| 120 | 161 |
| 121 scoped_ptr<InputStreamReader> input_stream_reader( | 162 scoped_ptr<InputStreamReader> input_stream_reader( |
| 122 CreateStreamReader(stream.get())); | 163 CreateStreamReader(input_stream.get())); |
| 123 DCHECK(input_stream_reader); | 164 DCHECK(input_stream_reader); |
| 124 | 165 |
| 125 DCHECK(!input_stream_reader_wrapper_); | 166 DCHECK(!input_stream_reader_wrapper_); |
| 126 input_stream_reader_wrapper_ = | 167 input_stream_reader_wrapper_ = new InputStreamReaderWrapper( |
| 127 new InputStreamReaderWrapper(stream.Pass(), input_stream_reader.Pass()); | 168 input_stream.Pass(), input_stream_reader.Pass()); |
| 128 | 169 |
| 129 PostTaskAndReplyWithResult( | 170 PostTaskAndReplyWithResult( |
| 130 GetWorkerThreadRunner(), | 171 GetWorkerThreadRunner(), |
| 131 FROM_HERE, | 172 FROM_HERE, |
| 132 base::Bind(&InputStreamReaderWrapper::Seek, | 173 base::Bind(&InputStreamReaderWrapper::Seek, |
| 133 input_stream_reader_wrapper_, | 174 input_stream_reader_wrapper_, |
| 134 byte_range_), | 175 byte_range_), |
| 135 base::Bind(&AndroidStreamReaderURLRequestJob::OnReaderSeekCompleted, | 176 base::Bind(&AndroidStreamReaderURLRequestJob::OnReaderSeekCompleted, |
| 136 weak_factory_.GetWeakPtr())); | 177 weak_factory_.GetWeakPtr())); |
| 137 } | 178 } |
| 138 | 179 |
| 139 void AndroidStreamReaderURLRequestJob::OnReaderSeekCompleted(int result) { | 180 void AndroidStreamReaderURLRequestJob::OnReaderSeekCompleted(int result) { |
| 181 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 140 // Clear the IO_PENDING status set in Start(). | 182 // Clear the IO_PENDING status set in Start(). |
| 141 SetStatus(net::URLRequestStatus()); | 183 SetStatus(net::URLRequestStatus()); |
| 142 if (result >= 0) { | 184 if (result >= 0) { |
| 143 set_expected_content_size(result); | 185 set_expected_content_size(result); |
| 144 NotifyHeadersComplete(); | 186 NotifyHeadersComplete(); |
| 145 } else { | 187 } else { |
| 146 NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, result)); | 188 NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, result)); |
| 147 } | 189 } |
| 148 } | 190 } |
| 149 | 191 |
| 150 void AndroidStreamReaderURLRequestJob::OnReaderReadCompleted(int result) { | 192 void AndroidStreamReaderURLRequestJob::OnReaderReadCompleted(int result) { |
| 193 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 151 // The URLRequest API contract requires that: | 194 // The URLRequest API contract requires that: |
| 152 // * NotifyDone be called once, to set the status code, indicate the job is | 195 // * NotifyDone be called once, to set the status code, indicate the job is |
| 153 // finished (there will be no further IO), | 196 // finished (there will be no further IO), |
| 154 // * NotifyReadComplete be called if false is returned from ReadRawData to | 197 // * NotifyReadComplete be called if false is returned from ReadRawData to |
| 155 // indicate that the IOBuffer will not be used by the job anymore. | 198 // 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 | 199 // There might be multiple calls to ReadRawData (and thus multiple calls to |
| 157 // NotifyReadComplete), which is why NotifyDone is called only on errors | 200 // NotifyReadComplete), which is why NotifyDone is called only on errors |
| 158 // (result < 0) and end of data (result == 0). | 201 // (result < 0) and end of data (result == 0). |
| 159 if (result == 0) { | 202 if (result == 0) { |
| 160 NotifyDone(net::URLRequestStatus()); | 203 NotifyDone(net::URLRequestStatus()); |
| 161 } else if (result < 0) { | 204 } else if (result < 0) { |
| 162 NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, result)); | 205 NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, result)); |
| 163 } else { | 206 } else { |
| 164 // Clear the IO_PENDING status. | 207 // Clear the IO_PENDING status. |
| 165 SetStatus(net::URLRequestStatus()); | 208 SetStatus(net::URLRequestStatus()); |
| 166 } | 209 } |
| 167 NotifyReadComplete(result); | 210 NotifyReadComplete(result); |
| 168 } | 211 } |
| 169 | 212 |
| 170 base::TaskRunner* AndroidStreamReaderURLRequestJob::GetWorkerThreadRunner() { | 213 base::TaskRunner* AndroidStreamReaderURLRequestJob::GetWorkerThreadRunner() { |
| 171 return static_cast<base::TaskRunner*>(BrowserThread::GetBlockingPool()); | 214 return static_cast<base::TaskRunner*>(BrowserThread::GetBlockingPool()); |
| 172 } | 215 } |
| 173 | 216 |
| 174 bool AndroidStreamReaderURLRequestJob::ReadRawData(net::IOBuffer* dest, | 217 bool AndroidStreamReaderURLRequestJob::ReadRawData(net::IOBuffer* dest, |
| 175 int dest_size, | 218 int dest_size, |
| 176 int* bytes_read) { | 219 int* bytes_read) { |
| 220 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 177 DCHECK(input_stream_reader_wrapper_); | 221 DCHECK(input_stream_reader_wrapper_); |
| 178 | 222 |
| 179 PostTaskAndReplyWithResult( | 223 PostTaskAndReplyWithResult( |
| 180 GetWorkerThreadRunner(), | 224 GetWorkerThreadRunner(), |
| 181 FROM_HERE, | 225 FROM_HERE, |
| 182 base::Bind(&InputStreamReaderWrapper::ReadRawData, | 226 base::Bind(&InputStreamReaderWrapper::ReadRawData, |
| 183 input_stream_reader_wrapper_, | 227 input_stream_reader_wrapper_, |
| 184 make_scoped_refptr(dest), | 228 make_scoped_refptr(dest), |
| 185 dest_size), | 229 dest_size), |
| 186 base::Bind(&AndroidStreamReaderURLRequestJob::OnReaderReadCompleted, | 230 base::Bind(&AndroidStreamReaderURLRequestJob::OnReaderReadCompleted, |
| 187 weak_factory_.GetWeakPtr())); | 231 weak_factory_.GetWeakPtr())); |
| 188 | 232 |
| 189 SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, | 233 SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, |
| 190 net::ERR_IO_PENDING)); | 234 net::ERR_IO_PENDING)); |
| 191 return false; | 235 return false; |
| 192 } | 236 } |
| 193 | 237 |
| 194 bool AndroidStreamReaderURLRequestJob::GetMimeType( | 238 bool AndroidStreamReaderURLRequestJob::GetMimeType( |
| 195 std::string* mime_type) const { | 239 std::string* mime_type) const { |
| 240 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 196 JNIEnv* env = AttachCurrentThread(); | 241 JNIEnv* env = AttachCurrentThread(); |
| 197 DCHECK(env); | 242 DCHECK(env); |
| 198 | 243 |
| 199 if (!input_stream_reader_wrapper_) | 244 if (!input_stream_reader_wrapper_) |
| 200 return false; | 245 return false; |
| 201 | 246 |
| 202 // Since it's possible for this call to alter the InputStream a | 247 // Since it's possible for this call to alter the InputStream a |
| 203 // Seek or ReadRawData operation running in the background is not permitted. | 248 // Seek or ReadRawData operation running in the background is not permitted. |
| 204 DCHECK(!request_->status().is_io_pending()); | 249 DCHECK(!request_->status().is_io_pending()); |
| 205 | 250 |
| 206 return delegate_->GetMimeType( | 251 return delegate_->GetMimeType( |
| 207 env, request(), input_stream_reader_wrapper_->input_stream(), mime_type); | 252 env, request(), input_stream_reader_wrapper_->input_stream(), mime_type); |
| 208 } | 253 } |
| 209 | 254 |
| 210 bool AndroidStreamReaderURLRequestJob::GetCharset(std::string* charset) { | 255 bool AndroidStreamReaderURLRequestJob::GetCharset(std::string* charset) { |
| 256 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 211 JNIEnv* env = AttachCurrentThread(); | 257 JNIEnv* env = AttachCurrentThread(); |
| 212 DCHECK(env); | 258 DCHECK(env); |
| 213 | 259 |
| 214 if (!input_stream_reader_wrapper_) | 260 if (!input_stream_reader_wrapper_) |
| 215 return false; | 261 return false; |
| 216 | 262 |
| 217 // Since it's possible for this call to alter the InputStream a | 263 // Since it's possible for this call to alter the InputStream a |
| 218 // Seek or ReadRawData operation running in the background is not permitted. | 264 // Seek or ReadRawData operation running in the background is not permitted. |
| 219 DCHECK(!request_->status().is_io_pending()); | 265 DCHECK(!request_->status().is_io_pending()); |
| 220 | 266 |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 235 } else { | 281 } else { |
| 236 // We don't support multiple range requests in one single URL request, | 282 // We don't support multiple range requests in one single URL request, |
| 237 // because we need to do multipart encoding here. | 283 // because we need to do multipart encoding here. |
| 238 NotifyDone(net::URLRequestStatus( | 284 NotifyDone(net::URLRequestStatus( |
| 239 net::URLRequestStatus::FAILED, | 285 net::URLRequestStatus::FAILED, |
| 240 net::ERR_REQUEST_RANGE_NOT_SATISFIABLE)); | 286 net::ERR_REQUEST_RANGE_NOT_SATISFIABLE)); |
| 241 } | 287 } |
| 242 } | 288 } |
| 243 } | 289 } |
| 244 } | 290 } |
| OLD | NEW |