diff options
-rw-r--r-- | webkit/fileapi/file_system_file_util_proxy.cc | 19 | ||||
-rw-r--r-- | webkit/fileapi/file_system_file_util_proxy.h | 13 | ||||
-rw-r--r-- | webkit/fileapi/local_file_system_operation.cc | 110 | ||||
-rw-r--r-- | webkit/fileapi/local_file_system_operation.h | 47 | ||||
-rw-r--r-- | webkit/fileapi/local_file_system_operation_unittest.cc | 3 | ||||
-rw-r--r-- | webkit/fileapi/obfuscated_file_util.cc | 6 | ||||
-rw-r--r-- | webkit/fileapi/remove_operation_delegate.cc | 166 | ||||
-rw-r--r-- | webkit/fileapi/remove_operation_delegate.h | 64 | ||||
-rw-r--r-- | webkit/fileapi/syncable/syncable_file_system_operation.cc | 3 | ||||
-rw-r--r-- | webkit/fileapi/webkit_fileapi.gypi | 2 |
10 files changed, 382 insertions, 51 deletions
diff --git a/webkit/fileapi/file_system_file_util_proxy.cc b/webkit/fileapi/file_system_file_util_proxy.cc index b9ce096..d7caf8e 100644 --- a/webkit/fileapi/file_system_file_util_proxy.cc +++ b/webkit/fileapi/file_system_file_util_proxy.cc @@ -108,15 +108,28 @@ class ReadDirectoryHelper { } // namespace // static -bool FileSystemFileUtilProxy::Delete( +bool FileSystemFileUtilProxy::DeleteFile( + FileSystemOperationContext* context, + FileSystemFileUtil* file_util, + const FileSystemURL& url, + const StatusCallback& callback) { + return base::PostTaskAndReplyWithResult( + context->task_runner(), FROM_HERE, + Bind(&FileSystemFileUtil::DeleteFile, Unretained(file_util), + context, url), + callback); +} + +// static +bool FileSystemFileUtilProxy::DeleteDirectory( FileSystemOperationContext* context, FileSystemFileUtil* file_util, const FileSystemURL& url, - bool recursive, const StatusCallback& callback) { return base::PostTaskAndReplyWithResult( context->task_runner(), FROM_HERE, - Bind(&FileUtilHelper::Delete, context, file_util, url, recursive), + Bind(&FileSystemFileUtil::DeleteDirectory, Unretained(file_util), + context, url), callback); } diff --git a/webkit/fileapi/file_system_file_util_proxy.h b/webkit/fileapi/file_system_file_util_proxy.h index 654fbf9..955cd1b 100644 --- a/webkit/fileapi/file_system_file_util_proxy.h +++ b/webkit/fileapi/file_system_file_util_proxy.h @@ -41,13 +41,18 @@ class FileSystemFileUtilProxy { FileSystemFileUtil::SnapshotFilePolicy snapshot_policy)> SnapshotFileCallback; - // Deletes a file or a directory on the given context's task_runner. - // It is an error to delete a non-empty directory with recursive=false. - static bool Delete( + // Deletes a file on the given context's task_runner. + static bool DeleteFile( + FileSystemOperationContext* context, + FileSystemFileUtil* file_util, + const FileSystemURL& url, + const StatusCallback& callback); + + // Deletes a directory on the given context's task_runner. + static bool DeleteDirectory( FileSystemOperationContext* context, FileSystemFileUtil* file_util, const FileSystemURL& url, - bool recursive, const StatusCallback& callback); // Creates or opens a file with the given flags by calling |file_util|'s diff --git a/webkit/fileapi/local_file_system_operation.cc b/webkit/fileapi/local_file_system_operation.cc index 1aa7071..80524a0 100644 --- a/webkit/fileapi/local_file_system_operation.cc +++ b/webkit/fileapi/local_file_system_operation.cc @@ -20,6 +20,7 @@ #include "webkit/fileapi/file_system_url.h" #include "webkit/fileapi/file_system_util.h" #include "webkit/fileapi/file_writer_delegate.h" +#include "webkit/fileapi/remove_operation_delegate.h" #include "webkit/fileapi/sandbox_file_stream_writer.h" #include "webkit/quota/quota_manager.h" #include "webkit/quota/quota_types.h" @@ -44,6 +45,8 @@ bool IsCrossOperationAllowed(FileSystemType src_type, } // namespace +// LocalFileSystemOperation::ScopedUpdateNotifier ----------------------------- + class LocalFileSystemOperation::ScopedUpdateNotifier { public: ScopedUpdateNotifier(FileSystemOperationContext* operation_context, @@ -71,6 +74,8 @@ LocalFileSystemOperation::ScopedUpdateNotifier::~ScopedUpdateNotifier() { &FileUpdateObserver::OnEndUpdate, MakeTuple(url_)); } +// LocalFileSystemOperation --------------------------------------------------- + LocalFileSystemOperation::~LocalFileSystemOperation() { } @@ -187,7 +192,7 @@ void LocalFileSystemOperation::DirectoryExists(const FileSystemURL& url, } FileSystemFileUtilProxy::GetFileInfo( - operation_context_.get(), src_util_, url, + operation_context(), src_util_, url, base::Bind(&LocalFileSystemOperation::DidDirectoryExists, base::Owned(this), callback)); } @@ -204,7 +209,7 @@ void LocalFileSystemOperation::FileExists(const FileSystemURL& url, } FileSystemFileUtilProxy::GetFileInfo( - operation_context_.get(), src_util_, url, + operation_context(), src_util_, url, base::Bind(&LocalFileSystemOperation::DidFileExists, base::Owned(this), callback)); } @@ -221,7 +226,7 @@ void LocalFileSystemOperation::GetMetadata( } FileSystemFileUtilProxy::GetFileInfo( - operation_context_.get(), src_util_, url, + operation_context(), src_util_, url, base::Bind(&LocalFileSystemOperation::DidGetMetadata, base::Owned(this), callback)); } @@ -238,7 +243,7 @@ void LocalFileSystemOperation::ReadDirectory( } FileSystemFileUtilProxy::ReadDirectory( - operation_context_.get(), src_util_, url, + operation_context(), src_util_, url, base::Bind(&LocalFileSystemOperation::DidReadDirectory, base::Owned(this), callback)); } @@ -247,18 +252,12 @@ void LocalFileSystemOperation::Remove(const FileSystemURL& url, bool recursive, const StatusCallback& callback) { DCHECK(SetPendingOperationType(kOperationRemove)); - - base::PlatformFileError result = SetUp(url, &src_util_, SETUP_FOR_WRITE); - if (result != base::PLATFORM_FILE_OK) { - callback.Run(result); - delete this; - return; - } - - FileSystemFileUtilProxy::Delete( - operation_context_.get(), src_util_, url, recursive, - base::Bind(&LocalFileSystemOperation::DidFinishFileOperation, - base::Owned(this), callback)); + DCHECK(!remove_operation_delegate_); + remove_operation_delegate_.reset(new RemoveOperationDelegate(this, callback)); + if (recursive) + remove_operation_delegate_->RunRecursively(url); + else + remove_operation_delegate_->Run(url); } void LocalFileSystemOperation::Write( @@ -301,7 +300,7 @@ void LocalFileSystemOperation::TouchFile(const FileSystemURL& url, } FileSystemFileUtilProxy::Touch( - operation_context_.get(), src_util_, url, + operation_context(), src_util_, url, last_access_time, last_modified_time, base::Bind(&LocalFileSystemOperation::DidTouchFile, base::Owned(this), callback)); @@ -405,7 +404,7 @@ void LocalFileSystemOperation::SyncGetPlatformPath(const FileSystemURL& url, return; } - src_util_->GetLocalFilePath(operation_context_.get(), url, platform_path); + src_util_->GetLocalFilePath(operation_context(), url, platform_path); delete this; } @@ -423,7 +422,7 @@ void LocalFileSystemOperation::CreateSnapshotFile( } FileSystemFileUtilProxy::CreateSnapshotFile( - operation_context_.get(), src_util_, url, + operation_context(), src_util_, url, base::Bind(&LocalFileSystemOperation::DidCreateSnapshotFile, base::Owned(this), callback)); } @@ -450,6 +449,40 @@ void LocalFileSystemOperation::CopyInForeignFile( base::Bind(callback, base::PLATFORM_FILE_ERROR_FAILED)); } +void LocalFileSystemOperation::RemoveFile( + const FileSystemURL& url, + const StatusCallback& callback) { + DCHECK(SetPendingOperationType(kOperationRemove)); + base::PlatformFileError result = SetUp(url, &src_util_, SETUP_FOR_WRITE); + if (result != base::PLATFORM_FILE_OK) { + callback.Run(result); + delete this; + return; + } + + FileSystemFileUtilProxy::DeleteFile( + operation_context(), src_util_, url, + base::Bind(&LocalFileSystemOperation::DidFinishFileOperation, + base::Owned(this), callback)); +} + +void LocalFileSystemOperation::RemoveDirectory( + const FileSystemURL& url, + const StatusCallback& callback) { + DCHECK(SetPendingOperationType(kOperationRemove)); + base::PlatformFileError result = SetUp(url, &src_util_, SETUP_FOR_WRITE); + if (result != base::PLATFORM_FILE_OK) { + callback.Run(result); + delete this; + return; + } + + FileSystemFileUtilProxy::DeleteDirectory( + operation_context(), src_util_, url, + base::Bind(&LocalFileSystemOperation::DidFinishFileOperation, + base::Owned(this), callback)); +} + LocalFileSystemOperation::LocalFileSystemOperation( FileSystemContext* file_system_context, scoped_ptr<FileSystemOperationContext> operation_context) @@ -457,6 +490,7 @@ LocalFileSystemOperation::LocalFileSystemOperation( operation_context_(operation_context.Pass()), src_util_(NULL), dest_util_(NULL), + overriding_operation_context_(NULL), is_cross_operation_(false), peer_handle_(base::kNullProcessHandle), pending_operation_(kOperationNone), @@ -474,7 +508,7 @@ void LocalFileSystemOperation::GetUsageAndQuotaThenRunTask( !file_system_context()->GetQuotaUtil(url.type())) { // If we don't have the quota manager or the requested filesystem type // does not support quota, we should be able to let it go. - operation_context_->set_allowed_bytes_growth(kint64max); + operation_context()->set_allowed_bytes_growth(kint64max); task.Run(); return; } @@ -499,7 +533,7 @@ void LocalFileSystemOperation::DidGetUsageAndQuotaAndRunTask( return; } - operation_context_->set_allowed_bytes_growth(quota - usage); + operation_context()->set_allowed_bytes_growth(quota - usage); task.Run(); } @@ -556,7 +590,7 @@ void LocalFileSystemOperation::DoCreateFile( const StatusCallback& callback, bool exclusive) { FileSystemFileUtilProxy::EnsureFileExists( - operation_context_.get(), + operation_context(), src_util_, url, base::Bind( exclusive ? @@ -570,7 +604,7 @@ void LocalFileSystemOperation::DoCreateDirectory( const StatusCallback& callback, bool exclusive, bool recursive) { FileSystemFileUtilProxy::CreateDirectory( - operation_context_.get(), + operation_context(), src_util_, url, exclusive, recursive, base::Bind(&LocalFileSystemOperation::DidFinishFileOperation, base::Owned(this), callback)); @@ -580,7 +614,7 @@ void LocalFileSystemOperation::DoCopy(const FileSystemURL& src_url, const FileSystemURL& dest_url, const StatusCallback& callback) { FileSystemFileUtilProxy::Copy( - operation_context_.get(), + operation_context(), src_util_, dest_util_, src_url, dest_url, base::Bind(&LocalFileSystemOperation::DidFinishFileOperation, @@ -592,7 +626,7 @@ void LocalFileSystemOperation::DoCopyInForeignFile( const FileSystemURL& dest_url, const StatusCallback& callback) { FileSystemFileUtilProxy::CopyInForeignFile( - operation_context_.get(), + operation_context(), dest_util_, src_local_disk_file_path, dest_url, base::Bind(&LocalFileSystemOperation::DidFinishFileOperation, @@ -603,7 +637,7 @@ void LocalFileSystemOperation::DoMove(const FileSystemURL& src_url, const FileSystemURL& dest_url, const StatusCallback& callback) { FileSystemFileUtilProxy::Move( - operation_context_.get(), + operation_context(), src_util_, dest_util_, src_url, dest_url, base::Bind(&LocalFileSystemOperation::DidFinishFileOperation, @@ -614,7 +648,7 @@ void LocalFileSystemOperation::DoTruncate(const FileSystemURL& url, const StatusCallback& callback, int64 length) { FileSystemFileUtilProxy::Truncate( - operation_context_.get(), src_util_, url, length, + operation_context(), src_util_, url, length, base::Bind(&LocalFileSystemOperation::DidFinishFileOperation, base::Owned(this), callback)); } @@ -623,7 +657,7 @@ void LocalFileSystemOperation::DoOpenFile(const FileSystemURL& url, const OpenFileCallback& callback, int file_flags) { FileSystemFileUtilProxy::CreateOrOpen( - operation_context_.get(), src_util_, url, file_flags, + operation_context(), src_util_, url, file_flags, base::Bind(&LocalFileSystemOperation::DidOpenFile, base::Owned(this), callback)); } @@ -709,7 +743,7 @@ void LocalFileSystemOperation::DidWrite( const bool complete = ( write_status != FileWriterDelegate::SUCCESS_IO_PENDING); if (complete && write_status != FileWriterDelegate::ERROR_WRITE_NOT_STARTED) { - operation_context_->change_observers()->Notify( + operation_context()->change_observers()->Notify( &FileChangeObserver::OnModifyFile, MakeTuple(url)); } @@ -761,23 +795,29 @@ base::PlatformFileError LocalFileSystemOperation::SetUp( mode != SETUP_FOR_READ) return base::PLATFORM_FILE_ERROR_SECURITY; - if (!file_system_context()->GetMountPointProvider( - url.type())->IsAccessAllowed(url)) - return base::PLATFORM_FILE_ERROR_SECURITY; - DCHECK(file_util); if (!*file_util) *file_util = file_system_context()->GetFileUtil(url.type()); if (!*file_util) return base::PLATFORM_FILE_ERROR_SECURITY; + // If this operation is created for recursive sub-operations (i.e. + // operation context is overridden from another operation) we skip + // some duplicated security checks. + if (overriding_operation_context_) + return base::PLATFORM_FILE_OK; + + if (!file_system_context()->GetMountPointProvider( + url.type())->IsAccessAllowed(url)) + return base::PLATFORM_FILE_ERROR_SECURITY; + if (mode == SETUP_FOR_READ) { // TODO(kinuko): This doesn't work well for cross-filesystem operation // in the current architecture since the operation context (thus the // observers) is configured for the destination URL while this method // could be called for both src and dest URL. if (!is_cross_operation_) { - operation_context_->access_observers()->Notify( + operation_context()->access_observers()->Notify( &FileAccessObserver::OnAccess, MakeTuple(url)); } return base::PLATFORM_FILE_OK; @@ -786,7 +826,7 @@ base::PlatformFileError LocalFileSystemOperation::SetUp( DCHECK(mode == SETUP_FOR_WRITE || mode == SETUP_FOR_CREATE); scoped_update_notifiers_.push_back(new ScopedUpdateNotifier( - operation_context_.get(), url)); + operation_context(), url)); // Any write access is disallowed on the root path. if (url.path().value().length() == 0 || diff --git a/webkit/fileapi/local_file_system_operation.h b/webkit/fileapi/local_file_system_operation.h index e80e91f..7a5b57c 100644 --- a/webkit/fileapi/local_file_system_operation.h +++ b/webkit/fileapi/local_file_system_operation.h @@ -25,6 +25,7 @@ class CrosMountPointProvider; namespace fileapi { class FileSystemContext; +class RemoveOperationDelegate; // FileSystemOperation implementation for local file systems. class WEBKIT_STORAGE_EXPORT LocalFileSystemOperation @@ -78,10 +79,39 @@ class WEBKIT_STORAGE_EXPORT LocalFileSystemOperation const FileSystemURL& path, const SnapshotFileCallback& callback) OVERRIDE; + // Copies in a single file from a different filesystem. + // + // This returns: + // - PLATFORM_FILE_ERROR_NOT_FOUND if |src_file_path| + // or the parent directory of |dest_url| does not exist. + // - PLATFORM_FILE_ERROR_INVALID_OPERATION if |dest_url| exists and + // is not a file. + // - PLATFORM_FILE_ERROR_FAILED if |dest_url| does not exist and + // its parent path is a file. + // void CopyInForeignFile(const FilePath& src_local_disk_path, const FileSystemURL& dest_url, const StatusCallback& callback); + // Removes a single file. + // + // This returns: + // - PLATFORM_FILE_ERROR_NOT_FOUND if |url| does not exist. + // - PLATFORM_FILE_ERROR_NOT_A_FILE if |url| is not a file. + // + void RemoveFile(const FileSystemURL& url, + const StatusCallback& callback); + + // Removes a single empty directory. + // + // This returns: + // - PLATFORM_FILE_ERROR_NOT_FOUND if |url| does not exist. + // - PLATFORM_FILE_ERROR_NOT_A_DIRECTORY if |url| is not a directory. + // - PLATFORM_FILE_ERROR_NOT_EMPTY if |url| is not empty. + // + void RemoveDirectory(const FileSystemURL& url, + const StatusCallback& callback); + // Synchronously gets the platform path for the given |url|. void SyncGetPlatformPath(const FileSystemURL& url, FilePath* platform_path); @@ -108,6 +138,7 @@ class WEBKIT_STORAGE_EXPORT LocalFileSystemOperation friend class FileSystemQuotaTest; friend class LocalFileSystemTestOriginHelper; + friend class RemoveOperationDelegate; friend class SyncableFileSystemOperation; LocalFileSystemOperation( @@ -119,6 +150,8 @@ class WEBKIT_STORAGE_EXPORT LocalFileSystemOperation } FileSystemOperationContext* operation_context() const { + if (overriding_operation_context_) + return overriding_operation_context_; return operation_context_.get(); } @@ -230,12 +263,24 @@ class WEBKIT_STORAGE_EXPORT LocalFileSystemOperation // Returns false if there's another inflight pending operation. bool SetPendingOperationType(OperationType type); + // Overrides this operation's operation context by given |context|. + // This operation won't own |context| and the |context| needs to outlive + // this operation. + // + // Called only from operation delegates when they create sub-operations + // for performing a recursive operation. + void set_overriding_operation_context(FileSystemOperationContext* context) { + overriding_operation_context_ = context; + } + scoped_refptr<FileSystemContext> file_system_context_; scoped_ptr<FileSystemOperationContext> operation_context_; FileSystemFileUtil* src_util_; // Not owned. FileSystemFileUtil* dest_util_; // Not owned. + FileSystemOperationContext* overriding_operation_context_; + // Indicates if this operation is for cross filesystem operation or not. // TODO(kinuko): This should be cleaned up. bool is_cross_operation_; @@ -248,6 +293,8 @@ class WEBKIT_STORAGE_EXPORT LocalFileSystemOperation friend class FileWriterDelegate; scoped_ptr<FileWriterDelegate> file_writer_delegate_; + scoped_ptr<RemoveOperationDelegate> remove_operation_delegate_; + // write_callback is kept in this class for so that we can dispatch it when // the operation is cancelled. calcel_callback is kept for canceling a // Truncate() operation. We can't actually stop Truncate in another thread; diff --git a/webkit/fileapi/local_file_system_operation_unittest.cc b/webkit/fileapi/local_file_system_operation_unittest.cc index 604f91d..d170b7c 100644 --- a/webkit/fileapi/local_file_system_operation_unittest.cc +++ b/webkit/fileapi/local_file_system_operation_unittest.cc @@ -1046,9 +1046,6 @@ TEST_F(LocalFileSystemOperationTest, TestRemoveSuccess) { EXPECT_EQ(base::PLATFORM_FILE_OK, status()); EXPECT_FALSE(DirectoryExists(parent_dir_path)); - // Remove is not a 'read' access. - EXPECT_EQ(0, quota_manager_proxy()->notify_storage_accessed_count()); - EXPECT_EQ(2, change_observer()->get_and_reset_remove_directory_count()); EXPECT_EQ(1, change_observer()->get_and_reset_remove_file_count()); EXPECT_TRUE(change_observer()->HasNoChange()); diff --git a/webkit/fileapi/obfuscated_file_util.cc b/webkit/fileapi/obfuscated_file_util.cc index 4e743c6..9bd64bc 100644 --- a/webkit/fileapi/obfuscated_file_util.cc +++ b/webkit/fileapi/obfuscated_file_util.cc @@ -813,10 +813,8 @@ PlatformFileError ObfuscatedFileUtil::DeleteFile( error != base::PLATFORM_FILE_OK) return error; - if (file_info.is_directory()) { - NOTREACHED(); - return base::PLATFORM_FILE_ERROR_FAILED; - } + if (file_info.is_directory()) + return base::PLATFORM_FILE_ERROR_NOT_A_FILE; int64 growth = -UsageForPath(file_info.name.size()) - platform_file_info.size; AllocateQuota(context, growth); diff --git a/webkit/fileapi/remove_operation_delegate.cc b/webkit/fileapi/remove_operation_delegate.cc new file mode 100644 index 0000000..3dafbdb --- /dev/null +++ b/webkit/fileapi/remove_operation_delegate.cc @@ -0,0 +1,166 @@ +// Copyright (c) 2013 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/fileapi/remove_operation_delegate.h" + +#include "base/bind.h" +#include "webkit/fileapi/file_system_context.h" +#include "webkit/fileapi/file_system_operation_context.h" +#include "webkit/fileapi/local_file_system_operation.h" + +namespace fileapi { + +RemoveOperationDelegate::RemoveOperationDelegate( + LocalFileSystemOperation* original_operation, + const StatusCallback& callback) + : original_operation_(original_operation), + callback_(callback), + inflight_operations_(0) { +} + +RemoveOperationDelegate::~RemoveOperationDelegate() {} + +void RemoveOperationDelegate::Run(const FileSystemURL& url) { + LocalFileSystemOperation* operation = NewOperation(url); + if (!operation) + return; + operation->RemoveFile(url, base::Bind( + &RemoveOperationDelegate::DidTryRemoveFile, AsWeakPtr(), url)); +} + +void RemoveOperationDelegate::RunRecursively(const FileSystemURL& url) { + DCHECK(pending_directories_.empty()); + pending_directories_.push(url); + ProcessNextDirectory(base::PLATFORM_FILE_OK); +} + +void RemoveOperationDelegate::DidTryRemoveFile( + const FileSystemURL& url, + base::PlatformFileError error) { + if (error == base::PLATFORM_FILE_OK || + error != base::PLATFORM_FILE_ERROR_NOT_A_FILE) { + callback_.Run(error); + return; + } + LocalFileSystemOperation* operation = NewOperation(url); + if (!operation) + return; + operation->RemoveDirectory(url, callback_); +} + +void RemoveOperationDelegate::ProcessNextDirectory( + base::PlatformFileError error) { + if (error != base::PLATFORM_FILE_OK) { + callback_.Run(error); + return; + } + if (inflight_operations_ > 0) + return; + if (pending_directories_.empty()) { + RemoveNextDirectory(error); + return; + } + FileSystemURL url = pending_directories_.front(); + pending_directories_.pop(); + LocalFileSystemOperation* operation = NewOperation(url); + if (!operation) + return; + inflight_operations_++; + operation->ReadDirectory( + url, base::Bind(&RemoveOperationDelegate::DidReadDirectory, + AsWeakPtr(), url)); +} + +void RemoveOperationDelegate::DidReadDirectory( + const FileSystemURL& parent, + base::PlatformFileError error, + const FileEntryList& entries, + bool has_more) { + if (error != base::PLATFORM_FILE_OK) { + if (error == base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY) { + // The given path may have been a file, so try RemoveFile. + inflight_operations_--; + DCHECK_GE(inflight_operations_, 0); + RemoveFile(parent); + return; + } + callback_.Run(error); + return; + } + for (size_t i = 0; i < entries.size(); i++) { + FileSystemURL url = parent.WithPath(parent.path().Append(entries[i].name)); + if (entries[i].is_directory) { + pending_directories_.push(url); + continue; + } + RemoveFile(url); + } + if (has_more) + return; + + to_remove_directories_.push(parent); + inflight_operations_--; + DCHECK_GE(inflight_operations_, 0); + ProcessNextDirectory(base::PLATFORM_FILE_OK); +} + +void RemoveOperationDelegate::RemoveFile(const FileSystemURL& url) { + LocalFileSystemOperation* operation = NewOperation(url); + if (!operation) + return; + inflight_operations_++; + operation->RemoveFile(url, base::Bind( + &RemoveOperationDelegate::DidRemoveFile, AsWeakPtr())); +} + +void RemoveOperationDelegate::DidRemoveFile(base::PlatformFileError error) { + inflight_operations_--; + DCHECK_GE(inflight_operations_, 0); + if (error != base::PLATFORM_FILE_OK && + error != base::PLATFORM_FILE_ERROR_NOT_FOUND) { + callback_.Run(error); + return; + } + ProcessNextDirectory(error); +} + +void RemoveOperationDelegate::RemoveNextDirectory( + base::PlatformFileError error) { + DCHECK_EQ(0, inflight_operations_); + DCHECK(pending_directories_.empty()); + if (error != base::PLATFORM_FILE_OK || + to_remove_directories_.empty()) { + callback_.Run(error); + return; + } + FileSystemURL url = to_remove_directories_.top(); + to_remove_directories_.pop(); + LocalFileSystemOperation* operation = NewOperation(url); + if (!operation) + return; + operation->RemoveDirectory(url, base::Bind( + &RemoveOperationDelegate::RemoveNextDirectory, + AsWeakPtr())); +} + +LocalFileSystemOperation* RemoveOperationDelegate::NewOperation( + const FileSystemURL& url) { + base::PlatformFileError error; + FileSystemOperation* operation = original_operation_->file_system_context()-> + CreateFileSystemOperation(url, &error); + if (error != base::PLATFORM_FILE_OK) { + callback_.Run(error); + return NULL; + } + LocalFileSystemOperation* local_operation = + operation->AsLocalFileSystemOperation(); + DCHECK(local_operation); + + // Let the new operation inherit from the original operation. + local_operation->set_overriding_operation_context( + original_operation_->operation_context()); + return local_operation; +} + +} // namespace fileapi diff --git a/webkit/fileapi/remove_operation_delegate.h b/webkit/fileapi/remove_operation_delegate.h new file mode 100644 index 0000000..43ea9d2 --- /dev/null +++ b/webkit/fileapi/remove_operation_delegate.h @@ -0,0 +1,64 @@ +// Copyright (c) 2013 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. + +#ifndef WEBKIT_FILEAPI_REMOVE_OPERATION_DELEGATE_H_ +#define WEBKIT_FILEAPI_REMOVE_OPERATION_DELEGATE_H_ + +#include <queue> +#include <stack> + +#include "base/basictypes.h" +#include "base/callback.h" +#include "base/memory/weak_ptr.h" +#include "webkit/fileapi/file_system_operation.h" +#include "webkit/fileapi/file_system_url.h" + +namespace fileapi { + +class FileSystemURL; +class LocalFileSystemOperation; + +class RemoveOperationDelegate + : public base::SupportsWeakPtr<RemoveOperationDelegate> { + public: + typedef FileSystemOperation::StatusCallback StatusCallback; + typedef FileSystemOperation::FileEntryList FileEntryList; + + RemoveOperationDelegate(LocalFileSystemOperation* original_operation, + const StatusCallback& callback); + virtual ~RemoveOperationDelegate(); + + void Run(const FileSystemURL& url); + void RunRecursively(const FileSystemURL& url); + + private: + void ProcessNextDirectory(base::PlatformFileError error); + void DidTryRemoveFile( + const FileSystemURL& url, + base::PlatformFileError error); + void DidReadDirectory( + const FileSystemURL& parent, + base::PlatformFileError error, + const FileEntryList& entries, + bool has_more); + void RemoveFile(const FileSystemURL& url); + void DidRemoveFile(base::PlatformFileError error); + void RemoveNextDirectory(base::PlatformFileError error); + + LocalFileSystemOperation* NewOperation(const FileSystemURL& url); + + LocalFileSystemOperation* original_operation_; + StatusCallback callback_; + + std::queue<FileSystemURL> pending_directories_; + std::stack<FileSystemURL> to_remove_directories_; + + int inflight_operations_; + + DISALLOW_COPY_AND_ASSIGN(RemoveOperationDelegate); +}; + +} // namespace fileapi + +#endif // WEBKIT_FILEAPI_REMOVE_OPERATION_DELEGATE_H_ diff --git a/webkit/fileapi/syncable/syncable_file_system_operation.cc b/webkit/fileapi/syncable/syncable_file_system_operation.cc index 8954f26..981efdf 100644 --- a/webkit/fileapi/syncable/syncable_file_system_operation.cc +++ b/webkit/fileapi/syncable/syncable_file_system_operation.cc @@ -314,8 +314,7 @@ void SyncableFileSystemOperation::Cancel( LocalFileSystemOperation* SyncableFileSystemOperation::AsLocalFileSystemOperation() { - NOTREACHED(); - return NULL; + return file_system_operation_; } void SyncableFileSystemOperation::CreateSnapshotFile( diff --git a/webkit/fileapi/webkit_fileapi.gypi b/webkit/fileapi/webkit_fileapi.gypi index 324f9e5..ec9f7ad 100644 --- a/webkit/fileapi/webkit_fileapi.gypi +++ b/webkit/fileapi/webkit_fileapi.gypi @@ -79,6 +79,8 @@ '../fileapi/obfuscated_file_util.cc', '../fileapi/obfuscated_file_util.h', '../fileapi/remote_file_system_proxy.h', + '../fileapi/remove_operation_delegate.cc', + '../fileapi/remove_operation_delegate.h', '../fileapi/sandbox_file_stream_writer.cc', '../fileapi/sandbox_file_stream_writer.h', '../fileapi/sandbox_mount_point_provider.cc', |