| 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..0c1d08bf4e11ed710205d48b71949ad611ee9732 100644
|
| --- a/net/base/upload_file_element_reader.cc
|
| +++ b/net/base/upload_file_element_reader.cc
|
| @@ -7,9 +7,11 @@
|
| #include "base/bind.h"
|
| #include "base/file_util.h"
|
| #include "base/location.h"
|
| +#include "base/task_runner_util.h"
|
| #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,14 +22,13 @@ namespace {
|
| // UploadFileElementReader::GetContentLength() when set to non-zero.
|
| uint64 overriding_content_length = 0;
|
|
|
| -// This method is used to implement Init().
|
| -void InitInternal(const FilePath& path,
|
| - uint64 range_offset,
|
| - uint64 range_length,
|
| - const base::Time& expected_modification_time,
|
| - scoped_ptr<FileStream>* out_file_stream,
|
| - uint64* out_content_length,
|
| - int* out_result) {
|
| +// This function is used to implement Init().
|
| +int InitInternal(const FilePath& path,
|
| + uint64 range_offset,
|
| + uint64 range_length,
|
| + const base::Time& expected_modification_time,
|
| + scoped_ptr<FileStream>* out_file_stream,
|
| + uint64* out_content_length) {
|
| scoped_ptr<FileStream> file_stream(new FileStream(NULL));
|
| int64 rv = file_stream->OpenSync(
|
| path, base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ);
|
| @@ -64,12 +65,38 @@ void InitInternal(const FilePath& path,
|
| base::PlatformFileInfo info;
|
| if (file_util::GetFileInfo(path, &info) &&
|
| expected_modification_time.ToTimeT() != info.last_modified.ToTimeT()) {
|
| - *out_result = ERR_UPLOAD_FILE_CHANGED;
|
| - return;
|
| + return ERR_UPLOAD_FILE_CHANGED;
|
| }
|
| }
|
|
|
| - *out_result = OK;
|
| + return OK;
|
| +}
|
| +
|
| +// This function is used to implement Read().
|
| +int ReadInternal(scoped_refptr<IOBuffer> buf,
|
| + int buf_length,
|
| + uint64 bytes_remaining,
|
| + FileStream* file_stream) {
|
| + 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);
|
| + }
|
| + }
|
| + return num_bytes_to_read;
|
| }
|
|
|
| } // namespace
|
| @@ -100,8 +127,8 @@ UploadFileElementReader::~UploadFileElementReader() {
|
| int UploadFileElementReader::Init(const CompletionCallback& callback) {
|
| scoped_ptr<FileStream>* file_stream = new scoped_ptr<FileStream>;
|
| uint64* content_length = new uint64;
|
| - int* result = new int;
|
| - const bool posted = base::WorkerPool::PostTaskAndReply(
|
| + const bool posted = base::PostTaskAndReplyWithResult(
|
| + base::WorkerPool::GetTaskRunner(true /* task_is_slow */),
|
| FROM_HERE,
|
| base::Bind(&InitInternal,
|
| path_,
|
| @@ -109,15 +136,12 @@ int UploadFileElementReader::Init(const CompletionCallback& callback) {
|
| range_length_,
|
| expected_modification_time_,
|
| file_stream,
|
| - content_length,
|
| - result),
|
| + content_length),
|
| base::Bind(&UploadFileElementReader::OnInitCompleted,
|
| weak_ptr_factory_.GetWeakPtr(),
|
| base::Owned(file_stream),
|
| base::Owned(content_length),
|
| - base::Owned(result),
|
| - callback),
|
| - true /* task_is_slow */);
|
| + callback));
|
| DCHECK(posted);
|
| return ERR_IO_PENDING;
|
| }
|
| @@ -128,10 +152,10 @@ int UploadFileElementReader::InitSync() {
|
|
|
| scoped_ptr<FileStream> file_stream;
|
| uint64 content_length = 0;
|
| - int result = OK;
|
| - InitInternal(path_, range_offset_, range_length_, expected_modification_time_,
|
| - &file_stream, &content_length, &result);
|
| - OnInitCompleted(&file_stream, &content_length, &result, CompletionCallback());
|
| + const int result = InitInternal(path_, range_offset_, range_length_,
|
| + expected_modification_time_,
|
| + &file_stream, &content_length);
|
| + OnInitCompleted(&file_stream, &content_length, CompletionCallback(), result);
|
| return result;
|
| }
|
|
|
| @@ -145,44 +169,64 @@ 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) {
|
| + DCHECK(!callback.is_null());
|
| +
|
| + if (BytesRemaining() == 0)
|
| + return 0;
|
| +
|
| + // Save the value of file_stream_.get() before base::Passed() invalidates it.
|
| + FileStream* file_stream_ptr = file_stream_.get();
|
| + // 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::PostTaskAndReplyWithResult(
|
| + base::WorkerPool::GetTaskRunner(true /* task_is_slow */),
|
| + FROM_HERE,
|
| + base::Bind(&ReadInternal,
|
| + scoped_refptr<IOBuffer>(buf),
|
| + buf_length,
|
| + BytesRemaining(),
|
| + file_stream_ptr),
|
| + base::Bind(&UploadFileElementReader::OnReadCompleted,
|
| + weak_ptr_factory_.GetWeakPtr(),
|
| + base::Passed(&file_stream_),
|
| + callback));
|
| + 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;
|
| + const int result = ReadInternal(buf, buf_length, BytesRemaining(),
|
| + file_stream_.get());
|
| + OnReadCompleted(file_stream_.Pass(), CompletionCallback(), result);
|
| + return result;
|
| }
|
|
|
| void UploadFileElementReader::OnInitCompleted(
|
| scoped_ptr<FileStream>* file_stream,
|
| uint64* content_length,
|
| - int* result,
|
| - const CompletionCallback& callback) {
|
| + const CompletionCallback& callback,
|
| + int result) {
|
| file_stream_.swap(*file_stream);
|
| content_length_ = *content_length;
|
| bytes_remaining_ = GetContentLength();
|
| if (!callback.is_null())
|
| - callback.Run(*result);
|
| + callback.Run(result);
|
| +}
|
| +
|
| +void UploadFileElementReader::OnReadCompleted(
|
| + scoped_ptr<FileStream> file_stream,
|
| + const CompletionCallback& callback,
|
| + int result) {
|
| + 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::
|
|
|