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..835758b9b5ec8cf82acbd3f4e8d379113431370f 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 |
@@ -12,6 +12,7 @@ |
#include "base/bind_helpers.h" |
#include "base/lazy_instance.h" |
#include "base/message_loop.h" |
+#include "base/message_loop_proxy.h" |
#include "base/task_runner.h" |
#include "base/threading/sequenced_worker_pool.h" |
#include "base/threading/thread.h" |
@@ -81,19 +82,57 @@ AndroidStreamReaderURLRequestJob::AndroidStreamReaderURLRequestJob( |
AndroidStreamReaderURLRequestJob::~AndroidStreamReaderURLRequestJob() { |
} |
+namespace { |
+ |
+typedef base::Callback< |
+ void(scoped_ptr<AndroidStreamReaderURLRequestJob::Delegate>, |
+ scoped_ptr<InputStream>)> OnInputStreamOpenedCallback; |
+ |
+// static |
+void OpenInputStreamOnWorkerThread( |
+ scoped_refptr<base::MessageLoopProxy> job_thread_proxy, |
+ scoped_ptr<AndroidStreamReaderURLRequestJob::Delegate> delegate, |
+ const GURL& url, |
+ OnInputStreamOpenedCallback callback) { |
+ |
+ JNIEnv* env = AttachCurrentThread(); |
+ DCHECK(env); |
+ |
+ scoped_ptr<InputStream> input_stream = delegate->OpenInputStream(env, url); |
+ job_thread_proxy->PostTask(FROM_HERE, |
+ base::Bind(callback, |
+ base::Passed(delegate.Pass()), |
+ base::Passed(input_stream.Pass()))); |
+} |
+ |
+} // namespace |
+ |
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. |
+ GetWorkerThreadRunner()->PostTask( |
FROM_HERE, |
base::Bind( |
- &AndroidStreamReaderURLRequestJob::StartAsync, |
- weak_factory_.GetWeakPtr())); |
+ &OpenInputStreamOnWorkerThread, |
+ MessageLoop::current()->message_loop_proxy(), |
+ // 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_), |
+ request()->url(), |
+ base::Bind(&AndroidStreamReaderURLRequestJob::OnInputStreamOpened, |
+ weak_factory_.GetWeakPtr()))); |
} |
void AndroidStreamReaderURLRequestJob::Kill() { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
weak_factory_.InvalidateWeakPtrs(); |
URLRequestJob::Kill(); |
} |
@@ -103,28 +142,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<Delegate> returned_delegate, |
+ scoped_ptr<android_webview::InputStream> input_stream) { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ DCHECK(returned_delegate); |
+ delegate_ = returned_delegate.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 +180,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 +192,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 +219,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 +239,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 +255,7 @@ bool AndroidStreamReaderURLRequestJob::GetMimeType( |
} |
bool AndroidStreamReaderURLRequestJob::GetCharset(std::string* charset) { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
JNIEnv* env = AttachCurrentThread(); |
DCHECK(env); |