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

Side by Side Diff: webkit/fileapi/cross_file_util_helper.cc

Issue 9616033: Merge CrossFileUtilHelper to FileUtilHelper as Copy() and Move(). (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 8 years, 9 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « webkit/fileapi/cross_file_util_helper.h ('k') | webkit/fileapi/file_system_file_util_proxy.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "webkit/fileapi/cross_file_util_helper.h"
6
7 #include "webkit/fileapi/file_system_file_util.h"
8 #include "webkit/fileapi/file_system_operation_context.h"
9 #include "webkit/fileapi/file_system_path.h"
10 #include "webkit/fileapi/file_util_helper.h"
11
12 using base::PlatformFileError;
13
14 namespace fileapi {
15
16 CrossFileUtilHelper::CrossFileUtilHelper(
17 FileSystemOperationContext* context,
18 FileSystemFileUtil* src_util,
19 FileSystemFileUtil* dest_util,
20 const FileSystemPath& src_path,
21 const FileSystemPath& dest_path,
22 Operation operation)
23 : context_(context),
24 src_util_(src_util),
25 dest_util_(dest_util),
26 src_root_path_(src_path),
27 dest_root_path_(dest_path),
28 operation_(operation) {}
29
30 CrossFileUtilHelper::~CrossFileUtilHelper() {}
31
32 base::PlatformFileError CrossFileUtilHelper::DoWork() {
33 base::PlatformFileError error =
34 PerformErrorCheckAndPreparationForMoveAndCopy();
35 if (error != base::PLATFORM_FILE_OK)
36 return error;
37 if (src_util_->DirectoryExists(context_, src_root_path_)) {
38 return CopyOrMoveDirectory(src_root_path_, dest_root_path_);
39 }
40 return CopyOrMoveFile(src_root_path_, dest_root_path_);
41 }
42
43 PlatformFileError
44 CrossFileUtilHelper::PerformErrorCheckAndPreparationForMoveAndCopy() {
45 // Exits earlier if the source path does not exist.
46 if (!src_util_->PathExists(context_, src_root_path_))
47 return base::PLATFORM_FILE_ERROR_NOT_FOUND;
48
49 bool same_file_system =
50 (src_root_path_.origin() == dest_root_path_.origin()) &&
51 (src_root_path_.type() == dest_root_path_.type());
52
53 // The parent of the |dest_root_path_| does not exist.
54 if (!ParentExists(dest_root_path_, dest_util_))
55 return base::PLATFORM_FILE_ERROR_NOT_FOUND;
56
57 // It is an error to try to copy/move an entry into its child.
58 if (same_file_system && src_root_path_.IsParent(dest_root_path_))
59 return base::PLATFORM_FILE_ERROR_INVALID_OPERATION;
60
61 // Now it is ok to return if the |dest_root_path_| does not exist.
62 if (!dest_util_->PathExists(context_, dest_root_path_))
63 return base::PLATFORM_FILE_OK;
64
65 // |src_root_path_| exists and is a directory.
66 // |dest_root_path_| exists and is a file.
67 bool src_is_directory = src_util_->DirectoryExists(context_, src_root_path_);
68 bool dest_is_directory =
69 dest_util_->DirectoryExists(context_, dest_root_path_);
70
71 // Either one of |src_root_path_| or |dest_root_path_| is directory,
72 // while the other is not.
73 if (src_is_directory != dest_is_directory)
74 return base::PLATFORM_FILE_ERROR_INVALID_OPERATION;
75
76 // It is an error to copy/move an entry into the same path.
77 if (same_file_system && (src_root_path_.internal_path() ==
78 dest_root_path_.internal_path()))
79 return base::PLATFORM_FILE_ERROR_EXISTS;
80
81 if (dest_is_directory) {
82 // It is an error to copy/move an entry to a non-empty directory.
83 // Otherwise the copy/move attempt must overwrite the destination, but
84 // the file_util's Copy or Move method doesn't perform overwrite
85 // on all platforms, so we delete the destination directory here.
86 if (base::PLATFORM_FILE_OK !=
87 dest_util_->DeleteSingleDirectory(context_, dest_root_path_)) {
88 if (!dest_util_->IsDirectoryEmpty(context_, dest_root_path_))
89 return base::PLATFORM_FILE_ERROR_NOT_EMPTY;
90 return base::PLATFORM_FILE_ERROR_FAILED;
91 }
92 }
93 return base::PLATFORM_FILE_OK;
94 }
95
96 bool CrossFileUtilHelper::ParentExists(
97 const FileSystemPath& path, FileSystemFileUtil* file_util) {
98 // If path is in the root, path.DirName() will be ".",
99 // since we use paths with no leading '/'.
100 FilePath parent = path.internal_path().DirName();
101 if (parent == FilePath(FILE_PATH_LITERAL(".")))
102 return true;
103 return file_util->DirectoryExists(
104 context_, path.WithInternalPath(parent));
105 }
106
107 PlatformFileError CrossFileUtilHelper::CopyOrMoveDirectory(
108 const FileSystemPath& src_path,
109 const FileSystemPath& dest_path) {
110 // At this point we must have gone through
111 // PerformErrorCheckAndPreparationForMoveAndCopy so this must be true.
112 DCHECK(!((src_path.origin() == dest_path.origin()) &&
113 (src_path.type() == dest_path.type())) ||
114 !src_path.IsParent(dest_path));
115
116 PlatformFileError error = dest_util_->CreateDirectory(
117 context_, dest_path, false, false);
118 if (error != base::PLATFORM_FILE_OK)
119 return error;
120
121 scoped_ptr<FileSystemFileUtil::AbstractFileEnumerator> file_enum(
122 src_util_->CreateFileEnumerator(context_, src_path,
123 true /* recursive */));
124 FilePath src_file_path_each;
125 while (!(src_file_path_each = file_enum->Next()).empty()) {
126 FilePath dest_file_path_each(dest_path.internal_path());
127 src_path.internal_path().AppendRelativePath(
128 src_file_path_each, &dest_file_path_each);
129
130 if (file_enum->IsDirectory()) {
131 PlatformFileError error = dest_util_->CreateDirectory(
132 context_,
133 dest_path.WithInternalPath(dest_file_path_each),
134 true /* exclusive */, false /* recursive */);
135 if (error != base::PLATFORM_FILE_OK)
136 return error;
137 } else {
138 PlatformFileError error = CopyOrMoveFile(
139 src_path.WithInternalPath(src_file_path_each),
140 dest_path.WithInternalPath(dest_file_path_each));
141 if (error != base::PLATFORM_FILE_OK)
142 return error;
143 }
144 }
145
146 if (operation_ == OPERATION_MOVE) {
147 PlatformFileError error =
148 FileUtilHelper::Delete(context_, src_util_,
149 src_path, true /* recursive */);
150 if (error != base::PLATFORM_FILE_OK)
151 return error;
152 }
153
154 return base::PLATFORM_FILE_OK;
155 }
156
157 PlatformFileError CrossFileUtilHelper::CopyOrMoveFile(
158 const FileSystemPath& src_path,
159 const FileSystemPath& dest_path) {
160 if ((src_path.origin() == dest_path.origin()) &&
161 (src_path.type() == dest_path.type())) {
162 DCHECK(src_util_ == dest_util_);
163 // Source and destination are in the same FileSystemFileUtil; now we can
164 // safely call FileSystemFileUtil method on src_util_ (== dest_util_).
165 return src_util_->CopyOrMoveFile(context_, src_path, dest_path,
166 operation_ == OPERATION_COPY);
167 }
168
169 // Resolve the src_path's underlying file path.
170 base::PlatformFileInfo file_info;
171 FilePath platform_file_path;
172 PlatformFileError error = src_util_->GetFileInfo(
173 context_, src_path, &file_info, &platform_file_path);
174 if (error != base::PLATFORM_FILE_OK)
175 return error;
176
177 // Call CopyInForeignFile() on the dest_util_ with the resolved source path
178 // to perform limited cross-FileSystemFileUtil copy/move.
179 error = dest_util_->CopyInForeignFile(
180 context_, src_path.WithInternalPath(platform_file_path), dest_path);
181
182 if (operation_ == OPERATION_COPY || error != base::PLATFORM_FILE_OK)
183 return error;
184 return src_util_->DeleteFile(context_, src_path);
185 }
186
187 } // namespace fileapi
OLDNEW
« no previous file with comments | « webkit/fileapi/cross_file_util_helper.h ('k') | webkit/fileapi/file_system_file_util_proxy.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698