diff options
author | dmikurube@chromium.org <dmikurube@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-04-13 09:49:21 +0000 |
---|---|---|
committer | dmikurube@chromium.org <dmikurube@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-04-13 09:49:21 +0000 |
commit | b4bd05478c5e4475d4cc91d05825094f931799e2 (patch) | |
tree | 057a80d03ac51a820142c57b14d0f4a851e1c23c /webkit/fileapi | |
parent | 64822d64607a6247f796196dd18af20c9da7745f (diff) | |
download | chromium_src-b4bd05478c5e4475d4cc91d05825094f931799e2.zip chromium_src-b4bd05478c5e4475d4cc91d05825094f931799e2.tar.gz chromium_src-b4bd05478c5e4475d4cc91d05825094f931799e2.tar.bz2 |
Extract a recursive copy function as a shared and non-virtual function.
This extraction is required to stack FileUtil layers without duplicated code of recursive copy. No tests because it doesn't change any behavior.
BUG=none
TEST=none
Review URL: http://codereview.chromium.org/6772005
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@81388 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/fileapi')
-rw-r--r-- | webkit/fileapi/file_system_file_util.cc | 117 | ||||
-rw-r--r-- | webkit/fileapi/file_system_file_util.h | 46 |
2 files changed, 152 insertions, 11 deletions
diff --git a/webkit/fileapi/file_system_file_util.cc b/webkit/fileapi/file_system_file_util.cc index 1dceed2..aadc1cb 100644 --- a/webkit/fileapi/file_system_file_util.cc +++ b/webkit/fileapi/file_system_file_util.cc @@ -5,9 +5,12 @@ #include "webkit/fileapi/file_system_file_util.h" #include "base/file_util_proxy.h" +#include "base/logging.h" +#include "base/scoped_ptr.h" namespace fileapi { +// static FileSystemFileUtil* FileSystemFileUtil::GetInstance() { return Singleton<FileSystemFileUtil>::get(); } @@ -129,10 +132,11 @@ PlatformFileError FileSystemFileUtil::Copy( context, src_file_path, dest_file_path); if (error_code != base::PLATFORM_FILE_OK) return error_code; - if (!file_util::CopyDirectory(src_file_path, dest_file_path, - true /* recursive */)) - return base::PLATFORM_FILE_ERROR_FAILED; - return base::PLATFORM_FILE_OK; + + if (file_util::DirectoryExists(src_file_path)) + return CopyDirectory(context, src_file_path, dest_file_path); + else + return CopyOrMoveFile(context, src_file_path, dest_file_path, true); } PlatformFileError FileSystemFileUtil::Move( @@ -145,9 +149,16 @@ PlatformFileError FileSystemFileUtil::Move( context, src_file_path, dest_file_path); if (error_code != base::PLATFORM_FILE_OK) return error_code; - if (!file_util::Move(src_file_path, dest_file_path)) - return base::PLATFORM_FILE_ERROR_FAILED; - return base::PLATFORM_FILE_OK; + + // TODO(dmikurube): ReplaceFile if in the same filesystem. + if (file_util::DirectoryExists(src_file_path)) { + PlatformFileError error = + CopyDirectory(context, src_file_path, dest_file_path); + if (error != base::PLATFORM_FILE_OK) + return error; + return Delete(context, src_file_path, true); + } else + return CopyOrMoveFile(context, src_file_path, dest_file_path, false); } PlatformFileError FileSystemFileUtil::Delete( @@ -250,6 +261,62 @@ FileSystemFileUtil::PerformCommonCheckAndPreparationForMoveAndCopy( return base::PLATFORM_FILE_OK; } +PlatformFileError FileSystemFileUtil::CopyOrMoveFile( + FileSystemOperationContext* unused, + const FilePath& src_file_path, + const FilePath& dest_file_path, + bool copy) { + if (copy) { + if (file_util::CopyFile(src_file_path, dest_file_path)) + return base::PLATFORM_FILE_OK; + } else { + DCHECK(!file_util::DirectoryExists(src_file_path)); + if (file_util::Move(src_file_path, dest_file_path)) + return base::PLATFORM_FILE_OK; + } + return base::PLATFORM_FILE_ERROR_FAILED; +} + +PlatformFileError FileSystemFileUtil::CopyDirectory( + FileSystemOperationContext* context, + const FilePath& src_file_path, + const FilePath& dest_file_path) { + // Re-check PerformCommonCheckAndPreparationForMoveAndCopy() by DCHECK. + DCHECK(DirectoryExists(context, src_file_path)); + DCHECK(DirectoryExists(context, dest_file_path.DirName())); + DCHECK(!src_file_path.IsParent(dest_file_path)); + DCHECK(!PathExists(context, dest_file_path)); + + if (!DirectoryExists(context, dest_file_path)) { + PlatformFileError error = CreateDirectory(context, + dest_file_path, false, false); + if (error != base::PLATFORM_FILE_OK) + return error; + } + + scoped_ptr<AbstractFileEnumerator> file_enum( + CreateFileEnumerator(src_file_path)); + FilePath src_file_path_each; + while (!(src_file_path_each = file_enum->Next()).empty()) { + FilePath dest_file_path_each(dest_file_path); + src_file_path.AppendRelativePath(src_file_path_each, &dest_file_path_each); + + if (file_enum->IsDirectory()) { + PlatformFileError error = CreateDirectory(context, + dest_file_path_each, false, false); + if (error != base::PLATFORM_FILE_OK) + return error; + } else { + // CopyOrMoveFile here is the virtual overridden member function. + PlatformFileError error = CopyOrMoveFile( + context, src_file_path_each, dest_file_path_each, true); + if (error != base::PLATFORM_FILE_OK) + return error; + } + } + return base::PLATFORM_FILE_OK; +} + bool FileSystemFileUtil::PathExists( FileSystemOperationContext* unused, const FilePath& file_path) { @@ -268,4 +335,40 @@ bool FileSystemFileUtil::IsDirectoryEmpty( return file_util::IsDirectoryEmpty(file_path); } +class FileSystemFileEnumerator + : public FileSystemFileUtil::AbstractFileEnumerator { + public: + FileSystemFileEnumerator(const FilePath& root_path, + bool recursive, + file_util::FileEnumerator::FILE_TYPE file_type) + : file_enum_(root_path, recursive, file_type) { + } + + ~FileSystemFileEnumerator() {} + + virtual FilePath Next(); + virtual bool IsDirectory(); + + private: + file_util::FileEnumerator file_enum_; +}; + +FilePath FileSystemFileEnumerator::Next() { + return file_enum_.Next(); +} + +bool FileSystemFileEnumerator::IsDirectory() { + file_util::FileEnumerator::FindInfo file_util_info; + file_enum_.GetFindInfo(&file_util_info); + return file_util::FileEnumerator::IsDirectory(file_util_info); +} + +FileSystemFileUtil::AbstractFileEnumerator* +FileSystemFileUtil::CreateFileEnumerator(const FilePath& root_path) { + return new FileSystemFileEnumerator( + root_path, true, static_cast<file_util::FileEnumerator::FILE_TYPE>( + file_util::FileEnumerator::FILES | + file_util::FileEnumerator::DIRECTORIES)); +} + } // namespace fileapi diff --git a/webkit/fileapi/file_system_file_util.h b/webkit/fileapi/file_system_file_util.h index a208ae4..9d3eb26 100644 --- a/webkit/fileapi/file_system_file_util.h +++ b/webkit/fileapi/file_system_file_util.h @@ -64,7 +64,7 @@ class FileSystemFileUtil { FileSystemOperationContext* context, const FilePath& file_path, bool* created); - // Retrieves the information about a file. It is invalid to pass NULL for the + // Retrieves the information about a file. It is invalid to pass NULL for the // callback. virtual PlatformFileError GetFileInfo( FileSystemOperationContext* context, @@ -85,19 +85,24 @@ class FileSystemFileUtil { bool exclusive, bool recursive); + // TODO(dmikurube): Make this method non-virtual if it's possible. + // It conflicts with LocalFileSystemFileUtil for now. + // // Copies a file or a directory from |src_file_path| to |dest_file_path| // Error cases: - // If destination file doesn't exist or destination's parent - // doesn't exists. + // If destination's parent doesn't exist. // If source dir exists but destination path is an existing file. // If source file exists but destination path is an existing directory. // If source is a parent of destination. - // If source doesn't exists. + // If source doesn't exist. virtual PlatformFileError Copy( FileSystemOperationContext* context, const FilePath& src_file_path, const FilePath& dest_file_path); + // TODO(dmikurube): Make this method non-virtual if it's possible. + // It conflicts with LocalFileSystemFileUtil for now. + // // Moves a file or a directory from src_file_path to dest_file_path. // Error cases are similar to Copy method's error cases. virtual PlatformFileError Move( @@ -127,12 +132,22 @@ class FileSystemFileUtil { const FilePath& path, int64 length); + // It will be implemented by each subclass such as FileSystemFileEnumerator. + class AbstractFileEnumerator { + public: + // Returns an empty string if there are no more results. + virtual FilePath Next() = 0; + + virtual bool IsDirectory() = 0; + }; + protected: FileSystemFileUtil() { } // This also removes the destination directory if it's non-empty and all // other checks are passed (so that the copy/move correctly overwrites the // destination). + // This method is non-virtual, not to be overridden. PlatformFileError PerformCommonCheckAndPreparationForMoveAndCopy( FileSystemOperationContext* unused, const FilePath& src_file_path, @@ -150,6 +165,29 @@ class FileSystemFileUtil { FileSystemOperationContext* unused, const FilePath& file_path); + // Copies or moves a single file. + virtual PlatformFileError CopyOrMoveFile( + FileSystemOperationContext* context, + const FilePath& src_file_path, + const FilePath& dest_file_path, + bool copy); + + // Performs recursive copy by calling CopyOrMoveFile for individual files. + // Operations for recursive traversal are encapsulated in this method. + // It assumes src_file_path and dest_file_path have passed + // PerformCommonCheckAndPreparationForMoveAndCopy(). + // This method is non-virtual, not to be overridden. + PlatformFileError CopyDirectory( + FileSystemOperationContext* context, + const FilePath& src_file_path, + const FilePath& dest_file_path); + + // Returns a pointer to a new instance of AbstractFileEnumerator which is + // implemented for each FileUtil subclass. The instance needs to be freed + // by the caller. + virtual AbstractFileEnumerator* CreateFileEnumerator( + const FilePath& root_path); + friend struct DefaultSingletonTraits<FileSystemFileUtil>; DISALLOW_COPY_AND_ASSIGN(FileSystemFileUtil); }; |