Convert MessageLoopProxy to TaskRunner in FileUtilProxy

Also adding unittests to FileUtilProxy.

BUG=123558,77454
TEST=FileUtilProxyTest.*


Review URL: http://codereview.chromium.org/10095028

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@133484 0039d316-1c4b-4281-b951-d872f2087c98


CrOS-Libchrome-Original-Commit: 77e07b84f56ef033bb2a1dc6a6578b393868517a
diff --git a/base/base.gyp b/base/base.gyp
index a7108af..9126900 100644
--- a/base/base.gyp
+++ b/base/base.gyp
@@ -154,6 +154,7 @@
         'environment_unittest.cc',
         'file_descriptor_shuffle_unittest.cc',
         'file_path_unittest.cc',
+        'file_util_proxy_unittest.cc',
         'file_util_unittest.cc',
         'file_version_info_unittest.cc',
         'gmock_unittest.cc',
diff --git a/base/file_util_proxy.cc b/base/file_util_proxy.cc
index 25d1718..62ac2e4 100644
--- a/base/file_util_proxy.cc
+++ b/base/file_util_proxy.cc
@@ -7,7 +7,7 @@
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/file_util.h"
-#include "base/message_loop_proxy.h"
+#include "base/task_runner.h"
 #include "base/task_runner_util.h"
 
 namespace base {
@@ -23,9 +23,9 @@
 // Helper classes or routines for individual methods.
 class CreateOrOpenHelper {
  public:
-  CreateOrOpenHelper(MessageLoopProxy* message_loop_proxy,
+  CreateOrOpenHelper(TaskRunner* task_runner,
                      const FileUtilProxy::CloseTask& close_task)
-      : message_loop_proxy_(message_loop_proxy),
+      : task_runner_(task_runner),
         close_task_(close_task),
         file_handle_(kInvalidPlatformFileValue),
         created_(false),
@@ -33,7 +33,7 @@
 
   ~CreateOrOpenHelper() {
     if (file_handle_ != kInvalidPlatformFileValue) {
-      message_loop_proxy_->PostTask(
+      task_runner_->PostTask(
           FROM_HERE,
           base::Bind(base::IgnoreResult(close_task_), file_handle_));
     }
@@ -49,7 +49,7 @@
   }
 
  private:
-  scoped_refptr<MessageLoopProxy> message_loop_proxy_;
+  scoped_refptr<TaskRunner> task_runner_;
   FileUtilProxy::CloseTask close_task_;
   PlatformFile file_handle_;
   bool created_;
@@ -59,14 +59,14 @@
 
 class CreateTemporaryHelper {
  public:
-  CreateTemporaryHelper(MessageLoopProxy* message_loop_proxy)
-      : message_loop_proxy_(message_loop_proxy),
+  CreateTemporaryHelper(TaskRunner* task_runner)
+      : task_runner_(task_runner),
         file_handle_(kInvalidPlatformFileValue),
         error_(PLATFORM_FILE_OK) {}
 
   ~CreateTemporaryHelper() {
     if (file_handle_ != kInvalidPlatformFileValue) {
-      FileUtilProxy::Close(message_loop_proxy_, file_handle_,
+      FileUtilProxy::Close(task_runner_, file_handle_,
                            FileUtilProxy::StatusCallback());
     }
   }
@@ -92,7 +92,7 @@
   }
 
  private:
-  scoped_refptr<MessageLoopProxy> message_loop_proxy_;
+  scoped_refptr<TaskRunner> task_runner_;
   PlatformFile file_handle_;
   FilePath file_path_;
   PlatformFileError error_;
@@ -224,11 +224,11 @@
 
 // static
 bool FileUtilProxy::CreateOrOpen(
-    scoped_refptr<MessageLoopProxy> message_loop_proxy,
+    TaskRunner* task_runner,
     const FilePath& file_path, int file_flags,
     const CreateOrOpenCallback& callback) {
   return RelayCreateOrOpen(
-      message_loop_proxy,
+      task_runner,
       base::Bind(&CreateOrOpenAdapter, file_path, file_flags),
       base::Bind(&CloseAdapter),
       callback);
@@ -236,11 +236,11 @@
 
 // static
 bool FileUtilProxy::CreateTemporary(
-    scoped_refptr<MessageLoopProxy> message_loop_proxy,
+    TaskRunner* task_runner,
     int additional_file_flags,
     const CreateTemporaryCallback& callback) {
-  CreateTemporaryHelper* helper = new CreateTemporaryHelper(message_loop_proxy);
-  return message_loop_proxy->PostTaskAndReply(
+  CreateTemporaryHelper* helper = new CreateTemporaryHelper(task_runner);
+  return task_runner->PostTaskAndReply(
       FROM_HERE,
       Bind(&CreateTemporaryHelper::RunWork, Unretained(helper),
            additional_file_flags),
@@ -249,11 +249,11 @@
 
 // static
 bool FileUtilProxy::Close(
-    scoped_refptr<MessageLoopProxy> message_loop_proxy,
+    TaskRunner* task_runner,
     base::PlatformFile file_handle,
     const StatusCallback& callback) {
   return RelayClose(
-      message_loop_proxy,
+      task_runner,
       base::Bind(&CloseAdapter),
       file_handle, callback);
 }
@@ -261,11 +261,11 @@
 // Retrieves the information about a file. It is invalid to pass NULL for the
 // callback.
 bool FileUtilProxy::GetFileInfo(
-    scoped_refptr<MessageLoopProxy> message_loop_proxy,
+    TaskRunner* task_runner,
     const FilePath& file_path,
     const GetFileInfoCallback& callback) {
   GetFileInfoHelper* helper = new GetFileInfoHelper;
-  return message_loop_proxy->PostTaskAndReply(
+  return task_runner->PostTaskAndReply(
       FROM_HERE,
       Bind(&GetFileInfoHelper::RunWorkForFilePath,
            Unretained(helper), file_path),
@@ -274,11 +274,11 @@
 
 // static
 bool FileUtilProxy::GetFileInfoFromPlatformFile(
-    scoped_refptr<MessageLoopProxy> message_loop_proxy,
+    TaskRunner* task_runner,
     PlatformFile file,
     const GetFileInfoCallback& callback) {
   GetFileInfoHelper* helper = new GetFileInfoHelper;
-  return message_loop_proxy->PostTaskAndReply(
+  return task_runner->PostTaskAndReply(
       FROM_HERE,
       Bind(&GetFileInfoHelper::RunWorkForPlatformFile,
            Unretained(helper), file),
@@ -286,30 +286,30 @@
 }
 
 // static
-bool FileUtilProxy::Delete(scoped_refptr<MessageLoopProxy> message_loop_proxy,
+bool FileUtilProxy::Delete(TaskRunner* task_runner,
                            const FilePath& file_path,
                            bool recursive,
                            const StatusCallback& callback) {
   return RelayFileTask(
-      message_loop_proxy, FROM_HERE,
+      task_runner, FROM_HERE,
       Bind(&DeleteAdapter, file_path, recursive),
       callback);
 }
 
 // static
 bool FileUtilProxy::RecursiveDelete(
-    scoped_refptr<MessageLoopProxy> message_loop_proxy,
+    TaskRunner* task_runner,
     const FilePath& file_path,
     const StatusCallback& callback) {
   return RelayFileTask(
-      message_loop_proxy, FROM_HERE,
+      task_runner, FROM_HERE,
       Bind(&DeleteAdapter, file_path, true /* recursive */),
       callback);
 }
 
 // static
 bool FileUtilProxy::Read(
-    scoped_refptr<MessageLoopProxy> message_loop_proxy,
+    TaskRunner* task_runner,
     PlatformFile file,
     int64 offset,
     int bytes_to_read,
@@ -318,7 +318,7 @@
     return false;
   }
   ReadHelper* helper = new ReadHelper(bytes_to_read);
-  return message_loop_proxy->PostTaskAndReply(
+  return task_runner->PostTaskAndReply(
       FROM_HERE,
       Bind(&ReadHelper::RunWork, Unretained(helper), file, offset),
       Bind(&ReadHelper::Reply, Owned(helper), callback));
@@ -326,7 +326,7 @@
 
 // static
 bool FileUtilProxy::Write(
-    scoped_refptr<MessageLoopProxy> message_loop_proxy,
+    TaskRunner* task_runner,
     PlatformFile file,
     int64 offset,
     const char* buffer,
@@ -336,7 +336,7 @@
     return false;
   }
   WriteHelper* helper = new WriteHelper(buffer, bytes_to_write);
-  return message_loop_proxy->PostTaskAndReply(
+  return task_runner->PostTaskAndReply(
       FROM_HERE,
       Bind(&WriteHelper::RunWork, Unretained(helper), file, offset),
       Bind(&WriteHelper::Reply, Owned(helper), callback));
@@ -344,13 +344,13 @@
 
 // static
 bool FileUtilProxy::Touch(
-    scoped_refptr<MessageLoopProxy> message_loop_proxy,
+    TaskRunner* task_runner,
     PlatformFile file,
     const Time& last_access_time,
     const Time& last_modified_time,
     const StatusCallback& callback) {
   return base::PostTaskAndReplyWithResult(
-      message_loop_proxy,
+      task_runner,
       FROM_HERE,
       Bind(&TouchPlatformFile, file,
            last_access_time, last_modified_time),
@@ -359,13 +359,13 @@
 
 // static
 bool FileUtilProxy::Touch(
-    scoped_refptr<MessageLoopProxy> message_loop_proxy,
+    TaskRunner* task_runner,
     const FilePath& file_path,
     const Time& last_access_time,
     const Time& last_modified_time,
     const StatusCallback& callback) {
   return base::PostTaskAndReplyWithResult(
-      message_loop_proxy,
+      task_runner,
       FROM_HERE,
       Bind(&file_util::TouchFile, file_path,
            last_access_time, last_modified_time),
@@ -374,12 +374,12 @@
 
 // static
 bool FileUtilProxy::Truncate(
-    scoped_refptr<MessageLoopProxy> message_loop_proxy,
+    TaskRunner* task_runner,
     PlatformFile file,
     int64 length,
     const StatusCallback& callback) {
   return base::PostTaskAndReplyWithResult(
-      message_loop_proxy,
+      task_runner,
       FROM_HERE,
       Bind(&TruncatePlatformFile, file, length),
       Bind(&CallWithTranslatedParameter, callback));
@@ -387,11 +387,11 @@
 
 // static
 bool FileUtilProxy::Flush(
-    scoped_refptr<MessageLoopProxy> message_loop_proxy,
+    TaskRunner* task_runner,
     PlatformFile file,
     const StatusCallback& callback) {
   return base::PostTaskAndReplyWithResult(
-      message_loop_proxy,
+      task_runner,
       FROM_HERE,
       Bind(&FlushPlatformFile, file),
       Bind(&CallWithTranslatedParameter, callback));
@@ -399,23 +399,23 @@
 
 // static
 bool FileUtilProxy::RelayFileTask(
-    scoped_refptr<MessageLoopProxy> message_loop_proxy,
+    TaskRunner* task_runner,
     const tracked_objects::Location& from_here,
     const FileTask& file_task,
     const StatusCallback& callback) {
   return base::PostTaskAndReplyWithResult(
-      message_loop_proxy, from_here, file_task, callback);
+      task_runner, from_here, file_task, callback);
 }
 
 // static
 bool FileUtilProxy::RelayCreateOrOpen(
-    scoped_refptr<MessageLoopProxy> message_loop_proxy,
+    TaskRunner* task_runner,
     const CreateOrOpenTask& open_task,
     const CloseTask& close_task,
     const CreateOrOpenCallback& callback) {
   CreateOrOpenHelper* helper = new CreateOrOpenHelper(
-      message_loop_proxy, close_task);
-  return message_loop_proxy->PostTaskAndReply(
+      task_runner, close_task);
+  return task_runner->PostTaskAndReply(
       FROM_HERE,
       Bind(&CreateOrOpenHelper::RunWork, Unretained(helper), open_task),
       Bind(&CreateOrOpenHelper::Reply, Owned(helper), callback));
@@ -423,12 +423,12 @@
 
 // static
 bool FileUtilProxy::RelayClose(
-    scoped_refptr<MessageLoopProxy> message_loop_proxy,
+    TaskRunner* task_runner,
     const CloseTask& close_task,
     PlatformFile file_handle,
     const StatusCallback& callback) {
   return base::PostTaskAndReplyWithResult(
-      message_loop_proxy, FROM_HERE, Bind(close_task, file_handle), callback);
+      task_runner, FROM_HERE, Bind(close_task, file_handle), callback);
 }
 
 }  // namespace base
diff --git a/base/file_util_proxy.h b/base/file_util_proxy.h
index 0b2cae5..954c451 100644
--- a/base/file_util_proxy.h
+++ b/base/file_util_proxy.h
@@ -17,7 +17,7 @@
 
 namespace base {
 
-class MessageLoopProxy;
+class TaskRunner;
 class Time;
 
 // This class provides asynchronous access to common file routines.
@@ -59,7 +59,7 @@
   // callback. If PLATFORM_FILE_CREATE is set in |file_flags| it always tries to
   // create a new file at the given |file_path| and calls back with
   // PLATFORM_FILE_ERROR_FILE_EXISTS if the |file_path| already exists.
-  static bool CreateOrOpen(scoped_refptr<MessageLoopProxy> message_loop_proxy,
+  static bool CreateOrOpen(TaskRunner* task_runner,
                            const FilePath& file_path,
                            int file_flags,
                            const CreateOrOpenCallback& callback);
@@ -73,44 +73,44 @@
   // Set |additional_file_flags| to 0 for synchronous writes and set to
   // base::PLATFORM_FILE_ASYNC to support asynchronous file operations.
   static bool CreateTemporary(
-      scoped_refptr<MessageLoopProxy> message_loop_proxy,
+      TaskRunner* task_runner,
       int additional_file_flags,
       const CreateTemporaryCallback& callback);
 
   // Close the given file handle.
-  static bool Close(scoped_refptr<MessageLoopProxy> message_loop_proxy,
+  static bool Close(TaskRunner* task_runner,
                     PlatformFile,
                     const StatusCallback& callback);
 
   // Retrieves the information about a file. It is invalid to pass a null
   // callback.
   static bool GetFileInfo(
-      scoped_refptr<MessageLoopProxy> message_loop_proxy,
+      TaskRunner* task_runner,
       const FilePath& file_path,
       const GetFileInfoCallback& callback);
 
   static bool GetFileInfoFromPlatformFile(
-      scoped_refptr<MessageLoopProxy> message_loop_proxy,
+      TaskRunner* task_runner,
       PlatformFile file,
       const GetFileInfoCallback& callback);
 
   // Deletes a file or a directory.
   // It is an error to delete a non-empty directory with recursive=false.
-  static bool Delete(scoped_refptr<MessageLoopProxy> message_loop_proxy,
+  static bool Delete(TaskRunner* task_runner,
                      const FilePath& file_path,
                      bool recursive,
                      const StatusCallback& callback);
 
   // Deletes a directory and all of its contents.
   static bool RecursiveDelete(
-      scoped_refptr<MessageLoopProxy> message_loop_proxy,
+      TaskRunner* task_runner,
       const FilePath& file_path,
       const StatusCallback& callback);
 
   // Reads from a file. On success, the file pointer is moved to position
   // |offset + bytes_to_read| in the file. The callback can be null.
   static bool Read(
-      scoped_refptr<MessageLoopProxy> message_loop_proxy,
+      TaskRunner* task_runner,
       PlatformFile file,
       int64 offset,
       int bytes_to_read,
@@ -121,7 +121,7 @@
   // |offset + bytes_to_write| in the file. The callback can be null.
   // |bytes_to_write| must be greater than zero.
   static bool Write(
-      scoped_refptr<MessageLoopProxy> message_loop_proxy,
+      TaskRunner* task_runner,
       PlatformFile file,
       int64 offset,
       const char* buffer,
@@ -130,7 +130,7 @@
 
   // Touches a file. The callback can be null.
   static bool Touch(
-      scoped_refptr<MessageLoopProxy> message_loop_proxy,
+      TaskRunner* task_runner,
       PlatformFile file,
       const Time& last_access_time,
       const Time& last_modified_time,
@@ -138,7 +138,7 @@
 
   // Touches a file. The callback can be null.
   static bool Touch(
-      scoped_refptr<MessageLoopProxy> message_loop_proxy,
+      TaskRunner* task_runner,
       const FilePath& file_path,
       const Time& last_access_time,
       const Time& last_modified_time,
@@ -148,7 +148,7 @@
   // current length of the file, the file will be extended with zeroes.
   // The callback can be null.
   static bool Truncate(
-      scoped_refptr<MessageLoopProxy> message_loop_proxy,
+      TaskRunner* task_runner,
       PlatformFile file,
       int64 length,
       const StatusCallback& callback);
@@ -157,32 +157,32 @@
   // current length of the file, the file will be extended with zeroes.
   // The callback can be null.
   static bool Truncate(
-      scoped_refptr<MessageLoopProxy> message_loop_proxy,
+      TaskRunner* task_runner,
       const FilePath& path,
       int64 length,
       const StatusCallback& callback);
 
   // Flushes a file. The callback can be null.
   static bool Flush(
-      scoped_refptr<MessageLoopProxy> message_loop_proxy,
+      TaskRunner* task_runner,
       PlatformFile file,
       const StatusCallback& callback);
 
   // Relay helpers.
   static bool RelayFileTask(
-      scoped_refptr<MessageLoopProxy> message_loop_proxy,
+      TaskRunner* task_runner,
       const tracked_objects::Location& from_here,
       const FileTask& task,
       const StatusCallback& callback);
 
   static bool RelayCreateOrOpen(
-      scoped_refptr<MessageLoopProxy> message_loop_proxy,
+      TaskRunner* task_runner,
       const CreateOrOpenTask& open_task,
       const CloseTask& close_task,
       const CreateOrOpenCallback& callback);
 
   static bool RelayClose(
-      scoped_refptr<MessageLoopProxy> message_loop_proxy,
+      TaskRunner* task_runner,
       const CloseTask& close_task,
       PlatformFile,
       const StatusCallback& callback);
diff --git a/base/file_util_proxy_unittest.cc b/base/file_util_proxy_unittest.cc
new file mode 100644
index 0000000..402385a
--- /dev/null
+++ b/base/file_util_proxy_unittest.cc
@@ -0,0 +1,407 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/file_util_proxy.h"
+
+#include <map>
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "base/memory/weak_ptr.h"
+#include "base/message_loop.h"
+#include "base/platform_file.h"
+#include "base/scoped_temp_dir.h"
+#include "base/threading/thread.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace base {
+
+class FileUtilProxyTest : public testing::Test {
+ public:
+  FileUtilProxyTest()
+      : message_loop_(MessageLoop::TYPE_IO),
+        file_thread_("FileUtilProxyTestFileThread"),
+        error_(PLATFORM_FILE_OK),
+        created_(false),
+        file_(kInvalidPlatformFileValue),
+        bytes_written_(-1),
+        weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {}
+
+  virtual void SetUp() OVERRIDE {
+    ASSERT_TRUE(dir_.CreateUniqueTempDir());
+    ASSERT_TRUE(file_thread_.Start());
+  }
+
+  virtual void TearDown() OVERRIDE {
+    if (file_ != kInvalidPlatformFileValue)
+      ClosePlatformFile(file_);
+  }
+
+  void DidFinish(PlatformFileError error) {
+    error_ = error;
+    MessageLoop::current()->Quit();
+  }
+
+  void DidCreateOrOpen(PlatformFileError error,
+                       PassPlatformFile file,
+                       bool created) {
+    error_ = error;
+    file_ = file.ReleaseValue();
+    created_ = created;
+    MessageLoop::current()->Quit();
+  }
+
+  void DidCreateTemporary(PlatformFileError error,
+                          PassPlatformFile file,
+                          const FilePath& path) {
+    error_ = error;
+    file_ = file.ReleaseValue();
+    path_ = path;
+    MessageLoop::current()->Quit();
+  }
+
+  void DidGetFileInfo(PlatformFileError error,
+                      const PlatformFileInfo& file_info) {
+    error_ = error;
+    file_info_ = file_info;
+    MessageLoop::current()->Quit();
+  }
+
+  void DidRead(PlatformFileError error,
+               const char* data,
+               int bytes_read) {
+    error_ = error;
+    buffer_.resize(bytes_read);
+    memcpy(&buffer_[0], data, bytes_read);
+    MessageLoop::current()->Quit();
+  }
+
+  void DidWrite(PlatformFileError error,
+                int bytes_written) {
+    error_ = error;
+    bytes_written_ = bytes_written;
+    MessageLoop::current()->Quit();
+  }
+
+ protected:
+  PlatformFile GetTestPlatformFile(int flags) {
+    if (file_ != kInvalidPlatformFileValue)
+      return file_;
+    bool created;
+    PlatformFileError error;
+    file_ = CreatePlatformFile(test_path(), flags, &created, &error);
+    EXPECT_EQ(PLATFORM_FILE_OK, error);
+    EXPECT_NE(kInvalidPlatformFileValue, file_);
+    return file_;
+  }
+
+  TaskRunner* file_task_runner() const {
+    return file_thread_.message_loop_proxy().get();
+  }
+  const FilePath& test_dir_path() const { return dir_.path(); }
+  const FilePath test_path() const { return dir_.path().AppendASCII("test"); }
+
+  MessageLoop message_loop_;
+  Thread file_thread_;
+
+  ScopedTempDir dir_;
+  PlatformFileError error_;
+  bool created_;
+  PlatformFile file_;
+  FilePath path_;
+  PlatformFileInfo file_info_;
+  std::vector<char> buffer_;
+  int bytes_written_;
+  WeakPtrFactory<FileUtilProxyTest> weak_factory_;
+};
+
+TEST_F(FileUtilProxyTest, CreateOrOpen_Create) {
+  FileUtilProxy::CreateOrOpen(
+      file_task_runner(),
+      test_path(),
+      PLATFORM_FILE_CREATE | PLATFORM_FILE_READ,
+      Bind(&FileUtilProxyTest::DidCreateOrOpen, weak_factory_.GetWeakPtr()));
+  MessageLoop::current()->Run();
+
+  EXPECT_EQ(PLATFORM_FILE_OK, error_);
+  EXPECT_TRUE(created_);
+  EXPECT_NE(kInvalidPlatformFileValue, file_);
+  EXPECT_TRUE(file_util::PathExists(test_path()));
+}
+
+TEST_F(FileUtilProxyTest, CreateOrOpen_Open) {
+  // Creates a file.
+  file_util::WriteFile(test_path(), NULL, 0);
+  ASSERT_TRUE(file_util::PathExists(test_path()));
+
+  // Opens the created file.
+  FileUtilProxy::CreateOrOpen(
+      file_task_runner(),
+      test_path(),
+      PLATFORM_FILE_OPEN | PLATFORM_FILE_READ,
+      Bind(&FileUtilProxyTest::DidCreateOrOpen, weak_factory_.GetWeakPtr()));
+  MessageLoop::current()->Run();
+
+  EXPECT_EQ(PLATFORM_FILE_OK, error_);
+  EXPECT_FALSE(created_);
+  EXPECT_NE(kInvalidPlatformFileValue, file_);
+}
+
+TEST_F(FileUtilProxyTest, CreateOrOpen_OpenNonExistent) {
+  FileUtilProxy::CreateOrOpen(
+      file_task_runner(),
+      test_path(),
+      PLATFORM_FILE_OPEN | PLATFORM_FILE_READ,
+      Bind(&FileUtilProxyTest::DidCreateOrOpen, weak_factory_.GetWeakPtr()));
+  MessageLoop::current()->Run();
+  EXPECT_EQ(PLATFORM_FILE_ERROR_NOT_FOUND, error_);
+  EXPECT_FALSE(created_);
+  EXPECT_EQ(kInvalidPlatformFileValue, file_);
+  EXPECT_FALSE(file_util::PathExists(test_path()));
+}
+
+TEST_F(FileUtilProxyTest, Close) {
+  // Creates a file.
+  PlatformFile file = GetTestPlatformFile(
+      PLATFORM_FILE_CREATE | PLATFORM_FILE_WRITE);
+
+#if defined(OS_WIN)
+  // This fails on Windows if the file is not closed.
+  EXPECT_FALSE(file_util::Move(test_path(),
+                               test_dir_path().AppendASCII("new")));
+#endif
+
+  FileUtilProxy::Close(
+      file_task_runner(),
+      file,
+      Bind(&FileUtilProxyTest::DidFinish, weak_factory_.GetWeakPtr()));
+  MessageLoop::current()->Run();
+  EXPECT_EQ(PLATFORM_FILE_OK, error_);
+
+  // Now it should pass on all platforms.
+  EXPECT_TRUE(file_util::Move(test_path(), test_dir_path().AppendASCII("new")));
+}
+
+TEST_F(FileUtilProxyTest, CreateTemporary) {
+  FileUtilProxy::CreateTemporary(
+      file_task_runner(), 0 /* additional_file_flags */,
+      Bind(&FileUtilProxyTest::DidCreateTemporary, weak_factory_.GetWeakPtr()));
+  MessageLoop::current()->Run();
+  EXPECT_EQ(PLATFORM_FILE_OK, error_);
+  EXPECT_TRUE(file_util::PathExists(path_));
+  EXPECT_NE(kInvalidPlatformFileValue, file_);
+
+  // The file should be writable.
+#if defined(OS_WIN)
+   HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+   OVERLAPPED overlapped = {0};
+   overlapped.hEvent = hEvent;
+   DWORD bytes_written;
+   if (!::WriteFile(file_, "test", 4, &bytes_written, &overlapped)) {
+     // Temporary file is created with ASYNC flag, so WriteFile may return 0
+     // with ERROR_IO_PENDING.
+     EXPECT_EQ(ERROR_IO_PENDING, GetLastError());
+     GetOverlappedResult(file_, &overlapped, &bytes_written, TRUE);
+   }
+   EXPECT_EQ(4, bytes_written);
+#else
+  // On POSIX ASYNC flag does not affect synchronous read/write behavior.
+  EXPECT_EQ(4, WritePlatformFile(file_, 0, "test", 4));
+#endif
+  EXPECT_TRUE(ClosePlatformFile(file_));
+  file_ = kInvalidPlatformFileValue;
+
+  // Make sure the written data can be read from the returned path.
+  std::string data;
+  EXPECT_TRUE(file_util::ReadFileToString(path_, &data));
+  EXPECT_EQ("test", data);
+}
+
+TEST_F(FileUtilProxyTest, GetFileInfo_File) {
+  // Setup.
+  ASSERT_EQ(4, file_util::WriteFile(test_path(), "test", 4));
+  PlatformFileInfo expected_info;
+  file_util::GetFileInfo(test_path(), &expected_info);
+
+  // Run.
+  FileUtilProxy::GetFileInfo(
+      file_task_runner(),
+      test_path(),
+      Bind(&FileUtilProxyTest::DidGetFileInfo, weak_factory_.GetWeakPtr()));
+  MessageLoop::current()->Run();
+
+  // Verify.
+  EXPECT_EQ(PLATFORM_FILE_OK, error_);
+  EXPECT_EQ(expected_info.size, file_info_.size);
+  EXPECT_EQ(expected_info.is_directory, file_info_.is_directory);
+  EXPECT_EQ(expected_info.is_symbolic_link, file_info_.is_symbolic_link);
+  EXPECT_EQ(expected_info.last_modified, file_info_.last_modified);
+  EXPECT_EQ(expected_info.last_accessed, file_info_.last_accessed);
+  EXPECT_EQ(expected_info.creation_time, file_info_.creation_time);
+}
+
+TEST_F(FileUtilProxyTest, GetFileInfo_Directory) {
+  // Setup.
+  ASSERT_TRUE(file_util::CreateDirectory(test_path()));
+  PlatformFileInfo expected_info;
+  file_util::GetFileInfo(test_path(), &expected_info);
+
+  // Run.
+  FileUtilProxy::GetFileInfo(
+      file_task_runner(),
+      test_path(),
+      Bind(&FileUtilProxyTest::DidGetFileInfo, weak_factory_.GetWeakPtr()));
+  MessageLoop::current()->Run();
+
+  // Verify.
+  EXPECT_EQ(PLATFORM_FILE_OK, error_);
+  EXPECT_EQ(expected_info.size, file_info_.size);
+  EXPECT_EQ(expected_info.is_directory, file_info_.is_directory);
+  EXPECT_EQ(expected_info.is_symbolic_link, file_info_.is_symbolic_link);
+  EXPECT_EQ(expected_info.last_modified, file_info_.last_modified);
+  EXPECT_EQ(expected_info.last_accessed, file_info_.last_accessed);
+  EXPECT_EQ(expected_info.creation_time, file_info_.creation_time);
+}
+
+TEST_F(FileUtilProxyTest, Read) {
+  // Setup.
+  const char expected_data[] = "bleh";
+  int expected_bytes = arraysize(expected_data);
+  ASSERT_EQ(expected_bytes,
+            file_util::WriteFile(test_path(), expected_data, expected_bytes));
+
+  // Run.
+  FileUtilProxy::Read(
+      file_task_runner(),
+      GetTestPlatformFile(PLATFORM_FILE_OPEN | PLATFORM_FILE_READ),
+      0,  // offset
+      128,
+      Bind(&FileUtilProxyTest::DidRead, weak_factory_.GetWeakPtr()));
+  MessageLoop::current()->Run();
+
+  // Verify.
+  EXPECT_EQ(PLATFORM_FILE_OK, error_);
+  EXPECT_EQ(expected_bytes, static_cast<int>(buffer_.size()));
+  for (size_t i = 0; i < buffer_.size(); ++i) {
+    EXPECT_EQ(expected_data[i], buffer_[i]);
+  }
+}
+
+TEST_F(FileUtilProxyTest, WriteAndFlush) {
+  const char data[] = "foo!";
+  int data_bytes = ARRAYSIZE_UNSAFE(data);
+  PlatformFile file = GetTestPlatformFile(
+      PLATFORM_FILE_CREATE | PLATFORM_FILE_WRITE);
+
+  FileUtilProxy::Write(
+      file_task_runner(),
+      file,
+      0,  // offset
+      data,
+      data_bytes,
+      Bind(&FileUtilProxyTest::DidWrite, weak_factory_.GetWeakPtr()));
+  MessageLoop::current()->Run();
+  EXPECT_EQ(PLATFORM_FILE_OK, error_);
+  EXPECT_EQ(data_bytes, bytes_written_);
+
+  // Flush the written data.  (So that the following read should always
+  // succeed.  On some platforms it may work with or without this flush.)
+  FileUtilProxy::Flush(
+      file_task_runner(),
+      file,
+      Bind(&FileUtilProxyTest::DidFinish, weak_factory_.GetWeakPtr()));
+  MessageLoop::current()->Run();
+  EXPECT_EQ(PLATFORM_FILE_OK, error_);
+
+  // Verify the written data.
+  char buffer[10];
+  EXPECT_EQ(data_bytes, file_util::ReadFile(test_path(), buffer, data_bytes));
+  for (int i = 0; i < data_bytes; ++i) {
+    EXPECT_EQ(data[i], buffer[i]);
+  }
+}
+
+TEST_F(FileUtilProxyTest, Touch) {
+  Time last_accessed_time = Time::Now() - TimeDelta::FromDays(12345);
+  Time last_modified_time = Time::Now() - TimeDelta::FromHours(98765);
+
+  FileUtilProxy::Touch(
+      file_task_runner(),
+      GetTestPlatformFile(PLATFORM_FILE_CREATE |
+                          PLATFORM_FILE_WRITE |
+                          PLATFORM_FILE_WRITE_ATTRIBUTES),
+      last_accessed_time,
+      last_modified_time,
+      Bind(&FileUtilProxyTest::DidFinish, weak_factory_.GetWeakPtr()));
+  MessageLoop::current()->Run();
+  EXPECT_EQ(PLATFORM_FILE_OK, error_);
+
+  PlatformFileInfo info;
+  file_util::GetFileInfo(test_path(), &info);
+
+  // The returned values may only have the seconds precision, so we cast
+  // the double values to int here.
+  EXPECT_EQ(static_cast<int>(last_modified_time.ToDoubleT()),
+            static_cast<int>(info.last_modified.ToDoubleT()));
+  EXPECT_EQ(static_cast<int>(last_accessed_time.ToDoubleT()),
+            static_cast<int>(info.last_accessed.ToDoubleT()));
+}
+
+TEST_F(FileUtilProxyTest, Truncate_Shrink) {
+  // Setup.
+  const char kTestData[] = "0123456789";
+  ASSERT_EQ(10, file_util::WriteFile(test_path(), kTestData, 10));
+  PlatformFileInfo info;
+  file_util::GetFileInfo(test_path(), &info);
+  ASSERT_EQ(10, info.size);
+
+  // Run.
+  FileUtilProxy::Truncate(
+      file_task_runner(),
+      GetTestPlatformFile(PLATFORM_FILE_OPEN | PLATFORM_FILE_WRITE),
+      7,
+      Bind(&FileUtilProxyTest::DidFinish, weak_factory_.GetWeakPtr()));
+  MessageLoop::current()->Run();
+
+  // Verify.
+  file_util::GetFileInfo(test_path(), &info);
+  ASSERT_EQ(7, info.size);
+
+  char buffer[7];
+  EXPECT_EQ(7, file_util::ReadFile(test_path(), buffer, 7));
+  int i = 0;
+  for (; i < 7; ++i)
+    EXPECT_EQ(kTestData[i], buffer[i]);
+}
+
+TEST_F(FileUtilProxyTest, Truncate_Expand) {
+  // Setup.
+  const char kTestData[] = "9876543210";
+  ASSERT_EQ(10, file_util::WriteFile(test_path(), kTestData, 10));
+  PlatformFileInfo info;
+  file_util::GetFileInfo(test_path(), &info);
+  ASSERT_EQ(10, info.size);
+
+  // Run.
+  FileUtilProxy::Truncate(
+      file_task_runner(),
+      GetTestPlatformFile(PLATFORM_FILE_OPEN | PLATFORM_FILE_WRITE),
+      53,
+      Bind(&FileUtilProxyTest::DidFinish, weak_factory_.GetWeakPtr()));
+  MessageLoop::current()->Run();
+
+  // Verify.
+  file_util::GetFileInfo(test_path(), &info);
+  ASSERT_EQ(53, info.size);
+
+  char buffer[53];
+  EXPECT_EQ(53, file_util::ReadFile(test_path(), buffer, 53));
+  int i = 0;
+  for (; i < 10; ++i)
+    EXPECT_EQ(kTestData[i], buffer[i]);
+  for (; i < 53; ++i)
+    EXPECT_EQ(0, buffer[i]);
+}
+
+}  // namespace base