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

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

Issue 7066033: Enable cross-filesystem moves and copies. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Readability tweak from Michael Created 9 years, 7 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
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "webkit/fileapi/file_system_file_util.h" 5 #include "webkit/fileapi/file_system_file_util.h"
6 6
7 #include <stack> 7 #include <stack>
8 8
9 #include "base/file_util_proxy.h" 9 #include "base/file_util_proxy.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "base/scoped_ptr.h" 11 #include "base/scoped_ptr.h"
12 #include "webkit/fileapi/file_system_operation_context.h" 12 #include "webkit/fileapi/file_system_operation_context.h"
13 13
14 namespace fileapi { 14 namespace fileapi {
15 15
16 namespace {
17
18 // This assumes that the root exists.
19 bool ParentExists(FileSystemOperationContext* context,
20 FileSystemFileUtil* file_util, const FilePath& file_path) {
21 // If file_path is in the root, file_path.DirName() will be ".",
22 // since we use paths with no leading '/'.
23 FilePath parent = file_path.DirName();
24 if (parent == FilePath(FILE_PATH_LITERAL(".")))
25 return true;
26 return file_util->DirectoryExists(context, parent);
27 }
28
29 }
30
16 // static 31 // static
17 FileSystemFileUtil* FileSystemFileUtil::GetInstance() { 32 FileSystemFileUtil* FileSystemFileUtil::GetInstance() {
18 return Singleton<FileSystemFileUtil>::get(); 33 return Singleton<FileSystemFileUtil>::get();
19 } 34 }
20 35
21 PlatformFileError FileSystemFileUtil::CreateOrOpen( 36 PlatformFileError FileSystemFileUtil::CreateOrOpen(
22 FileSystemOperationContext* unused, 37 FileSystemOperationContext* unused,
23 const FilePath& file_path, int file_flags, 38 const FilePath& file_path, int file_flags,
24 PlatformFile* file_handle, bool* created) { 39 PlatformFile* file_handle, bool* created) {
25 if (!file_util::DirectoryExists(file_path.DirName())) { 40 if (!file_util::DirectoryExists(file_path.DirName())) {
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
141 PlatformFileError error_code; 156 PlatformFileError error_code;
142 error_code = 157 error_code =
143 PerformCommonCheckAndPreparationForMoveAndCopy( 158 PerformCommonCheckAndPreparationForMoveAndCopy(
144 context, src_file_path, dest_file_path); 159 context, src_file_path, dest_file_path);
145 if (error_code != base::PLATFORM_FILE_OK) 160 if (error_code != base::PLATFORM_FILE_OK)
146 return error_code; 161 return error_code;
147 162
148 if (DirectoryExists(context, src_file_path)) 163 if (DirectoryExists(context, src_file_path))
149 return CopyOrMoveDirectory(context, src_file_path, dest_file_path, 164 return CopyOrMoveDirectory(context, src_file_path, dest_file_path,
150 true /* copy */); 165 true /* copy */);
151 else 166 return CopyOrMoveFileHelper(context, src_file_path, dest_file_path,
152 return CopyOrMoveFile(context, src_file_path, dest_file_path, 167 true /* copy */);
153 true /* copy */);
154 } 168 }
155 169
156 PlatformFileError FileSystemFileUtil::Move( 170 PlatformFileError FileSystemFileUtil::Move(
157 FileSystemOperationContext* context, 171 FileSystemOperationContext* context,
158 const FilePath& src_file_path, 172 const FilePath& src_file_path,
159 const FilePath& dest_file_path) { 173 const FilePath& dest_file_path) {
160 PlatformFileError error_code; 174 PlatformFileError error_code;
161 error_code = 175 error_code =
162 PerformCommonCheckAndPreparationForMoveAndCopy( 176 PerformCommonCheckAndPreparationForMoveAndCopy(
163 context, src_file_path, dest_file_path); 177 context, src_file_path, dest_file_path);
164 if (error_code != base::PLATFORM_FILE_OK) 178 if (error_code != base::PLATFORM_FILE_OK)
165 return error_code; 179 return error_code;
166 180
167 // TODO(dmikurube): ReplaceFile if in the same domain and filesystem type. 181 // TODO(dmikurube): ReplaceFile if in the same domain and filesystem type.
168 if (DirectoryExists(context, src_file_path)) 182 if (DirectoryExists(context, src_file_path))
169 return CopyOrMoveDirectory(context, src_file_path, dest_file_path, 183 return CopyOrMoveDirectory(context, src_file_path, dest_file_path,
170 false /* copy */); 184 false /* copy */);
171 else 185 return CopyOrMoveFileHelper(context, src_file_path, dest_file_path,
172 return CopyOrMoveFile(context, src_file_path, dest_file_path, 186 false /* copy */);
173 false /* copy */);
174 } 187 }
175 188
176 PlatformFileError FileSystemFileUtil::Delete( 189 PlatformFileError FileSystemFileUtil::Delete(
177 FileSystemOperationContext* context, 190 FileSystemOperationContext* context,
178 const FilePath& file_path, 191 const FilePath& file_path,
179 bool recursive) { 192 bool recursive) {
180 if (DirectoryExists(context, file_path)) { 193 if (DirectoryExists(context, file_path)) {
181 if (!recursive) 194 if (!recursive)
182 return DeleteSingleDirectory(context, file_path); 195 return DeleteSingleDirectory(context, file_path);
183 else 196 else
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
215 error_code = base::PLATFORM_FILE_ERROR_FAILED; 228 error_code = base::PLATFORM_FILE_ERROR_FAILED;
216 base::ClosePlatformFile(file); 229 base::ClosePlatformFile(file);
217 return error_code; 230 return error_code;
218 } 231 }
219 232
220 PlatformFileError 233 PlatformFileError
221 FileSystemFileUtil::PerformCommonCheckAndPreparationForMoveAndCopy( 234 FileSystemFileUtil::PerformCommonCheckAndPreparationForMoveAndCopy(
222 FileSystemOperationContext* context, 235 FileSystemOperationContext* context,
223 const FilePath& src_file_path, 236 const FilePath& src_file_path,
224 const FilePath& dest_file_path) { 237 const FilePath& dest_file_path) {
238 bool same_file_system =
239 (context->src_origin_url() == context->dest_origin_url()) &&
240 (context->src_type() == context->dest_type());
241 FileSystemFileUtil* dest_util = context->dest_file_system_file_util();
242 DCHECK(dest_util);
243 FileSystemOperationContext local_dest_context(
244 context->file_system_context(), dest_util);
245 FileSystemOperationContext* dest_context;
246 if (same_file_system) {
247 dest_context = context;
248 DCHECK(context->src_file_system_file_util() ==
249 context->dest_file_system_file_util());
250 } else {
251 // All the single-path virtual FSFU methods expect the context information
252 // to be in the src_* variables, not the dest_* variables, so we have to
253 // make a new context if we want to call them on the dest_file_path.
254 dest_context = &local_dest_context;
255 dest_context->set_src_type(context->dest_type());
256 dest_context->set_src_origin_url(context->dest_origin_url());
257 dest_context->set_src_virtual_path(context->dest_virtual_path());
258 dest_context->set_allowed_bytes_growth(context->allowed_bytes_growth());
259 }
260
225 // Exits earlier if the source path does not exist. 261 // Exits earlier if the source path does not exist.
226 if (!PathExists(context, src_file_path)) 262 if (!PathExists(context, src_file_path))
227 return base::PLATFORM_FILE_ERROR_NOT_FOUND; 263 return base::PLATFORM_FILE_ERROR_NOT_FOUND;
228 264
229 // The parent of the |dest_file_path| does not exist. 265 // The parent of the |dest_file_path| does not exist.
230 if (!DirectoryExists(context, dest_file_path.DirName())) 266 if (!ParentExists(dest_context, dest_util, dest_file_path))
231 return base::PLATFORM_FILE_ERROR_NOT_FOUND; 267 return base::PLATFORM_FILE_ERROR_NOT_FOUND;
232 268
233 // It is an error to try to copy/move an entry into its child. 269 // It is an error to try to copy/move an entry into its child.
234 if (src_file_path.IsParent(dest_file_path)) 270 if (same_file_system && src_file_path.IsParent(dest_file_path))
235 return base::PLATFORM_FILE_ERROR_INVALID_OPERATION; 271 return base::PLATFORM_FILE_ERROR_INVALID_OPERATION;
236 272
237 // Now it is ok to return if the |dest_file_path| does not exist. 273 // Now it is ok to return if the |dest_file_path| does not exist.
238 if (!PathExists(context, dest_file_path)) 274 if (!dest_util->PathExists(dest_context, dest_file_path))
239 return base::PLATFORM_FILE_OK; 275 return base::PLATFORM_FILE_OK;
240 276
241 // |src_file_path| exists and is a directory. 277 // |src_file_path| exists and is a directory.
242 // |dest_file_path| exists and is a file. 278 // |dest_file_path| exists and is a file.
243 bool src_is_directory = DirectoryExists(context, src_file_path); 279 bool src_is_directory = DirectoryExists(context, src_file_path);
244 bool dest_is_directory = DirectoryExists(context, dest_file_path); 280 bool dest_is_directory =
281 dest_util->DirectoryExists(dest_context, dest_file_path);
245 if (src_is_directory && !dest_is_directory) 282 if (src_is_directory && !dest_is_directory)
246 return base::PLATFORM_FILE_ERROR_INVALID_OPERATION; 283 return base::PLATFORM_FILE_ERROR_INVALID_OPERATION;
247 284
248 // |src_file_path| exists and is a file. 285 // |src_file_path| exists and is a file.
249 // |dest_file_path| exists and is a directory. 286 // |dest_file_path| exists and is a directory.
250 if (!src_is_directory && dest_is_directory) 287 if (!src_is_directory && dest_is_directory)
251 return base::PLATFORM_FILE_ERROR_INVALID_OPERATION; 288 return base::PLATFORM_FILE_ERROR_INVALID_OPERATION;
252 289
253 // It is an error to copy/move an entry into the same path. 290 // It is an error to copy/move an entry into the same path.
254 if (src_file_path.value() == dest_file_path.value()) 291 if (same_file_system && (src_file_path.value() == dest_file_path.value()))
255 return base::PLATFORM_FILE_ERROR_EXISTS; 292 return base::PLATFORM_FILE_ERROR_EXISTS;
256 293
257 if (dest_is_directory) { 294 if (dest_is_directory) {
258 // It is an error to copy/move an entry to a non-empty directory. 295 // It is an error to copy/move an entry to a non-empty directory.
259 // Otherwise the copy/move attempt must overwrite the destination, but 296 // Otherwise the copy/move attempt must overwrite the destination, but
260 // the file_util's Copy or Move method doesn't perform overwrite 297 // the file_util's Copy or Move method doesn't perform overwrite
261 // on all platforms, so we delete the destination directory here. 298 // on all platforms, so we delete the destination directory here.
262 // TODO(kinuko): may be better to change the file_util::{Copy,Move}. 299 // TODO(kinuko): may be better to change the file_util::{Copy,Move}.
263 if (base::PLATFORM_FILE_OK != 300 if (base::PLATFORM_FILE_OK !=
264 Delete(context, dest_file_path, false /* recursive */)) { 301 dest_util->Delete(dest_context, dest_file_path,
265 if (!IsDirectoryEmpty(context, dest_file_path)) 302 false /* recursive */)) {
303 if (!dest_util->IsDirectoryEmpty(dest_context, dest_file_path))
266 return base::PLATFORM_FILE_ERROR_NOT_EMPTY; 304 return base::PLATFORM_FILE_ERROR_NOT_EMPTY;
267 return base::PLATFORM_FILE_ERROR_FAILED; 305 return base::PLATFORM_FILE_ERROR_FAILED;
268 } 306 }
269 } 307 }
270 return base::PLATFORM_FILE_OK; 308 return base::PLATFORM_FILE_OK;
271 } 309 }
272 310
273 PlatformFileError FileSystemFileUtil::CopyOrMoveFile( 311 PlatformFileError FileSystemFileUtil::CopyOrMoveFile(
274 FileSystemOperationContext* unused, 312 FileSystemOperationContext* unused,
275 const FilePath& src_file_path, 313 const FilePath& src_file_path,
276 const FilePath& dest_file_path, 314 const FilePath& dest_file_path,
277 bool copy) { 315 bool copy) {
278 if (copy) { 316 if (copy) {
279 if (file_util::CopyFile(src_file_path, dest_file_path)) 317 if (file_util::CopyFile(src_file_path, dest_file_path))
280 return base::PLATFORM_FILE_OK; 318 return base::PLATFORM_FILE_OK;
281 } else { 319 } else {
282 DCHECK(!file_util::DirectoryExists(src_file_path)); 320 DCHECK(!file_util::DirectoryExists(src_file_path));
283 if (file_util::Move(src_file_path, dest_file_path)) 321 if (file_util::Move(src_file_path, dest_file_path))
284 return base::PLATFORM_FILE_OK; 322 return base::PLATFORM_FILE_OK;
285 } 323 }
286 return base::PLATFORM_FILE_ERROR_FAILED; 324 return base::PLATFORM_FILE_ERROR_FAILED;
287 } 325 }
288 326
327 PlatformFileError FileSystemFileUtil::CopyInForeignFile(
328 FileSystemOperationContext* context,
329 const FilePath& src_file_path,
330 const FilePath& dest_file_path) {
331 return CopyOrMoveFile(context, src_file_path, dest_file_path, true);
332 }
333
289 PlatformFileError FileSystemFileUtil::CopyOrMoveDirectory( 334 PlatformFileError FileSystemFileUtil::CopyOrMoveDirectory(
290 FileSystemOperationContext* context, 335 FileSystemOperationContext* context,
291 const FilePath& src_file_path, 336 const FilePath& src_file_path,
292 const FilePath& dest_file_path, 337 const FilePath& dest_file_path,
293 bool copy) { 338 bool copy) {
339 FileSystemFileUtil* dest_util = context->dest_file_system_file_util();
340 FileSystemOperationContext dest_context(
341 context->file_system_context(), dest_util);
342 // All the single-path virtual FSFU methods expect the context information to
343 // be in the src_* variables, not the dest_* variables, so we have to make a
344 // new context if we want to call them on the dest_file_path.
345 dest_context.set_src_type(context->dest_type());
346 dest_context.set_src_origin_url(context->dest_origin_url());
347 dest_context.set_src_virtual_path(context->dest_virtual_path());
348 dest_context.set_allowed_bytes_growth(context->allowed_bytes_growth());
349
294 // Re-check PerformCommonCheckAndPreparationForMoveAndCopy() by DCHECK. 350 // Re-check PerformCommonCheckAndPreparationForMoveAndCopy() by DCHECK.
295 DCHECK(DirectoryExists(context, src_file_path)); 351 DCHECK(DirectoryExists(context, src_file_path));
296 DCHECK(DirectoryExists(context, dest_file_path.DirName())); 352 DCHECK(ParentExists(&dest_context, dest_util, dest_file_path));
297 DCHECK(!src_file_path.IsParent(dest_file_path)); 353 DCHECK(!dest_util->PathExists(&dest_context, dest_file_path));
298 DCHECK(!PathExists(context, dest_file_path)); 354 if ((context->src_origin_url() == context->dest_origin_url()) &&
355 (context->src_type() == context->dest_type()))
356 DCHECK(!src_file_path.IsParent(dest_file_path));
299 357
300 if (!DirectoryExists(context, dest_file_path)) { 358 if (!dest_util->DirectoryExists(&dest_context, dest_file_path)) {
301 PlatformFileError error = CreateDirectory(context, 359 PlatformFileError error = dest_util->CreateDirectory(&dest_context,
302 dest_file_path, false, false); 360 dest_file_path, false, false);
303 if (error != base::PLATFORM_FILE_OK) 361 if (error != base::PLATFORM_FILE_OK)
304 return error; 362 return error;
305 } 363 }
306 364
307 scoped_ptr<AbstractFileEnumerator> file_enum( 365 scoped_ptr<AbstractFileEnumerator> file_enum(
308 CreateFileEnumerator(context, src_file_path)); 366 CreateFileEnumerator(context, src_file_path));
309 FilePath src_file_path_each; 367 FilePath src_file_path_each;
310 while (!(src_file_path_each = file_enum->Next()).empty()) { 368 while (!(src_file_path_each = file_enum->Next()).empty()) {
311 FilePath dest_file_path_each(dest_file_path); 369 FilePath dest_file_path_each(dest_file_path);
312 src_file_path.AppendRelativePath(src_file_path_each, &dest_file_path_each); 370 src_file_path.AppendRelativePath(src_file_path_each, &dest_file_path_each);
313 371
314 if (file_enum->IsDirectory()) { 372 if (file_enum->IsDirectory()) {
315 PlatformFileError error = CreateDirectory(context, 373 PlatformFileError error = dest_util->CreateDirectory(&dest_context,
316 dest_file_path_each, false, false); 374 dest_file_path_each, false, false);
317 if (error != base::PLATFORM_FILE_OK) 375 if (error != base::PLATFORM_FILE_OK)
318 return error; 376 return error;
319 } else { 377 } else {
320 // CopyOrMoveFile here is the virtual overridden member function. 378 PlatformFileError error = CopyOrMoveFileHelper(
321 PlatformFileError error = CopyOrMoveFile(
322 context, src_file_path_each, dest_file_path_each, copy); 379 context, src_file_path_each, dest_file_path_each, copy);
323 if (error != base::PLATFORM_FILE_OK) 380 if (error != base::PLATFORM_FILE_OK)
324 return error; 381 return error;
325 } 382 }
326 } 383 }
327 384
328 if (!copy) { 385 if (!copy) {
329 PlatformFileError error = Delete(context, src_file_path, true); 386 PlatformFileError error = Delete(context, src_file_path, true);
330 if (error != base::PLATFORM_FILE_OK) 387 if (error != base::PLATFORM_FILE_OK)
331 return error; 388 return error;
332 } 389 }
333 return base::PLATFORM_FILE_OK; 390 return base::PLATFORM_FILE_OK;
334 } 391 }
335 392
393 PlatformFileError FileSystemFileUtil::CopyOrMoveFileHelper(
394 FileSystemOperationContext* context,
395 const FilePath& src_file_path,
396 const FilePath& dest_file_path,
397 bool copy) {
398 // CopyOrMoveFile here is the virtual overridden member function.
399 if ((context->src_origin_url() == context->dest_origin_url()) &&
400 (context->src_type() == context->dest_type())) {
401 DCHECK(context->src_file_system_file_util() ==
402 context->dest_file_system_file_util());
403 return CopyOrMoveFile(context, src_file_path, dest_file_path, copy);
404 }
405 base::PlatformFileInfo file_info;
406 FilePath platform_file_path;
407 PlatformFileError error_code;
408 error_code =
409 GetFileInfo(context, src_file_path, &file_info, &platform_file_path);
410 if (error_code != base::PLATFORM_FILE_OK)
411 return error_code;
412
413 DCHECK(context->dest_file_system_file_util());
414 error_code = context->dest_file_system_file_util()->CopyInForeignFile(
415 context, platform_file_path, dest_file_path);
416 if (copy || error_code != base::PLATFORM_FILE_OK)
417 return error_code;
418 return DeleteFile(context, src_file_path);
419 }
420
421
336 PlatformFileError FileSystemFileUtil::DeleteFile( 422 PlatformFileError FileSystemFileUtil::DeleteFile(
337 FileSystemOperationContext* unused, 423 FileSystemOperationContext* unused,
338 const FilePath& file_path) { 424 const FilePath& file_path) {
339 if (!file_util::PathExists(file_path)) 425 if (!file_util::PathExists(file_path))
340 return base::PLATFORM_FILE_ERROR_NOT_FOUND; 426 return base::PLATFORM_FILE_ERROR_NOT_FOUND;
341 if (file_util::DirectoryExists(file_path)) 427 if (file_util::DirectoryExists(file_path))
342 return base::PLATFORM_FILE_ERROR_NOT_A_FILE; 428 return base::PLATFORM_FILE_ERROR_NOT_A_FILE;
343 if (!file_util::Delete(file_path, false)) 429 if (!file_util::Delete(file_path, false))
344 return base::PLATFORM_FILE_ERROR_FAILED; 430 return base::PLATFORM_FILE_ERROR_FAILED;
345 return base::PLATFORM_FILE_OK; 431 return base::PLATFORM_FILE_OK;
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
445 FileSystemFileUtil::CreateFileEnumerator( 531 FileSystemFileUtil::CreateFileEnumerator(
446 FileSystemOperationContext* unused, 532 FileSystemOperationContext* unused,
447 const FilePath& root_path) { 533 const FilePath& root_path) {
448 return new FileSystemFileEnumerator( 534 return new FileSystemFileEnumerator(
449 root_path, true, static_cast<file_util::FileEnumerator::FILE_TYPE>( 535 root_path, true, static_cast<file_util::FileEnumerator::FILE_TYPE>(
450 file_util::FileEnumerator::FILES | 536 file_util::FileEnumerator::FILES |
451 file_util::FileEnumerator::DIRECTORIES)); 537 file_util::FileEnumerator::DIRECTORIES));
452 } 538 }
453 539
454 } // namespace fileapi 540 } // namespace fileapi
OLDNEW
« no previous file with comments | « webkit/fileapi/file_system_file_util.h ('k') | webkit/fileapi/file_system_file_util_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698