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

Unified Diff: webkit/fileapi/fileapi_file_util.cc

Issue 7470037: [Refactor] to rename and re-layer the file_util stack layers. (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: Rebased. Created 9 years, 5 months 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/fileapi_file_util.cc
diff --git a/webkit/fileapi/fileapi_file_util.cc b/webkit/fileapi/fileapi_file_util.cc
new file mode 100644
index 0000000000000000000000000000000000000000..9162534a6fb3a188a028aa8433fc2ef99826ee46
--- /dev/null
+++ b/webkit/fileapi/fileapi_file_util.cc
@@ -0,0 +1,280 @@
+// Copyright (c) 2011 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/fileapi_file_util.h"
+
+#include <stack>
+
+#include "base/memory/scoped_ptr.h"
+#include "webkit/fileapi/file_system_operation_context.h"
+
+namespace fileapi {
+
+namespace {
+
+// This assumes that the root exists.
+bool ParentExists(FileSystemOperationContext* context,
+ FileUtil* file_util, const FilePath& file_path) {
+ // If file_path is in the root, file_path.DirName() will be ".",
+ // since we use paths with no leading '/'.
+ FilePath parent = file_path.DirName();
+ if (parent == FilePath(FILE_PATH_LITERAL(".")))
+ return true;
+ return file_util->DirectoryExists(context, parent);
+}
+
+} // namespace
+
+PlatformFileError FileUtil::Copy(
+ FileSystemOperationContext* context,
+ const FilePath& src_file_path,
+ const FilePath& dest_file_path) {
+ PlatformFileError error_code;
+ error_code =
+ PerformCommonCheckAndPreparationForMoveAndCopy(
+ context, src_file_path, dest_file_path);
+ if (error_code != base::PLATFORM_FILE_OK)
+ return error_code;
+
+ if (DirectoryExists(context, src_file_path))
+ return CopyOrMoveDirectory(context, src_file_path, dest_file_path,
+ true /* copy */);
+ return CopyOrMoveFileHelper(context, src_file_path, dest_file_path,
+ true /* copy */);
+}
+
+
+PlatformFileError FileUtil::Move(
+ FileSystemOperationContext* context,
+ const FilePath& src_file_path,
+ const FilePath& dest_file_path) {
+ PlatformFileError error_code;
+ error_code =
+ PerformCommonCheckAndPreparationForMoveAndCopy(
+ context, src_file_path, dest_file_path);
+ if (error_code != base::PLATFORM_FILE_OK)
+ return error_code;
+
+ // TODO(dmikurube): ReplaceFile if in the same domain and filesystem type.
+ if (DirectoryExists(context, src_file_path))
+ return CopyOrMoveDirectory(context, src_file_path, dest_file_path,
+ false /* copy */);
+ return CopyOrMoveFileHelper(context, src_file_path, dest_file_path,
+ false /* copy */);
+}
+
+PlatformFileError FileUtil::Delete(
+ FileSystemOperationContext* context,
+ const FilePath& file_path,
+ bool recursive) {
+ if (DirectoryExists(context, file_path)) {
+ if (!recursive)
+ return DeleteSingleDirectory(context, file_path);
+ else
+ return DeleteDirectoryRecursive(context, file_path);
+ } else {
+ return DeleteFile(context, file_path);
+ }
+}
+
+PlatformFileError
+FileUtil::PerformCommonCheckAndPreparationForMoveAndCopy(
+ FileSystemOperationContext* context,
+ const FilePath& src_file_path,
+ const FilePath& dest_file_path) {
+ bool same_file_system =
+ (context->src_origin_url() == context->dest_origin_url()) &&
+ (context->src_type() == context->dest_type());
+ FileUtil* dest_util = context->dest_file_util();
+ DCHECK(dest_util);
+ if (same_file_system)
+ DCHECK(context->src_file_util() == context->dest_file_util());
+ // All the single-path virtual FSFU methods expect the context information
+ // to be in the src_* variables, not the dest_* variables, so we have to
+ // make a new context if we want to call them on the dest_file_path.
+ scoped_ptr<FileSystemOperationContext> dest_context(
+ context->CreateInheritedContextForDest());
+
+ // Exits earlier if the source path does not exist.
+ if (!PathExists(context, src_file_path))
+ return base::PLATFORM_FILE_ERROR_NOT_FOUND;
+
+ // The parent of the |dest_file_path| does not exist.
+ if (!ParentExists(dest_context.get(), dest_util, dest_file_path))
+ return base::PLATFORM_FILE_ERROR_NOT_FOUND;
+
+ // It is an error to try to copy/move an entry into its child.
+ if (same_file_system && src_file_path.IsParent(dest_file_path))
+ return base::PLATFORM_FILE_ERROR_INVALID_OPERATION;
+
+ // Now it is ok to return if the |dest_file_path| does not exist.
+ if (!dest_util->PathExists(dest_context.get(), dest_file_path))
+ return base::PLATFORM_FILE_OK;
+
+ // |src_file_path| exists and is a directory.
+ // |dest_file_path| exists and is a file.
+ bool src_is_directory = DirectoryExists(context, src_file_path);
+ bool dest_is_directory =
+ dest_util->DirectoryExists(dest_context.get(), dest_file_path);
+ if (src_is_directory && !dest_is_directory)
+ return base::PLATFORM_FILE_ERROR_INVALID_OPERATION;
+
+ // |src_file_path| exists and is a file.
+ // |dest_file_path| exists and is a directory.
+ if (!src_is_directory && dest_is_directory)
+ return base::PLATFORM_FILE_ERROR_INVALID_OPERATION;
+
+ // It is an error to copy/move an entry into the same path.
+ if (same_file_system && (src_file_path.value() == dest_file_path.value()))
+ return base::PLATFORM_FILE_ERROR_EXISTS;
+
+ if (dest_is_directory) {
+ // It is an error to copy/move an entry to a non-empty directory.
+ // Otherwise the copy/move attempt must overwrite the destination, but
+ // the file_util's Copy or Move method doesn't perform overwrite
+ // on all platforms, so we delete the destination directory here.
+ // TODO(kinuko): may be better to change the file_util::{Copy,Move}.
+ PlatformFileError error = dest_util->Delete(
+ dest_context.get(), dest_file_path, false /* recursive */);
+ context->ImportAllowedBytesGrowth(*dest_context);
+ if (base::PLATFORM_FILE_OK != error) {
+ if (!dest_util->IsDirectoryEmpty(dest_context.get(), dest_file_path))
+ return base::PLATFORM_FILE_ERROR_NOT_EMPTY;
+ return base::PLATFORM_FILE_ERROR_FAILED;
+ }
+ }
+ return base::PLATFORM_FILE_OK;
+}
+
+PlatformFileError FileUtil::CopyOrMoveDirectory(
+ FileSystemOperationContext* context,
+ const FilePath& src_file_path,
+ const FilePath& dest_file_path,
+ bool copy) {
+ FileUtil* dest_util = context->dest_file_util();
+ scoped_ptr<FileSystemOperationContext> dest_context(
+ context->CreateInheritedContextForDest());
+
+ // Re-check PerformCommonCheckAndPreparationForMoveAndCopy() by DCHECK.
+ DCHECK(DirectoryExists(context, src_file_path));
+ DCHECK(ParentExists(dest_context.get(), dest_util, dest_file_path));
+ DCHECK(!dest_util->PathExists(dest_context.get(), dest_file_path));
+ if ((context->src_origin_url() == context->dest_origin_url()) &&
+ (context->src_type() == context->dest_type()))
+ DCHECK(!src_file_path.IsParent(dest_file_path));
+
+ if (!dest_util->DirectoryExists(dest_context.get(), dest_file_path)) {
+ PlatformFileError error = dest_util->CreateDirectory(dest_context.get(),
+ dest_file_path, false, false);
+ context->ImportAllowedBytesGrowth(*dest_context);
+ if (error != base::PLATFORM_FILE_OK)
+ return error;
+ }
+
+ scoped_ptr<AbstractFileEnumerator> file_enum(
+ CreateFileEnumerator(context, 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()) {
+ scoped_ptr<FileSystemOperationContext> new_directory_context(
+ dest_context->CreateInheritedContextWithNewVirtualPaths(
+ dest_file_path_each, FilePath()));
+ PlatformFileError error = dest_util->CreateDirectory(
+ new_directory_context.get(), dest_file_path_each, false, false);
+ context->ImportAllowedBytesGrowth(*new_directory_context);
+ if (error != base::PLATFORM_FILE_OK)
+ return error;
+ } else {
+ scoped_ptr<FileSystemOperationContext> copy_context(
+ context->CreateInheritedContextWithNewVirtualPaths(
+ src_file_path_each, dest_file_path_each));
+ PlatformFileError error = CopyOrMoveFileHelper(
+ copy_context.get(), src_file_path_each, dest_file_path_each, copy);
+ context->ImportAllowedBytesGrowth(*copy_context);
+ if (error != base::PLATFORM_FILE_OK)
+ return error;
+ }
+ }
+
+ if (!copy) {
+ PlatformFileError error = Delete(context, src_file_path, true);
+ if (error != base::PLATFORM_FILE_OK)
+ return error;
+ }
+ return base::PLATFORM_FILE_OK;
+}
+
+PlatformFileError FileUtil::CopyOrMoveFileHelper(
+ FileSystemOperationContext* context,
+ const FilePath& src_file_path,
+ const FilePath& dest_file_path,
+ bool copy) {
+ // CopyOrMoveFile here is the virtual overridden member function.
+ if ((context->src_origin_url() == context->dest_origin_url()) &&
+ (context->src_type() == context->dest_type())) {
+ DCHECK(context->src_file_util() == context->dest_file_util());
+ return CopyOrMoveFile(context, src_file_path, dest_file_path, copy);
+ }
+ base::PlatformFileInfo file_info;
+ FilePath platform_file_path;
+ PlatformFileError error_code;
+ error_code =
+ GetFileInfo(context, src_file_path, &file_info, &platform_file_path);
+ if (error_code != base::PLATFORM_FILE_OK)
+ return error_code;
+
+ DCHECK(context->dest_file_util());
+ error_code = context->dest_file_util()->CopyInForeignFile(
+ context, platform_file_path, dest_file_path);
+ if (copy || error_code != base::PLATFORM_FILE_OK)
+ return error_code;
+ return DeleteFile(context, src_file_path);
+}
+
+PlatformFileError FileUtil::DeleteDirectoryRecursive(
+ FileSystemOperationContext* context,
+ const FilePath& file_path) {
+ scoped_ptr<AbstractFileEnumerator> file_enum(
+ CreateFileEnumerator(context, file_path));
+ FilePath file_path_each;
+
+ std::stack<FilePath> directories;
+ while (!(file_path_each = file_enum->Next()).empty()) {
+ if (file_enum->IsDirectory()) {
+ directories.push(file_path_each);
+ } else {
+ // DeleteFile here is the virtual overridden member function.
+ scoped_ptr<FileSystemOperationContext> inherited_context(
+ context->CreateInheritedContextWithNewVirtualPaths(
+ file_path_each, FilePath()));
+ PlatformFileError error =
+ DeleteFile(inherited_context.get(), file_path_each);
+ context->ImportAllowedBytesGrowth(*inherited_context);
+ if (error == base::PLATFORM_FILE_ERROR_NOT_FOUND)
+ return base::PLATFORM_FILE_ERROR_FAILED;
+ else if (error != base::PLATFORM_FILE_OK)
+ return error;
+ }
+ }
+
+ while (!directories.empty()) {
+ scoped_ptr<FileSystemOperationContext> inherited_context(
+ context->CreateInheritedContextWithNewVirtualPaths(
+ directories.top(), FilePath()));
+ PlatformFileError error =
+ DeleteSingleDirectory(inherited_context.get(), directories.top());
+ context->ImportAllowedBytesGrowth(*inherited_context);
+ if (error == base::PLATFORM_FILE_ERROR_NOT_FOUND)
+ return base::PLATFORM_FILE_ERROR_FAILED;
+ else if (error != base::PLATFORM_FILE_OK)
+ return error;
+ directories.pop();
+ }
+ return DeleteSingleDirectory(context, file_path);
+}
+
+} // namespace fileapi

Powered by Google App Engine
This is Rietveld 408576698