Chromium Code Reviews| Index: android_webview/browser/net/android_stream_reader_url_request_job.cc |
| diff --git a/android_webview/browser/net/android_stream_reader_url_request_job.cc b/android_webview/browser/net/android_stream_reader_url_request_job.cc |
| index 3050094aecc419fb85cc366fa6194dc5d9be5a16..635746e59848a9db0a1b1c531e8765c57fcc74b4 100644 |
| --- a/android_webview/browser/net/android_stream_reader_url_request_job.cc |
| +++ b/android_webview/browser/net/android_stream_reader_url_request_job.cc |
| @@ -68,6 +68,15 @@ class InputStreamReaderWrapper : |
| DISALLOW_COPY_AND_ASSIGN(InputStreamReaderWrapper); |
| }; |
| +// In unittests the Job isn't created on the IO thread making it slightly |
| +// harder to post back to the job's thread. We use a helper data structure to |
| +// be able to use PostTaskAndReplyWithResult with OpenInputStreamOnWorkerThread |
| +// which will take care of posting back to the Job's thread. |
| +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
|
| + scoped_ptr<InputStream> input_stream; |
| + scoped_ptr<AndroidStreamReaderURLRequestJob::Delegate> delegate; |
| +}; |
| + |
| AndroidStreamReaderURLRequestJob::AndroidStreamReaderURLRequestJob( |
| net::URLRequest* request, |
| net::NetworkDelegate* network_delegate, |
| @@ -81,19 +90,47 @@ AndroidStreamReaderURLRequestJob::AndroidStreamReaderURLRequestJob( |
| AndroidStreamReaderURLRequestJob::~AndroidStreamReaderURLRequestJob() { |
| } |
| +// static |
| +scoped_ptr<AndroidStreamReaderURLRequestJob::OpenInputStreamResult> |
| +AndroidStreamReaderURLRequestJob::OpenInputStreamOnWorkerThread( |
| + scoped_ptr<AndroidStreamReaderURLRequestJob::Delegate> delegate, |
| + const GURL& url) { |
| + JNIEnv* env = AttachCurrentThread(); |
| + DCHECK(env); |
| + |
| + scoped_ptr<AndroidStreamReaderURLRequestJob::OpenInputStreamResult> result( |
| + new AndroidStreamReaderURLRequestJob::OpenInputStreamResult()); |
| + result->input_stream = delegate->OpenInputStream(env, url); |
| + result->delegate = delegate.Pass(); |
| + return result.Pass(); |
| +} |
| + |
| void AndroidStreamReaderURLRequestJob::Start() { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| // Start reading asynchronously so that all error reporting and data |
| // callbacks happen as they would for network requests. |
| SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, |
| net::ERR_IO_PENDING)); |
| - MessageLoop::current()->PostTask( |
| + |
| + // This could be done in the InputStreamReader but would force more |
| + // complex synchronization in the delegate. |
| + PostTaskAndReplyWithResult( |
| + GetWorkerThreadRunner(), |
| FROM_HERE, |
| base::Bind( |
| - &AndroidStreamReaderURLRequestJob::StartAsync, |
| - weak_factory_.GetWeakPtr())); |
| + &OpenInputStreamOnWorkerThread, |
| + // This is intentional - the job could be deleted while the callback |
| + // is executing on the background thread. |
| + // The delegate will be "returned" to the job once the InputStream |
| + // open attempt is completed. |
| + 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
|
| + request()->url()), |
| + base::Bind(&AndroidStreamReaderURLRequestJob::OnInputStreamOpened, |
| + weak_factory_.GetWeakPtr())); |
| } |
| void AndroidStreamReaderURLRequestJob::Kill() { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| weak_factory_.InvalidateWeakPtrs(); |
| URLRequestJob::Kill(); |
| } |
| @@ -103,28 +140,32 @@ AndroidStreamReaderURLRequestJob::CreateStreamReader(InputStream* stream) { |
| return make_scoped_ptr(new InputStreamReader(stream)); |
| } |
| -void AndroidStreamReaderURLRequestJob::StartAsync() { |
| - JNIEnv* env = AttachCurrentThread(); |
| - DCHECK(env); |
| - |
| - // This could be done in the InputStreamReader but would force more |
| - // complex synchronization in the delegate. |
| - scoped_ptr<android_webview::InputStream> stream( |
| - delegate_->OpenInputStream(env, request())); |
| - |
| - if (!stream) { |
| - NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, |
| - net::ERR_FAILED)); |
| +void AndroidStreamReaderURLRequestJob::OnInputStreamOpened( |
| + scoped_ptr<OpenInputStreamResult> result) { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + DCHECK(result->delegate); |
| + delegate_ = result->delegate.Pass(); |
| + scoped_ptr<InputStream> input_stream = result->input_stream.Pass(); |
| + |
| + if (!input_stream) { |
| + bool restart_required = false; |
| + delegate_->OnInputStreamOpenFailed(request(), &restart_required); |
| + if (restart_required) { |
| + NotifyRestartRequired(); |
| + } else { |
| + NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, |
| + net::ERR_FAILED)); |
| + } |
| return; |
| } |
| scoped_ptr<InputStreamReader> input_stream_reader( |
| - CreateStreamReader(stream.get())); |
| + CreateStreamReader(input_stream.get())); |
| DCHECK(input_stream_reader); |
| DCHECK(!input_stream_reader_wrapper_); |
| - input_stream_reader_wrapper_ = |
| - new InputStreamReaderWrapper(stream.Pass(), input_stream_reader.Pass()); |
| + input_stream_reader_wrapper_ = new InputStreamReaderWrapper( |
| + input_stream.Pass(), input_stream_reader.Pass()); |
| PostTaskAndReplyWithResult( |
| GetWorkerThreadRunner(), |
| @@ -137,6 +178,7 @@ void AndroidStreamReaderURLRequestJob::StartAsync() { |
| } |
| void AndroidStreamReaderURLRequestJob::OnReaderSeekCompleted(int result) { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| // Clear the IO_PENDING status set in Start(). |
| SetStatus(net::URLRequestStatus()); |
| if (result >= 0) { |
| @@ -148,6 +190,7 @@ void AndroidStreamReaderURLRequestJob::OnReaderSeekCompleted(int result) { |
| } |
| void AndroidStreamReaderURLRequestJob::OnReaderReadCompleted(int result) { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| // The URLRequest API contract requires that: |
| // * NotifyDone be called once, to set the status code, indicate the job is |
| // finished (there will be no further IO), |
| @@ -174,6 +217,7 @@ base::TaskRunner* AndroidStreamReaderURLRequestJob::GetWorkerThreadRunner() { |
| bool AndroidStreamReaderURLRequestJob::ReadRawData(net::IOBuffer* dest, |
| int dest_size, |
| int* bytes_read) { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| DCHECK(input_stream_reader_wrapper_); |
| PostTaskAndReplyWithResult( |
| @@ -193,6 +237,7 @@ bool AndroidStreamReaderURLRequestJob::ReadRawData(net::IOBuffer* dest, |
| bool AndroidStreamReaderURLRequestJob::GetMimeType( |
| std::string* mime_type) const { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| JNIEnv* env = AttachCurrentThread(); |
| DCHECK(env); |
| @@ -208,6 +253,7 @@ bool AndroidStreamReaderURLRequestJob::GetMimeType( |
| } |
| bool AndroidStreamReaderURLRequestJob::GetCharset(std::string* charset) { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| JNIEnv* env = AttachCurrentThread(); |
| DCHECK(env); |