summaryrefslogtreecommitdiffstats
path: root/webkit/fileapi
diff options
context:
space:
mode:
authordmikurube@chromium.org <dmikurube@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-04-13 09:49:21 +0000
committerdmikurube@chromium.org <dmikurube@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-04-13 09:49:21 +0000
commitb4bd05478c5e4475d4cc91d05825094f931799e2 (patch)
tree057a80d03ac51a820142c57b14d0f4a851e1c23c /webkit/fileapi
parent64822d64607a6247f796196dd18af20c9da7745f (diff)
downloadchromium_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.cc117
-rw-r--r--webkit/fileapi/file_system_file_util.h46
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);
};