diff options
Diffstat (limited to 'webkit/blob/local_file_reader.cc')
-rw-r--r-- | webkit/blob/local_file_reader.cc | 215 |
1 files changed, 127 insertions, 88 deletions
diff --git a/webkit/blob/local_file_reader.cc b/webkit/blob/local_file_reader.cc index 8b5fb05..068ad13 100644 --- a/webkit/blob/local_file_reader.cc +++ b/webkit/blob/local_file_reader.cc @@ -30,6 +30,39 @@ bool VerifySnapshotTime(const base::Time& expected_modification_time, file_info.last_modified.ToTimeT(); } +void DidGetFileInfoForGetLength(const net::Int64CompletionCallback& callback, + const base::Time& expected_modification_time, + base::PlatformFileError error, + const base::PlatformFileInfo& file_info) { + if (file_info.is_directory) { + callback.Run(net::ERR_FILE_NOT_FOUND); + return; + } + if (error != base::PLATFORM_FILE_OK) { + callback.Run(LocalFileReader::PlatformFileErrorToNetError(error)); + return; + } + if (!VerifySnapshotTime(expected_modification_time, file_info)) { + callback.Run(net::ERR_UPLOAD_FILE_CHANGED); + return; + } + callback.Run(file_info.size); +} + +void DidSeekFile(const LocalFileReader::OpenFileStreamCallback& callback, + scoped_ptr<net::FileStream> stream_impl, + int64 initial_offset, + int64 new_offset) { + int result = net::OK; + if (new_offset < 0) + result = static_cast<int>(new_offset); + else if (new_offset != initial_offset) + result = net::ERR_REQUEST_RANGE_NOT_SATISFIABLE; + callback.Run(result, stream_impl.Pass()); +} + +void EmptyCompletionCallback(int) {} + } // namespace // static @@ -47,6 +80,70 @@ int LocalFileReader::PlatformFileErrorToNetError( } } +// A helper class to open, verify and seek a file stream for a given path. +class LocalFileReader::OpenFileStreamHelper { + public: + explicit OpenFileStreamHelper(base::MessageLoopProxy* file_thread_proxy) + : file_thread_proxy_(file_thread_proxy), + file_handle_(base::kInvalidPlatformFileValue), + result_(net::OK) {} + ~OpenFileStreamHelper() { + if (file_handle_ != base::kInvalidPlatformFileValue) { + file_thread_proxy_->PostTask( + FROM_HERE, + base::Bind(base::IgnoreResult(&base::ClosePlatformFile), + file_handle_)); + } + } + + void OpenAndVerifyOnFileThread(const FilePath& file_path, + const base::Time& expected_modification_time) { + base::PlatformFileError file_error = base::PLATFORM_FILE_OK; + file_handle_ = base::CreatePlatformFile( + file_path, kOpenFlagsForRead, NULL, &file_error); + if (file_error != base::PLATFORM_FILE_OK) { + result_ = PlatformFileErrorToNetError(file_error); + return; + } + DCHECK_NE(base::kInvalidPlatformFileValue, file_handle_); + base::PlatformFileInfo file_info; + if (!base::GetPlatformFileInfo(file_handle_, &file_info)) { + result_ = net::ERR_FAILED; + return; + } + if (!VerifySnapshotTime(expected_modification_time, file_info)) { + result_ = net::ERR_UPLOAD_FILE_CHANGED; + return; + } + result_ = net::OK; + } + + void OpenStreamOnCallingThread(int64 initial_offset, + const OpenFileStreamCallback& callback) { + DCHECK(!callback.is_null()); + scoped_ptr<net::FileStream> stream_impl; + if (result_ != net::OK) { + callback.Run(result_, stream_impl.Pass()); + return; + } + stream_impl.reset( + new net::FileStream(file_handle_, kOpenFlagsForRead, NULL)); + file_handle_ = base::kInvalidPlatformFileValue; + result_ = stream_impl->Seek(net::FROM_BEGIN, initial_offset, + base::Bind(&DidSeekFile, callback, + base::Passed(&stream_impl), + initial_offset)); + if (result_ != net::ERR_IO_PENDING) + callback.Run(result_, stream_impl.Pass()); + } + + private: + scoped_refptr<base::MessageLoopProxy> file_thread_proxy_; + base::PlatformFile file_handle_; + int result_; + DISALLOW_COPY_AND_ASSIGN(OpenFileStreamHelper); +}; + LocalFileReader::LocalFileReader( base::MessageLoopProxy* file_thread_proxy, const FilePath& file_path, @@ -60,6 +157,9 @@ LocalFileReader::LocalFileReader( weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {} LocalFileReader::~LocalFileReader() { + if (!stream_impl_.get()) + return; + stream_impl_->Close(base::Bind(&EmptyCompletionCallback)); } int LocalFileReader::Read(net::IOBuffer* buf, int buf_len, @@ -67,113 +167,52 @@ int LocalFileReader::Read(net::IOBuffer* buf, int buf_len, DCHECK(!has_pending_open_); if (stream_impl_.get()) return stream_impl_->Read(buf, buf_len, callback); - return Open(base::Bind(&LocalFileReader::DidOpenForRead, - weak_factory_.GetWeakPtr(), + return Open(base::Bind(&LocalFileReader::DidOpen, weak_factory_.GetWeakPtr(), make_scoped_refptr(buf), buf_len, callback)); } int LocalFileReader::GetLength(const net::Int64CompletionCallback& callback) { const bool posted = base::FileUtilProxy::GetFileInfo( file_thread_proxy_, file_path_, - base::Bind(&LocalFileReader::DidGetFileInfoForGetLength, - weak_factory_.GetWeakPtr(), callback)); + base::Bind(&DidGetFileInfoForGetLength, callback, + expected_modification_time_)); DCHECK(posted); return net::ERR_IO_PENDING; } -int LocalFileReader::Open(const net::CompletionCallback& callback) { +int LocalFileReader::Open(const OpenFileStreamCallback& callback) { DCHECK(!has_pending_open_); DCHECK(!stream_impl_.get()); has_pending_open_ = true; - - // Call GetLength first to make it perform last-modified-time verification, - // and then call DidVerifyForOpen for do the rest. - return GetLength(base::Bind(&LocalFileReader::DidVerifyForOpen, - weak_factory_.GetWeakPtr(), callback)); -} - -void LocalFileReader::DidVerifyForOpen( - const net::CompletionCallback& callback, - int64 get_length_result) { - if (get_length_result < 0) { - callback.Run(static_cast<int>(get_length_result)); - return; - } - - stream_impl_.reset(new net::FileStream(NULL)); - const int result = stream_impl_->Open( - file_path_, kOpenFlagsForRead, - base::Bind(&LocalFileReader::DidOpenFileStream, - weak_factory_.GetWeakPtr(), - callback)); - if (result != net::ERR_IO_PENDING) - callback.Run(result); -} - -void LocalFileReader::DidOpenFileStream( - const net::CompletionCallback& callback, - int result) { - if (result != net::OK) { - callback.Run(result); - return; - } - result = stream_impl_->Seek(net::FROM_BEGIN, initial_offset_, - base::Bind(&LocalFileReader::DidSeekFileStream, - weak_factory_.GetWeakPtr(), - callback)); - if (result != net::ERR_IO_PENDING) { - callback.Run(result); - } -} - -void LocalFileReader::DidSeekFileStream( - const net::CompletionCallback& callback, - int64 seek_result) { - if (seek_result < 0) { - callback.Run(static_cast<int>(seek_result)); - return; - } - if (seek_result != initial_offset_) { - callback.Run(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE); - return; - } - callback.Run(net::OK); + OpenFileStreamHelper* helper = new OpenFileStreamHelper(file_thread_proxy_); + const bool posted = file_thread_proxy_->PostTaskAndReply( + FROM_HERE, + base::Bind(&OpenFileStreamHelper::OpenAndVerifyOnFileThread, + base::Unretained(helper), file_path_, + expected_modification_time_), + base::Bind(&OpenFileStreamHelper::OpenStreamOnCallingThread, + base::Owned(helper), initial_offset_, callback)); + DCHECK(posted); + return net::ERR_IO_PENDING; } -void LocalFileReader::DidOpenForRead(net::IOBuffer* buf, - int buf_len, - const net::CompletionCallback& callback, - int open_result) { +void LocalFileReader::DidOpen(net::IOBuffer* buf, + int buf_len, + const net::CompletionCallback& callback, + int open_error, + scoped_ptr<net::FileStream> stream_impl) { DCHECK(has_pending_open_); + DCHECK(!stream_impl_.get()); has_pending_open_ = false; - if (open_result != net::OK) { - stream_impl_.reset(); - callback.Run(open_result); + if (open_error != net::OK) { + callback.Run(open_error); return; } - DCHECK(stream_impl_.get()); - const int read_result = stream_impl_->Read(buf, buf_len, callback); - if (read_result != net::ERR_IO_PENDING) - callback.Run(read_result); -} - -void LocalFileReader::DidGetFileInfoForGetLength( - const net::Int64CompletionCallback& callback, - base::PlatformFileError error, - const base::PlatformFileInfo& file_info) { - if (file_info.is_directory) { - callback.Run(net::ERR_FILE_NOT_FOUND); - return; - } - if (error != base::PLATFORM_FILE_OK) { - callback.Run(LocalFileReader::PlatformFileErrorToNetError(error)); - return; - } - if (!VerifySnapshotTime(expected_modification_time_, file_info)) { - callback.Run(net::ERR_UPLOAD_FILE_CHANGED); - return; - } - callback.Run(file_info.size); + DCHECK(stream_impl.get()); + stream_impl_ = stream_impl.Pass(); + const int read_error = stream_impl_->Read(buf, buf_len, callback); + if (read_error != net::ERR_IO_PENDING) + callback.Run(read_error); } } // namespace webkit_blob |