Chromium Code Reviews| Index: webkit/blob/blob_url_request_job.cc |
| diff --git a/webkit/blob/blob_url_request_job.cc b/webkit/blob/blob_url_request_job.cc |
| index 9f78e66669be7d23003a810ff745397576be9e47..f693f8f08914fdb61798f7c25c29d01bb2115952 100644 |
| --- a/webkit/blob/blob_url_request_job.cc |
| +++ b/webkit/blob/blob_url_request_job.cc |
| @@ -11,6 +11,7 @@ |
| #include "base/message_loop.h" |
| #include "base/message_loop_proxy.h" |
| #include "base/string_number_conversions.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" |
| @@ -40,6 +41,10 @@ static const char kHTTPRequestedRangeNotSatisfiableText[] = |
| "Requested Range Not Satisfiable"; |
| static const char kHTTPInternalErrorText[] = "Internal Server Error"; |
| +static const int kFileOpenFlags = base::PLATFORM_FILE_OPEN | |
| + base::PLATFORM_FILE_READ | |
| + base::PLATFORM_FILE_ASYNC; |
| + |
| BlobURLRequestJob::BlobURLRequestJob( |
| net::URLRequest* request, |
| BlobData* blob_data, |
| @@ -64,6 +69,9 @@ BlobURLRequestJob::BlobURLRequestJob( |
| } |
| BlobURLRequestJob::~BlobURLRequestJob() { |
| + // FileStream's destructor won't close it for us because we passed in our own |
| + // file handle. |
| + CloseStream(); |
| } |
| void BlobURLRequestJob::Start() { |
| @@ -89,8 +97,15 @@ void BlobURLRequestJob::DidStart() { |
| CountSize(); |
| } |
| +void BlobURLRequestJob::CloseStream() { |
| + if (stream_ != NULL) { |
| + stream_->Close(); |
| + stream_.reset(NULL); |
| + } |
| +} |
| + |
| void BlobURLRequestJob::Kill() { |
| - stream_.Close(); |
| + CloseStream(); |
| net::URLRequestJob::Kill(); |
| callback_factory_.RevokeAll(); |
| @@ -98,28 +113,10 @@ void BlobURLRequestJob::Kill() { |
| } |
| void BlobURLRequestJob::ResolveFile(const FilePath& file_path) { |
| - // If the file thread proxy is provided, we can use it get the file info. |
| - if (file_thread_proxy_) { |
| - base::FileUtilProxy::GetFileInfo( |
| - file_thread_proxy_, |
| - file_path, |
| - callback_factory_.NewCallback(&BlobURLRequestJob::DidResolve)); |
| - return; |
| - } |
| - |
| - // Otherwise, we use current thread, i.e. IO thread, as this is the case when |
| - // we run the unittest or test shell. |
| - // TODO(jianli): Consider using the proxy of current thread. |
| - base::PlatformFileInfo file_info; |
| - bool exists = file_util::GetFileInfo(file_path, &file_info); |
| - |
| - // Continue asynchronously. |
| - MessageLoop::current()->PostTask( |
| - FROM_HERE, |
| - method_factory_.NewRunnableMethod( |
| - &BlobURLRequestJob::DidResolve, |
| - exists ? base::PLATFORM_FILE_OK : base::PLATFORM_FILE_ERROR_NOT_FOUND, |
| - file_info)); |
| + base::FileUtilProxy::GetFileInfo( |
| + file_thread_proxy_, |
| + file_path, |
| + callback_factory_.NewCallback(&BlobURLRequestJob::DidResolve)); |
| } |
| void BlobURLRequestJob::DidResolve(base::PlatformFileError rv, |
| @@ -254,6 +251,17 @@ bool BlobURLRequestJob::ReadLoop(int* bytes_read) { |
| return true; |
| } |
| +int BlobURLRequestJob::ComputeBytesToRead() { |
|
jianli
2011/03/10 22:50:42
Since we do not change anything in this method, we
adamk
2011/03/10 23:06:12
Done.
|
| + int64 current_item_remaining_bytes = |
| + item_length_list_[item_index_] - current_item_offset_; |
| + int bytes_to_read = (read_buf_remaining_bytes_ > current_item_remaining_bytes) |
| + ? static_cast<int>(current_item_remaining_bytes) |
| + : read_buf_remaining_bytes_; |
| + if (bytes_to_read > remaining_bytes_) |
| + bytes_to_read = static_cast<int>(remaining_bytes_); |
| + return bytes_to_read; |
| +} |
| + |
| bool BlobURLRequestJob::ReadItem() { |
| // Are we done with reading all the blob data? |
| if (remaining_bytes_ == 0) |
| @@ -266,16 +274,8 @@ bool BlobURLRequestJob::ReadItem() { |
| return false; |
| } |
| - const BlobData::Item& item = blob_data_->items().at(item_index_); |
| - |
| // Compute the bytes to read for current item. |
| - int64 current_item_remaining_bytes = |
| - item_length_list_[item_index_] - current_item_offset_; |
| - int bytes_to_read = (read_buf_remaining_bytes_ > current_item_remaining_bytes) |
| - ? static_cast<int>(current_item_remaining_bytes) |
| - : read_buf_remaining_bytes_; |
| - if (bytes_to_read > remaining_bytes_) |
| - bytes_to_read = static_cast<int>(remaining_bytes_); |
| + int bytes_to_read = ComputeBytesToRead(); |
| // If nothing to read for current item, advance to next item. |
| if (bytes_to_read == 0) { |
| @@ -284,11 +284,12 @@ bool BlobURLRequestJob::ReadItem() { |
| } |
| // Do the reading. |
| + const BlobData::Item& item = blob_data_->items().at(item_index_); |
| switch (item.type()) { |
| case BlobData::TYPE_DATA: |
| return ReadBytes(item, bytes_to_read); |
| case BlobData::TYPE_FILE: |
| - return ReadFile(item, bytes_to_read); |
| + return DispatchReadFile(item, bytes_to_read); |
|
jianli
2011/03/10 22:50:42
Since the produced bytes_to_read is not immediatel
adamk
2011/03/10 23:06:12
Well, we already have it here, and it's needed abo
|
| default: |
| DCHECK(false); |
| return false; |
| @@ -307,33 +308,51 @@ bool BlobURLRequestJob::ReadBytes(const BlobData::Item& item, |
| return true; |
| } |
| -bool BlobURLRequestJob::ReadFile(const BlobData::Item& item, |
| - int bytes_to_read) { |
| - DCHECK(read_buf_remaining_bytes_ >= bytes_to_read); |
| +bool BlobURLRequestJob::DispatchReadFile(const BlobData::Item& item, |
| + int bytes_to_read) { |
| + // If the stream already exists, keep reading from it. |
| + if (stream_ != NULL) |
| + return ReadFile(item, bytes_to_read); |
| + |
| + base::FileUtilProxy::CreateOrOpen( |
| + file_thread_proxy_, item.file_path(), kFileOpenFlags, |
| + callback_factory_.NewCallback(&BlobURLRequestJob::DidOpen)); |
| + SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0)); |
| + return false; |
| +} |
| - // Open the file if not yet. |
| - if (!stream_.IsOpen()) { |
| - int rv = stream_.Open(item.file_path(), base::PLATFORM_FILE_OPEN | |
| - base::PLATFORM_FILE_READ | base::PLATFORM_FILE_ASYNC); |
| - if (rv != net::OK) { |
| - NotifyFailure(net::ERR_FAILED); |
| - return false; |
| - } |
| +void BlobURLRequestJob::DidOpen(base::PlatformFileError rv, |
| + base::PassPlatformFile file, |
| + bool created) { |
| + if (rv != base::PLATFORM_FILE_OK) { |
| + NotifyFailure(net::ERR_FAILED); |
| + return; |
| + } |
| - // Seek the file if needed. |
| - int64 offset = current_item_offset_ + static_cast<int64>(item.offset()); |
| - if (offset > 0) { |
| - if (offset != stream_.Seek(net::FROM_BEGIN, offset)) { |
| - NotifyFailure(net::ERR_FAILED); |
| - return false; |
| - } |
| - } |
| + DCHECK(!stream_.get()); |
| + stream_.reset(new net::FileStream(file.ReleaseValue(), kFileOpenFlags)); |
| + |
| + // Seek the file if needed. |
| + const BlobData::Item& item = blob_data_->items().at(item_index_); |
| + int64 offset = current_item_offset_ + static_cast<int64>(item.offset()); |
| + if (offset > 0 && offset != stream_->Seek(net::FROM_BEGIN, offset)) { |
| + NotifyFailure(net::ERR_FAILED); |
| + return; |
| } |
| + ReadFile(item, ComputeBytesToRead()); |
| +} |
| + |
| +bool BlobURLRequestJob::ReadFile(const BlobData::Item& item, |
| + int bytes_to_read) { |
| + DCHECK(stream_.get()); |
| + DCHECK(stream_->IsOpen()); |
| + DCHECK(read_buf_remaining_bytes_ >= bytes_to_read); |
| + |
| // Start the asynchronous reading. |
| - int rv = stream_.Read(read_buf_->data() + read_buf_offset_, |
| - bytes_to_read, |
| - &io_callback_); |
| + int rv = stream_->Read(read_buf_->data() + read_buf_offset_, |
| + bytes_to_read, |
| + &io_callback_); |
| // If I/O pending error is returned, we just need to wait. |
| if (rv == net::ERR_IO_PENDING) { |
| @@ -348,7 +367,11 @@ bool BlobURLRequestJob::ReadFile(const BlobData::Item& item, |
| } |
| // Otherwise, data is immediately available. |
| - AdvanceBytesRead(rv); |
| + if (GetStatus().is_io_pending()) |
| + DidRead(rv); |
| + else |
| + AdvanceBytesRead(rv); |
| + |
| return true; |
| } |
| @@ -376,8 +399,7 @@ void BlobURLRequestJob::DidRead(int result) { |
| void BlobURLRequestJob::AdvanceItem() { |
| // Close the stream if the current item is a file. |
| - if (stream_.IsOpen()) |
| - stream_.Close(); |
| + CloseStream(); |
| // Advance to the next item. |
| item_index_++; |