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

Side by Side Diff: base/file_util_proxy.cc

Issue 3567012: Support removeRecursively and new copy/move behaviors for FileSystem API (Closed)
Patch Set: '' Created 10 years, 2 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
« no previous file with comments | « base/file_util_proxy.h ('k') | base/platform_file.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
OLDNEW
« no previous file with comments | « base/file_util_proxy.h ('k') | base/platform_file.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698