file_util_proxy.cc revision 731df977c0511bca2206b5f333555b1205ff1f43
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
3// found in the LICENSE file.
4
5#include "base/file_util_proxy.h"
6
7#include "base/message_loop_proxy.h"
8
9// TODO(jianli): Move the code from anonymous namespace to base namespace so
10// that all of the base:: prefixes would be unnecessary.
11namespace {
12
13namespace {
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
18// destination).
19static base::PlatformFileError PerformCommonCheckAndPreparationForMoveAndCopy(
20    const FilePath& src_file_path,
21    const FilePath& dest_file_path) {
22  // Exits earlier if the source path does not exist.
23  if (!file_util::PathExists(src_file_path))
24    return base::PLATFORM_FILE_ERROR_NOT_FOUND;
25
26  // The parent of the |dest_file_path| does not exist.
27  if (!file_util::DirectoryExists(dest_file_path.DirName()))
28    return base::PLATFORM_FILE_ERROR_NOT_FOUND;
29
30  // It is an error to try to copy/move an entry into its child.
31  if (src_file_path.IsParent(dest_file_path))
32    return base::PLATFORM_FILE_ERROR_INVALID_OPERATION;
33
34  // Now it is ok to return if the |dest_file_path| does not exist.
35  if (!file_util::PathExists(dest_file_path))
36    return base::PLATFORM_FILE_OK;
37
38  // |src_file_path| exists and is a directory.
39  // |dest_file_path| exists and is a file.
40  bool src_is_directory = file_util::DirectoryExists(src_file_path);
41  bool dest_is_directory = file_util::DirectoryExists(dest_file_path);
42  if (src_is_directory && !dest_is_directory)
43    return base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY;
44
45  // |src_file_path| exists and is a file.
46  // |dest_file_path| exists and is a directory.
47  if (!src_is_directory && dest_is_directory)
48    return base::PLATFORM_FILE_ERROR_NOT_A_FILE;
49
50  // It is an error to copy/move an entry into the same path.
51  if (src_file_path.value() == dest_file_path.value())
52    return base::PLATFORM_FILE_ERROR_EXISTS;
53
54  if (dest_is_directory) {
55    // It is an error to copy/move an entry to a non-empty directory.
56    // Otherwise the copy/move attempt must overwrite the destination, but
57    // the file_util's Copy or Move method doesn't perform overwrite
58    // on all platforms, so we delete the destination directory here.
59    // TODO(kinuko): may be better to change the file_util::{Copy,Move}.
60    if (!file_util::Delete(dest_file_path, false /* recursive */)) {
61      if (!file_util::IsDirectoryEmpty(dest_file_path))
62        return base::PLATFORM_FILE_ERROR_NOT_EMPTY;
63      return base::PLATFORM_FILE_ERROR_FAILED;
64    }
65  }
66  return base::PLATFORM_FILE_OK;
67}
68
69} // anonymous namespace
70
71class MessageLoopRelay
72    : public base::RefCountedThreadSafe<MessageLoopRelay> {
73 public:
74  MessageLoopRelay()
75      : origin_message_loop_proxy_(
76            base::MessageLoopProxy::CreateForCurrentThread()),
77        error_code_(base::PLATFORM_FILE_OK) {
78  }
79
80  bool Start(scoped_refptr<base::MessageLoopProxy> message_loop_proxy,
81             const tracked_objects::Location& from_here) {
82    return message_loop_proxy->PostTask(
83        from_here,
84        NewRunnableMethod(this, &MessageLoopRelay::ProcessOnTargetThread));
85  }
86
87 protected:
88  friend class base::RefCountedThreadSafe<MessageLoopRelay>;
89  virtual ~MessageLoopRelay() {}
90
91  // Called to perform work on the FILE thread.
92  virtual void RunWork() = 0;
93
94  // Called to notify the callback on the origin thread.
95  virtual void RunCallback() = 0;
96
97  void set_error_code(base::PlatformFileError error_code) {
98    error_code_ = error_code;
99  }
100
101  base::PlatformFileError error_code() const {
102    return error_code_;
103  }
104
105 private:
106  void ProcessOnTargetThread() {
107    RunWork();
108    origin_message_loop_proxy_->PostTask(
109        FROM_HERE,
110        NewRunnableMethod(this, &MessageLoopRelay::RunCallback));
111  }
112
113  scoped_refptr<base::MessageLoopProxy> origin_message_loop_proxy_;
114  base::PlatformFileError error_code_;
115};
116
117class RelayCreateOrOpen : public MessageLoopRelay {
118 public:
119  RelayCreateOrOpen(
120      scoped_refptr<base::MessageLoopProxy> message_loop_proxy,
121      const FilePath& file_path,
122      int file_flags,
123      base::FileUtilProxy::CreateOrOpenCallback* callback)
124      : message_loop_proxy_(message_loop_proxy),
125        file_path_(file_path),
126        file_flags_(file_flags),
127        callback_(callback),
128        file_handle_(base::kInvalidPlatformFileValue),
129        created_(false) {
130    DCHECK(callback);
131  }
132
133 protected:
134  virtual ~RelayCreateOrOpen() {
135    if (file_handle_ != base::kInvalidPlatformFileValue)
136      base::FileUtilProxy::Close(message_loop_proxy_, file_handle_, NULL);
137  }
138
139  virtual void RunWork() {
140    if (!file_util::DirectoryExists(file_path_.DirName())) {
141      // If its parent does not exist, should return NOT_FOUND error.
142      set_error_code(base::PLATFORM_FILE_ERROR_NOT_FOUND);
143      return;
144    }
145    base::PlatformFileError error_code = base::PLATFORM_FILE_OK;
146    file_handle_ = base::CreatePlatformFile(file_path_, file_flags_,
147                                            &created_, &error_code);
148    set_error_code(error_code);
149  }
150
151  virtual void RunCallback() {
152    callback_->Run(error_code(), base::PassPlatformFile(&file_handle_),
153                   created_);
154    delete callback_;
155  }
156
157 private:
158  scoped_refptr<base::MessageLoopProxy> message_loop_proxy_;
159  FilePath file_path_;
160  int file_flags_;
161  base::FileUtilProxy::CreateOrOpenCallback* callback_;
162  base::PlatformFile file_handle_;
163  bool created_;
164};
165
166class RelayCreateTemporary : public MessageLoopRelay {
167 public:
168  RelayCreateTemporary(
169      scoped_refptr<base::MessageLoopProxy> message_loop_proxy,
170      base::FileUtilProxy::CreateTemporaryCallback* callback)
171      : message_loop_proxy_(message_loop_proxy),
172        callback_(callback),
173        file_handle_(base::kInvalidPlatformFileValue) {
174    DCHECK(callback);
175  }
176
177 protected:
178  virtual ~RelayCreateTemporary() {
179    if (file_handle_ != base::kInvalidPlatformFileValue)
180      base::FileUtilProxy::Close(message_loop_proxy_, file_handle_, NULL);
181  }
182
183  virtual void RunWork() {
184    // TODO(darin): file_util should have a variant of CreateTemporaryFile
185    // that returns a FilePath and a PlatformFile.
186    file_util::CreateTemporaryFile(&file_path_);
187
188    // Use a fixed set of flags that are appropriate for writing to a temporary
189    // file from the IO thread using a net::FileStream.
190    int file_flags =
191        base::PLATFORM_FILE_CREATE_ALWAYS |
192        base::PLATFORM_FILE_WRITE |
193        base::PLATFORM_FILE_ASYNC |
194        base::PLATFORM_FILE_TEMPORARY;
195    base::PlatformFileError error_code = base::PLATFORM_FILE_OK;
196    file_handle_ = base::CreatePlatformFile(file_path_, file_flags,
197                                            NULL, &error_code);
198    set_error_code(error_code);
199  }
200
201  virtual void RunCallback() {
202    callback_->Run(error_code(), base::PassPlatformFile(&file_handle_),
203                   file_path_);
204    delete callback_;
205  }
206
207 private:
208  scoped_refptr<base::MessageLoopProxy> message_loop_proxy_;
209  base::FileUtilProxy::CreateTemporaryCallback* callback_;
210  base::PlatformFile file_handle_;
211  FilePath file_path_;
212};
213
214class RelayWithStatusCallback : public MessageLoopRelay {
215 public:
216  explicit RelayWithStatusCallback(
217      base::FileUtilProxy::StatusCallback* callback)
218      : callback_(callback) {
219    // It is OK for callback to be NULL.
220  }
221
222 protected:
223  virtual void RunCallback() {
224    // The caller may not have been interested in the result.
225    if (callback_) {
226      callback_->Run(error_code());
227      delete callback_;
228    }
229  }
230
231 private:
232  base::FileUtilProxy::StatusCallback* callback_;
233};
234
235class RelayClose : public RelayWithStatusCallback {
236 public:
237  RelayClose(base::PlatformFile file_handle,
238             base::FileUtilProxy::StatusCallback* callback)
239      : RelayWithStatusCallback(callback),
240        file_handle_(file_handle) {
241  }
242
243 protected:
244  virtual void RunWork() {
245    if (!base::ClosePlatformFile(file_handle_))
246      set_error_code(base::PLATFORM_FILE_ERROR_FAILED);
247  }
248
249 private:
250  base::PlatformFile file_handle_;
251};
252
253class RelayEnsureFileExists : public MessageLoopRelay {
254 public:
255  RelayEnsureFileExists(
256      scoped_refptr<base::MessageLoopProxy> message_loop_proxy,
257      const FilePath& file_path,
258      base::FileUtilProxy::EnsureFileExistsCallback* callback)
259      : message_loop_proxy_(message_loop_proxy),
260        file_path_(file_path),
261        callback_(callback),
262        created_(false) {
263    DCHECK(callback);
264  }
265
266 protected:
267  virtual void RunWork() {
268    if (!file_util::DirectoryExists(file_path_.DirName())) {
269      // If its parent does not exist, should return NOT_FOUND error.
270      set_error_code(base::PLATFORM_FILE_ERROR_NOT_FOUND);
271      return;
272    }
273    base::PlatformFileError error_code = base::PLATFORM_FILE_OK;
274    // Tries to create the |file_path_| exclusively.  This should fail
275    // with PLATFORM_FILE_ERROR_EXISTS if the path already exists.
276    base::PlatformFile handle = base::CreatePlatformFile(
277        file_path_,
278        base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_READ,
279        &created_, &error_code);
280    if (error_code == base::PLATFORM_FILE_ERROR_EXISTS) {
281      // Make sure created_ is false.
282      created_ = false;
283      error_code = base::PLATFORM_FILE_OK;
284    }
285    if (handle != base::kInvalidPlatformFileValue)
286      base::ClosePlatformFile(handle);
287    set_error_code(error_code);
288  }
289
290  virtual void RunCallback() {
291    callback_->Run(error_code(), created_);
292    delete callback_;
293  }
294
295 private:
296  scoped_refptr<base::MessageLoopProxy> message_loop_proxy_;
297  FilePath file_path_;
298  base::FileUtilProxy::EnsureFileExistsCallback* callback_;
299  bool created_;
300};
301
302class RelayDelete : public RelayWithStatusCallback {
303 public:
304  RelayDelete(const FilePath& file_path,
305              bool recursive,
306              base::FileUtilProxy::StatusCallback* callback)
307      : RelayWithStatusCallback(callback),
308        file_path_(file_path),
309        recursive_(recursive) {
310  }
311
312 protected:
313  virtual void RunWork() {
314    if (!file_util::PathExists(file_path_)) {
315      set_error_code(base::PLATFORM_FILE_ERROR_NOT_FOUND);
316      return;
317    }
318    if (!file_util::Delete(file_path_, recursive_)) {
319      if (!recursive_ && !file_util::IsDirectoryEmpty(file_path_)) {
320        set_error_code(base::PLATFORM_FILE_ERROR_NOT_EMPTY);
321        return;
322      }
323      set_error_code(base::PLATFORM_FILE_ERROR_FAILED);
324    }
325  }
326
327 private:
328  FilePath file_path_;
329  bool recursive_;
330};
331
332class RelayCopy : public RelayWithStatusCallback {
333 public:
334  RelayCopy(const FilePath& src_file_path,
335            const FilePath& dest_file_path,
336            base::FileUtilProxy::StatusCallback* callback)
337      : RelayWithStatusCallback(callback),
338        src_file_path_(src_file_path),
339        dest_file_path_(dest_file_path) {
340  }
341
342 protected:
343  virtual void RunWork() {
344    set_error_code(PerformCommonCheckAndPreparationForMoveAndCopy(
345        src_file_path_, dest_file_path_));
346    if (error_code() != base::PLATFORM_FILE_OK)
347      return;
348    if (!file_util::CopyDirectory(src_file_path_, dest_file_path_,
349        true /* recursive */))
350      set_error_code(base::PLATFORM_FILE_ERROR_FAILED);
351  }
352
353 private:
354  FilePath src_file_path_;
355  FilePath dest_file_path_;
356};
357
358class RelayMove : public RelayWithStatusCallback {
359 public:
360  RelayMove(const FilePath& src_file_path,
361            const FilePath& dest_file_path,
362            base::FileUtilProxy::StatusCallback* callback)
363      : RelayWithStatusCallback(callback),
364        src_file_path_(src_file_path),
365        dest_file_path_(dest_file_path) {
366  }
367
368 protected:
369  virtual void RunWork() {
370    set_error_code(PerformCommonCheckAndPreparationForMoveAndCopy(
371        src_file_path_, dest_file_path_));
372    if (error_code() != base::PLATFORM_FILE_OK)
373      return;
374    if (!file_util::Move(src_file_path_, dest_file_path_))
375      set_error_code(base::PLATFORM_FILE_ERROR_FAILED);
376  }
377
378 private:
379  FilePath src_file_path_;
380  FilePath dest_file_path_;
381};
382
383class RelayCreateDirectory : public RelayWithStatusCallback {
384 public:
385  RelayCreateDirectory(
386      const FilePath& file_path,
387      bool exclusive,
388      bool recursive,
389      base::FileUtilProxy::StatusCallback* callback)
390      : RelayWithStatusCallback(callback),
391        file_path_(file_path),
392        exclusive_(exclusive),
393        recursive_(recursive) {
394  }
395
396 protected:
397  virtual void RunWork() {
398    bool path_exists = file_util::PathExists(file_path_);
399    // If parent dir of file doesn't exist.
400    if (!recursive_ && !file_util::PathExists(file_path_.DirName())) {
401      set_error_code(base::PLATFORM_FILE_ERROR_NOT_FOUND);
402      return;
403    }
404    if (exclusive_ && path_exists) {
405      set_error_code(base::PLATFORM_FILE_ERROR_EXISTS);
406      return;
407    }
408    // If file exists at the path.
409    if (path_exists && !file_util::DirectoryExists(file_path_)) {
410      set_error_code(base::PLATFORM_FILE_ERROR_EXISTS);
411      return;
412    }
413    if (!file_util::CreateDirectory(file_path_))
414      set_error_code(base::PLATFORM_FILE_ERROR_FAILED);
415  }
416
417 private:
418  FilePath file_path_;
419  bool exclusive_;
420  bool recursive_;
421};
422
423class RelayReadDirectory : public MessageLoopRelay {
424 public:
425  RelayReadDirectory(const FilePath& file_path,
426      base::FileUtilProxy::ReadDirectoryCallback* callback)
427      : callback_(callback), file_path_(file_path) {
428    DCHECK(callback);
429  }
430
431 protected:
432  virtual void RunWork() {
433    // TODO(kkanetkar): Implement directory read in multiple chunks.
434    if (!file_util::DirectoryExists(file_path_)) {
435      set_error_code(base::PLATFORM_FILE_ERROR_NOT_FOUND);
436      return;
437    }
438
439    file_util::FileEnumerator file_enum(
440        file_path_, false, static_cast<file_util::FileEnumerator::FILE_TYPE>(
441        file_util::FileEnumerator::FILES |
442        file_util::FileEnumerator::DIRECTORIES));
443    FilePath current;
444    while (!(current = file_enum.Next()).empty()) {
445      base::file_util_proxy::Entry entry;
446      file_util::FileEnumerator::FindInfo info;
447      file_enum.GetFindInfo(&info);
448      entry.is_directory = file_enum.IsDirectory(info);
449      // This will just give the entry's name instead of entire path
450      // if we use current.value().
451      entry.name = file_util::FileEnumerator::GetFilename(info).value();
452      entries_.push_back(entry);
453    }
454  }
455
456  virtual void RunCallback() {
457    callback_->Run(error_code(), entries_);
458    delete callback_;
459  }
460
461 private:
462  base::FileUtilProxy::ReadDirectoryCallback* callback_;
463  FilePath file_path_;
464  std::vector<base::file_util_proxy::Entry> entries_;
465};
466
467class RelayGetFileInfo : public MessageLoopRelay {
468 public:
469  RelayGetFileInfo(const FilePath& file_path,
470                   base::FileUtilProxy::GetFileInfoCallback* callback)
471      : callback_(callback),
472        file_path_(file_path) {
473    DCHECK(callback);
474  }
475
476 protected:
477  virtual void RunWork() {
478    if (!file_util::PathExists(file_path_)) {
479      set_error_code(base::PLATFORM_FILE_ERROR_NOT_FOUND);
480      return;
481    }
482    if (!file_util::GetFileInfo(file_path_, &file_info_))
483      set_error_code(base::PLATFORM_FILE_ERROR_FAILED);
484  }
485
486  virtual void RunCallback() {
487    callback_->Run(error_code(), file_info_);
488    delete callback_;
489  }
490
491 private:
492  base::FileUtilProxy::GetFileInfoCallback* callback_;
493  FilePath file_path_;
494  base::PlatformFileInfo file_info_;
495};
496
497class RelayGetFileInfoFromPlatformFile : public MessageLoopRelay {
498 public:
499  RelayGetFileInfoFromPlatformFile(
500      base::PlatformFile file,
501      base::FileUtilProxy::GetFileInfoCallback* callback)
502      : callback_(callback),
503        file_(file) {
504    DCHECK(callback);
505  }
506
507 protected:
508  virtual void RunWork() {
509    if (!base::GetPlatformFileInfo(file_, &file_info_))
510      set_error_code(base::PLATFORM_FILE_ERROR_FAILED);
511  }
512
513  virtual void RunCallback() {
514    callback_->Run(error_code(), file_info_);
515    delete callback_;
516  }
517
518 private:
519  base::FileUtilProxy::GetFileInfoCallback* callback_;
520  base::PlatformFile file_;
521  base::PlatformFileInfo file_info_;
522};
523
524class RelayRead : public MessageLoopRelay {
525 public:
526  RelayRead(base::PlatformFile file,
527            int64 offset,
528            char* buffer,
529            int bytes_to_read,
530            base::FileUtilProxy::ReadWriteCallback* callback)
531      : file_(file),
532        offset_(offset),
533        buffer_(buffer),
534        bytes_to_read_(bytes_to_read),
535        callback_(callback),
536        bytes_read_(0) {
537  }
538
539 protected:
540  virtual void RunWork() {
541    bytes_read_ = base::ReadPlatformFile(file_, offset_, buffer_,
542                                         bytes_to_read_);
543    if (bytes_read_ < 0)
544      set_error_code(base::PLATFORM_FILE_ERROR_FAILED);
545  }
546
547  virtual void RunCallback() {
548    if (callback_) {
549      callback_->Run(error_code(), bytes_read_);
550      delete callback_;
551    }
552  }
553
554 private:
555  base::PlatformFile file_;
556  int64 offset_;
557  char* buffer_;
558  int bytes_to_read_;
559  base::FileUtilProxy::ReadWriteCallback* callback_;
560  int bytes_read_;
561};
562
563class RelayWrite : public MessageLoopRelay {
564 public:
565  RelayWrite(base::PlatformFile file,
566             int64 offset,
567             const char* buffer,
568             int bytes_to_write,
569             base::FileUtilProxy::ReadWriteCallback* callback)
570      : file_(file),
571        offset_(offset),
572        buffer_(buffer),
573        bytes_to_write_(bytes_to_write),
574        callback_(callback) {
575  }
576
577 protected:
578  virtual void RunWork() {
579    bytes_written_ = base::WritePlatformFile(file_, offset_, buffer_,
580                                             bytes_to_write_);
581    if (bytes_written_ < 0)
582      set_error_code(base::PLATFORM_FILE_ERROR_FAILED);
583  }
584
585  virtual void RunCallback() {
586    if (callback_) {
587      callback_->Run(error_code(), bytes_written_);
588      delete callback_;
589    }
590  }
591
592 private:
593  base::PlatformFile file_;
594  int64 offset_;
595  const char* buffer_;
596  int bytes_to_write_;
597  base::FileUtilProxy::ReadWriteCallback* callback_;
598  int bytes_written_;
599};
600
601class RelayTouch : public RelayWithStatusCallback {
602 public:
603  RelayTouch(base::PlatformFile file,
604             const base::Time& last_access_time,
605             const base::Time& last_modified_time,
606             base::FileUtilProxy::StatusCallback* callback)
607      : RelayWithStatusCallback(callback),
608        file_(file),
609        last_access_time_(last_access_time),
610        last_modified_time_(last_modified_time) {
611  }
612
613 protected:
614  virtual void RunWork() {
615    if (!base::TouchPlatformFile(file_, last_access_time_, last_modified_time_))
616      set_error_code(base::PLATFORM_FILE_ERROR_FAILED);
617  }
618
619 private:
620  base::PlatformFile file_;
621  base::Time last_access_time_;
622  base::Time last_modified_time_;
623};
624
625class RelayTouchFilePath : public RelayWithStatusCallback {
626 public:
627  RelayTouchFilePath(const FilePath& file_path,
628                     const base::Time& last_access_time,
629                     const base::Time& last_modified_time,
630                     base::FileUtilProxy::StatusCallback* callback)
631      : RelayWithStatusCallback(callback),
632        file_path_(file_path),
633        last_access_time_(last_access_time),
634        last_modified_time_(last_modified_time) {
635  }
636
637 protected:
638  virtual void RunWork() {
639    if (!file_util::TouchFile(
640            file_path_, last_access_time_, last_modified_time_))
641      set_error_code(base::PLATFORM_FILE_ERROR_FAILED);
642  }
643
644 private:
645  FilePath file_path_;
646  base::Time last_access_time_;
647  base::Time last_modified_time_;
648};
649
650class RelayTruncatePlatformFile : public RelayWithStatusCallback {
651 public:
652  RelayTruncatePlatformFile(base::PlatformFile file,
653                            int64 length,
654                            base::FileUtilProxy::StatusCallback* callback)
655      : RelayWithStatusCallback(callback),
656        file_(file),
657        length_(length) {
658  }
659
660 protected:
661  virtual void RunWork() {
662    if (!base::TruncatePlatformFile(file_, length_))
663      set_error_code(base::PLATFORM_FILE_ERROR_FAILED);
664  }
665
666 private:
667  base::PlatformFile file_;
668  int64 length_;
669};
670
671class RelayTruncate : public RelayWithStatusCallback {
672 public:
673  RelayTruncate(const FilePath& path,
674                int64 length,
675                base::FileUtilProxy::StatusCallback* callback)
676      : RelayWithStatusCallback(callback),
677        path_(path),
678        length_(length) {
679  }
680
681 protected:
682  virtual void RunWork() {
683    base::PlatformFileError error_code(base::PLATFORM_FILE_ERROR_FAILED);
684    base::PlatformFile file =
685        base::CreatePlatformFile(
686            path_,
687            base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_WRITE,
688            NULL,
689            &error_code);
690    if (error_code != base::PLATFORM_FILE_OK) {
691      set_error_code(error_code);
692      return;
693    }
694    if (!base::TruncatePlatformFile(file, length_))
695      set_error_code(base::PLATFORM_FILE_ERROR_FAILED);
696    base::ClosePlatformFile(file);
697  }
698
699 private:
700  FilePath path_;
701  int64 length_;
702};
703
704class RelayFlush : public RelayWithStatusCallback {
705 public:
706  RelayFlush(base::PlatformFile file,
707             base::FileUtilProxy::StatusCallback* callback)
708      : RelayWithStatusCallback(callback),
709        file_(file) {
710  }
711
712 protected:
713  virtual void RunWork() {
714    if (!base::FlushPlatformFile(file_))
715      set_error_code(base::PLATFORM_FILE_ERROR_FAILED);
716  }
717
718 private:
719  base::PlatformFile file_;
720};
721
722bool Start(const tracked_objects::Location& from_here,
723           scoped_refptr<base::MessageLoopProxy> message_loop_proxy,
724           scoped_refptr<MessageLoopRelay> relay) {
725  return relay->Start(message_loop_proxy, from_here);
726}
727
728}  // namespace
729
730namespace base {
731
732// static
733bool FileUtilProxy::CreateOrOpen(
734    scoped_refptr<MessageLoopProxy> message_loop_proxy,
735    const FilePath& file_path, int file_flags,
736    CreateOrOpenCallback* callback) {
737  return Start(FROM_HERE, message_loop_proxy, new RelayCreateOrOpen(
738      message_loop_proxy, file_path, file_flags, callback));
739}
740
741// static
742bool FileUtilProxy::CreateTemporary(
743    scoped_refptr<MessageLoopProxy> message_loop_proxy,
744    CreateTemporaryCallback* callback) {
745  return Start(FROM_HERE, message_loop_proxy,
746               new RelayCreateTemporary(message_loop_proxy, callback));
747}
748
749// static
750bool FileUtilProxy::CreateDirectory(
751    scoped_refptr<MessageLoopProxy> message_loop_proxy,
752    const FilePath& file_path,
753    bool exclusive,
754    bool recursive,
755    StatusCallback* callback) {
756  return Start(FROM_HERE, message_loop_proxy, new RelayCreateDirectory(
757      file_path, exclusive, recursive, callback));
758}
759
760// static
761bool FileUtilProxy::Close(scoped_refptr<MessageLoopProxy> message_loop_proxy,
762                          base::PlatformFile file_handle,
763                          StatusCallback* callback) {
764  return Start(FROM_HERE, message_loop_proxy,
765               new RelayClose(file_handle, callback));
766}
767
768// static
769bool FileUtilProxy::EnsureFileExists(
770    scoped_refptr<MessageLoopProxy> message_loop_proxy,
771    const FilePath& file_path,
772    EnsureFileExistsCallback* callback) {
773  return Start(FROM_HERE, message_loop_proxy, new RelayEnsureFileExists(
774      message_loop_proxy, file_path, callback));
775}
776
777// static
778bool FileUtilProxy::Delete(scoped_refptr<MessageLoopProxy> message_loop_proxy,
779                           const FilePath& file_path,
780                           bool recursive,
781                           StatusCallback* callback) {
782  return Start(FROM_HERE, message_loop_proxy,
783               new RelayDelete(file_path, recursive, callback));
784}
785
786// static
787bool FileUtilProxy::Copy(scoped_refptr<MessageLoopProxy> message_loop_proxy,
788                         const FilePath& src_file_path,
789                         const FilePath& dest_file_path,
790                         StatusCallback* callback) {
791  return Start(FROM_HERE, message_loop_proxy,
792               new RelayCopy(src_file_path, dest_file_path, callback));
793}
794
795// static
796bool FileUtilProxy::Move(scoped_refptr<MessageLoopProxy> message_loop_proxy,
797                         const FilePath& src_file_path,
798                         const FilePath& dest_file_path,
799                         StatusCallback* callback) {
800  return Start(FROM_HERE, message_loop_proxy,
801               new RelayMove(src_file_path, dest_file_path, callback));
802}
803
804// static
805bool FileUtilProxy::ReadDirectory(
806    scoped_refptr<MessageLoopProxy> message_loop_proxy,
807    const FilePath& file_path,
808    ReadDirectoryCallback* callback) {
809  return Start(FROM_HERE, message_loop_proxy, new RelayReadDirectory(
810               file_path, callback));
811}
812
813// Retrieves the information about a file. It is invalid to pass NULL for the
814// callback.
815bool FileUtilProxy::GetFileInfo(
816    scoped_refptr<MessageLoopProxy> message_loop_proxy,
817    const FilePath& file_path,
818    GetFileInfoCallback* callback) {
819  return Start(FROM_HERE, message_loop_proxy, new RelayGetFileInfo(
820               file_path, callback));
821}
822
823// static
824bool FileUtilProxy::RecursiveDelete(
825    scoped_refptr<MessageLoopProxy> message_loop_proxy,
826    const FilePath& file_path,
827    StatusCallback* callback) {
828  return Start(FROM_HERE, message_loop_proxy,
829               new RelayDelete(file_path, true, callback));
830}
831
832// static
833bool FileUtilProxy::GetFileInfoFromPlatformFile(
834    scoped_refptr<MessageLoopProxy> message_loop_proxy,
835    PlatformFile file,
836    GetFileInfoCallback* callback) {
837  return Start(FROM_HERE, message_loop_proxy,
838               new RelayGetFileInfoFromPlatformFile(file, callback));
839}
840
841// static
842bool FileUtilProxy::Read(
843    scoped_refptr<MessageLoopProxy> message_loop_proxy,
844    PlatformFile file,
845    int64 offset,
846    char* buffer,
847    int bytes_to_read,
848    ReadWriteCallback* callback) {
849  return Start(FROM_HERE, message_loop_proxy,
850               new RelayRead(file, offset, buffer, bytes_to_read, callback));
851}
852
853// static
854bool FileUtilProxy::Write(
855    scoped_refptr<MessageLoopProxy> message_loop_proxy,
856    PlatformFile file,
857    int64 offset,
858    const char* buffer,
859    int bytes_to_write,
860    ReadWriteCallback* callback) {
861  return Start(FROM_HERE, message_loop_proxy,
862               new RelayWrite(file, offset, buffer, bytes_to_write, callback));
863}
864
865// static
866bool FileUtilProxy::Touch(
867    scoped_refptr<MessageLoopProxy> message_loop_proxy,
868    PlatformFile file,
869    const base::Time& last_access_time,
870    const base::Time& last_modified_time,
871    StatusCallback* callback) {
872  return Start(FROM_HERE, message_loop_proxy,
873               new RelayTouch(file, last_access_time, last_modified_time,
874                              callback));
875}
876
877// static
878bool FileUtilProxy::Touch(
879    scoped_refptr<MessageLoopProxy> message_loop_proxy,
880    const FilePath& file_path,
881    const base::Time& last_access_time,
882    const base::Time& last_modified_time,
883    StatusCallback* callback) {
884  return Start(FROM_HERE, message_loop_proxy,
885               new RelayTouchFilePath(file_path, last_access_time,
886                                      last_modified_time, callback));
887}
888
889// static
890bool FileUtilProxy::Truncate(
891    scoped_refptr<MessageLoopProxy> message_loop_proxy,
892    PlatformFile file,
893    int64 length,
894    StatusCallback* callback) {
895  return Start(FROM_HERE, message_loop_proxy,
896               new RelayTruncatePlatformFile(file, length, callback));
897}
898
899// static
900bool FileUtilProxy::Truncate(
901    scoped_refptr<MessageLoopProxy> message_loop_proxy,
902    const FilePath& path,
903    int64 length,
904    StatusCallback* callback) {
905  return Start(FROM_HERE, message_loop_proxy,
906               new RelayTruncate(path, length, callback));
907}
908
909// static
910bool FileUtilProxy::Flush(
911    scoped_refptr<MessageLoopProxy> message_loop_proxy,
912    PlatformFile file,
913    StatusCallback* callback) {
914  return Start(FROM_HERE, message_loop_proxy, new RelayFlush(file, callback));
915}
916
917}  // namespace base
918