| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 "base/file_util_proxy.h" | 5 #include "base/file_util_proxy.h" |
| 6 | 6 |
| 7 #include "base/message_loop_proxy.h" | 7 #include "base/message_loop_proxy.h" |
| 8 | 8 |
| 9 // TODO(jianli): Move the code from anonymous namespace to base namespace so | 9 // TODO(jianli): Move the code from anonymous namespace to base namespace so |
| 10 // that all of the base:: prefixes would be unnecessary. | 10 // that all of the base:: prefixes would be unnecessary. |
| 11 namespace { | 11 namespace { |
| 12 | 12 |
| 13 namespace { |
| 14 |
| 15 // Performs common checks for move and copy. |
| 16 // This also removes the destination directory if it's non-empty and all other |
| 17 // checks are passed (so that the copy/move correctly overwrites the destination
). |
| 18 static base::PlatformFileError PerformCommonCheckAndPreparationForMoveAndCopy( |
| 19 const FilePath& src_file_path, |
| 20 const FilePath& dest_file_path) { |
| 21 // Exits earlier if the source path does not exist. |
| 22 if (!file_util::PathExists(src_file_path)) |
| 23 return base::PLATFORM_FILE_ERROR_NOT_FOUND; |
| 24 |
| 25 // The parent of the |dest_file_path| does not exist. |
| 26 if (!file_util::DirectoryExists(dest_file_path.DirName())) |
| 27 return base::PLATFORM_FILE_ERROR_NOT_FOUND; |
| 28 |
| 29 // It is an error to try to copy/move an entry into its child. |
| 30 if (file_util::ContainsPath(src_file_path, dest_file_path)) |
| 31 return base::PLATFORM_FILE_ERROR_INVALID_OPERATION; |
| 32 |
| 33 // Now it is ok to return if the |dest_file_path| does not exist. |
| 34 if (!file_util::PathExists(dest_file_path)) |
| 35 return base::PLATFORM_FILE_OK; |
| 36 |
| 37 // |src_file_path| exists and is a directory. |
| 38 // |dest_file_path| exists and is a file. |
| 39 bool src_is_directory = file_util::DirectoryExists(src_file_path); |
| 40 bool dest_is_directory = file_util::DirectoryExists(dest_file_path); |
| 41 if (src_is_directory && !dest_is_directory) |
| 42 return base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY; |
| 43 |
| 44 // |src_file_path| exists and is a file. |
| 45 // |dest_file_path| exists and is a directory. |
| 46 if (!src_is_directory && dest_is_directory) |
| 47 return base::PLATFORM_FILE_ERROR_NOT_A_FILE; |
| 48 |
| 49 // It is an error to copy/move an entry into the same path. |
| 50 if (src_file_path.value() == dest_file_path.value()) |
| 51 return base::PLATFORM_FILE_ERROR_EXISTS; |
| 52 |
| 53 if (dest_is_directory) { |
| 54 // It is an error to copy/move an entry to a non-empty directory. |
| 55 // Otherwise the copy/move attempt must overwrite the destination, but |
| 56 // the file_util's Copy or Move method doesn't perform overwrite |
| 57 // on all platforms, so we delete the destination directory here. |
| 58 // TODO(kinuko): may be better to change the file_util::{Copy,Move}. |
| 59 if (!file_util::Delete(dest_file_path, false /* recursive */)) { |
| 60 if (!file_util::IsDirectoryEmpty(dest_file_path)) |
| 61 return base::PLATFORM_FILE_ERROR_NOT_EMPTY; |
| 62 return base::PLATFORM_FILE_ERROR_FAILED; |
| 63 } |
| 64 } |
| 65 return base::PLATFORM_FILE_OK; |
| 66 } |
| 67 |
| 68 } // anonymous namespace |
| 69 |
| 13 class MessageLoopRelay | 70 class MessageLoopRelay |
| 14 : public base::RefCountedThreadSafe<MessageLoopRelay> { | 71 : public base::RefCountedThreadSafe<MessageLoopRelay> { |
| 15 public: | 72 public: |
| 16 MessageLoopRelay() | 73 MessageLoopRelay() |
| 17 : origin_message_loop_proxy_( | 74 : origin_message_loop_proxy_( |
| 18 base::MessageLoopProxy::CreateForCurrentThread()), | 75 base::MessageLoopProxy::CreateForCurrentThread()), |
| 19 error_code_(base::PLATFORM_FILE_OK) { | 76 error_code_(base::PLATFORM_FILE_OK) { |
| 20 } | 77 } |
| 21 | 78 |
| 22 bool Start(scoped_refptr<base::MessageLoopProxy> message_loop_proxy, | 79 bool Start(scoped_refptr<base::MessageLoopProxy> message_loop_proxy, |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 198 } | 255 } |
| 199 | 256 |
| 200 protected: | 257 protected: |
| 201 virtual void RunWork() { | 258 virtual void RunWork() { |
| 202 if (!file_util::PathExists(file_path_)) { | 259 if (!file_util::PathExists(file_path_)) { |
| 203 set_error_code(base::PLATFORM_FILE_ERROR_NOT_FOUND); | 260 set_error_code(base::PLATFORM_FILE_ERROR_NOT_FOUND); |
| 204 return; | 261 return; |
| 205 } | 262 } |
| 206 if (!file_util::Delete(file_path_, recursive_)) { | 263 if (!file_util::Delete(file_path_, recursive_)) { |
| 207 if (!recursive_ && !file_util::IsDirectoryEmpty(file_path_)) { | 264 if (!recursive_ && !file_util::IsDirectoryEmpty(file_path_)) { |
| 208 set_error_code(base::PLATFORM_FILE_ERROR_INVALID_OPERATION); | 265 set_error_code(base::PLATFORM_FILE_ERROR_NOT_EMPTY); |
| 209 return; | 266 return; |
| 210 } | 267 } |
| 211 set_error_code(base::PLATFORM_FILE_ERROR_FAILED); | 268 set_error_code(base::PLATFORM_FILE_ERROR_FAILED); |
| 212 } | 269 } |
| 213 } | 270 } |
| 214 | 271 |
| 215 private: | 272 private: |
| 216 FilePath file_path_; | 273 FilePath file_path_; |
| 217 bool recursive_; | 274 bool recursive_; |
| 218 }; | 275 }; |
| 219 | 276 |
| 220 class RelayCopy : public RelayWithStatusCallback { | 277 class RelayCopy : public RelayWithStatusCallback { |
| 221 public: | 278 public: |
| 222 RelayCopy(const FilePath& src_file_path, | 279 RelayCopy(const FilePath& src_file_path, |
| 223 const FilePath& dest_file_path, | 280 const FilePath& dest_file_path, |
| 224 base::FileUtilProxy::StatusCallback* callback) | 281 base::FileUtilProxy::StatusCallback* callback) |
| 225 : RelayWithStatusCallback(callback), | 282 : RelayWithStatusCallback(callback), |
| 226 src_file_path_(src_file_path), | 283 src_file_path_(src_file_path), |
| 227 dest_file_path_(dest_file_path) { | 284 dest_file_path_(dest_file_path) { |
| 228 } | 285 } |
| 229 | 286 |
| 230 protected: | 287 protected: |
| 231 virtual void RunWork() { | 288 virtual void RunWork() { |
| 232 bool dest_path_exists = file_util::PathExists(dest_file_path_); | 289 set_error_code(PerformCommonCheckAndPreparationForMoveAndCopy( |
| 233 if (!dest_path_exists && | 290 src_file_path_, dest_file_path_)); |
| 234 !file_util::DirectoryExists(dest_file_path_.DirName())) { | 291 if (error_code() != base::PLATFORM_FILE_OK) |
| 235 set_error_code(base::PLATFORM_FILE_ERROR_NOT_FOUND); | |
| 236 return; | 292 return; |
| 237 } | 293 if (!file_util::CopyDirectory(src_file_path_, dest_file_path_, |
| 238 // |src_file_path| exists and is a directory. | 294 true /* recursive */)) |
| 239 // |dest_file_path| exists and is a file. | |
| 240 if (file_util::DirectoryExists(src_file_path_) && | |
| 241 dest_path_exists && !file_util::DirectoryExists(dest_file_path_)) { | |
| 242 set_error_code(base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY); | |
| 243 return; | |
| 244 } | |
| 245 if (file_util::ContainsPath(src_file_path_, dest_file_path_)) { | |
| 246 set_error_code(base::PLATFORM_FILE_ERROR_FAILED); | 295 set_error_code(base::PLATFORM_FILE_ERROR_FAILED); |
| 247 return; | |
| 248 } | |
| 249 if (!file_util::CopyDirectory(src_file_path_, dest_file_path_, | |
| 250 true /* recursive */)) { | |
| 251 if (!file_util::PathExists(src_file_path_)) { | |
| 252 set_error_code(base::PLATFORM_FILE_ERROR_NOT_FOUND); | |
| 253 return; | |
| 254 } | |
| 255 if (src_file_path_.value() == dest_file_path_.value()) { | |
| 256 set_error_code(base::PLATFORM_FILE_ERROR_EXISTS); | |
| 257 return; | |
| 258 } | |
| 259 // Something else went wrong. | |
| 260 set_error_code(base::PLATFORM_FILE_ERROR_FAILED); | |
| 261 } | |
| 262 } | 296 } |
| 263 | 297 |
| 264 private: | 298 private: |
| 265 FilePath src_file_path_; | 299 FilePath src_file_path_; |
| 266 FilePath dest_file_path_; | 300 FilePath dest_file_path_; |
| 267 }; | 301 }; |
| 268 | 302 |
| 269 class RelayMove : public RelayWithStatusCallback { | 303 class RelayMove : public RelayWithStatusCallback { |
| 270 public: | 304 public: |
| 271 RelayMove(const FilePath& src_file_path, | 305 RelayMove(const FilePath& src_file_path, |
| 272 const FilePath& dest_file_path, | 306 const FilePath& dest_file_path, |
| 273 base::FileUtilProxy::StatusCallback* callback) | 307 base::FileUtilProxy::StatusCallback* callback) |
| 274 : RelayWithStatusCallback(callback), | 308 : RelayWithStatusCallback(callback), |
| 275 src_file_path_(src_file_path), | 309 src_file_path_(src_file_path), |
| 276 dest_file_path_(dest_file_path) { | 310 dest_file_path_(dest_file_path) { |
| 277 } | 311 } |
| 278 | 312 |
| 279 protected: | 313 protected: |
| 280 virtual void RunWork() { | 314 virtual void RunWork() { |
| 281 bool dest_path_exists = file_util::PathExists(dest_file_path_); | 315 set_error_code(PerformCommonCheckAndPreparationForMoveAndCopy( |
| 282 if (!dest_path_exists && | 316 src_file_path_, dest_file_path_)); |
| 283 !file_util::DirectoryExists(dest_file_path_.DirName())) { | 317 if (error_code() != base::PLATFORM_FILE_OK) |
| 284 set_error_code(base::PLATFORM_FILE_ERROR_NOT_FOUND); | |
| 285 return; | 318 return; |
| 286 } | 319 if (!file_util::Move(src_file_path_, dest_file_path_)) |
| 287 // |src_file_path| exists and is a directory. | |
| 288 // |dest_file_path| exists and is a file. | |
| 289 if (file_util::DirectoryExists(src_file_path_) && | |
| 290 dest_path_exists && | |
| 291 !file_util::DirectoryExists(dest_file_path_)) { | |
| 292 set_error_code(base::PLATFORM_FILE_ERROR_EXISTS); | |
| 293 return; | |
| 294 } | |
| 295 if (file_util::ContainsPath(src_file_path_, dest_file_path_)) { | |
| 296 set_error_code(base::PLATFORM_FILE_ERROR_INVALID_OPERATION); | |
| 297 return; | |
| 298 } | |
| 299 if (!file_util::Move(src_file_path_, dest_file_path_)) { | |
| 300 if (!file_util::PathExists(src_file_path_)) { | |
| 301 set_error_code(base::PLATFORM_FILE_ERROR_NOT_FOUND); | |
| 302 return; | |
| 303 } | |
| 304 if (src_file_path_.value() == dest_file_path_.value()) { | |
| 305 set_error_code(base::PLATFORM_FILE_ERROR_EXISTS); | |
| 306 return; | |
| 307 } | |
| 308 // Something else went wrong. | |
| 309 set_error_code(base::PLATFORM_FILE_ERROR_FAILED); | 320 set_error_code(base::PLATFORM_FILE_ERROR_FAILED); |
| 310 } | |
| 311 } | 321 } |
| 312 | 322 |
| 313 private: | 323 private: |
| 314 FilePath src_file_path_; | 324 FilePath src_file_path_; |
| 315 FilePath dest_file_path_; | 325 FilePath dest_file_path_; |
| 316 }; | 326 }; |
| 317 | 327 |
| 318 class RelayCreateDirectory : public RelayWithStatusCallback { | 328 class RelayCreateDirectory : public RelayWithStatusCallback { |
| 319 public: | 329 public: |
| 320 RelayCreateDirectory( | 330 RelayCreateDirectory( |
| (...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 663 bool FileUtilProxy::Close(scoped_refptr<MessageLoopProxy> message_loop_proxy, | 673 bool FileUtilProxy::Close(scoped_refptr<MessageLoopProxy> message_loop_proxy, |
| 664 base::PlatformFile file_handle, | 674 base::PlatformFile file_handle, |
| 665 StatusCallback* callback) { | 675 StatusCallback* callback) { |
| 666 return Start(FROM_HERE, message_loop_proxy, | 676 return Start(FROM_HERE, message_loop_proxy, |
| 667 new RelayClose(file_handle, callback)); | 677 new RelayClose(file_handle, callback)); |
| 668 } | 678 } |
| 669 | 679 |
| 670 // static | 680 // static |
| 671 bool FileUtilProxy::Delete(scoped_refptr<MessageLoopProxy> message_loop_proxy, | 681 bool FileUtilProxy::Delete(scoped_refptr<MessageLoopProxy> message_loop_proxy, |
| 672 const FilePath& file_path, | 682 const FilePath& file_path, |
| 683 bool recursive, |
| 673 StatusCallback* callback) { | 684 StatusCallback* callback) { |
| 674 return Start(FROM_HERE, message_loop_proxy, | 685 return Start(FROM_HERE, message_loop_proxy, |
| 675 new RelayDelete(file_path, false, callback)); | 686 new RelayDelete(file_path, recursive, callback)); |
| 676 } | 687 } |
| 677 | 688 |
| 678 // static | 689 // static |
| 679 bool FileUtilProxy::Copy(scoped_refptr<MessageLoopProxy> message_loop_proxy, | 690 bool FileUtilProxy::Copy(scoped_refptr<MessageLoopProxy> message_loop_proxy, |
| 680 const FilePath& src_file_path, | 691 const FilePath& src_file_path, |
| 681 const FilePath& dest_file_path, | 692 const FilePath& dest_file_path, |
| 682 StatusCallback* callback) { | 693 StatusCallback* callback) { |
| 683 return Start(FROM_HERE, message_loop_proxy, | 694 return Start(FROM_HERE, message_loop_proxy, |
| 684 new RelayCopy(src_file_path, dest_file_path, callback)); | 695 new RelayCopy(src_file_path, dest_file_path, callback)); |
| 685 } | 696 } |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 790 | 801 |
| 791 // static | 802 // static |
| 792 bool FileUtilProxy::Flush( | 803 bool FileUtilProxy::Flush( |
| 793 scoped_refptr<MessageLoopProxy> message_loop_proxy, | 804 scoped_refptr<MessageLoopProxy> message_loop_proxy, |
| 794 PlatformFile file, | 805 PlatformFile file, |
| 795 StatusCallback* callback) { | 806 StatusCallback* callback) { |
| 796 return Start(FROM_HERE, message_loop_proxy, new RelayFlush(file, callback)); | 807 return Start(FROM_HERE, message_loop_proxy, new RelayFlush(file, callback)); |
| 797 } | 808 } |
| 798 | 809 |
| 799 } // namespace base | 810 } // namespace base |
| OLD | NEW |