| Index: net/base/upload_file_element_reader.cc
|
| diff --git a/net/base/upload_file_element_reader.cc b/net/base/upload_file_element_reader.cc
|
| index 5cb143984c9e39f6bff1dcbcaf4185ed65fb4ab1..4a17595e2e1afc8044e25ce967956bf08a4e401c 100644
|
| --- a/net/base/upload_file_element_reader.cc
|
| +++ b/net/base/upload_file_element_reader.cc
|
| @@ -10,6 +10,7 @@
|
| #include "base/threading/thread_restrictions.h"
|
| #include "base/threading/worker_pool.h"
|
| #include "net/base/file_stream.h"
|
| +#include "net/base/io_buffer.h"
|
| #include "net/base/net_errors.h"
|
|
|
| namespace net {
|
| @@ -20,7 +21,7 @@ namespace {
|
| // UploadFileElementReader::GetContentLength() when set to non-zero.
|
| uint64 overriding_content_length = 0;
|
|
|
| -// This method is used to implement Init().
|
| +// This function is used to implement Init().
|
| void InitInternal(const FilePath& path,
|
| uint64 range_offset,
|
| uint64 range_length,
|
| @@ -72,6 +73,35 @@ void InitInternal(const FilePath& path,
|
| *out_result = OK;
|
| }
|
|
|
| +// This function is used to implement Read().
|
| +void ReadInternal(scoped_refptr<IOBuffer> buf,
|
| + int buf_length,
|
| + uint64 bytes_remaining,
|
| + FileStream* file_stream,
|
| + int* result) {
|
| + DCHECK_LT(0, buf_length);
|
| +
|
| + const uint64 num_bytes_to_read =
|
| + std::min(bytes_remaining, static_cast<uint64>(buf_length));
|
| +
|
| + if (num_bytes_to_read > 0) {
|
| + int num_bytes_consumed = 0;
|
| + // file_stream is NULL if the target file is
|
| + // missing or not readable.
|
| + if (file_stream) {
|
| + num_bytes_consumed = file_stream->ReadSync(buf->data(),
|
| + num_bytes_to_read);
|
| + }
|
| + if (num_bytes_consumed <= 0) {
|
| + // If there's less data to read than we initially observed, then
|
| + // pad with zero. Otherwise the server will hang waiting for the
|
| + // rest of the data.
|
| + memset(buf->data(), 0, num_bytes_to_read);
|
| + }
|
| + }
|
| + *result = num_bytes_to_read;
|
| +}
|
| +
|
| } // namespace
|
|
|
| UploadFileElementReader::UploadFileElementReader(
|
| @@ -145,32 +175,42 @@ uint64 UploadFileElementReader::BytesRemaining() const {
|
| return bytes_remaining_;
|
| }
|
|
|
| -int UploadFileElementReader::ReadSync(char* buf, int buf_length) {
|
| +int UploadFileElementReader::Read(IOBuffer* buf,
|
| + int buf_length,
|
| + const CompletionCallback& callback) {
|
| + if (BytesRemaining() == 0)
|
| + return 0;
|
| +
|
| + // Save the value of file_stream_.get() before base::Passed() invalidates it.
|
| + FileStream* file_stream_ptr = file_stream_.get();
|
| + int* result = new int;
|
| + // Pass the ownership of file_stream_ to the worker pool to safely perform
|
| + // operation even when |this| is destructed before the read completes.
|
| + const bool posted = base::WorkerPool::PostTaskAndReply(
|
| + FROM_HERE,
|
| + base::Bind(&ReadInternal,
|
| + scoped_refptr<IOBuffer>(buf),
|
| + buf_length,
|
| + BytesRemaining(),
|
| + file_stream_ptr,
|
| + result),
|
| + base::Bind(&UploadFileElementReader::OnReadCompleted,
|
| + weak_ptr_factory_.GetWeakPtr(),
|
| + base::Passed(&file_stream_),
|
| + base::Owned(result),
|
| + callback),
|
| + true /* task_is_slow */);
|
| + DCHECK(posted);
|
| + return ERR_IO_PENDING;
|
| +}
|
| +
|
| +int UploadFileElementReader::ReadSync(IOBuffer* buf, int buf_length) {
|
| // Temporarily allow until fix: http://crbug.com/72001.
|
| base::ThreadRestrictions::ScopedAllowIO allow_io;
|
| - DCHECK_LT(0, buf_length);
|
| -
|
| - const uint64 num_bytes_to_read =
|
| - static_cast<int>(std::min(BytesRemaining(),
|
| - static_cast<uint64>(buf_length)));
|
| - if (num_bytes_to_read > 0) {
|
| - int num_bytes_consumed = 0;
|
| - // file_stream_ is NULL if the target file is
|
| - // missing or not readable.
|
| - if (file_stream_.get()) {
|
| - num_bytes_consumed =
|
| - file_stream_->ReadSync(buf, num_bytes_to_read);
|
| - }
|
| - if (num_bytes_consumed <= 0) {
|
| - // If there's less data to read than we initially observed, then
|
| - // pad with zero. Otherwise the server will hang waiting for the
|
| - // rest of the data.
|
| - memset(buf, 0, num_bytes_to_read);
|
| - }
|
| - }
|
| - DCHECK_GE(bytes_remaining_, num_bytes_to_read);
|
| - bytes_remaining_ -= num_bytes_to_read;
|
| - return num_bytes_to_read;
|
| + int result = 0;
|
| + ReadInternal(buf, buf_length, BytesRemaining(), file_stream_.get(), &result);
|
| + OnReadCompleted(file_stream_.Pass(), &result, CompletionCallback());
|
| + return result;
|
| }
|
|
|
| void UploadFileElementReader::OnInitCompleted(
|
| @@ -185,6 +225,17 @@ void UploadFileElementReader::OnInitCompleted(
|
| callback.Run(*result);
|
| }
|
|
|
| +void UploadFileElementReader::OnReadCompleted(
|
| + scoped_ptr<FileStream> file_stream,
|
| + int* result,
|
| + const CompletionCallback& callback) {
|
| + file_stream_.swap(file_stream);
|
| + DCHECK_GE(static_cast<int>(bytes_remaining_), *result);
|
| + bytes_remaining_ -= *result;
|
| + if (!callback.is_null())
|
| + callback.Run(*result);
|
| +}
|
| +
|
| UploadFileElementReader::ScopedOverridingContentLengthForTests::
|
| ScopedOverridingContentLengthForTests(uint64 value) {
|
| overriding_content_length = value;
|
|
|