Base: Move platform_file.* to files/file.*

PlatformFile has grown beyond the initial expectations and it doesn't make
sense to continue supporting individual function wrappers instead of a
proper file class.

BUG=322664
TEST=base_unittests
R=brettw@chromium.org

Review URL: https://codereview.chromium.org/93513002

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


CrOS-Libchrome-Original-Commit: f62ac7d5fc78bf1fa97895912dc6554d699209f7
diff --git a/base/files/file.cc b/base/files/file.cc
index bb411b8..4902f15 100644
--- a/base/files/file.cc
+++ b/base/files/file.cc
@@ -2,30 +2,63 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "base/files/file.h"
+
+// TODO(rvargas): remove this (needed for kInvalidPlatformFileValue).
 #include "base/platform_file.h"
 
 namespace base {
 
-PlatformFileInfo::PlatformFileInfo()
+File::Info::Info()
     : size(0),
       is_directory(false),
       is_symbolic_link(false) {
 }
 
-PlatformFileInfo::~PlatformFileInfo() {}
+File::Info::~Info() {
+}
+
+File::File()
+    : file_(kInvalidPlatformFileValue),
+      error_(FILE_OK),
+      created_(false),
+      async_(false) {
+}
 
 #if !defined(OS_NACL)
-PlatformFile CreatePlatformFile(const FilePath& name,
-                                int flags,
-                                bool* created,
-                                PlatformFileError* error) {
+File::File(const FilePath& name, uint32 flags)
+    : file_(kInvalidPlatformFileValue),
+      error_(FILE_OK),
+      created_(false),
+      async_(false) {
   if (name.ReferencesParent()) {
-    if (error)
-      *error = PLATFORM_FILE_ERROR_ACCESS_DENIED;
-    return kInvalidPlatformFileValue;
+    error_ = FILE_ERROR_ACCESS_DENIED;
+    return;
   }
-  return CreatePlatformFileUnsafe(name, flags, created, error);
+  CreateBaseFileUnsafe(name, flags);
 }
 #endif
 
+File::File(RValue other)
+    : file_(other.object->TakePlatformFile()),
+      error_(other.object->error()),
+      created_(other.object->created()),
+      async_(other.object->async_) {
+}
+
+File::~File() {
+  Close();
+}
+
+File& File::operator=(RValue other) {
+  if (this != other.object) {
+    Close();
+    SetPlatformFile(other.object->TakePlatformFile());
+    error_ = other.object->error();
+    created_ = other.object->created();
+    async_ = other.object->async_;
+  }
+  return *this;
+}
+
 }  // namespace base
diff --git a/base/files/file.h b/base/files/file.h
index 62b5c35..d1e0e8c 100644
--- a/base/files/file.h
+++ b/base/files/file.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef BASE_PLATFORM_FILE_H_
-#define BASE_PLATFORM_FILE_H_
+#ifndef BASE_FILES_FILE_H_
+#define BASE_FILES_FILE_H_
 
 #include "build/build_config.h"
 #if defined(OS_WIN)
@@ -15,270 +15,266 @@
 #include "base/base_export.h"
 #include "base/basictypes.h"
 #include "base/files/file_path.h"
+#include "base/move.h"
 #include "base/time/time.h"
 
+#if defined(OS_WIN)
+#include "base/win/scoped_handle.h"
+#endif
+
 namespace base {
 
-// PLATFORM_FILE_(OPEN|CREATE).* are mutually exclusive. You should specify
-// exactly one of the five (possibly combining with other flags) when opening
-// or creating a file.
-// PLATFORM_FILE_(WRITE|APPEND) are mutually exclusive. This is so that APPEND
-// behavior will be consistent with O_APPEND on POSIX.
-// PLATFORM_FILE_EXCLUSIVE_(READ|WRITE) only grant exclusive access to the file
-// on creation on POSIX; for existing files, consider using LockPlatformFile().
-enum PlatformFileFlags {
-  PLATFORM_FILE_OPEN = 1 << 0,             // Opens a file, only if it exists.
-  PLATFORM_FILE_CREATE = 1 << 1,           // Creates a new file, only if it
-                                           // does not already exist.
-  PLATFORM_FILE_OPEN_ALWAYS = 1 << 2,      // May create a new file.
-  PLATFORM_FILE_CREATE_ALWAYS = 1 << 3,    // May overwrite an old file.
-  PLATFORM_FILE_OPEN_TRUNCATED = 1 << 4,   // Opens a file and truncates it,
-                                           // only if it exists.
-  PLATFORM_FILE_READ = 1 << 5,
-  PLATFORM_FILE_WRITE = 1 << 6,
-  PLATFORM_FILE_APPEND = 1 << 7,
-  PLATFORM_FILE_EXCLUSIVE_READ = 1 << 8,   // EXCLUSIVE is opposite of Windows
-                                           // SHARE
-  PLATFORM_FILE_EXCLUSIVE_WRITE = 1 << 9,
-  PLATFORM_FILE_ASYNC = 1 << 10,
-  PLATFORM_FILE_TEMPORARY = 1 << 11,       // Used on Windows only
-  PLATFORM_FILE_HIDDEN = 1 << 12,          // Used on Windows only
-  PLATFORM_FILE_DELETE_ON_CLOSE = 1 << 13,
-
-  PLATFORM_FILE_WRITE_ATTRIBUTES = 1 << 14,  // Used on Windows only
-
-  PLATFORM_FILE_SHARE_DELETE = 1 << 15,      // Used on Windows only
-
-  PLATFORM_FILE_TERMINAL_DEVICE = 1 << 16,   // Serial port flags
-  PLATFORM_FILE_BACKUP_SEMANTICS = 1 << 17,  // Used on Windows only
-
-  PLATFORM_FILE_EXECUTE = 1 << 18,           // Used on Windows only
-};
-
-// This enum has been recorded in multiple histograms. If the order of the
-// fields needs to change, please ensure that those histograms are obsolete or
-// have been moved to a different enum.
-//
-// PLATFORM_FILE_ERROR_ACCESS_DENIED is returned when a call fails because of
-// a filesystem restriction. PLATFORM_FILE_ERROR_SECURITY is returned when a
-// browser policy doesn't allow the operation to be executed.
-enum PlatformFileError {
-  PLATFORM_FILE_OK = 0,
-  PLATFORM_FILE_ERROR_FAILED = -1,
-  PLATFORM_FILE_ERROR_IN_USE = -2,
-  PLATFORM_FILE_ERROR_EXISTS = -3,
-  PLATFORM_FILE_ERROR_NOT_FOUND = -4,
-  PLATFORM_FILE_ERROR_ACCESS_DENIED = -5,
-  PLATFORM_FILE_ERROR_TOO_MANY_OPENED = -6,
-  PLATFORM_FILE_ERROR_NO_MEMORY = -7,
-  PLATFORM_FILE_ERROR_NO_SPACE = -8,
-  PLATFORM_FILE_ERROR_NOT_A_DIRECTORY = -9,
-  PLATFORM_FILE_ERROR_INVALID_OPERATION = -10,
-  PLATFORM_FILE_ERROR_SECURITY = -11,
-  PLATFORM_FILE_ERROR_ABORT = -12,
-  PLATFORM_FILE_ERROR_NOT_A_FILE = -13,
-  PLATFORM_FILE_ERROR_NOT_EMPTY = -14,
-  PLATFORM_FILE_ERROR_INVALID_URL = -15,
-  PLATFORM_FILE_ERROR_IO = -16,
-  // Put new entries here and increment PLATFORM_FILE_ERROR_MAX.
-  PLATFORM_FILE_ERROR_MAX = -17
-};
-
-// This explicit mapping matches both FILE_ on Windows and SEEK_ on Linux.
-enum PlatformFileWhence {
-  PLATFORM_FILE_FROM_BEGIN   = 0,
-  PLATFORM_FILE_FROM_CURRENT = 1,
-  PLATFORM_FILE_FROM_END     = 2
-};
-
-// Used to hold information about a given file.
-// If you add more fields to this structure (platform-specific fields are OK),
-// make sure to update all functions that use it in file_util_{win|posix}.cc
-// too, and the ParamTraits<base::PlatformFileInfo> implementation in
-// chrome/common/common_param_traits.cc.
-struct BASE_EXPORT PlatformFileInfo {
-  PlatformFileInfo();
-  ~PlatformFileInfo();
-
-  // The size of the file in bytes.  Undefined when is_directory is true.
-  int64 size;
-
-  // True if the file corresponds to a directory.
-  bool is_directory;
-
-  // True if the file corresponds to a symbolic link.
-  bool is_symbolic_link;
-
-  // The last modified time of a file.
-  base::Time last_modified;
-
-  // The last accessed time of a file.
-  base::Time last_accessed;
-
-  // The creation time of a file.
-  base::Time creation_time;
-};
-
 #if defined(OS_WIN)
 typedef HANDLE PlatformFile;
-const PlatformFile kInvalidPlatformFileValue = INVALID_HANDLE_VALUE;
-BASE_EXPORT PlatformFileError LastErrorToPlatformFileError(DWORD last_error);
 #elif defined(OS_POSIX)
 typedef int PlatformFile;
-const PlatformFile kInvalidPlatformFileValue = -1;
-BASE_EXPORT PlatformFileError ErrnoToPlatformFileError(int saved_errno);
 #endif
 
-// Creates or opens the given file. If |created| is provided, it will be set to
-// true if a new file was created [or an old one truncated to zero length to
-// simulate a new file, which can happen with PLATFORM_FILE_CREATE_ALWAYS], and
-// false otherwise.  |error| can be NULL.
+
+// Thin wrapper around an OS-level file.
+// Note that this class does not provide any support for asynchronous IO, other
+// than the ability to create asynchronous handles on Windows.
 //
-// This function fails with 'access denied' if the |name| contains path
-// traversal ('..') components.
-BASE_EXPORT PlatformFile CreatePlatformFile(const FilePath& name,
-                                            int flags,
-                                            bool* created,
-                                            PlatformFileError* error);
+// Note about const: this class does not attempt to determine if the underlying
+// file system object is affected by a particular method in order to consider
+// that method const or not. Only methods that deal with member variables in an
+// obvious non-modifying way are marked as const. Any method that forward calls
+// to the OS is not considered const, even if there is no apparent change to
+// member variables.
+class BASE_EXPORT File {
+  MOVE_ONLY_TYPE_FOR_CPP_03(File, RValue)
 
-// Same as CreatePlatformFile but allows paths with traversal (like \..\)
-// components. Use only with extreme care.
-BASE_EXPORT PlatformFile CreatePlatformFileUnsafe(const FilePath& name,
-                                                  int flags,
-                                                  bool* created,
-                                                  PlatformFileError* error);
-
-BASE_EXPORT FILE* FdopenPlatformFile(PlatformFile file, const char* mode);
-
-// Closes a file handle. Returns |true| on success and |false| otherwise.
-BASE_EXPORT bool ClosePlatformFile(PlatformFile file);
-
-// Changes current position in the file to an |offset| relative to an origin
-// defined by |whence|. Returns the resultant current position in the file
-// (relative to the start) or -1 in case of error.
-BASE_EXPORT int64 SeekPlatformFile(PlatformFile file,
-                                   PlatformFileWhence whence,
-                                   int64 offset);
-
-// Reads the given number of bytes (or until EOF is reached) starting with the
-// given offset. Returns the number of bytes read, or -1 on error. Note that
-// this function makes a best effort to read all data on all platforms, so it is
-// not intended for stream oriented files but instead for cases when the normal
-// expectation is that actually |size| bytes are read unless there is an error.
-BASE_EXPORT int ReadPlatformFile(PlatformFile file, int64 offset,
-                                 char* data, int size);
-
-// Same as above but without seek.
-BASE_EXPORT int ReadPlatformFileAtCurrentPos(PlatformFile file,
-                                             char* data, int size);
-
-// Reads the given number of bytes (or until EOF is reached) starting with the
-// given offset, but does not make any effort to read all data on all platforms.
-// Returns the number of bytes read, or -1 on error.
-BASE_EXPORT int ReadPlatformFileNoBestEffort(PlatformFile file, int64 offset,
-                                             char* data, int size);
-
-// Same as above but without seek.
-BASE_EXPORT int ReadPlatformFileCurPosNoBestEffort(PlatformFile file,
-                                                   char* data, int size);
-
-// Writes the given buffer into the file at the given offset, overwritting any
-// data that was previously there. Returns the number of bytes written, or -1
-// on error. Note that this function makes a best effort to write all data on
-// all platforms.
-// Ignores the offset and writes to the end of the file if the file was opened
-// with PLATFORM_FILE_APPEND.
-BASE_EXPORT int WritePlatformFile(PlatformFile file, int64 offset,
-                                  const char* data, int size);
-
-// Save as above but without seek.
-BASE_EXPORT int WritePlatformFileAtCurrentPos(PlatformFile file,
-                                              const char* data, int size);
-
-// Save as above but does not make any effort to write all data on all
-// platforms. Returns the number of bytes written, or -1 on error.
-BASE_EXPORT int WritePlatformFileCurPosNoBestEffort(PlatformFile file,
-                                                    const char* data, int size);
-
-// Truncates the given file to the given length. If |length| is greater than
-// the current size of the file, the file is extended with zeros. If the file
-// doesn't exist, |false| is returned.
-BASE_EXPORT bool TruncatePlatformFile(PlatformFile file, int64 length);
-
-// Flushes the buffers of the given file.
-BASE_EXPORT bool FlushPlatformFile(PlatformFile file);
-
-// Touches the given file.
-BASE_EXPORT bool TouchPlatformFile(PlatformFile file,
-                                   const Time& last_access_time,
-                                   const Time& last_modified_time);
-
-// Returns some information for the given file.
-BASE_EXPORT bool GetPlatformFileInfo(PlatformFile file, PlatformFileInfo* info);
-
-// Attempts to take an exclusive write lock on the file. Returns immediately
-// (i.e. does not wait for another process to unlock the file). If the lock
-// was obtained, the result will be PLATFORM_FILE_OK. A lock only guarantees
-// that other processes may not also take a lock on the same file with the
-// same API - it may still be opened, renamed, unlinked, etc.
-//
-// Common semantics:
-//  * Locks are held by processes, but not inherited by child processes.
-//  * Locks are released by the OS on file handle close or process termination.
-//  * Locks are reliable only on local filesystems.
-//  * Duplicated file handles may also write to locked files.
-// Windows-specific semantics:
-//  * Locks are mandatory for read/write APIs, advisory for mapping APIs.
-//  * Within a process, locking the same file (by the same or new handle)
-//    will fail.
-// POSIX-specific semantics:
-//  * Locks are advisory only.
-//  * Within a process, locking the same file (by the same or new handle)
-//    will succeed.
-//  * Closing any descriptor on a given file releases the lock.
-BASE_EXPORT PlatformFileError LockPlatformFile(PlatformFile file);
-
-// Unlock a file previously locked with LockPlatformFile.
-BASE_EXPORT PlatformFileError UnlockPlatformFile(PlatformFile file);
-
-// Use this class to pass ownership of a PlatformFile to a receiver that may or
-// may not want to accept it.  This class does not own the storage for the
-// PlatformFile.
-//
-// EXAMPLE:
-//
-//  void MaybeProcessFile(PassPlatformFile pass_file) {
-//    if (...) {
-//      PlatformFile file = pass_file.ReleaseValue();
-//      // Now, we are responsible for closing |file|.
-//    }
-//  }
-//
-//  void OpenAndMaybeProcessFile(const FilePath& path) {
-//    PlatformFile file = CreatePlatformFile(path, ...);
-//    MaybeProcessFile(PassPlatformFile(&file));
-//    if (file != kInvalidPlatformFileValue)
-//      ClosePlatformFile(file);
-//  }
-//
-class BASE_EXPORT PassPlatformFile {
  public:
-  explicit PassPlatformFile(PlatformFile* value) : value_(value) {
-  }
+  // FLAG_(OPEN|CREATE).* are mutually exclusive. You should specify exactly one
+  // of the five (possibly combining with other flags) when opening or creating
+  // a file.
+  // FLAG_(WRITE|APPEND) are mutually exclusive. This is so that APPEND behavior
+  // will be consistent with O_APPEND on POSIX.
+  // FLAG_EXCLUSIVE_(READ|WRITE) only grant exclusive access to the file on
+  // creation on POSIX; for existing files, consider using Lock().
+  enum Flags {
+    FLAG_OPEN = 1 << 0,             // Opens a file, only if it exists.
+    FLAG_CREATE = 1 << 1,           // Creates a new file, only if it does not
+                                    // already exist.
+    FLAG_OPEN_ALWAYS = 1 << 2,      // May create a new file.
+    FLAG_CREATE_ALWAYS = 1 << 3,    // May overwrite an old file.
+    FLAG_OPEN_TRUNCATED = 1 << 4,   // Opens a file and truncates it, only if it
+                                    // exists.
+    FLAG_READ = 1 << 5,
+    FLAG_WRITE = 1 << 6,
+    FLAG_APPEND = 1 << 7,
+    FLAG_EXCLUSIVE_READ = 1 << 8,   // EXCLUSIVE is opposite of Windows SHARE.
+    FLAG_EXCLUSIVE_WRITE = 1 << 9,
+    FLAG_ASYNC = 1 << 10,
+    FLAG_TEMPORARY = 1 << 11,       // Used on Windows only.
+    FLAG_HIDDEN = 1 << 12,          // Used on Windows only.
+    FLAG_DELETE_ON_CLOSE = 1 << 13,
+    FLAG_WRITE_ATTRIBUTES = 1 << 14,  // Used on Windows only.
+    FLAG_SHARE_DELETE = 1 << 15,      // Used on Windows only.
+    FLAG_TERMINAL_DEVICE = 1 << 16,   // Serial port flags.
+    FLAG_BACKUP_SEMANTICS = 1 << 17,  // Used on Windows only.
+    FLAG_EXECUTE = 1 << 18,           // Used on Windows only.
+  };
 
-  // Called to retrieve the PlatformFile stored in this object.  The caller
-  // gains ownership of the PlatformFile and is now responsible for closing it.
-  // Any subsequent calls to this method will return an invalid PlatformFile.
-  PlatformFile ReleaseValue() {
-    PlatformFile temp = *value_;
-    *value_ = kInvalidPlatformFileValue;
-    return temp;
-  }
+  // This enum has been recorded in multiple histograms. If the order of the
+  // fields needs to change, please ensure that those histograms are obsolete or
+  // have been moved to a different enum.
+  //
+  // FILE_ERROR_ACCESS_DENIED is returned when a call fails because of a
+  // filesystem restriction. FILE_ERROR_SECURITY is returned when a browser
+  // policy doesn't allow the operation to be executed.
+  enum Error {
+    FILE_OK = 0,
+    FILE_ERROR_FAILED = -1,
+    FILE_ERROR_IN_USE = -2,
+    FILE_ERROR_EXISTS = -3,
+    FILE_ERROR_NOT_FOUND = -4,
+    FILE_ERROR_ACCESS_DENIED = -5,
+    FILE_ERROR_TOO_MANY_OPENED = -6,
+    FILE_ERROR_NO_MEMORY = -7,
+    FILE_ERROR_NO_SPACE = -8,
+    FILE_ERROR_NOT_A_DIRECTORY = -9,
+    FILE_ERROR_INVALID_OPERATION = -10,
+    FILE_ERROR_SECURITY = -11,
+    FILE_ERROR_ABORT = -12,
+    FILE_ERROR_NOT_A_FILE = -13,
+    FILE_ERROR_NOT_EMPTY = -14,
+    FILE_ERROR_INVALID_URL = -15,
+    FILE_ERROR_IO = -16,
+    // Put new entries here and increment FILE_ERROR_MAX.
+    FILE_ERROR_MAX = -17
+  };
+
+  // This explicit mapping matches both FILE_ on Windows and SEEK_ on Linux.
+  enum Whence {
+    FROM_BEGIN   = 0,
+    FROM_CURRENT = 1,
+    FROM_END     = 2
+  };
+
+  // Used to hold information about a given file.
+  // If you add more fields to this structure (platform-specific fields are OK),
+  // make sure to update all functions that use it in file_util_{win|posix}.cc
+  // too, and the ParamTraits<base::PlatformFileInfo> implementation in
+  // chrome/common/common_param_traits.cc.
+  struct BASE_EXPORT Info {
+    Info();
+    ~Info();
+
+    // The size of the file in bytes.  Undefined when is_directory is true.
+    int64 size;
+
+    // True if the file corresponds to a directory.
+    bool is_directory;
+
+    // True if the file corresponds to a symbolic link.
+    bool is_symbolic_link;
+
+    // The last modified time of a file.
+    base::Time last_modified;
+
+    // The last accessed time of a file.
+    base::Time last_accessed;
+
+    // The creation time of a file.
+    base::Time creation_time;
+  };
+
+  File();
+
+  // Creates or opens the given file. This will fail with 'access denied' if the
+  // |name| contains path traversal ('..') components.
+  File(const FilePath& name, uint32 flags);
+
+  // Takes ownership of |platform_file|.
+  explicit File(PlatformFile platform_file);
+
+  // Move constructor for C++03 move emulation of this type.
+  File(RValue other);
+
+  ~File();
+
+  // Move operator= for C++03 move emulation of this type.
+  File& operator=(RValue other);
+
+  // Creates or opens the given file, allowing paths with traversal ('..')
+  // components. Use only with extreme care.
+  void CreateBaseFileUnsafe(const FilePath& name, uint32 flags);
+
+  bool IsValid() const;
+
+  // Returns true if a new file was created (or an old one truncated to zero
+  // length to simulate a new file, which can happen with
+  // FLAG_CREATE_ALWAYS), and false otherwise.
+  bool created() const { return created_; }
+
+  // Returns the OS result of opening this file.
+  Error error() const { return error_; }
+
+  PlatformFile GetPlatformFile() const { return file_; }
+  PlatformFile TakePlatformFile();
+
+  // Destroying this object closes the file automatically.
+  void Close();
+
+  // Changes current position in the file to an |offset| relative to an origin
+  // defined by |whence|. Returns the resultant current position in the file
+  // (relative to the start) or -1 in case of error.
+  int64 Seek(Whence whence, int64 offset);
+
+  // Reads the given number of bytes (or until EOF is reached) starting with the
+  // given offset. Returns the number of bytes read, or -1 on error. Note that
+  // this function makes a best effort to read all data on all platforms, so it
+  // is not intended for stream oriented files but instead for cases when the
+  // normal expectation is that actually |size| bytes are read unless there is
+  // an error.
+  int Read(int64 offset, char* data, int size);
+
+  // Same as above but without seek.
+  int ReadAtCurrentPos(char* data, int size);
+
+  // Reads the given number of bytes (or until EOF is reached) starting with the
+  // given offset, but does not make any effort to read all data on all
+  // platforms. Returns the number of bytes read, or -1 on error.
+  int ReadNoBestEffort(int64 offset, char* data, int size);
+
+  // Same as above but without seek.
+  int ReadAtCurrentPosNoBestEffort(char* data, int size);
+
+  // Writes the given buffer into the file at the given offset, overwritting any
+  // data that was previously there. Returns the number of bytes written, or -1
+  // on error. Note that this function makes a best effort to write all data on
+  // all platforms.
+  // Ignores the offset and writes to the end of the file if the file was opened
+  // with FLAG_APPEND.
+  int Write(int64 offset, const char* data, int size);
+
+  // Save as above but without seek.
+  int WriteAtCurrentPos(const char* data, int size);
+
+  // Save as above but does not make any effort to write all data on all
+  // platforms. Returns the number of bytes written, or -1 on error.
+  int WriteAtCurrentPosNoBestEffort(const char* data, int size);
+
+  // Truncates the file to the given length. If |length| is greater than the
+  // current size of the file, the file is extended with zeros. If the file
+  // doesn't exist, |false| is returned.
+  bool Truncate(int64 length);
+
+  // Flushes the buffers.
+  bool Flush();
+
+  // Updates the file times.
+  bool SetTimes(Time last_access_time, Time last_modified_time);
+
+  // Returns some basic information for the given file.
+  bool GetInfo(Info* info);
+
+  // Attempts to take an exclusive write lock on the file. Returns immediately
+  // (i.e. does not wait for another process to unlock the file). If the lock
+  // was obtained, the result will be FILE_OK. A lock only guarantees
+  // that other processes may not also take a lock on the same file with the
+  // same API - it may still be opened, renamed, unlinked, etc.
+  //
+  // Common semantics:
+  //  * Locks are held by processes, but not inherited by child processes.
+  //  * Locks are released by the OS on file close or process termination.
+  //  * Locks are reliable only on local filesystems.
+  //  * Duplicated file handles may also write to locked files.
+  // Windows-specific semantics:
+  //  * Locks are mandatory for read/write APIs, advisory for mapping APIs.
+  //  * Within a process, locking the same file (by the same or new handle)
+  //    will fail.
+  // POSIX-specific semantics:
+  //  * Locks are advisory only.
+  //  * Within a process, locking the same file (by the same or new handle)
+  //    will succeed.
+  //  * Closing any descriptor on a given file releases the lock.
+  Error Lock();
+
+  // Unlock a file previously locked.
+  Error Unlock();
+
+#if defined(OS_WIN)
+  static Error OSErrorToFileError(DWORD last_error);
+#elif defined(OS_POSIX)
+  static Error OSErrorToFileError(int saved_errno);
+#endif
 
  private:
-  PlatformFile* value_;
+  void SetPlatformFile(PlatformFile file);
+
+#if defined(OS_WIN)
+  win::ScopedHandle file_;
+#elif defined(OS_POSIX)
+  PlatformFile file_;
+#endif
+
+  Error error_;
+  bool created_;
+  bool async_;
 };
 
 }  // namespace base
 
-#endif  // BASE_PLATFORM_FILE_H_
+#endif  // BASE_FILES_FILE_H_
diff --git a/base/files/file_posix.cc b/base/files/file_posix.cc
index 028a382..9d97c33 100644
--- a/base/files/file_posix.cc
+++ b/base/files/file_posix.cc
@@ -2,16 +2,18 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/platform_file.h"
+#include "base/files/file.h"
 
-#include <fcntl.h>
 #include <errno.h>
+#include <fcntl.h>
 #include <sys/stat.h>
 #include <unistd.h>
 
 #include "base/files/file_path.h"
 #include "base/logging.h"
 #include "base/metrics/sparse_histogram.h"
+// TODO(rvargas): remove this (needed for kInvalidPlatformFileValue).
+#include "base/platform_file.h"
 #include "base/posix/eintr_wrapper.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread_restrictions.h"
@@ -23,9 +25,9 @@
 namespace base {
 
 // Make sure our Whence mappings match the system headers.
-COMPILE_ASSERT(PLATFORM_FILE_FROM_BEGIN   == SEEK_SET &&
-               PLATFORM_FILE_FROM_CURRENT == SEEK_CUR &&
-               PLATFORM_FILE_FROM_END     == SEEK_END, whence_matches_system);
+COMPILE_ASSERT(File::FROM_BEGIN   == SEEK_SET &&
+               File::FROM_CURRENT == SEEK_CUR &&
+               File::FROM_END     == SEEK_END, whence_matches_system);
 
 namespace {
 
@@ -75,15 +77,15 @@
 #endif
 }
 
-static PlatformFileError CallFctnlFlock(PlatformFile file, bool do_lock) {
+static File::Error CallFctnlFlock(PlatformFile file, bool do_lock) {
   struct flock lock;
   lock.l_type = F_WRLCK;
   lock.l_whence = SEEK_SET;
   lock.l_start = 0;
   lock.l_len = 0;  // Lock entire file.
   if (HANDLE_EINTR(fcntl(file, do_lock ? F_SETLK : F_UNLCK, &lock)) == -1)
-    return ErrnoToPlatformFileError(errno);
-  return PLATFORM_FILE_OK;
+    return File::OSErrorToFileError(errno);
+  return File::FILE_OK;
 }
 #else  // defined(OS_NACL)
 
@@ -109,9 +111,9 @@
   return 0;
 }
 
-static PlatformFileError CallFctnlFlock(PlatformFile file, bool do_lock) {
+static File::Error CallFctnlFlock(PlatformFile file, bool do_lock) {
   NOTIMPLEMENTED();  // NaCl doesn't implement flock struct.
-  return PLATFORM_FILE_ERROR_INVALID_OPERATION;
+  return File::FILE_ERROR_INVALID_OPERATION;
 }
 #endif  // defined(OS_NACL)
 
@@ -119,57 +121,53 @@
 
 // NaCl doesn't implement system calls to open files directly.
 #if !defined(OS_NACL)
-// TODO(erikkay): does it make sense to support PLATFORM_FILE_EXCLUSIVE_* here?
-PlatformFile CreatePlatformFileUnsafe(const FilePath& name,
-                                      int flags,
-                                      bool* created,
-                                      PlatformFileError* error) {
+// TODO(erikkay): does it make sense to support FLAG_EXCLUSIVE_* here?
+void File::CreateBaseFileUnsafe(const FilePath& name, uint32 flags) {
   base::ThreadRestrictions::AssertIOAllowed();
+  DCHECK(!IsValid());
+  DCHECK(!(flags & FLAG_ASYNC));
 
   int open_flags = 0;
-  if (flags & PLATFORM_FILE_CREATE)
+  if (flags & FLAG_CREATE)
     open_flags = O_CREAT | O_EXCL;
 
-  if (created)
-    *created = false;
+  created_ = false;
 
-  if (flags & PLATFORM_FILE_CREATE_ALWAYS) {
+  if (flags & FLAG_CREATE_ALWAYS) {
     DCHECK(!open_flags);
     open_flags = O_CREAT | O_TRUNC;
   }
 
-  if (flags & PLATFORM_FILE_OPEN_TRUNCATED) {
+  if (flags & FLAG_OPEN_TRUNCATED) {
     DCHECK(!open_flags);
-    DCHECK(flags & PLATFORM_FILE_WRITE);
+    DCHECK(flags & FLAG_WRITE);
     open_flags = O_TRUNC;
   }
 
-  if (!open_flags && !(flags & PLATFORM_FILE_OPEN) &&
-      !(flags & PLATFORM_FILE_OPEN_ALWAYS)) {
+  if (!open_flags && !(flags & FLAG_OPEN) && !(flags & FLAG_OPEN_ALWAYS)) {
     NOTREACHED();
     errno = EOPNOTSUPP;
-    if (error)
-      *error = PLATFORM_FILE_ERROR_FAILED;
-    return kInvalidPlatformFileValue;
+    error_ = FILE_ERROR_FAILED;
+    return;
   }
 
-  if (flags & PLATFORM_FILE_WRITE && flags & PLATFORM_FILE_READ) {
+  if (flags & FLAG_WRITE && flags & FLAG_READ) {
     open_flags |= O_RDWR;
-  } else if (flags & PLATFORM_FILE_WRITE) {
+  } else if (flags & FLAG_WRITE) {
     open_flags |= O_WRONLY;
-  } else if (!(flags & PLATFORM_FILE_READ) &&
-             !(flags & PLATFORM_FILE_WRITE_ATTRIBUTES) &&
-             !(flags & PLATFORM_FILE_APPEND) &&
-             !(flags & PLATFORM_FILE_OPEN_ALWAYS)) {
+  } else if (!(flags & FLAG_READ) &&
+             !(flags & FLAG_WRITE_ATTRIBUTES) &&
+             !(flags & FLAG_APPEND) &&
+             !(flags & FLAG_OPEN_ALWAYS)) {
     NOTREACHED();
   }
 
-  if (flags & PLATFORM_FILE_TERMINAL_DEVICE)
+  if (flags & FLAG_TERMINAL_DEVICE)
     open_flags |= O_NOCTTY | O_NDELAY;
 
-  if (flags & PLATFORM_FILE_APPEND && flags & PLATFORM_FILE_READ)
+  if (flags & FLAG_APPEND && flags & FLAG_READ)
     open_flags |= O_APPEND | O_RDWR;
-  else if (flags & PLATFORM_FILE_APPEND)
+  else if (flags & FLAG_APPEND)
     open_flags |= O_APPEND | O_WRONLY;
 
   COMPILE_ASSERT(O_RDONLY == 0, O_RDONLY_must_equal_zero);
@@ -179,70 +177,73 @@
   mode |= S_IRGRP | S_IROTH;
 #endif
 
-  int descriptor =
-      HANDLE_EINTR(open(name.value().c_str(), open_flags, mode));
+  int descriptor = HANDLE_EINTR(open(name.value().c_str(), open_flags, mode));
 
-  if (flags & PLATFORM_FILE_OPEN_ALWAYS) {
+  if (flags & FLAG_OPEN_ALWAYS) {
     if (descriptor < 0) {
       open_flags |= O_CREAT;
-      if (flags & PLATFORM_FILE_EXCLUSIVE_READ ||
-          flags & PLATFORM_FILE_EXCLUSIVE_WRITE) {
+      if (flags & FLAG_EXCLUSIVE_READ || flags & FLAG_EXCLUSIVE_WRITE)
         open_flags |= O_EXCL;   // together with O_CREAT implies O_NOFOLLOW
-      }
-      descriptor = HANDLE_EINTR(
-          open(name.value().c_str(), open_flags, mode));
-      if (created && descriptor >= 0)
-        *created = true;
+
+      descriptor = HANDLE_EINTR(open(name.value().c_str(), open_flags, mode));
+      if (descriptor >= 0)
+        created_ = true;
     }
   }
 
-  if (created && (descriptor >= 0) &&
-      (flags & (PLATFORM_FILE_CREATE_ALWAYS | PLATFORM_FILE_CREATE)))
-    *created = true;
+  if (descriptor >= 0 && (flags & (FLAG_CREATE_ALWAYS | FLAG_CREATE)))
+    created_ = true;
 
-  if ((descriptor >= 0) && (flags & PLATFORM_FILE_DELETE_ON_CLOSE)) {
+  if ((descriptor >= 0) && (flags & FLAG_DELETE_ON_CLOSE))
     unlink(name.value().c_str());
-  }
 
-  if (error) {
-    if (descriptor >= 0)
-      *error = PLATFORM_FILE_OK;
-    else
-      *error = ErrnoToPlatformFileError(errno);
-  }
+  if (descriptor >= 0)
+    error_ = FILE_OK;
+  else
+    error_ = File::OSErrorToFileError(errno);
 
-  return descriptor;
-}
-
-FILE* FdopenPlatformFile(PlatformFile file, const char* mode) {
-  return fdopen(file, mode);
+  file_ = descriptor;
 }
 #endif  // !defined(OS_NACL)
 
-bool ClosePlatformFile(PlatformFile file) {
-  base::ThreadRestrictions::AssertIOAllowed();
-  return !IGNORE_EINTR(close(file));
+bool File::IsValid() const {
+  return file_ >= 0;
 }
 
-int64 SeekPlatformFile(PlatformFile file,
-                       PlatformFileWhence whence,
-                       int64 offset) {
+PlatformFile File::TakePlatformFile() {
+  PlatformFile file = file_;
+  file_ = kInvalidPlatformFileValue;
+  return file;
+}
+
+void File::Close() {
   base::ThreadRestrictions::AssertIOAllowed();
-  if (file < 0 || offset < 0)
+  if (!IsValid())
+    return;
+
+  if (!IGNORE_EINTR(close(file_)))
+    file_ = kInvalidPlatformFileValue;
+}
+
+int64 File::Seek(Whence whence, int64 offset) {
+  base::ThreadRestrictions::AssertIOAllowed();
+  DCHECK(IsValid());
+  if (file_ < 0 || offset < 0)
     return -1;
 
-  return lseek(file, static_cast<off_t>(offset), static_cast<int>(whence));
+  return lseek(file_, static_cast<off_t>(offset), static_cast<int>(whence));
 }
 
-int ReadPlatformFile(PlatformFile file, int64 offset, char* data, int size) {
+int File::Read(int64 offset, char* data, int size) {
   base::ThreadRestrictions::AssertIOAllowed();
-  if (file < 0 || size < 0)
+  DCHECK(IsValid());
+  if (size < 0)
     return -1;
 
   int bytes_read = 0;
   int rv;
   do {
-    rv = HANDLE_EINTR(pread(file, data + bytes_read,
+    rv = HANDLE_EINTR(pread(file_, data + bytes_read,
                             size - bytes_read, offset + bytes_read));
     if (rv <= 0)
       break;
@@ -253,15 +254,16 @@
   return bytes_read ? bytes_read : rv;
 }
 
-int ReadPlatformFileAtCurrentPos(PlatformFile file, char* data, int size) {
+int File::ReadAtCurrentPos(char* data, int size) {
   base::ThreadRestrictions::AssertIOAllowed();
-  if (file < 0 || size < 0)
+  DCHECK(IsValid());
+  if (size < 0)
     return -1;
 
   int bytes_read = 0;
   int rv;
   do {
-    rv = HANDLE_EINTR(read(file, data, size));
+    rv = HANDLE_EINTR(read(file_, data, size));
     if (rv <= 0)
       break;
 
@@ -271,38 +273,36 @@
   return bytes_read ? bytes_read : rv;
 }
 
-int ReadPlatformFileNoBestEffort(PlatformFile file, int64 offset,
-                                 char* data, int size) {
+int File::ReadNoBestEffort(int64 offset, char* data, int size) {
   base::ThreadRestrictions::AssertIOAllowed();
-  if (file < 0)
-    return -1;
+  DCHECK(IsValid());
 
-  return HANDLE_EINTR(pread(file, data, size, offset));
+  return HANDLE_EINTR(pread(file_, data, size, offset));
 }
 
-int ReadPlatformFileCurPosNoBestEffort(PlatformFile file,
-                                       char* data, int size) {
+int File::ReadAtCurrentPosNoBestEffort(char* data, int size) {
   base::ThreadRestrictions::AssertIOAllowed();
-  if (file < 0 || size < 0)
+  DCHECK(IsValid());
+  if (size < 0)
     return -1;
 
-  return HANDLE_EINTR(read(file, data, size));
+  return HANDLE_EINTR(read(file_, data, size));
 }
 
-int WritePlatformFile(PlatformFile file, int64 offset,
-                      const char* data, int size) {
+int File::Write(int64 offset, const char* data, int size) {
   base::ThreadRestrictions::AssertIOAllowed();
 
-  if (IsOpenAppend(file))
-    return WritePlatformFileAtCurrentPos(file, data, size);
+  if (IsOpenAppend(file_))
+    return WriteAtCurrentPos(data, size);
 
-  if (file < 0 || size < 0)
+  DCHECK(IsValid());
+  if (size < 0)
     return -1;
 
   int bytes_written = 0;
   int rv;
   do {
-    rv = HANDLE_EINTR(pwrite(file, data + bytes_written,
+    rv = HANDLE_EINTR(pwrite(file_, data + bytes_written,
                              size - bytes_written, offset + bytes_written));
     if (rv <= 0)
       break;
@@ -313,16 +313,16 @@
   return bytes_written ? bytes_written : rv;
 }
 
-int WritePlatformFileAtCurrentPos(PlatformFile file,
-                                  const char* data, int size) {
+int File::WriteAtCurrentPos(const char* data, int size) {
   base::ThreadRestrictions::AssertIOAllowed();
-  if (file < 0 || size < 0)
+  DCHECK(IsValid());
+  if (size < 0)
     return -1;
 
   int bytes_written = 0;
   int rv;
   do {
-    rv = HANDLE_EINTR(write(file, data, size));
+    rv = HANDLE_EINTR(write(file_, data, size));
     if (rv <= 0)
       break;
 
@@ -332,44 +332,43 @@
   return bytes_written ? bytes_written : rv;
 }
 
-int WritePlatformFileCurPosNoBestEffort(PlatformFile file,
-                                        const char* data, int size) {
+int File::WriteAtCurrentPosNoBestEffort(const char* data, int size) {
   base::ThreadRestrictions::AssertIOAllowed();
-  if (file < 0 || size < 0)
+  DCHECK(IsValid());
+  if (size < 0)
     return -1;
 
-  return HANDLE_EINTR(write(file, data, size));
+  return HANDLE_EINTR(write(file_, data, size));
 }
 
-bool TruncatePlatformFile(PlatformFile file, int64 length) {
+bool File::Truncate(int64 length) {
   base::ThreadRestrictions::AssertIOAllowed();
-  return ((file >= 0) && !CallFtruncate(file, length));
+  DCHECK(IsValid());
+  return !CallFtruncate(file_, length);
 }
 
-bool FlushPlatformFile(PlatformFile file) {
+bool File::Flush() {
   base::ThreadRestrictions::AssertIOAllowed();
-  return !CallFsync(file);
+  DCHECK(IsValid());
+  return !CallFsync(file_);
 }
 
-bool TouchPlatformFile(PlatformFile file, const base::Time& last_access_time,
-                       const base::Time& last_modified_time) {
+bool File::SetTimes(Time last_access_time, Time last_modified_time) {
   base::ThreadRestrictions::AssertIOAllowed();
-  if (file < 0)
-    return false;
+  DCHECK(IsValid());
 
   timeval times[2];
   times[0] = last_access_time.ToTimeVal();
   times[1] = last_modified_time.ToTimeVal();
 
-  return !CallFutimes(file, times);
+  return !CallFutimes(file_, times);
 }
 
-bool GetPlatformFileInfo(PlatformFile file, PlatformFileInfo* info) {
-  if (!info)
-    return false;
+bool File::GetInfo(Info* info) {
+  DCHECK(IsValid());
 
   stat_wrapper_t file_info;
-  if (CallFstat(file, &file_info))
+  if (CallFstat(file_, &file_info))
     return false;
 
   info->is_directory = S_ISDIR(file_info.st_mode);
@@ -422,44 +421,50 @@
   return true;
 }
 
-PlatformFileError LockPlatformFile(PlatformFile file) {
-  return CallFctnlFlock(file, true);
+File::Error File::Lock() {
+  return CallFctnlFlock(file_, true);
 }
 
-PlatformFileError UnlockPlatformFile(PlatformFile file) {
-  return CallFctnlFlock(file, false);
+File::Error File::Unlock() {
+  return CallFctnlFlock(file_, false);
 }
 
-PlatformFileError ErrnoToPlatformFileError(int saved_errno) {
+// Static.
+File::Error File::OSErrorToFileError(int saved_errno) {
   switch (saved_errno) {
     case EACCES:
     case EISDIR:
     case EROFS:
     case EPERM:
-      return PLATFORM_FILE_ERROR_ACCESS_DENIED;
+      return FILE_ERROR_ACCESS_DENIED;
 #if !defined(OS_NACL)  // ETXTBSY not defined by NaCl.
     case ETXTBSY:
-      return PLATFORM_FILE_ERROR_IN_USE;
+      return FILE_ERROR_IN_USE;
 #endif
     case EEXIST:
-      return PLATFORM_FILE_ERROR_EXISTS;
+      return FILE_ERROR_EXISTS;
     case ENOENT:
-      return PLATFORM_FILE_ERROR_NOT_FOUND;
+      return FILE_ERROR_NOT_FOUND;
     case EMFILE:
-      return PLATFORM_FILE_ERROR_TOO_MANY_OPENED;
+      return FILE_ERROR_TOO_MANY_OPENED;
     case ENOMEM:
-      return PLATFORM_FILE_ERROR_NO_MEMORY;
+      return FILE_ERROR_NO_MEMORY;
     case ENOSPC:
-      return PLATFORM_FILE_ERROR_NO_SPACE;
+      return FILE_ERROR_NO_SPACE;
     case ENOTDIR:
-      return PLATFORM_FILE_ERROR_NOT_A_DIRECTORY;
+      return FILE_ERROR_NOT_A_DIRECTORY;
     default:
 #if !defined(OS_NACL)  // NaCl build has no metrics code.
       UMA_HISTOGRAM_SPARSE_SLOWLY("PlatformFile.UnknownErrors.Posix",
                                   saved_errno);
 #endif
-      return PLATFORM_FILE_ERROR_FAILED;
+      return FILE_ERROR_FAILED;
   }
 }
 
+void File::SetPlatformFile(PlatformFile file) {
+  DCHECK_EQ(file_, kInvalidPlatformFileValue);
+  file_ = file;
+}
+
 }  // namespace base
diff --git a/base/files/file_unittest.cc b/base/files/file_unittest.cc
index 0da3cf0..178f867 100644
--- a/base/files/file_unittest.cc
+++ b/base/files/file_unittest.cc
@@ -3,193 +3,148 @@
 // found in the LICENSE file.
 
 #include "base/file_util.h"
+#include "base/files/file.h"
 #include "base/files/scoped_temp_dir.h"
-#include "base/platform_file.h"
 #include "base/time/time.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+using base::File;
 using base::FilePath;
 
-namespace {
-
-// Reads from a file the given number of bytes, or until EOF is reached.
-// Returns the number of bytes read.
-int ReadFully(base::PlatformFile file, int64 offset, char* data, int size) {
-  return base::ReadPlatformFile(file, offset, data, size);
-}
-
-// Writes the given number of bytes to a file.
-// Returns the number of bytes written.
-int WriteFully(base::PlatformFile file, int64 offset,
-               const char* data, int size) {
-  return base::WritePlatformFile(file, offset, data, size);
-}
-
-} // namespace
-
-TEST(PlatformFile, CreatePlatformFile) {
+TEST(File, Create) {
   base::ScopedTempDir temp_dir;
   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
   FilePath file_path = temp_dir.path().AppendASCII("create_file_1");
 
-  // Open a file that doesn't exist.
-  base::PlatformFileError error_code = base::PLATFORM_FILE_OK;
-  base::PlatformFile file = base::CreatePlatformFile(
-      file_path,
-      base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ,
-      NULL,
-      &error_code);
-  EXPECT_EQ(base::kInvalidPlatformFileValue, file);
-  EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, error_code);
+  {
+    // Open a file that doesn't exist.
+    File file(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
+    EXPECT_FALSE(file.IsValid());
+    EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, file.error());
+  }
 
-  // Open or create a file.
-  bool created = false;
-  error_code = base::PLATFORM_FILE_OK;
-  file = base::CreatePlatformFile(
-      file_path,
-      base::PLATFORM_FILE_OPEN_ALWAYS | base::PLATFORM_FILE_READ,
-      &created,
-      &error_code);
-  EXPECT_NE(base::kInvalidPlatformFileValue, file);
-  EXPECT_TRUE(created);
-  EXPECT_EQ(base::PLATFORM_FILE_OK, error_code);
-  base::ClosePlatformFile(file);
+  {
+    // Open or create a file.
+    File file(file_path, base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_READ);
+    EXPECT_TRUE(file.IsValid());
+    EXPECT_TRUE(file.created());
+    EXPECT_EQ(base::File::FILE_OK, file.error());
+  }
 
-  // Open an existing file.
-  created = false;
-  file = base::CreatePlatformFile(
-      file_path,
-      base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ,
-      &created,
-      &error_code);
-  EXPECT_NE(base::kInvalidPlatformFileValue, file);
-  EXPECT_FALSE(created);
-  EXPECT_EQ(base::PLATFORM_FILE_OK, error_code);
-  base::ClosePlatformFile(file);
+  {
+    // Open an existing file.
+    File file(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
+    EXPECT_TRUE(file.IsValid());
+    EXPECT_FALSE(file.created());
+    EXPECT_EQ(base::File::FILE_OK, file.error());
 
-  // Create a file that exists.
-  file = base::CreatePlatformFile(
-      file_path,
-      base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_READ,
-      &created,
-      &error_code);
-  EXPECT_EQ(base::kInvalidPlatformFileValue, file);
-  EXPECT_FALSE(created);
-  EXPECT_EQ(base::PLATFORM_FILE_ERROR_EXISTS, error_code);
+    // This time verify closing the file.
+    file.Close();
+    EXPECT_FALSE(file.IsValid());
+  }
 
-  // Create or overwrite a file.
-  error_code = base::PLATFORM_FILE_OK;
-  file = base::CreatePlatformFile(
-      file_path,
-      base::PLATFORM_FILE_CREATE_ALWAYS | base::PLATFORM_FILE_READ,
-      &created,
-      &error_code);
-  EXPECT_NE(base::kInvalidPlatformFileValue, file);
-  EXPECT_TRUE(created);
-  EXPECT_EQ(base::PLATFORM_FILE_OK, error_code);
-  base::ClosePlatformFile(file);
+  {
+    // Create a file that exists.
+    File file(file_path, base::File::FLAG_CREATE | base::File::FLAG_READ);
+    EXPECT_FALSE(file.IsValid());
+    EXPECT_FALSE(file.created());
+    EXPECT_EQ(base::File::FILE_ERROR_EXISTS, file.error());
+  }
 
-  // Create a delete-on-close file.
-  created = false;
-  file_path = temp_dir.path().AppendASCII("create_file_2");
-  file = base::CreatePlatformFile(
-      file_path,
-      base::PLATFORM_FILE_OPEN_ALWAYS | base::PLATFORM_FILE_DELETE_ON_CLOSE |
-          base::PLATFORM_FILE_READ,
-      &created,
-      &error_code);
-  EXPECT_NE(base::kInvalidPlatformFileValue, file);
-  EXPECT_TRUE(created);
-  EXPECT_EQ(base::PLATFORM_FILE_OK, error_code);
+  {
+    // Create or overwrite a file.
+    File file(file_path,
+              base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_READ);
+    EXPECT_TRUE(file.IsValid());
+    EXPECT_TRUE(file.created());
+    EXPECT_EQ(base::File::FILE_OK, file.error());
+  }
 
-  EXPECT_TRUE(base::ClosePlatformFile(file));
+  {
+    // Create a delete-on-close file.
+    file_path = temp_dir.path().AppendASCII("create_file_2");
+    File file(file_path,
+              base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_READ |
+                  base::File::FLAG_DELETE_ON_CLOSE);
+    EXPECT_TRUE(file.IsValid());
+    EXPECT_TRUE(file.created());
+    EXPECT_EQ(base::File::FILE_OK, file.error());
+  }
+
   EXPECT_FALSE(base::PathExists(file_path));
 }
 
-TEST(PlatformFile, DeleteOpenFile) {
+TEST(File, DeleteOpenFile) {
   base::ScopedTempDir temp_dir;
   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
   FilePath file_path = temp_dir.path().AppendASCII("create_file_1");
 
   // Create a file.
-  bool created = false;
-  base::PlatformFileError error_code = base::PLATFORM_FILE_OK;
-  base::PlatformFile file = base::CreatePlatformFile(
-      file_path,
-      base::PLATFORM_FILE_OPEN_ALWAYS | base::PLATFORM_FILE_READ |
-          base::PLATFORM_FILE_SHARE_DELETE,
-      &created,
-      &error_code);
-  EXPECT_NE(base::kInvalidPlatformFileValue, file);
-  EXPECT_TRUE(created);
-  EXPECT_EQ(base::PLATFORM_FILE_OK, error_code);
+  File file(file_path,
+            base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_READ |
+                base::File::FLAG_SHARE_DELETE);
+  EXPECT_TRUE(file.IsValid());
+  EXPECT_TRUE(file.created());
+  EXPECT_EQ(base::File::FILE_OK, file.error());
 
   // Open an existing file and mark it as delete on close.
-  created = false;
-  base::PlatformFile same_file = base::CreatePlatformFile(
-      file_path,
-      base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_DELETE_ON_CLOSE |
-          base::PLATFORM_FILE_READ,
-      &created,
-      &error_code);
-  EXPECT_NE(base::kInvalidPlatformFileValue, file);
-  EXPECT_FALSE(created);
-  EXPECT_EQ(base::PLATFORM_FILE_OK, error_code);
+  File same_file(file_path,
+                 base::File::FLAG_OPEN | base::File::FLAG_DELETE_ON_CLOSE |
+                     base::File::FLAG_READ);
+  EXPECT_TRUE(file.IsValid());
+  EXPECT_FALSE(same_file.created());
+  EXPECT_EQ(base::File::FILE_OK, same_file.error());
 
   // Close both handles and check that the file is gone.
-  base::ClosePlatformFile(file);
-  base::ClosePlatformFile(same_file);
+  file.Close();
+  same_file.Close();
   EXPECT_FALSE(base::PathExists(file_path));
 }
 
-TEST(PlatformFile, ReadWritePlatformFile) {
+TEST(File, ReadWrite) {
   base::ScopedTempDir temp_dir;
   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
   FilePath file_path = temp_dir.path().AppendASCII("read_write_file");
-  base::PlatformFile file = base::CreatePlatformFile(
-      file_path,
-      base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_READ |
-          base::PLATFORM_FILE_WRITE,
-      NULL,
-      NULL);
-  EXPECT_NE(base::kInvalidPlatformFileValue, file);
+  File file(file_path,
+            base::File::FLAG_CREATE | base::File::FLAG_READ |
+                base::File::FLAG_WRITE);
+  ASSERT_TRUE(file.IsValid());
 
   char data_to_write[] = "test";
   const int kTestDataSize = 4;
 
   // Write 0 bytes to the file.
-  int bytes_written = WriteFully(file, 0, data_to_write, 0);
+  int bytes_written = file.Write(0, data_to_write, 0);
   EXPECT_EQ(0, bytes_written);
 
   // Write "test" to the file.
-  bytes_written = WriteFully(file, 0, data_to_write, kTestDataSize);
+  bytes_written = file.Write(0, data_to_write, kTestDataSize);
   EXPECT_EQ(kTestDataSize, bytes_written);
 
   // Read from EOF.
   char data_read_1[32];
-  int bytes_read = ReadFully(file, kTestDataSize, data_read_1, kTestDataSize);
+  int bytes_read = file.Read(kTestDataSize, data_read_1, kTestDataSize);
   EXPECT_EQ(0, bytes_read);
 
   // Read from somewhere in the middle of the file.
   const int kPartialReadOffset = 1;
-  bytes_read = ReadFully(file, kPartialReadOffset, data_read_1, kTestDataSize);
+  bytes_read = file.Read(kPartialReadOffset, data_read_1, kTestDataSize);
   EXPECT_EQ(kTestDataSize - kPartialReadOffset, bytes_read);
   for (int i = 0; i < bytes_read; i++)
     EXPECT_EQ(data_to_write[i + kPartialReadOffset], data_read_1[i]);
 
   // Read 0 bytes.
-  bytes_read = ReadFully(file, 0, data_read_1, 0);
+  bytes_read = file.Read(0, data_read_1, 0);
   EXPECT_EQ(0, bytes_read);
 
   // Read the entire file.
-  bytes_read = ReadFully(file, 0, data_read_1, kTestDataSize);
+  bytes_read = file.Read(0, data_read_1, kTestDataSize);
   EXPECT_EQ(kTestDataSize, bytes_read);
   for (int i = 0; i < bytes_read; i++)
     EXPECT_EQ(data_to_write[i], data_read_1[i]);
 
   // Read again, but using the trivial native wrapper.
-  bytes_read = base::ReadPlatformFileNoBestEffort(file, 0, data_read_1,
-                                                  kTestDataSize);
+  bytes_read = file.ReadNoBestEffort(0, data_read_1, kTestDataSize);
   EXPECT_LE(bytes_read, kTestDataSize);
   for (int i = 0; i < bytes_read; i++)
     EXPECT_EQ(data_to_write[i], data_read_1[i]);
@@ -197,7 +152,7 @@
   // Write past the end of the file.
   const int kOffsetBeyondEndOfFile = 10;
   const int kPartialWriteLength = 2;
-  bytes_written = WriteFully(file, kOffsetBeyondEndOfFile,
+  bytes_written = file.Write(kOffsetBeyondEndOfFile,
                              data_to_write, kPartialWriteLength);
   EXPECT_EQ(kPartialWriteLength, bytes_written);
 
@@ -208,7 +163,7 @@
 
   // Make sure the file was zero-padded.
   char data_read_2[32];
-  bytes_read = ReadFully(file, 0, data_read_2, static_cast<int>(file_size));
+  bytes_read = file.Read(0, data_read_2, static_cast<int>(file_size));
   EXPECT_EQ(file_size, bytes_read);
   for (int i = 0; i < kTestDataSize; i++)
     EXPECT_EQ(data_to_write[i], data_read_2[i]);
@@ -216,92 +171,81 @@
     EXPECT_EQ(0, data_read_2[i]);
   for (int i = kOffsetBeyondEndOfFile; i < file_size; i++)
     EXPECT_EQ(data_to_write[i - kOffsetBeyondEndOfFile], data_read_2[i]);
-
-  // Close the file handle to allow the temp directory to be deleted.
-  base::ClosePlatformFile(file);
 }
 
-TEST(PlatformFile, AppendPlatformFile) {
+TEST(File, Append) {
   base::ScopedTempDir temp_dir;
   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
   FilePath file_path = temp_dir.path().AppendASCII("append_file");
-  base::PlatformFile file = base::CreatePlatformFile(
-      file_path,
-      base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_APPEND,
-      NULL,
-      NULL);
-  EXPECT_NE(base::kInvalidPlatformFileValue, file);
+  File file(file_path, base::File::FLAG_CREATE | base::File::FLAG_APPEND);
+  ASSERT_TRUE(file.IsValid());
 
   char data_to_write[] = "test";
   const int kTestDataSize = 4;
 
   // Write 0 bytes to the file.
-  int bytes_written = WriteFully(file, 0, data_to_write, 0);
+  int bytes_written = file.Write(0, data_to_write, 0);
   EXPECT_EQ(0, bytes_written);
 
   // Write "test" to the file.
-  bytes_written = WriteFully(file, 0, data_to_write, kTestDataSize);
+  bytes_written = file.Write(0, data_to_write, kTestDataSize);
   EXPECT_EQ(kTestDataSize, bytes_written);
 
-  base::ClosePlatformFile(file);
-  file = base::CreatePlatformFile(
-      file_path,
-      base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ |
-          base::PLATFORM_FILE_APPEND,
-      NULL,
-      NULL);
-  EXPECT_NE(base::kInvalidPlatformFileValue, file);
+  file.Close();
+  File file2(file_path,
+             base::File::FLAG_OPEN | base::File::FLAG_READ |
+                 base::File::FLAG_APPEND);
+  ASSERT_TRUE(file2.IsValid());
+
+  // Test passing the file around.
+  file = file2.Pass();
+  EXPECT_FALSE(file2.IsValid());
+  ASSERT_TRUE(file.IsValid());
 
   char append_data_to_write[] = "78";
   const int kAppendDataSize = 2;
 
   // Append "78" to the file.
-  bytes_written = WriteFully(file, 0, append_data_to_write, kAppendDataSize);
+  bytes_written = file.Write(0, append_data_to_write, kAppendDataSize);
   EXPECT_EQ(kAppendDataSize, bytes_written);
 
   // Read the entire file.
   char data_read_1[32];
-  int bytes_read = ReadFully(file, 0, data_read_1,
+  int bytes_read = file.Read(0, data_read_1,
                              kTestDataSize + kAppendDataSize);
   EXPECT_EQ(kTestDataSize + kAppendDataSize, bytes_read);
   for (int i = 0; i < kTestDataSize; i++)
     EXPECT_EQ(data_to_write[i], data_read_1[i]);
   for (int i = 0; i < kAppendDataSize; i++)
     EXPECT_EQ(append_data_to_write[i], data_read_1[kTestDataSize + i]);
-
-  // Close the file handle to allow the temp directory to be deleted.
-  base::ClosePlatformFile(file);
 }
 
 
-TEST(PlatformFile, TruncatePlatformFile) {
+TEST(File, Truncate) {
   base::ScopedTempDir temp_dir;
   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
   FilePath file_path = temp_dir.path().AppendASCII("truncate_file");
-  base::PlatformFile file = base::CreatePlatformFile(
-      file_path,
-      base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_READ |
-          base::PLATFORM_FILE_WRITE,
-      NULL,
-      NULL);
-  EXPECT_NE(base::kInvalidPlatformFileValue, file);
+  File file(file_path,
+            base::File::FLAG_CREATE | base::File::FLAG_READ |
+                base::File::FLAG_WRITE);
+  ASSERT_TRUE(file.IsValid());
 
   // Write "test" to the file.
   char data_to_write[] = "test";
   int kTestDataSize = 4;
-  int bytes_written = WriteFully(file, 0, data_to_write, kTestDataSize);
+  int bytes_written = file.Write(0, data_to_write, kTestDataSize);
   EXPECT_EQ(kTestDataSize, bytes_written);
 
   // Extend the file.
   const int kExtendedFileLength = 10;
   int64 file_size = 0;
-  EXPECT_TRUE(base::TruncatePlatformFile(file, kExtendedFileLength));
+  EXPECT_TRUE(file.Truncate(kExtendedFileLength));
   EXPECT_TRUE(file_util::GetFileSize(file_path, &file_size));
   EXPECT_EQ(kExtendedFileLength, file_size);
 
   // Make sure the file was zero-padded.
   char data_read[32];
-  int bytes_read = ReadFully(file, 0, data_read, static_cast<int>(file_size));
+  int bytes_read = file.Read(0, data_read, static_cast<int>(file_size));
   EXPECT_EQ(file_size, bytes_read);
   for (int i = 0; i < kTestDataSize; i++)
     EXPECT_EQ(data_to_write[i], data_read[i]);
@@ -310,39 +254,33 @@
 
   // Truncate the file.
   const int kTruncatedFileLength = 2;
-  EXPECT_TRUE(base::TruncatePlatformFile(file, kTruncatedFileLength));
+  EXPECT_TRUE(file.Truncate(kTruncatedFileLength));
   EXPECT_TRUE(file_util::GetFileSize(file_path, &file_size));
   EXPECT_EQ(kTruncatedFileLength, file_size);
 
   // Make sure the file was truncated.
-  bytes_read = ReadFully(file, 0, data_read, kTestDataSize);
+  bytes_read = file.Read(0, data_read, kTestDataSize);
   EXPECT_EQ(file_size, bytes_read);
   for (int i = 0; i < file_size; i++)
     EXPECT_EQ(data_to_write[i], data_read[i]);
-
-  // Close the file handle to allow the temp directory to be deleted.
-  base::ClosePlatformFile(file);
 }
 
 // Flakily fails: http://crbug.com/86494
 #if defined(OS_ANDROID)
-TEST(PlatformFile, TouchGetInfoPlatformFile) {
+TEST(File, TouchGetInfo) {
 #else
-TEST(PlatformFile, DISABLED_TouchGetInfoPlatformFile) {
+TEST(File, DISABLED_TouchGetInfo) {
 #endif
   base::ScopedTempDir temp_dir;
   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-  base::PlatformFile file = base::CreatePlatformFile(
-      temp_dir.path().AppendASCII("touch_get_info_file"),
-      base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_WRITE |
-          base::PLATFORM_FILE_WRITE_ATTRIBUTES,
-      NULL,
-      NULL);
-  EXPECT_NE(base::kInvalidPlatformFileValue, file);
+  File file(temp_dir.path().AppendASCII("touch_get_info_file"),
+            base::File::FLAG_CREATE | base::File::FLAG_WRITE |
+                base::File::FLAG_WRITE_ATTRIBUTES);
+  ASSERT_TRUE(file.IsValid());
 
   // Get info for a newly created file.
-  base::PlatformFileInfo info;
-  EXPECT_TRUE(base::GetPlatformFileInfo(file, &info));
+  base::File::Info info;
+  EXPECT_TRUE(file.GetInfo(&info));
 
   // Add 2 seconds to account for possible rounding errors on
   // filesystems that use a 1s or 2s timestamp granularity.
@@ -358,7 +296,7 @@
   // Write "test" to the file.
   char data[] = "test";
   const int kTestDataSize = 4;
-  int bytes_written = WriteFully(file, 0, data, kTestDataSize);
+  int bytes_written = file.Write(0, data, kTestDataSize);
   EXPECT_EQ(kTestDataSize, bytes_written);
 
   // Change the last_accessed and last_modified dates.
@@ -370,11 +308,10 @@
   base::Time new_last_modified =
       info.last_modified + base::TimeDelta::FromMinutes(567);
 
-  EXPECT_TRUE(base::TouchPlatformFile(file, new_last_accessed,
-                                      new_last_modified));
+  EXPECT_TRUE(file.SetTimes(new_last_accessed, new_last_modified));
 
   // Make sure the file info was updated accordingly.
-  EXPECT_TRUE(base::GetPlatformFileInfo(file, &info));
+  EXPECT_TRUE(file.GetInfo(&info));
   EXPECT_EQ(info.size, kTestDataSize);
   EXPECT_FALSE(info.is_directory);
   EXPECT_FALSE(info.is_symbolic_link);
@@ -394,41 +331,30 @@
 
   EXPECT_EQ(info.creation_time.ToInternalValue(),
             creation_time.ToInternalValue());
-
-  // Close the file handle to allow the temp directory to be deleted.
-  base::ClosePlatformFile(file);
 }
 
-TEST(PlatformFile, ReadFileAtCurrentPosition) {
+TEST(File, ReadFileAtCurrentPosition) {
   base::ScopedTempDir temp_dir;
   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
   FilePath file_path =
       temp_dir.path().AppendASCII("read_file_at_current_position");
-  base::PlatformFile file = base::CreatePlatformFile(
-      file_path,
-      base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_READ |
-          base::PLATFORM_FILE_WRITE,
-      NULL, NULL);
-  EXPECT_NE(base::kInvalidPlatformFileValue, file);
+  File file(file_path,
+            base::File::FLAG_CREATE | base::File::FLAG_READ |
+                base::File::FLAG_WRITE);
+  EXPECT_TRUE(file.IsValid());
 
   const char kData[] = "test";
   const int kDataSize = arraysize(kData) - 1;
-  EXPECT_EQ(kDataSize, WriteFully(file, 0, kData, kDataSize));
+  EXPECT_EQ(kDataSize, file.Write(0, kData, kDataSize));
 
-  EXPECT_EQ(0, SeekPlatformFile(
-      file, base::PLATFORM_FILE_FROM_BEGIN, 0));
+  EXPECT_EQ(0, file.Seek(base::File::FROM_BEGIN, 0));
 
   char buffer[kDataSize];
   int first_chunk_size = kDataSize / 2;
-  EXPECT_EQ(first_chunk_size,
-            base::ReadPlatformFileAtCurrentPos(
-                file, buffer, first_chunk_size));
+  EXPECT_EQ(first_chunk_size, file.ReadAtCurrentPos(buffer, first_chunk_size));
   EXPECT_EQ(kDataSize - first_chunk_size,
-            base::ReadPlatformFileAtCurrentPos(
-                file, buffer + first_chunk_size,
-                kDataSize - first_chunk_size));
+            file.ReadAtCurrentPos(buffer + first_chunk_size,
+                                  kDataSize - first_chunk_size));
   EXPECT_EQ(std::string(buffer, buffer + kDataSize),
             std::string(kData));
-
-  base::ClosePlatformFile(file);
 }