Chromium Code Reviews| 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 |