| 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 030f80a687afbe10bfe60e0c003a5ab9ad5c6eaa..3050094aecc419fb85cc366fa6194dc5d9be5a16 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
|
| @@ -30,6 +30,44 @@ using base::android::AttachCurrentThread;
|
| using base::PostTaskAndReplyWithResult;
|
| using content::BrowserThread;
|
|
|
| +// The requests posted to the worker thread might outlive the job. Thread-safe
|
| +// ref counting is used to ensure that the InputStream and InputStreamReader
|
| +// members of this class are still there when the closure is run on the worker
|
| +// thread.
|
| +class InputStreamReaderWrapper :
|
| + public base::RefCountedThreadSafe<InputStreamReaderWrapper> {
|
| + public:
|
| + InputStreamReaderWrapper(
|
| + scoped_ptr<InputStream> input_stream,
|
| + scoped_ptr<InputStreamReader> input_stream_reader)
|
| + : input_stream_(input_stream.Pass()),
|
| + input_stream_reader_(input_stream_reader.Pass()) {
|
| + DCHECK(input_stream_);
|
| + DCHECK(input_stream_reader_);
|
| + }
|
| +
|
| + android_webview::InputStream* input_stream() {
|
| + return input_stream_.get();
|
| + }
|
| +
|
| + int Seek(const net::HttpByteRange& byte_range) {
|
| + return input_stream_reader_->Seek(byte_range);
|
| + }
|
| +
|
| + int ReadRawData(net::IOBuffer* buffer, int buffer_size) {
|
| + return input_stream_reader_->ReadRawData(buffer, buffer_size);
|
| + }
|
| +
|
| + private:
|
| + friend class base::RefCountedThreadSafe<InputStreamReaderWrapper>;
|
| + ~InputStreamReaderWrapper() {}
|
| +
|
| + scoped_ptr<android_webview::InputStream> input_stream_;
|
| + scoped_ptr<android_webview::InputStreamReader> input_stream_reader_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(InputStreamReaderWrapper);
|
| +};
|
| +
|
| AndroidStreamReaderURLRequestJob::AndroidStreamReaderURLRequestJob(
|
| net::URLRequest* request,
|
| net::NetworkDelegate* network_delegate,
|
| @@ -37,7 +75,7 @@ AndroidStreamReaderURLRequestJob::AndroidStreamReaderURLRequestJob(
|
| : URLRequestJob(request, network_delegate),
|
| delegate_(delegate.Pass()),
|
| ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {
|
| - DCHECK(delegate_.get());
|
| + DCHECK(delegate_);
|
| }
|
|
|
| AndroidStreamReaderURLRequestJob::~AndroidStreamReaderURLRequestJob() {
|
| @@ -46,7 +84,8 @@ AndroidStreamReaderURLRequestJob::~AndroidStreamReaderURLRequestJob() {
|
| void AndroidStreamReaderURLRequestJob::Start() {
|
| // 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, 0));
|
| + SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING,
|
| + net::ERR_IO_PENDING));
|
| MessageLoop::current()->PostTask(
|
| FROM_HERE,
|
| base::Bind(
|
| @@ -59,9 +98,9 @@ void AndroidStreamReaderURLRequestJob::Kill() {
|
| URLRequestJob::Kill();
|
| }
|
|
|
| -scoped_refptr<InputStreamReader>
|
| +scoped_ptr<InputStreamReader>
|
| AndroidStreamReaderURLRequestJob::CreateStreamReader(InputStream* stream) {
|
| - return make_scoped_refptr(new InputStreamReader(stream));
|
| + return make_scoped_ptr(new InputStreamReader(stream));
|
| }
|
|
|
| void AndroidStreamReaderURLRequestJob::StartAsync() {
|
| @@ -70,27 +109,34 @@ void AndroidStreamReaderURLRequestJob::StartAsync() {
|
|
|
| // This could be done in the InputStreamReader but would force more
|
| // complex synchronization in the delegate.
|
| - stream_ = delegate_->OpenInputStream(env, request());
|
| - if (!stream_) {
|
| - NotifyDone(
|
| - net::URLRequestStatus(net::URLRequestStatus::FAILED, net::ERR_FAILED));
|
| + scoped_ptr<android_webview::InputStream> stream(
|
| + delegate_->OpenInputStream(env, request()));
|
| +
|
| + if (!stream) {
|
| + NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED,
|
| + net::ERR_FAILED));
|
| return;
|
| }
|
|
|
| - DCHECK(!input_stream_reader_);
|
| - input_stream_reader_ = CreateStreamReader(stream_.get());
|
| - CHECK(input_stream_reader_);
|
| + scoped_ptr<InputStreamReader> input_stream_reader(
|
| + CreateStreamReader(stream.get()));
|
| + DCHECK(input_stream_reader);
|
| +
|
| + DCHECK(!input_stream_reader_wrapper_);
|
| + input_stream_reader_wrapper_ =
|
| + new InputStreamReaderWrapper(stream.Pass(), input_stream_reader.Pass());
|
|
|
| PostTaskAndReplyWithResult(
|
| GetWorkerThreadRunner(),
|
| FROM_HERE,
|
| - base::Bind(&InputStreamReader::Seek, input_stream_reader_, byte_range_),
|
| + base::Bind(&InputStreamReaderWrapper::Seek,
|
| + input_stream_reader_wrapper_,
|
| + byte_range_),
|
| base::Bind(&AndroidStreamReaderURLRequestJob::OnReaderSeekCompleted,
|
| weak_factory_.GetWeakPtr()));
|
| }
|
|
|
| -void AndroidStreamReaderURLRequestJob::OnReaderSeekCompleted(
|
| - int result) {
|
| +void AndroidStreamReaderURLRequestJob::OnReaderSeekCompleted(int result) {
|
| // Clear the IO_PENDING status set in Start().
|
| SetStatus(net::URLRequestStatus());
|
| if (result >= 0) {
|
| @@ -101,8 +147,7 @@ void AndroidStreamReaderURLRequestJob::OnReaderSeekCompleted(
|
| }
|
| }
|
|
|
| -void AndroidStreamReaderURLRequestJob::OnReaderReadCompleted(
|
| - int result) {
|
| +void AndroidStreamReaderURLRequestJob::OnReaderReadCompleted(int result) {
|
| // 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),
|
| @@ -129,19 +174,20 @@ base::TaskRunner* AndroidStreamReaderURLRequestJob::GetWorkerThreadRunner() {
|
| bool AndroidStreamReaderURLRequestJob::ReadRawData(net::IOBuffer* dest,
|
| int dest_size,
|
| int* bytes_read) {
|
| - DCHECK(input_stream_reader_);
|
| + DCHECK(input_stream_reader_wrapper_);
|
|
|
| PostTaskAndReplyWithResult(
|
| GetWorkerThreadRunner(),
|
| FROM_HERE,
|
| - base::Bind(&InputStreamReader::ReadRawData,
|
| - input_stream_reader_,
|
| - base::Unretained(dest),
|
| + base::Bind(&InputStreamReaderWrapper::ReadRawData,
|
| + input_stream_reader_wrapper_,
|
| + make_scoped_refptr(dest),
|
| dest_size),
|
| base::Bind(&AndroidStreamReaderURLRequestJob::OnReaderReadCompleted,
|
| weak_factory_.GetWeakPtr()));
|
|
|
| - SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0));
|
| + SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING,
|
| + net::ERR_IO_PENDING));
|
| return false;
|
| }
|
|
|
| @@ -150,21 +196,30 @@ bool AndroidStreamReaderURLRequestJob::GetMimeType(
|
| JNIEnv* env = AttachCurrentThread();
|
| DCHECK(env);
|
|
|
| - if (!stream_)
|
| + if (!input_stream_reader_wrapper_)
|
| return false;
|
|
|
| - return delegate_->GetMimeType(env, request(), *stream_, mime_type);
|
| + // Since it's possible for this call to alter the InputStream a
|
| + // Seek or ReadRawData operation running in the background is not permitted.
|
| + DCHECK(!request_->status().is_io_pending());
|
| +
|
| + return delegate_->GetMimeType(
|
| + env, request(), input_stream_reader_wrapper_->input_stream(), mime_type);
|
| }
|
|
|
| -bool AndroidStreamReaderURLRequestJob::GetCharset(
|
| - std::string* charset) {
|
| +bool AndroidStreamReaderURLRequestJob::GetCharset(std::string* charset) {
|
| JNIEnv* env = AttachCurrentThread();
|
| DCHECK(env);
|
|
|
| - if (!stream_)
|
| + if (!input_stream_reader_wrapper_)
|
| return false;
|
|
|
| - return delegate_->GetCharset(env, request(), *stream_, charset);
|
| + // Since it's possible for this call to alter the InputStream a
|
| + // Seek or ReadRawData operation running in the background is not permitted.
|
| + DCHECK(!request_->status().is_io_pending());
|
| +
|
| + return delegate_->GetCharset(
|
| + env, request(), input_stream_reader_wrapper_->input_stream(), charset);
|
| }
|
|
|
| void AndroidStreamReaderURLRequestJob::SetExtraRequestHeaders(
|
|
|