diff options
Diffstat (limited to 'webkit/blob/blob_url_request_job.cc')
-rw-r--r-- | webkit/blob/blob_url_request_job.cc | 166 |
1 files changed, 61 insertions, 105 deletions
diff --git a/webkit/blob/blob_url_request_job.cc b/webkit/blob/blob_url_request_job.cc index d6be8a5..1a360f1 100644 --- a/webkit/blob/blob_url_request_job.cc +++ b/webkit/blob/blob_url_request_job.cc @@ -6,14 +6,11 @@ #include "base/bind.h" #include "base/compiler_specific.h" -#include "base/file_path.h" -#include "base/file_util.h" #include "base/file_util_proxy.h" #include "base/message_loop.h" #include "base/message_loop_proxy.h" +#include "base/stl_util.h" #include "base/string_number_conversions.h" -#include "base/threading/thread_restrictions.h" -#include "net/base/file_stream.h" #include "net/base/io_buffer.h" #include "net/base/net_errors.h" #include "net/http/http_request_headers.h" @@ -23,6 +20,7 @@ #include "net/url_request/url_request.h" #include "net/url_request/url_request_error_job.h" #include "net/url_request/url_request_status.h" +#include "webkit/blob/local_file_reader.h" namespace webkit_blob { @@ -71,9 +69,7 @@ BlobURLRequestJob::BlobURLRequestJob( } BlobURLRequestJob::~BlobURLRequestJob() { - // FileStream's destructor won't close it for us because we passed in our own - // file handle. - CloseFileStream(); + STLDeleteValues(&index_to_reader_); } void BlobURLRequestJob::Start() { @@ -84,7 +80,7 @@ void BlobURLRequestJob::Start() { } void BlobURLRequestJob::Kill() { - CloseFileStream(); + DeleteCurrentFileReader(); net::URLRequestJob::Kill(); weak_factory_.InvalidateWeakPtrs(); @@ -185,9 +181,8 @@ void BlobURLRequestJob::CountSize() { const BlobData::Item& item = blob_data_->items().at(i); if (item.type == BlobData::TYPE_FILE) { ++pending_get_file_info_count_; - base::FileUtilProxy::GetFileInfo( - file_thread_proxy_, item.file_path, - base::Bind(&BlobURLRequestJob::DidGetFileItemInfo, + GetFileReader(i)->GetLength( + base::Bind(&BlobURLRequestJob::DidGetFileItemLength, weak_factory_.GetWeakPtr(), i)); continue; } @@ -227,41 +222,28 @@ void BlobURLRequestJob::DidCountSize(int error) { NotifySuccess(); } -void BlobURLRequestJob::DidGetFileItemInfo( - size_t index, - base::PlatformFileError rv, - const base::PlatformFileInfo& file_info) { +void BlobURLRequestJob::DidGetFileItemLength(size_t index, int result) { // Do nothing if we have encountered an error. if (error_) return; - if (rv == base::PLATFORM_FILE_ERROR_NOT_FOUND) { + if (result == net::ERR_UPLOAD_FILE_CHANGED) { NotifyFailure(net::ERR_FILE_NOT_FOUND); return; - } else if (rv != base::PLATFORM_FILE_OK) { - NotifyFailure(net::ERR_FAILED); + } else if (result < 0) { + NotifyFailure(result); return; } - // Validate the expected modification time. - // 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. DCHECK_LT(index, blob_data_->items().size()); const BlobData::Item& item = blob_data_->items().at(index); DCHECK(item.type == BlobData::TYPE_FILE); - if (!item.expected_modification_time.is_null() && - item.expected_modification_time.ToTimeT() != - file_info.last_modified.ToTimeT()) { - NotifyFailure(net::ERR_FILE_NOT_FOUND); - return; - } - // If item length is -1, we need to use the file size being resolved // in the real time. int64 item_length = static_cast<int64>(item.length); if (item_length == -1) - item_length = file_info.size; + item_length = result; // Cache the size and add it to the total size. DCHECK_LT(index, item_length_list_.size()); @@ -283,6 +265,20 @@ void BlobURLRequestJob::Seek(int64 offset) { // Set the offset that need to jump to for the first item in the range. current_item_offset_ = offset; + + if (offset == 0) + return; + + // Adjust the offset of the first stream if it is of file type. + const BlobData::Item& item = blob_data_->items().at(current_item_index_); + if (item.type == BlobData::TYPE_FILE) { + DeleteCurrentFileReader(); + index_to_reader_[current_item_index_] = new LocalFileReader( + file_thread_proxy_, + item.file_path, + item.offset + offset, + item.expected_modification_time); + } } bool BlobURLRequestJob::ReadItem() { @@ -312,7 +308,7 @@ bool BlobURLRequestJob::ReadItem() { case BlobData::TYPE_DATA: return ReadBytesItem(item, bytes_to_read); case BlobData::TYPE_FILE: - return ReadFileItem(item, bytes_to_read); + return ReadFileItem(GetFileReader(current_item_index_), bytes_to_read); default: DCHECK(false); return false; @@ -320,8 +316,8 @@ bool BlobURLRequestJob::ReadItem() { } void BlobURLRequestJob::AdvanceItem() { - // Close the stream if the current item is a file. - CloseFileStream(); + // Close the file if the current item is a file. + DeleteCurrentFileReader(); // Advance to the next item. current_item_index_++; @@ -357,79 +353,24 @@ bool BlobURLRequestJob::ReadBytesItem(const BlobData::Item& item, return true; } -bool BlobURLRequestJob::ReadFileItem(const BlobData::Item& item, +bool BlobURLRequestJob::ReadFileItem(LocalFileReader* reader, int bytes_to_read) { - // If the stream already exists, keep reading from it. - if (stream_ != NULL) - return ReadFileStream(bytes_to_read); - - base::FileUtilProxy::CreateOrOpen( - file_thread_proxy_, item.file_path, kFileOpenFlags, - base::Bind(&BlobURLRequestJob::DidOpenFile, - weak_factory_.GetWeakPtr(), bytes_to_read)); - SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0)); - return false; -} - -void BlobURLRequestJob::DidOpenFile(int bytes_to_read, - base::PlatformFileError rv, - base::PassPlatformFile file, - bool created) { - if (rv != base::PLATFORM_FILE_OK) { - NotifyFailure(net::ERR_FAILED); - return; - } - - DCHECK(!stream_.get()); - stream_.reset(new net::FileStream(file.ReleaseValue(), kFileOpenFlags, NULL)); - - const BlobData::Item& item = blob_data_->items().at(current_item_index_); - { - // stream_.SeekSync() blocks the IO thread, see http://crbug.com/75548. - base::ThreadRestrictions::ScopedAllowIO allow_io; - int64 offset = current_item_offset_ + static_cast<int64>(item.offset); - if (offset > 0 && offset != stream_->SeekSync(net::FROM_BEGIN, offset)) { - NotifyFailure(net::ERR_FAILED); - return; - } - } - - ReadFileStream(bytes_to_read); -} - -bool BlobURLRequestJob::ReadFileStream(int bytes_to_read) { - DCHECK(stream_.get()); - DCHECK(stream_->IsOpen()); DCHECK_GE(read_buf_->BytesRemaining(), bytes_to_read); - - // Start the asynchronous reading. - int rv = stream_->Read(read_buf_, - bytes_to_read, - base::Bind(&BlobURLRequestJob::DidReadFileStream, - base::Unretained(this))); - - // If I/O pending error is returned, we just need to wait. - if (rv == net::ERR_IO_PENDING) { - SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0)); - return false; - } - - // For all other errors (and for unexpected EOF case), bail out. - if (rv <= 0) { - NotifyFailure(net::ERR_FAILED); + DCHECK(reader); + const int result = reader->Read( + read_buf_, bytes_to_read, + base::Bind(&BlobURLRequestJob::DidReadFile, + base::Unretained(this))); + if (result != net::ERR_IO_PENDING) { + DCHECK(result != net::OK); + NotifyFailure(result); return false; } - - // Otherwise, data is immediately available. - if (GetStatus().is_io_pending()) - DidReadFileStream(rv); - else - AdvanceBytesRead(rv); - - return true; + SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0)); + return false; } -void BlobURLRequestJob::DidReadFileStream(int result) { +void BlobURLRequestJob::DidReadFile(int result) { if (result <= 0) { NotifyFailure(net::ERR_FAILED); return; @@ -451,12 +392,11 @@ void BlobURLRequestJob::DidReadFileStream(int result) { NotifyReadComplete(bytes_read); } -void BlobURLRequestJob::CloseFileStream() { - if (stream_ != NULL) { - // stream_.Close() blocks the IO thread, see http://crbug.com/75548. - base::ThreadRestrictions::ScopedAllowIO allow_io; - stream_->CloseSync(); - stream_.reset(NULL); +void BlobURLRequestJob::DeleteCurrentFileReader() { + IndexToReaderMap::iterator found = index_to_reader_.find(current_item_index_); + if (found != index_to_reader_.end() && found->second) { + delete found->second; + index_to_reader_.erase(found); } } @@ -578,4 +518,20 @@ void BlobURLRequestJob::HeadersCompleted(int status_code, NotifyHeadersComplete(); } +LocalFileReader* BlobURLRequestJob::GetFileReader(size_t index) { + DCHECK_LT(index, blob_data_->items().size()); + const BlobData::Item& item = blob_data_->items().at(index); + if (item.type != BlobData::TYPE_FILE) + return NULL; + if (index_to_reader_.find(index) == index_to_reader_.end()) { + index_to_reader_[index] = new LocalFileReader( + file_thread_proxy_, + item.file_path, + item.offset, + item.expected_modification_time); + } + DCHECK(index_to_reader_[index]); + return index_to_reader_[index]; +} + } // namespace webkit_blob |