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

Side by Side 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, 4 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
OLDNEW
(Empty)
1 // Copyright (c) 2011 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/fileapi_file_util.h"
6
7 #include <stack>
8
9 #include "base/memory/scoped_ptr.h"
10 #include "webkit/fileapi/file_system_operation_context.h"
11
12 namespace fileapi {
13
14 namespace {
15
16 // This assumes that the root exists.
17 bool ParentExists(FileSystemOperationContext* context,
18 FileUtil* file_util, const FilePath& file_path) {
19 // If file_path is in the root, file_path.DirName() will be ".",
20 // since we use paths with no leading '/'.
21 FilePath parent = file_path.DirName();
22 if (parent == FilePath(FILE_PATH_LITERAL(".")))
23 return true;
24 return file_util->DirectoryExists(context, parent);
25 }
26
27 } // namespace
28
29 PlatformFileError FileUtil::Copy(
30 FileSystemOperationContext* context,
31 const FilePath& src_file_path,
32 const FilePath& dest_file_path) {
33 PlatformFileError error_code;
34 error_code =
35 PerformCommonCheckAndPreparationForMoveAndCopy(
36 context, src_file_path, dest_file_path);
37 if (error_code != base::PLATFORM_FILE_OK)
38 return error_code;
39
40 if (DirectoryExists(context, src_file_path))
41 return CopyOrMoveDirectory(context, src_file_path, dest_file_path,
42 true /* copy */);
43 return CopyOrMoveFileHelper(context, src_file_path, dest_file_path,
44 true /* copy */);
45 }
46
47
48 PlatformFileError FileUtil::Move(
49 FileSystemOperationContext* context,
50 const FilePath& src_file_path,
51 const FilePath& dest_file_path) {
52 PlatformFileError error_code;
53 error_code =
54 PerformCommonCheckAndPreparationForMoveAndCopy(
55 context, src_file_path, dest_file_path);
56 if (error_code != base::PLATFORM_FILE_OK)
57 return error_code;
58
59 // TODO(dmikurube): ReplaceFile if in the same domain and filesystem type.
60 if (DirectoryExists(context, src_file_path))
61 return CopyOrMoveDirectory(context, src_file_path, dest_file_path,
62 false /* copy */);
63 return CopyOrMoveFileHelper(context, src_file_path, dest_file_path,
64 false /* copy */);
65 }
66
67 PlatformFileError FileUtil::Delete(
68 FileSystemOperationContext* context,
69 const FilePath& file_path,
70 bool recursive) {
71 if (DirectoryExists(context, file_path)) {
72 if (!recursive)
73 return DeleteSingleDirectory(context, file_path);
74 else
75 return DeleteDirectoryRecursive(context, file_path);
76 } else {
77 return DeleteFile(context, file_path);
78 }
79 }
80
81 PlatformFileError
82 FileUtil::PerformCommonCheckAndPreparationForMoveAndCopy(
83 FileSystemOperationContext* context,
84 const FilePath& src_file_path,
85 const FilePath& dest_file_path) {
86 bool same_file_system =
87 (context->src_origin_url() == context->dest_origin_url()) &&
88 (context->src_type() == context->dest_type());
89 FileUtil* dest_util = context->dest_file_util();
90 DCHECK(dest_util);
91 if (same_file_system)
92 DCHECK(context->src_file_util() == context->dest_file_util());
93 // All the single-path virtual FSFU methods expect the context information
94 // to be in the src_* variables, not the dest_* variables, so we have to
95 // make a new context if we want to call them on the dest_file_path.
96 scoped_ptr<FileSystemOperationContext> dest_context(
97 context->CreateInheritedContextForDest());
98
99 // Exits earlier if the source path does not exist.
100 if (!PathExists(context, src_file_path))
101 return base::PLATFORM_FILE_ERROR_NOT_FOUND;
102
103 // The parent of the |dest_file_path| does not exist.
104 if (!ParentExists(dest_context.get(), dest_util, dest_file_path))
105 return base::PLATFORM_FILE_ERROR_NOT_FOUND;
106
107 // It is an error to try to copy/move an entry into its child.
108 if (same_file_system && src_file_path.IsParent(dest_file_path))
109 return base::PLATFORM_FILE_ERROR_INVALID_OPERATION;
110
111 // Now it is ok to return if the |dest_file_path| does not exist.
112 if (!dest_util->PathExists(dest_context.get(), dest_file_path))
113 return base::PLATFORM_FILE_OK;
114
115 // |src_file_path| exists and is a directory.
116 // |dest_file_path| exists and is a file.
117 bool src_is_directory = DirectoryExists(context, src_file_path);
118 bool dest_is_directory =
119 dest_util->DirectoryExists(dest_context.get(), dest_file_path);
120 if (src_is_directory && !dest_is_directory)
121 return base::PLATFORM_FILE_ERROR_INVALID_OPERATION;
122
123 // |src_file_path| exists and is a file.
124 // |dest_file_path| exists and is a directory.
125 if (!src_is_directory && dest_is_directory)
126 return base::PLATFORM_FILE_ERROR_INVALID_OPERATION;
127
128 // It is an error to copy/move an entry into the same path.
129 if (same_file_system && (src_file_path.value() == dest_file_path.value()))
130 return base::PLATFORM_FILE_ERROR_EXISTS;
131
132 if (dest_is_directory) {
133 // It is an error to copy/move an entry to a non-empty directory.
134 // Otherwise the copy/move attempt must overwrite the destination, but
135 // the file_util's Copy or Move method doesn't perform overwrite
136 // on all platforms, so we delete the destination directory here.
137 // TODO(kinuko): may be better to change the file_util::{Copy,Move}.
138 PlatformFileError error = dest_util->Delete(
139 dest_context.get(), dest_file_path, false /* recursive */);
140 context->ImportAllowedBytesGrowth(*dest_context);
141 if (base::PLATFORM_FILE_OK != error) {
142 if (!dest_util->IsDirectoryEmpty(dest_context.get(), dest_file_path))
143 return base::PLATFORM_FILE_ERROR_NOT_EMPTY;
144 return base::PLATFORM_FILE_ERROR_FAILED;
145 }
146 }
147 return base::PLATFORM_FILE_OK;
148 }
149
150 PlatformFileError FileUtil::CopyOrMoveDirectory(
151 FileSystemOperationContext* context,
152 const FilePath& src_file_path,
153 const FilePath& dest_file_path,
154 bool copy) {
155 FileUtil* dest_util = context->dest_file_util();
156 scoped_ptr<FileSystemOperationContext> dest_context(
157 context->CreateInheritedContextForDest());
158
159 // Re-check PerformCommonCheckAndPreparationForMoveAndCopy() by DCHECK.
160 DCHECK(DirectoryExists(context, src_file_path));
161 DCHECK(ParentExists(dest_context.get(), dest_util, dest_file_path));
162 DCHECK(!dest_util->PathExists(dest_context.get(), dest_file_path));
163 if ((context->src_origin_url() == context->dest_origin_url()) &&
164 (context->src_type() == context->dest_type()))
165 DCHECK(!src_file_path.IsParent(dest_file_path));
166
167 if (!dest_util->DirectoryExists(dest_context.get(), dest_file_path)) {
168 PlatformFileError error = dest_util->CreateDirectory(dest_context.get(),
169 dest_file_path, false, false);
170 context->ImportAllowedBytesGrowth(*dest_context);
171 if (error != base::PLATFORM_FILE_OK)
172 return error;
173 }
174
175 scoped_ptr<AbstractFileEnumerator> file_enum(
176 CreateFileEnumerator(context, src_file_path));
177 FilePath src_file_path_each;
178 while (!(src_file_path_each = file_enum->Next()).empty()) {
179 FilePath dest_file_path_each(dest_file_path);
180 src_file_path.AppendRelativePath(src_file_path_each, &dest_file_path_each);
181
182 if (file_enum->IsDirectory()) {
183 scoped_ptr<FileSystemOperationContext> new_directory_context(
184 dest_context->CreateInheritedContextWithNewVirtualPaths(
185 dest_file_path_each, FilePath()));
186 PlatformFileError error = dest_util->CreateDirectory(
187 new_directory_context.get(), dest_file_path_each, false, false);
188 context->ImportAllowedBytesGrowth(*new_directory_context);
189 if (error != base::PLATFORM_FILE_OK)
190 return error;
191 } else {
192 scoped_ptr<FileSystemOperationContext> copy_context(
193 context->CreateInheritedContextWithNewVirtualPaths(
194 src_file_path_each, dest_file_path_each));
195 PlatformFileError error = CopyOrMoveFileHelper(
196 copy_context.get(), src_file_path_each, dest_file_path_each, copy);
197 context->ImportAllowedBytesGrowth(*copy_context);
198 if (error != base::PLATFORM_FILE_OK)
199 return error;
200 }
201 }
202
203 if (!copy) {
204 PlatformFileError error = Delete(context, src_file_path, true);
205 if (error != base::PLATFORM_FILE_OK)
206 return error;
207 }
208 return base::PLATFORM_FILE_OK;
209 }
210
211 PlatformFileError FileUtil::CopyOrMoveFileHelper(
212 FileSystemOperationContext* context,
213 const FilePath& src_file_path,
214 const FilePath& dest_file_path,
215 bool copy) {
216 // CopyOrMoveFile here is the virtual overridden member function.
217 if ((context->src_origin_url() == context->dest_origin_url()) &&
218 (context->src_type() == context->dest_type())) {
219 DCHECK(context->src_file_util() == context->dest_file_util());
220 return CopyOrMoveFile(context, src_file_path, dest_file_path, copy);
221 }
222 base::PlatformFileInfo file_info;
223 FilePath platform_file_path;
224 PlatformFileError error_code;
225 error_code =
226 GetFileInfo(context, src_file_path, &file_info, &platform_file_path);
227 if (error_code != base::PLATFORM_FILE_OK)
228 return error_code;
229
230 DCHECK(context->dest_file_util());
231 error_code = context->dest_file_util()->CopyInForeignFile(
232 context, platform_file_path, dest_file_path);
233 if (copy || error_code != base::PLATFORM_FILE_OK)
234 return error_code;
235 return DeleteFile(context, src_file_path);
236 }
237
238 PlatformFileError FileUtil::DeleteDirectoryRecursive(
239 FileSystemOperationContext* context,
240 const FilePath& file_path) {
241 scoped_ptr<AbstractFileEnumerator> file_enum(
242 CreateFileEnumerator(context, file_path));
243 FilePath file_path_each;
244
245 std::stack<FilePath> directories;
246 while (!(file_path_each = file_enum->Next()).empty()) {
247 if (file_enum->IsDirectory()) {
248 directories.push(file_path_each);
249 } else {
250 // DeleteFile here is the virtual overridden member function.
251 scoped_ptr<FileSystemOperationContext> inherited_context(
252 context->CreateInheritedContextWithNewVirtualPaths(
253 file_path_each, FilePath()));
254 PlatformFileError error =
255 DeleteFile(inherited_context.get(), file_path_each);
256 context->ImportAllowedBytesGrowth(*inherited_context);
257 if (error == base::PLATFORM_FILE_ERROR_NOT_FOUND)
258 return base::PLATFORM_FILE_ERROR_FAILED;
259 else if (error != base::PLATFORM_FILE_OK)
260 return error;
261 }
262 }
263
264 while (!directories.empty()) {
265 scoped_ptr<FileSystemOperationContext> inherited_context(
266 context->CreateInheritedContextWithNewVirtualPaths(
267 directories.top(), FilePath()));
268 PlatformFileError error =
269 DeleteSingleDirectory(inherited_context.get(), directories.top());
270 context->ImportAllowedBytesGrowth(*inherited_context);
271 if (error == base::PLATFORM_FILE_ERROR_NOT_FOUND)
272 return base::PLATFORM_FILE_ERROR_FAILED;
273 else if (error != base::PLATFORM_FILE_OK)
274 return error;
275 directories.pop();
276 }
277 return DeleteSingleDirectory(context, file_path);
278 }
279
280 } // namespace fileapi
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698