summaryrefslogtreecommitdiffstats
path: root/webkit/blob/local_file_reader.cc
diff options
context:
space:
mode:
Diffstat (limited to 'webkit/blob/local_file_reader.cc')
-rw-r--r--webkit/blob/local_file_reader.cc215
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