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

Unified Diff: webkit/fileapi/file_system_operation.cc

Issue 4821005: Make FileSystemOperation's lifetime more explicit. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: '' Created 10 years, 1 month 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/fileapi/file_system_operation.cc
diff --git a/webkit/fileapi/file_system_operation.cc b/webkit/fileapi/file_system_operation.cc
index fe077581fb7a4d3ad4da81370ffce8696da61471..88783411b5774a4516d7b731e3a1d7c771b7f7d3 100644
--- a/webkit/fileapi/file_system_operation.cc
+++ b/webkit/fileapi/file_system_operation.cc
@@ -11,11 +11,72 @@
namespace fileapi {
+namespace {
+
+// A helper callback dispatcher class to make it easy to control
+// FileSystemOperation's lifetime. Calling any callback methods of this
+// class would delete the corresponding FileSystemOperation.
+class DispatchAndDeleteCallbackWrapper
+ : public FileSystemCallbackDispatcher {
+ public:
+ DispatchAndDeleteCallbackWrapper(
+ FileSystemOperation* operation,
+ FileSystemCallbackDispatcher* dispatcher)
+ : operation_(operation),
+ dispatcher_(dispatcher) { }
+
+ // Returns the wrapped dispatcher.
+ // This would be useful when the caller does not want to delete the operation.
+ FileSystemCallbackDispatcher* wrapped() const { return dispatcher_.get(); }
+
+ virtual void DidSucceed() {
+ dispatcher_->DidSucceed();
+ delete operation_;
+ }
+
+ virtual void DidReadMetadata(const base::PlatformFileInfo& file_info) {
+ dispatcher_->DidReadMetadata(file_info);
+ delete operation_;
+ }
+
+ virtual void DidReadDirectory(
+ const std::vector<base::FileUtilProxy::Entry>& entries,
+ bool has_more) {
+ dispatcher_->DidReadDirectory(entries, has_more);
+ delete operation_;
+ }
+
+ virtual void DidOpenFileSystem(const std::string& name,
+ const FilePath& root_path) {
+ dispatcher_->DidOpenFileSystem(name, root_path);
+ delete operation_;
+ }
+
+ virtual void DidFail(base::PlatformFileError error_code) {
+ dispatcher_->DidFail(error_code);
+ delete operation_;
+ }
+
+ virtual void DidWrite(int64 bytes, bool complete) {
+ dispatcher_->DidWrite(bytes, complete);
+ if (complete)
+ delete operation_;
+ }
+
+ private:
+ FileSystemOperation* operation_;
+ scoped_ptr<FileSystemCallbackDispatcher> dispatcher_;
+};
+
+} // namespace
+
FileSystemOperation::FileSystemOperation(
FileSystemCallbackDispatcher* dispatcher,
scoped_refptr<base::MessageLoopProxy> proxy)
: proxy_(proxy),
- dispatcher_(dispatcher),
+ destructive_dispatcher_(
+ new DispatchAndDeleteCallbackWrapper(
+ ALLOW_THIS_IN_INITIALIZER_LIST(this), dispatcher)),
ericu 2010/11/16 19:26:54 This seems a bit odd to me. We're creating a wrap
callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)),
cancel_operation_(NULL) {
DCHECK(dispatcher);
@@ -158,7 +219,7 @@ void FileSystemOperation::OnFileOpenedForWrite(
base::PassPlatformFile file,
bool created) {
if (base::PLATFORM_FILE_OK != rv) {
- dispatcher_->DidFail(rv);
+ destructive_dispatcher()->DidFail(rv);
return;
}
file_writer_delegate_->Start(file.ReleaseValue(), blob_request_.get());
@@ -204,8 +265,8 @@ void FileSystemOperation::Cancel(FileSystemOperation* cancel_operation) {
blob_request_->Cancel();
// This deletes us, and by proxy deletes file_writer_delegate_ if any.
- dispatcher_->DidFail(base::PLATFORM_FILE_ERROR_ABORT);
- cancel_operation->dispatcher_->DidSucceed();
+ destructive_dispatcher()->DidFail(base::PLATFORM_FILE_ERROR_ABORT);
+ cancel_operation->destructive_dispatcher()->DidSucceed();
} else {
#ifndef NDEBUG
DCHECK(kOperationTruncate == pending_operation_);
@@ -214,15 +275,22 @@ void FileSystemOperation::Cancel(FileSystemOperation* cancel_operation) {
// since it's been proxied to another thread. We need to save the
// cancel_operation so that when the truncate returns, it can see that it's
// been cancelled, report it, and report that the cancel has succeeded.
+ DCHECK(!cancel_operation_);
cancel_operation_ = cancel_operation;
}
}
+FileSystemCallbackDispatcher*
+ FileSystemOperation::non_destructive_dispatcher() const {
+ return static_cast<DispatchAndDeleteCallbackWrapper*>(
+ destructive_dispatcher_.get())->wrapped();
+}
+
void FileSystemOperation::DidEnsureFileExistsExclusive(
base::PlatformFileError rv, bool created) {
- if (rv == base::PLATFORM_FILE_OK && !created)
- dispatcher_->DidFail(base::PLATFORM_FILE_ERROR_EXISTS);
- else
+ if (rv == base::PLATFORM_FILE_OK && !created) {
+ destructive_dispatcher()->DidFail(base::PLATFORM_FILE_ERROR_EXISTS);
+ } else
DidFinishFileOperation(rv);
}
@@ -237,14 +305,15 @@ void FileSystemOperation::DidFinishFileOperation(
#ifndef NDEBUG
DCHECK(kOperationTruncate == pending_operation_);
#endif
- FileSystemOperation *cancel_op = cancel_operation_;
- // This call deletes us, so we have to extract cancel_op first.
- dispatcher_->DidFail(base::PLATFORM_FILE_ERROR_ABORT);
- cancel_op->dispatcher_->DidSucceed();
+
+ // Call non-destructive dispatcher's method not to delete this instance yet.
+ non_destructive_dispatcher()->DidFail(base::PLATFORM_FILE_ERROR_ABORT);
+ cancel_operation_->destructive_dispatcher()->DidSucceed();
+ delete this;
} else if (rv == base::PLATFORM_FILE_OK) {
- dispatcher_->DidSucceed();
+ destructive_dispatcher()->DidSucceed();
} else {
- dispatcher_->DidFail(rv);
+ destructive_dispatcher()->DidFail(rv);
}
}
@@ -253,11 +322,11 @@ void FileSystemOperation::DidDirectoryExists(
const base::PlatformFileInfo& file_info) {
if (rv == base::PLATFORM_FILE_OK) {
if (file_info.is_directory)
- dispatcher_->DidSucceed();
+ destructive_dispatcher()->DidSucceed();
else
- dispatcher_->DidFail(base::PLATFORM_FILE_ERROR_FAILED);
+ destructive_dispatcher()->DidFail(base::PLATFORM_FILE_ERROR_FAILED);
} else {
- dispatcher_->DidFail(rv);
+ destructive_dispatcher()->DidFail(rv);
}
}
@@ -266,11 +335,11 @@ void FileSystemOperation::DidFileExists(
const base::PlatformFileInfo& file_info) {
if (rv == base::PLATFORM_FILE_OK) {
if (file_info.is_directory)
- dispatcher_->DidFail(base::PLATFORM_FILE_ERROR_FAILED);
+ destructive_dispatcher()->DidFail(base::PLATFORM_FILE_ERROR_FAILED);
else
- dispatcher_->DidSucceed();
+ destructive_dispatcher()->DidSucceed();
} else {
- dispatcher_->DidFail(rv);
+ destructive_dispatcher()->DidFail(rv);
}
}
@@ -278,18 +347,18 @@ void FileSystemOperation::DidGetMetadata(
base::PlatformFileError rv,
const base::PlatformFileInfo& file_info) {
if (rv == base::PLATFORM_FILE_OK)
- dispatcher_->DidReadMetadata(file_info);
+ destructive_dispatcher()->DidReadMetadata(file_info);
else
- dispatcher_->DidFail(rv);
+ destructive_dispatcher()->DidFail(rv);
}
void FileSystemOperation::DidReadDirectory(
base::PlatformFileError rv,
const std::vector<base::FileUtilProxy::Entry>& entries) {
if (rv == base::PLATFORM_FILE_OK)
- dispatcher_->DidReadDirectory(entries, false /* has_more */);
+ destructive_dispatcher()->DidReadDirectory(entries, false /* has_more */);
else
- dispatcher_->DidFail(rv);
+ destructive_dispatcher()->DidFail(rv);
}
void FileSystemOperation::DidWrite(
@@ -297,16 +366,16 @@ void FileSystemOperation::DidWrite(
int64 bytes,
bool complete) {
if (rv == base::PLATFORM_FILE_OK)
- dispatcher_->DidWrite(bytes, complete);
+ destructive_dispatcher()->DidWrite(bytes, complete);
ericu 2010/11/16 19:26:54 Given that we explicitly don't want to delete the
else
- dispatcher_->DidFail(rv);
+ destructive_dispatcher()->DidFail(rv);
}
void FileSystemOperation::DidTouchFile(base::PlatformFileError rv) {
if (rv == base::PLATFORM_FILE_OK)
- dispatcher_->DidSucceed();
+ destructive_dispatcher()->DidSucceed();
else
- dispatcher_->DidFail(rv);
+ destructive_dispatcher()->DidFail(rv);
}
} // namespace fileapi

Powered by Google App Engine
This is Rietveld 408576698