Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(229)

Unified Diff: webkit/chromeos/fileapi/file_util_async.cc

Issue 8907014: Implement async verision of FileSystemFileUtil and in-memory file system for testing purposes. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address comments Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: webkit/chromeos/fileapi/file_util_async.cc
diff --git a/webkit/chromeos/fileapi/file_util_async.cc b/webkit/chromeos/fileapi/file_util_async.cc
new file mode 100644
index 0000000000000000000000000000000000000000..eecab187ed03e27046ef1aeadaad80d365c7dfa0
--- /dev/null
+++ b/webkit/chromeos/fileapi/file_util_async.cc
@@ -0,0 +1,313 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "webkit/chromeos/fileapi/file_util_async.h"
+
+#include "base/bind.h"
+#include "base/memory/weak_ptr.h"
+#include "base/message_loop.h"
+
+namespace fileapi {
+
+// Only one read/write operation may be active at any moment.
+class FileUtilAsyncFileStream : public AsyncFileStream {
+ public:
+ virtual void Read(
+ char* buffer,
+ int64 length,
+ const ReadWriteCallback& callback) OVERRIDE;
+ virtual void Write(
+ const char* buffer,
+ int64 length,
+ const ReadWriteCallback& callback) OVERRIDE;
+ virtual void Seek(
+ int64 offset,
+ const StatusCallback& callback) OVERRIDE;
+
+ private:
+ friend class FileUtilAsync;
+
+ virtual ~FileUtilAsyncFileStream() {}
+
+ FileUtilAsyncFileStream(
+ FileUtilAsync* file_util,
+ const FilePath& file_path,
+ int flags);
+
+ void DoSeek(
+ int64 offset,
+ const StatusCallback& callback,
+ PlatformFileError get_file_info_res,
+ const base::PlatformFileInfo& file_info);
+
+ void DidReadOrWrite(
+ const ReadWriteCallback& callback,
+ int64 offset,
+ PlatformFileError result,
+ int64 written);
+
+ FileUtilAsync* file_util_; // This class does not own FileUtilAsync.
+ FilePath file_path_;
+ int flags_;
+ bool pending_operation_;
+ int64 offset_;
+ base::WeakPtrFactory<FileUtilAsyncFileStream> weak_ptr_factory_;
+};
+
+FileUtilAsyncFileStream::FileUtilAsyncFileStream(
+ FileUtilAsync* file_util,
+ const FilePath& file_path,
+ int flags)
+ : file_util_(file_util),
+ file_path_(file_path),
+ flags_(flags),
+ pending_operation_(false),
+ offset_(0),
+ weak_ptr_factory_(this) {
+}
+
+void FileUtilAsyncFileStream::Read(
+ char* buffer,
+ int64 length,
+ const ReadWriteCallback& callback) {
+ DCHECK(!pending_operation_);
+ if ((flags_ & base::PLATFORM_FILE_READ) == 0) {
+ MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(callback, base::PLATFORM_FILE_ERROR_INVALID_OPERATION, 0));
+ return;
+ }
+
+ pending_operation_ = true;
+
+ file_util_->Read(
+ file_path_, offset_, buffer, length,
+ base::Bind(&FileUtilAsyncFileStream::DidReadOrWrite,
+ weak_ptr_factory_.GetWeakPtr(), callback, offset_));
+}
+
+void FileUtilAsyncFileStream::Write(
+ const char* buffer,
+ int64 length,
+ const ReadWriteCallback& callback) {
+ DCHECK(!pending_operation_);
+ if ((flags_ & base::PLATFORM_FILE_WRITE) == 0) {
+ MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(callback, base::PLATFORM_FILE_ERROR_INVALID_OPERATION, 0));
+ return;
+ }
+
+ pending_operation_ = true;
+
+ file_util_->Write(
+ file_path_, offset_, buffer, length,
+ base::Bind(&FileUtilAsyncFileStream::DidReadOrWrite,
+ weak_ptr_factory_.GetWeakPtr(), callback, offset_));
+}
+
+void FileUtilAsyncFileStream::Seek(
+ int64 offset,
+ const StatusCallback& callback) {
+ file_util_->GetFileInfo(
+ file_path_,
+ base::Bind(&FileUtilAsyncFileStream::DoSeek,
+ weak_ptr_factory_.GetWeakPtr(), offset, callback));
+}
+
+void FileUtilAsyncFileStream::DoSeek(
+ int64 offset,
+ const StatusCallback& callback,
+ PlatformFileError get_file_info_res,
+ const base::PlatformFileInfo& file_info) {
+ if (get_file_info_res != base::PLATFORM_FILE_OK) {
+ callback.Run(get_file_info_res);
+ return;
+ }
+
+ if (offset > file_info.size) {
+ callback.Run(base::PLATFORM_FILE_ERROR_INVALID_OPERATION);
+ // ... or should if be _FAILED?
kinuko 2011/12/14 03:39:22 Not really sure if we want this error check. (For
satorux1 2011/12/14 04:43:26 I'm not sure too. lseek() allows a larger offset a
+ return;
+ }
+
+ offset_ = offset;
+ callback.Run(base::PLATFORM_FILE_OK);
+}
+
+void FileUtilAsyncFileStream::DidReadOrWrite(
+ const ReadWriteCallback& callback,
+ int64 offset,
+ PlatformFileError result,
+ int64 written) {
+ DCHECK(pending_operation_);
+ pending_operation_ = false;
+ if (result == base::PLATFORM_FILE_OK) {
+ offset_ = offset + written;
+ }
+
+ callback.Run(result, written);
+}
+
+FileUtilAsync::FileUtilAsync() {
+}
+
+// Depending on the flags value the flow of file opening will be one of
+// the following:
+//
+// PLATFORM_FILE_OPEN:
+// GetFileInfo
+// DidGetFileInfoForOpen
+// OpenVerifiedFile
+//
+// PLATFORM_FILE_CREATE:
+// Create
+// DidCreateOrTruncateForOpen
+// OpenVerifiedFile
+//
+// PLATFORM_FILE_OPEN_ALWAYS:
+// GetFileInfo
+// DidGetFileInfoForOpen
+// OpenVerifiedFile OR Create
+// DidCreateOrTruncateForOpen
+// OpenVerifiedFile
+//
+// PLATFORM_FILE_CREATE_ALWAYS:
+// Truncate
+// OpenTruncatedFileOrCreate
+// OpenVerifiedFile OR Create
+// DidCreateOrTruncateForOpen
+// OpenVerifiedFile
+//
+// PLATFORM_FILE_OPEN_TRUNCATED:
+// Truncate
+// DidCreateOrTruncateForOpen
+// OpenVerifiedFile
+//
+void FileUtilAsync::Open(
+ const FilePath& file_path,
+ int flags,
+ const OpenCallback& callback) {
+ int create_flag = flags & (base::PLATFORM_FILE_OPEN |
+ base::PLATFORM_FILE_CREATE |
+ base::PLATFORM_FILE_OPEN_ALWAYS |
+ base::PLATFORM_FILE_CREATE_ALWAYS |
+ base::PLATFORM_FILE_OPEN_TRUNCATED);
+ switch (create_flag) {
+ case base::PLATFORM_FILE_OPEN:
+ case base::PLATFORM_FILE_OPEN_ALWAYS:
+ GetFileInfo(
+ file_path,
+ base::Bind(&FileUtilAsync::DidGetFileInfoForOpen,
+ base::Unretained(this), file_path, flags, callback));
+
+ break;
+
+ case base::PLATFORM_FILE_CREATE:
+ Create(
+ file_path,
+ base::Bind(&FileUtilAsync::DidCreateOrTruncateForOpen,
+ base::Unretained(this), file_path, flags, 0, callback));
+ break;
+
+ case base::PLATFORM_FILE_CREATE_ALWAYS:
+ Truncate(
+ file_path,
+ 0,
+ base::Bind(&FileUtilAsync::OpenTruncatedFileOrCreate,
+ base::Unretained(this), file_path, flags, callback));
+
+ case base::PLATFORM_FILE_OPEN_TRUNCATED:
+ Truncate(
+ file_path,
+ 0,
+ base::Bind(&FileUtilAsync::DidCreateOrTruncateForOpen,
+ base::Unretained(this), file_path, flags, 0, callback));
+ break;
+
+ default:
+ MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&FileUtilAsync::ReturnOpenError,
+ base::Unretained(this),
+ base::PLATFORM_FILE_ERROR_INVALID_OPERATION, callback));
kinuko 2011/12/14 03:39:22 I think this should work: Bind(callback, INVALID_O
satorux1 2011/12/14 04:43:26 Good idea. Done.
+ }
+}
+
+void FileUtilAsync::OpenVerifiedFile(
+ const FilePath& file_path,
+ int flags,
+ const OpenCallback& callback) {
+ callback.Run(base::PLATFORM_FILE_OK,
+ new FileUtilAsyncFileStream(this, file_path, flags));
+}
+
+void FileUtilAsync::DidGetFileInfoForOpen(
+ const FilePath& file_path,
+ int flags,
+ const OpenCallback& callback,
+ PlatformFileError get_info_res,
+ const base::PlatformFileInfo& file_info) {
+ if (get_info_res == base::PLATFORM_FILE_OK && file_info.is_directory) {
+ callback.Run(base::PLATFORM_FILE_ERROR_NOT_A_FILE, NULL);
+ return;
+ }
+
+ if (get_info_res == base::PLATFORM_FILE_OK) {
+ OpenVerifiedFile(file_path, flags, callback);
+ return;
+ }
+
+ if (get_info_res == base::PLATFORM_FILE_ERROR_NOT_FOUND &&
+ flags & base::PLATFORM_FILE_CREATE_ALWAYS) {
+ Create(file_path,
+ base::Bind(&FileUtilAsync::DidCreateOrTruncateForOpen,
+ base::Unretained(this), file_path, flags, 0, callback));
+ return;
+ }
+
+ callback.Run(get_info_res, NULL);
+}
+
+void FileUtilAsync::OpenTruncatedFileOrCreate(
+ const FilePath& file_path,
+ int flags,
+ const OpenCallback& callback,
+ PlatformFileError res) {
+ if (res == base::PLATFORM_FILE_OK) {
+ OpenVerifiedFile(file_path, flags, callback);
+ return;
+ }
+
+ if (res == base::PLATFORM_FILE_ERROR_NOT_FOUND) {
+ Create(
+ file_path,
+ base::Bind(&FileUtilAsync::DidCreateOrTruncateForOpen,
+ base::Unretained(this), file_path, flags, 0, callback));
kinuko 2011/12/14 03:39:22 need to return here?
satorux1 2011/12/14 04:43:26 Done.
+ }
+
+ callback.Run(res, NULL);
+}
+
+void FileUtilAsync::DidCreateOrTruncateForOpen(
+ const FilePath& file_path,
+ int flags,
+ int64 size,
+ const OpenCallback& callback,
+ PlatformFileError res) {
+ if (res != base::PLATFORM_FILE_OK) {
+ callback.Run(res, NULL);
+ return;
+ }
+
+ OpenVerifiedFile(file_path, flags, callback);
+}
+
+void FileUtilAsync::ReturnOpenError(
+ PlatformFileError error,
+ const OpenCallback& callback) {
+ callback.Run(error, NULL);
+}
+
+} // namespace fileapi

Powered by Google App Engine
This is Rietveld 408576698