diff options
Diffstat (limited to 'net/base/upload_file_element_reader.cc')
-rw-r--r-- | net/base/upload_file_element_reader.cc | 148 |
1 files changed, 101 insertions, 47 deletions
diff --git a/net/base/upload_file_element_reader.cc b/net/base/upload_file_element_reader.cc index b71c022..86be79d 100644 --- a/net/base/upload_file_element_reader.cc +++ b/net/base/upload_file_element_reader.cc @@ -4,8 +4,11 @@ #include "net/base/upload_file_element_reader.h" +#include "base/bind.h" #include "base/file_util.h" +#include "base/location.h" #include "base/threading/thread_restrictions.h" +#include "base/threading/worker_pool.h" #include "net/base/file_stream.h" #include "net/base/net_errors.h" @@ -17,6 +20,58 @@ 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) { + scoped_ptr<FileStream> file_stream(new FileStream(NULL)); + int64 rv = file_stream->OpenSync( + path, base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ); + if (rv != OK) { + // If the file can't be opened, we'll just upload an empty file. + DLOG(WARNING) << "Failed to open \"" << path.value() + << "\" for reading: " << rv; + file_stream.reset(); + } else if (range_offset) { + rv = file_stream->SeekSync(FROM_BEGIN, range_offset); + if (rv < 0) { + DLOG(WARNING) << "Failed to seek \"" << path.value() + << "\" to offset: " << range_offset << " (" << rv << ")"; + file_stream->CloseSync(); + file_stream.reset(); + } + } + + int64 length = 0; + if (file_stream.get() && + file_util::GetFileSize(path, &length) && + range_offset < static_cast<uint64>(length)) { + // Compensate for the offset. + length = std::min(length - range_offset, range_length); + } + *out_content_length = length; + out_file_stream->swap(file_stream); + + // If the underlying file has been changed and the expected file modification + // time is set, treat it as error. Note that the expected modification time + // from WebKit is based on time_t precision. So we have to convert both to + // time_t to compare. This check is used for sliced files. + if (!expected_modification_time.is_null()) { + base::PlatformFileInfo info; + if (file_util::GetFileInfo(path, &info) && + expected_modification_time.ToTimeT() != info.last_modified.ToTimeT()) { + *out_result = ERR_UPLOAD_FILE_CHANGED; + return; + } + } + + *out_result = OK; +} + } // namespace UploadFileElementReader::UploadFileElementReader( @@ -29,7 +84,8 @@ UploadFileElementReader::UploadFileElementReader( range_length_(range_length), expected_modification_time_(expected_modification_time), content_length_(0), - bytes_remaining_(0) { + bytes_remaining_(0), + weak_ptr_factory_(this) { } UploadFileElementReader::~UploadFileElementReader() { @@ -39,56 +95,42 @@ UploadFileElementReader::~UploadFileElementReader() { file_stream_->CloseSync(); } +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( + FROM_HERE, + base::Bind(&InitInternal, + path_, + range_offset_, + range_length_, + expected_modification_time_, + file_stream, + content_length, + result), + base::Bind(&UploadFileElementReader::OnInitCompleted, + weak_ptr_factory_.GetWeakPtr(), + base::Owned(file_stream), + base::Owned(content_length), + base::Owned(result), + callback), + true /* task_is_slow */); + DCHECK(posted); + return ERR_IO_PENDING; +} + int UploadFileElementReader::InitSync() { // Temporarily allow until fix: http://crbug.com/72001. base::ThreadRestrictions::ScopedAllowIO allow_io; - scoped_ptr<FileStream> file_stream(new FileStream(NULL)); - int64 rv = file_stream->OpenSync( - path_, base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ); - if (rv != OK) { - // If the file can't be opened, we'll just upload an empty file. - DLOG(WARNING) << "Failed to open \"" << path_.value() - << "\" for reading: " << rv; - file_stream.reset(); - } - if (file_stream.get() && range_offset_) { - rv = file_stream->SeekSync(FROM_BEGIN, range_offset_); - if (rv < 0) { - DLOG(WARNING) << "Failed to seek \"" << path_.value() - << "\" to offset: " << range_offset_ << " (" << rv - << ")"; - file_stream->CloseSync(); - file_stream.reset(); - } - } - file_stream_.reset(file_stream.release()); - - int64 length = 0; - if (file_stream_.get() && - file_util::GetFileSize(path_, &length) && - range_offset_ < static_cast<uint64>(length)) { - // Compensate for the offset. - length = std::min(length - range_offset_, range_length_); - } - content_length_ = length; - bytes_remaining_ = GetContentLength(); - - // If the underlying file has been changed and the expected file - // modification time is set, treat it as error. Note that the expected - // modification time from WebKit is based on time_t precision. So we - // have to convert both to time_t to compare. This check is used for - // sliced files. - if (!expected_modification_time_.is_null()) { - base::PlatformFileInfo info; - if (file_util::GetFileInfo(path_, &info) && - expected_modification_time_.ToTimeT() != - info.last_modified.ToTimeT()) { - return ERR_UPLOAD_FILE_CHANGED; - } - } - - return OK; + 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()); + return result; } uint64 UploadFileElementReader::GetContentLength() const { @@ -129,6 +171,18 @@ int UploadFileElementReader::ReadSync(char* buf, int buf_length) { return num_bytes_to_read; } +void UploadFileElementReader::OnInitCompleted( + scoped_ptr<FileStream>* file_stream, + uint64* content_length, + int* result, + const CompletionCallback& callback) { + file_stream_.swap(*file_stream); + content_length_ = *content_length; + bytes_remaining_ = GetContentLength(); + if (!callback.is_null()) + callback.Run(*result); +} + UploadFileElementReader::ScopedOverridingContentLengthForTests:: ScopedOverridingContentLengthForTests(uint64 value) { overriding_content_length = value; |