Refactored the PPB_Flash_File_ModuleLocal/FileRef to the new ppapi resource model

The refactors PPB_Flash_File_ModuleLocal/FileRef to the new resource model. Calls for both these interfaces are now made directly to the browser. This removes the in-process implementation for these interfaces also (as they are flash-only). Tests are added for PPB_Flash_File_ModuleLocal.

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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@171902 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/ppapi/c/private/ppb_flash_file.h b/ppapi/c/private/ppb_flash_file.h
index c5aeeafa..1473d45 100644
--- a/ppapi/c/private/ppb_flash_file.h
+++ b/ppapi/c/private/ppb_flash_file.h
@@ -31,18 +31,9 @@
 // Module-local file paths are '/'-separated UTF-8 strings, relative to a
 // module-specific root.
 struct PPB_Flash_File_ModuleLocal_3_0 {
-  // Does initialization necessary for proxying this interface on background
-  // threads. You must always call this function before using any other
-  // function in this interface for a given instance ID.
-  //
-  // Returns true if multithreaded access is supported. In this case you can
-  // use the rest of the functions from background threads. You may not call
-  // GetInterface or do any other PPAPI operations on background threads at
-  // this time.
+  // Deprecated. Returns true.
   bool (*CreateThreadAdapterForInstance)(PP_Instance instance);
-
-  // Call when an instance is destroyed when you've previously called
-  // CreateThreadAdapterForInstance.
+  // Deprecated. Does nothing.
   void (*ClearThreadAdapterForInstance)(PP_Instance instance);
 
   // Opens a file, returning a file descriptor (posix) or a HANDLE (win32) into
diff --git a/ppapi/ppapi_ipc.gypi b/ppapi/ppapi_ipc.gypi
index 8c23bf2..8e374b2 100644
--- a/ppapi/ppapi_ipc.gypi
+++ b/ppapi/ppapi_ipc.gypi
@@ -12,8 +12,6 @@
       # This part is shared between the targets defined below.
       ['ppapi_ipc_target==1', {
         'sources': [
-          'proxy/pepper_file_messages.cc',
-          'proxy/pepper_file_messages.h',
           'proxy/ppapi_messages.cc',
           'proxy/ppapi_messages.h',
           'proxy/ppapi_param_traits.cc',
diff --git a/ppapi/ppapi_proxy.gypi b/ppapi/ppapi_proxy.gypi
index f835ff2..81ec94f 100644
--- a/ppapi/ppapi_proxy.gypi
+++ b/ppapi/ppapi_proxy.gypi
@@ -39,6 +39,8 @@
           'proxy/flash_clipboard_resource.h',
           'proxy/flash_device_id_resource.cc',
           'proxy/flash_device_id_resource.h',
+          'proxy/flash_file_resource.cc',
+          'proxy/flash_file_resource.h',
           'proxy/flash_font_file_resource.cc',
           'proxy/flash_font_file_resource.h',
           'proxy/flash_fullscreen_resource.cc',
@@ -187,6 +189,7 @@
               'proxy/device_enumeration_resource_helper.cc',
               'proxy/flash_clipboard_resource.cc',
               'proxy/flash_device_id_resource.cc',
+              'proxy/flash_file_resource.cc',
               'proxy/flash_font_file_resource.cc',
               'proxy/flash_fullscreen_resource.cc',
               'proxy/flash_menu_resource.cc',
diff --git a/ppapi/ppapi_shared.gypi b/ppapi/ppapi_shared.gypi
index da446ef..9033612 100644
--- a/ppapi/ppapi_shared.gypi
+++ b/ppapi/ppapi_shared.gypi
@@ -55,8 +55,6 @@
           'shared_impl/ppb_file_io_shared.h',
           'shared_impl/ppb_file_ref_shared.cc',
           'shared_impl/ppb_file_ref_shared.h',
-          'shared_impl/ppb_flash_shared.cc',
-          'shared_impl/ppb_flash_shared.h',
           'shared_impl/ppb_gamepad_shared.cc',
           'shared_impl/ppb_gamepad_shared.h',
           'shared_impl/ppb_graphics_3d_shared.cc',
diff --git a/ppapi/proxy/flash_file_resource.cc b/ppapi/proxy/flash_file_resource.cc
new file mode 100644
index 0000000..ac9e555
--- /dev/null
+++ b/ppapi/proxy/flash_file_resource.cc
@@ -0,0 +1,231 @@
+// 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 "ppapi/proxy/flash_file_resource.h"
+
+#include "base/file_path.h"
+#include "ipc/ipc_message.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/shared_impl/file_type_conversion.h"
+#include "ppapi/shared_impl/scoped_pp_var.h"
+#include "ppapi/shared_impl/time_conversion.h"
+#include "ppapi/shared_impl/var.h"
+#include "ppapi/thunk/enter.h"
+
+namespace ppapi {
+namespace proxy {
+
+namespace {
+
+// Returns the path that a PPB_FileRef resource references as long as it is an
+// PP_FILESYSTEMTYPE_EXTERNAL path. Returns an empty string on error.
+std::string GetPathFromFileRef(PP_Resource file_ref) {
+  thunk::EnterResourceNoLock<thunk::PPB_FileRef_API> enter(file_ref, true);
+  if (enter.failed())
+    return std::string();
+  if (enter.object()->GetFileSystemType() != PP_FILESYSTEMTYPE_EXTERNAL)
+    return std::string();
+  ScopedPPVar var(ScopedPPVar::PassRef(), enter.object()->GetAbsolutePath());
+  StringVar* string_var = StringVar::FromPPVar(var.get());
+  if (!string_var)
+    return std::string();
+  return string_var->value();
+}
+
+}  // namespace
+
+FlashFileResource::FlashFileResource(Connection connection,
+                                     PP_Instance instance)
+    : PluginResource(connection, instance) {
+  SendCreate(BROWSER, PpapiHostMsg_FlashFile_Create());
+}
+
+FlashFileResource::~FlashFileResource() {
+}
+
+thunk::PPB_Flash_File_API* FlashFileResource::AsPPB_Flash_File_API() {
+  return this;
+}
+
+int32_t FlashFileResource::OpenFile(PP_Instance /*instance*/,
+                                    const char* path,
+                                    int32_t mode,
+                                    PP_FileHandle* file) {
+  return OpenFileHelper(path, PepperFilePath::DOMAIN_MODULE_LOCAL, mode, file);
+}
+
+int32_t FlashFileResource::RenameFile(PP_Instance /*instance*/,
+                                      const char* path_from,
+                                      const char* path_to) {
+  PepperFilePath pepper_from(PepperFilePath::DOMAIN_MODULE_LOCAL,
+                             FilePath::FromUTF8Unsafe(path_from));
+  PepperFilePath pepper_to(PepperFilePath::DOMAIN_MODULE_LOCAL,
+                           FilePath::FromUTF8Unsafe(path_to));
+
+  int32_t error = SyncCall<IPC::Message>(
+      BROWSER, PpapiHostMsg_FlashFile_RenameFile(pepper_from, pepper_to));
+
+  return error;
+}
+
+int32_t FlashFileResource::DeleteFileOrDir(PP_Instance /*instance*/,
+                                           const char* path,
+                                           PP_Bool recursive) {
+  PepperFilePath pepper_path(PepperFilePath::DOMAIN_MODULE_LOCAL,
+                             FilePath::FromUTF8Unsafe(path));
+
+  int32_t error = SyncCall<IPC::Message>(
+      BROWSER, PpapiHostMsg_FlashFile_DeleteFileOrDir(pepper_path,
+                                                      PP_ToBool(recursive)));
+
+  return error;
+}
+
+int32_t FlashFileResource::CreateDir(PP_Instance /*instance*/,
+                                     const char* path) {
+  PepperFilePath pepper_path(PepperFilePath::DOMAIN_MODULE_LOCAL,
+                             FilePath::FromUTF8Unsafe(path));
+
+  int32_t error = SyncCall<IPC::Message>(BROWSER,
+      PpapiHostMsg_FlashFile_CreateDir(pepper_path));
+
+  return error;
+}
+
+int32_t FlashFileResource::QueryFile(PP_Instance /*instance*/,
+                                     const char* path,
+                                     PP_FileInfo* info) {
+  return QueryFileHelper(path, PepperFilePath::DOMAIN_MODULE_LOCAL, info);
+}
+
+int32_t FlashFileResource::GetDirContents(PP_Instance /*instance*/,
+                                          const char* path,
+                                          PP_DirContents_Dev** contents) {
+  ppapi::DirContents entries;
+  PepperFilePath pepper_path(PepperFilePath::DOMAIN_MODULE_LOCAL,
+                             FilePath::FromUTF8Unsafe(path));
+
+  int32_t error = SyncCall<PpapiPluginMsg_FlashFile_GetDirContentsReply>(
+      BROWSER, PpapiHostMsg_FlashFile_GetDirContents(pepper_path), &entries);
+
+  if (error == PP_OK) {
+    // Copy the serialized dir entries to the output struct.
+    *contents = new PP_DirContents_Dev;
+    (*contents)->count = static_cast<int32_t>(entries.size());
+    (*contents)->entries = new PP_DirEntry_Dev[entries.size()];
+    for (size_t i = 0; i < entries.size(); i++) {
+      const ppapi::DirEntry& source = entries[i];
+      PP_DirEntry_Dev* dest = &(*contents)->entries[i];
+      std::string name = source.name.AsUTF8Unsafe();
+      char* name_copy = new char[name.size() + 1];
+      memcpy(name_copy, name.c_str(), name.size() + 1);
+      dest->name = name_copy;
+      dest->is_dir = PP_FromBool(source.is_dir);
+    }
+  }
+
+  return error;
+}
+
+void FlashFileResource::FreeDirContents(PP_Instance /*instance*/,
+                                        PP_DirContents_Dev* contents) {
+  for (int32_t i = 0; i < contents->count; ++i)
+    delete[] contents->entries[i].name;
+  delete[] contents->entries;
+  delete contents;
+}
+
+int32_t FlashFileResource::CreateTemporaryFile(PP_Instance /*instance*/,
+                                               PP_FileHandle* file) {
+  if (!file)
+    return PP_ERROR_BADARGUMENT;
+
+  IPC::Message unused;
+  ResourceMessageReplyParams reply_params;
+  int32_t error = GenericSyncCall(BROWSER,
+      PpapiHostMsg_FlashFile_CreateTemporaryFile(), &unused, &reply_params);
+  if (error != PP_OK)
+    return error;
+
+  IPC::PlatformFileForTransit transit_file;
+  if (!reply_params.TakeFileHandleAtIndex(0, &transit_file))
+    return PP_ERROR_FAILED;
+
+  *file = IPC::PlatformFileForTransitToPlatformFile(transit_file);
+  return PP_OK;
+}
+
+int32_t FlashFileResource::OpenFileRef(PP_Instance /*instance*/,
+                                       PP_Resource file_ref,
+                                       int32_t mode,
+                                       PP_FileHandle* file) {
+  return OpenFileHelper(GetPathFromFileRef(file_ref),
+                        PepperFilePath::DOMAIN_ABSOLUTE, mode, file);
+}
+
+int32_t FlashFileResource::QueryFileRef(PP_Instance /*instance*/,
+                                        PP_Resource file_ref,
+                                        PP_FileInfo* info) {
+  return QueryFileHelper(GetPathFromFileRef(file_ref),
+                         PepperFilePath::DOMAIN_ABSOLUTE, info);
+}
+
+int32_t FlashFileResource::OpenFileHelper(const std::string& path,
+                                          PepperFilePath::Domain domain_type,
+                                          int32_t mode,
+                                          PP_FileHandle* file) {
+  int flags = 0;
+  if (path.empty() ||
+      !ppapi::PepperFileOpenFlagsToPlatformFileFlags(mode, &flags) ||
+      !file)
+    return PP_ERROR_BADARGUMENT;
+
+  PepperFilePath pepper_path(domain_type, FilePath::FromUTF8Unsafe(path));
+
+  IPC::Message unused;
+  ResourceMessageReplyParams reply_params;
+  int32_t error = GenericSyncCall(BROWSER,
+      PpapiHostMsg_FlashFile_OpenFile(pepper_path, flags), &unused,
+      &reply_params);
+  if (error != PP_OK)
+    return error;
+
+  IPC::PlatformFileForTransit transit_file;
+  if (!reply_params.TakeFileHandleAtIndex(0, &transit_file))
+    return PP_ERROR_FAILED;
+
+  *file = IPC::PlatformFileForTransitToPlatformFile(transit_file);
+  return PP_OK;
+}
+
+int32_t FlashFileResource::QueryFileHelper(const std::string& path,
+                                           PepperFilePath::Domain domain_type,
+                                           PP_FileInfo* info) {
+  if (path.empty() || !info)
+    return PP_ERROR_BADARGUMENT;
+
+  base::PlatformFileInfo file_info;
+  PepperFilePath pepper_path(domain_type, FilePath::FromUTF8Unsafe(path));
+
+  int32_t error = SyncCall<PpapiPluginMsg_FlashFile_QueryFileReply>(BROWSER,
+      PpapiHostMsg_FlashFile_QueryFile(pepper_path), &file_info);
+
+  if (error == PP_OK) {
+    info->size = file_info.size;
+    info->creation_time = TimeToPPTime(file_info.creation_time);
+    info->last_access_time = TimeToPPTime(file_info.last_accessed);
+    info->last_modified_time = TimeToPPTime(file_info.last_modified);
+    info->system_type = PP_FILESYSTEMTYPE_EXTERNAL;
+    if (file_info.is_directory)
+      info->type = PP_FILETYPE_DIRECTORY;
+    else
+      info->type = PP_FILETYPE_REGULAR;
+  }
+
+  return error;
+}
+
+}  // namespace proxy
+}  // namespace ppapi
diff --git a/ppapi/proxy/flash_file_resource.h b/ppapi/proxy/flash_file_resource.h
new file mode 100644
index 0000000..f8c4b188
--- /dev/null
+++ b/ppapi/proxy/flash_file_resource.h
@@ -0,0 +1,73 @@
+// 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.
+
+#ifndef PPAPI_PROXY_FLASH_FILE_RESOURCE_H_
+#define PPAPI_PROXY_FLASH_FILE_RESOURCE_H_
+
+#include <string>
+
+#include "ppapi/proxy/connection.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/shared_impl/file_path.h"
+#include "ppapi/thunk/ppb_flash_file_api.h"
+
+namespace ppapi {
+namespace proxy {
+
+class FlashFileResource
+    : public PluginResource,
+      public thunk::PPB_Flash_File_API {
+ public:
+  FlashFileResource(Connection connection, PP_Instance instance);
+  virtual ~FlashFileResource();
+
+  // Resource overrides.
+  virtual thunk::PPB_Flash_File_API* AsPPB_Flash_File_API() OVERRIDE;
+
+  // PPB_Flash_Functions_API.
+  virtual int32_t OpenFile(PP_Instance instance,
+                           const char* path,
+                           int32_t mode,
+                           PP_FileHandle* file) OVERRIDE;
+  virtual int32_t RenameFile(PP_Instance instance,
+                             const char* path_from,
+                             const char* path_to) OVERRIDE;
+  virtual int32_t DeleteFileOrDir(PP_Instance instance,
+                                  const char* path,
+                                  PP_Bool recursive) OVERRIDE;
+  virtual int32_t CreateDir(PP_Instance instance, const char* path) OVERRIDE;
+  virtual int32_t QueryFile(PP_Instance instance,
+                            const char* path,
+                            PP_FileInfo* info) OVERRIDE;
+  virtual int32_t GetDirContents(PP_Instance instance,
+                                 const char* path,
+                                 PP_DirContents_Dev** contents) OVERRIDE;
+  virtual void FreeDirContents(PP_Instance instance,
+                               PP_DirContents_Dev* contents) OVERRIDE;
+  virtual int32_t CreateTemporaryFile(PP_Instance instance,
+                                      PP_FileHandle* file) OVERRIDE;
+  virtual int32_t OpenFileRef(PP_Instance instance,
+                              PP_Resource file_ref,
+                              int32_t mode,
+                              PP_FileHandle* file) OVERRIDE;
+  virtual int32_t QueryFileRef(PP_Instance instance,
+                               PP_Resource file_ref,
+                               PP_FileInfo* info) OVERRIDE;
+
+ private:
+  int32_t OpenFileHelper(const std::string& path,
+                         PepperFilePath::Domain domain_type,
+                         int32_t mode,
+                         PP_FileHandle* file);
+  int32_t QueryFileHelper(const std::string& path,
+                          PepperFilePath::Domain domain_type,
+                          PP_FileInfo* info);
+
+  DISALLOW_COPY_AND_ASSIGN(FlashFileResource);
+};
+
+}  // namespace proxy
+}  // namespace ppapi
+
+#endif  // PPAPI_PROXY_FLASH_FILE_RESOURCE_H_
diff --git a/ppapi/proxy/pepper_file_messages.cc b/ppapi/proxy/pepper_file_messages.cc
deleted file mode 100644
index 53b4fcb..0000000
--- a/ppapi/proxy/pepper_file_messages.cc
+++ /dev/null
@@ -1,68 +0,0 @@
-// 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.
-
-
-// Get basic type definitions.
-#define IPC_MESSAGE_IMPL
-#include "ppapi/proxy/pepper_file_messages.h"
-
-// Generate constructors.
-#include "ipc/struct_constructor_macros.h"
-#include "ppapi/proxy/pepper_file_messages.h"
-
-// Generate destructors.
-#include "ipc/struct_destructor_macros.h"
-#include "ppapi/proxy/pepper_file_messages.h"
-
-// Generate param traits write methods.
-#include "ipc/param_traits_write_macros.h"
-namespace IPC {
-#include "ppapi/proxy/pepper_file_messages.h"
-}  // namespace IPC
-
-// Generate param traits read methods.
-#include "ipc/param_traits_read_macros.h"
-namespace IPC {
-#include "ppapi/proxy/pepper_file_messages.h"
-}  // namespace IPC
-
-// Generate param traits log methods.
-#include "ipc/param_traits_log_macros.h"
-namespace IPC {
-#include "ppapi/proxy/pepper_file_messages.h"
-}  // namespace IPC
-
-namespace IPC {
-
-void ParamTraits<ppapi::PepperFilePath>::Write(Message* m,
-                                               const param_type& p) {
-  WriteParam(m, static_cast<unsigned>(p.domain()));
-  WriteParam(m, p.path());
-}
-
-bool ParamTraits<ppapi::PepperFilePath>::Read(const Message* m,
-                                              PickleIterator* iter,
-                                              param_type* p) {
-  unsigned domain;
-  FilePath path;
-  if (!ReadParam(m, iter, &domain) || !ReadParam(m, iter, &path))
-    return false;
-  if (domain > ppapi::PepperFilePath::DOMAIN_MAX_VALID)
-    return false;
-
-  *p = ppapi::PepperFilePath(
-      static_cast<ppapi::PepperFilePath::Domain>(domain), path);
-  return true;
-}
-
-void ParamTraits<ppapi::PepperFilePath>::Log(const param_type& p,
-                                             std::string* l) {
-  l->append("(");
-  LogParam(static_cast<unsigned>(p.domain()), l);
-  l->append(", ");
-  LogParam(p.path(), l);
-  l->append(")");
-}
-
-}  // namespace IPC
diff --git a/ppapi/proxy/pepper_file_messages.h b/ppapi/proxy/pepper_file_messages.h
deleted file mode 100644
index 3edd490..0000000
--- a/ppapi/proxy/pepper_file_messages.h
+++ /dev/null
@@ -1,82 +0,0 @@
-// 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.
-
-// Multiply-included message file, no traditional include guard.
-#include "ipc/ipc_message_macros.h"
-#include "ipc/ipc_param_traits.h"
-#include "ipc/ipc_platform_file.h"
-#include "ppapi/proxy/ppapi_proxy_export.h"
-#include "ppapi/shared_impl/dir_contents.h"
-#include "ppapi/shared_impl/file_path.h"
-
-// Singly-included section since need custom serialization.
-#ifndef PPAPI_SHARED_IMPL_PEPPER_FILE_MESSAGES_H_
-#define PPAPI_SHARED_IMPL_PEPPER_FILE_MESSAGES_H_
-
-namespace IPC {
-
-template <>
-struct ParamTraits<ppapi::PepperFilePath> {
-  typedef ppapi::PepperFilePath param_type;
-  static void Write(Message* m, const param_type& p);
-  static bool Read(const Message* m, PickleIterator* iter, param_type* p);
-  static void Log(const param_type& p, std::string* l);
-};
-
-}  // namespace IPC
-
-#endif  // PPAPI_SHARED_IMPL_PEPPER_FILE_MESSAGES_H_
-
-#undef IPC_MESSAGE_EXPORT
-#define IPC_MESSAGE_EXPORT PPAPI_PROXY_EXPORT
-
-#define IPC_MESSAGE_START PepperFileMsgStart
-
-IPC_STRUCT_TRAITS_BEGIN(ppapi::DirEntry)
-  IPC_STRUCT_TRAITS_MEMBER(name)
-  IPC_STRUCT_TRAITS_MEMBER(is_dir)
-IPC_STRUCT_TRAITS_END()
-
-// Trusted Pepper Filesystem messages from the renderer to the browser.
-
-// Open the file.
-IPC_SYNC_MESSAGE_CONTROL2_2(PepperFileMsg_OpenFile,
-                            ppapi::PepperFilePath /* path */,
-                            int /* flags */,
-                            base::PlatformFileError /* error_code */,
-                            IPC::PlatformFileForTransit /* result */)
-
-// Rename the file.
-IPC_SYNC_MESSAGE_CONTROL2_1(PepperFileMsg_RenameFile,
-                            ppapi::PepperFilePath /* from_path */,
-                            ppapi::PepperFilePath /* to_path */,
-                            base::PlatformFileError /* error_code */)
-
-// Delete the file.
-IPC_SYNC_MESSAGE_CONTROL2_1(PepperFileMsg_DeleteFileOrDir,
-                            ppapi::PepperFilePath /* path */,
-                            bool /* recursive */,
-                            base::PlatformFileError /* error_code */)
-
-// Create the directory.
-IPC_SYNC_MESSAGE_CONTROL1_1(PepperFileMsg_CreateDir,
-                            ppapi::PepperFilePath /* path */,
-                            base::PlatformFileError /* error_code */)
-
-// Query the file's info.
-IPC_SYNC_MESSAGE_CONTROL1_2(PepperFileMsg_QueryFile,
-                            ppapi::PepperFilePath /* path */,
-                            base::PlatformFileInfo, /* info */
-                            base::PlatformFileError /* error_code */)
-
-// Get the directory's contents.
-IPC_SYNC_MESSAGE_CONTROL1_2(PepperFileMsg_GetDirContents,
-                            ppapi::PepperFilePath /* path */,
-                            ppapi::DirContents, /* contents */
-                            base::PlatformFileError /* error_code */)
-
-// Create a temporary file.
-IPC_SYNC_MESSAGE_CONTROL0_2(PepperFileMsg_CreateTemporaryFile,
-                            base::PlatformFileError /* error_code */,
-                            IPC::PlatformFileForTransit /* file */)
diff --git a/ppapi/proxy/plugin_dispatcher.cc b/ppapi/proxy/plugin_dispatcher.cc
index 939327b2..b864d99 100644
--- a/ppapi/proxy/plugin_dispatcher.cc
+++ b/ppapi/proxy/plugin_dispatcher.cc
@@ -16,6 +16,7 @@
 #include "ppapi/c/ppp_instance.h"
 #include "ppapi/proxy/flash_resource.h"
 #include "ppapi/proxy/flash_clipboard_resource.h"
+#include "ppapi/proxy/flash_file_resource.h"
 #include "ppapi/proxy/gamepad_resource.h"
 #include "ppapi/proxy/interface_list.h"
 #include "ppapi/proxy/interface_proxy.h"
diff --git a/ppapi/proxy/plugin_dispatcher.h b/ppapi/proxy/plugin_dispatcher.h
index 98f43a69..8d12e39d 100644
--- a/ppapi/proxy/plugin_dispatcher.h
+++ b/ppapi/proxy/plugin_dispatcher.h
@@ -35,9 +35,6 @@
 
 namespace proxy {
 
-class FlashClipboardResource;
-class FlashResource;
-class GamepadResource;
 class ResourceMessageReplyParams;
 
 // Used to keep track of per-instance data.
diff --git a/ppapi/proxy/plugin_resource.cc b/ppapi/proxy/plugin_resource.cc
index fca0630..3dd47baa 100644
--- a/ppapi/proxy/plugin_resource.cc
+++ b/ppapi/proxy/plugin_resource.cc
@@ -108,16 +108,17 @@
       new PpapiHostMsg_ResourceCall(call_params, nested_msg));
 }
 
-int32_t PluginResource::GenericSyncCall(Destination dest,
-                                        const IPC::Message& msg,
-                                        IPC::Message* reply) {
+int32_t PluginResource::GenericSyncCall(
+    Destination dest,
+    const IPC::Message& msg,
+    IPC::Message* reply,
+    ResourceMessageReplyParams* reply_params) {
   ResourceMessageCallParams params(pp_resource(), GetNextSequence());
   params.set_has_callback();
-  ResourceMessageReplyParams reply_params;
   bool success = GetSender(dest)->Send(new PpapiHostMsg_ResourceSyncCall(
-      params, msg, &reply_params, reply));
+      params, msg, reply_params, reply));
   if (success)
-    return reply_params.result();
+    return reply_params->result();
   return PP_ERROR_FAILED;
 }
 
diff --git a/ppapi/proxy/plugin_resource.h b/ppapi/proxy/plugin_resource.h
index 2363c8c..2e2e10f2 100644
--- a/ppapi/proxy/plugin_resource.h
+++ b/ppapi/proxy/plugin_resource.h
@@ -126,6 +126,11 @@
   int32_t SyncCall(
       Destination dest, const IPC::Message& msg, A* a, B* b, C* c, D* d, E* e);
 
+  int32_t GenericSyncCall(Destination dest,
+                          const IPC::Message& msg,
+                          IPC::Message* reply_msg,
+                          ResourceMessageReplyParams* reply_params);
+
  private:
   IPC::Sender* GetSender(Destination dest) {
     return dest == RENDERER ? connection_.renderer_sender :
@@ -138,10 +143,6 @@
                         const ResourceMessageCallParams& call_params,
                         const IPC::Message& nested_msg);
 
-  int32_t GenericSyncCall(Destination dest,
-                          const IPC::Message& msg,
-                          IPC::Message* reply_msg);
-
   int32_t GetNextSequence();
 
   Connection connection_;
@@ -177,14 +178,16 @@
 template <class ReplyMsgClass>
 int32_t PluginResource::SyncCall(Destination dest, const IPC::Message& msg) {
   IPC::Message reply;
-  return GenericSyncCall(dest, msg, &reply);
+  ResourceMessageReplyParams reply_params;
+  return GenericSyncCall(dest, msg, &reply, &reply_params);
 }
 
 template <class ReplyMsgClass, class A>
 int32_t PluginResource::SyncCall(
     Destination dest, const IPC::Message& msg, A* a) {
   IPC::Message reply;
-  int32_t result = GenericSyncCall(dest, msg, &reply);
+  ResourceMessageReplyParams reply_params;
+  int32_t result = GenericSyncCall(dest, msg, &reply, &reply_params);
 
   if (UnpackMessage<ReplyMsgClass>(reply, a))
     return result;
@@ -195,7 +198,8 @@
 int32_t PluginResource::SyncCall(
     Destination dest, const IPC::Message& msg, A* a, B* b) {
   IPC::Message reply;
-  int32_t result = GenericSyncCall(dest, msg, &reply);
+  ResourceMessageReplyParams reply_params;
+  int32_t result = GenericSyncCall(dest, msg, &reply, &reply_params);
 
   if (UnpackMessage<ReplyMsgClass>(reply, a, b))
     return result;
@@ -206,7 +210,8 @@
 int32_t PluginResource::SyncCall(
     Destination dest, const IPC::Message& msg, A* a, B* b, C* c) {
   IPC::Message reply;
-  int32_t result = GenericSyncCall(dest, msg, &reply);
+  ResourceMessageReplyParams reply_params;
+  int32_t result = GenericSyncCall(dest, msg, &reply, &reply_params);
 
   if (UnpackMessage<ReplyMsgClass>(reply, a, b, c))
     return result;
@@ -217,7 +222,8 @@
 int32_t PluginResource::SyncCall(
     Destination dest, const IPC::Message& msg, A* a, B* b, C* c, D* d) {
   IPC::Message reply;
-  int32_t result = GenericSyncCall(dest, msg, &reply);
+  ResourceMessageReplyParams reply_params;
+  int32_t result = GenericSyncCall(dest, msg, &reply, &reply_params);
 
   if (UnpackMessage<ReplyMsgClass>(reply, a, b, c, d))
     return result;
@@ -228,7 +234,8 @@
 int32_t PluginResource::SyncCall(
     Destination dest, const IPC::Message& msg, A* a, B* b, C* c, D* d, E* e) {
   IPC::Message reply;
-  int32_t result = GenericSyncCall(dest, msg, &reply);
+  ResourceMessageReplyParams reply_params;
+  int32_t result = GenericSyncCall(dest, msg, &reply, &reply_params);
 
   if (UnpackMessage<ReplyMsgClass>(reply, a, b, c, d, e))
     return result;
diff --git a/ppapi/proxy/ppapi_messages.h b/ppapi/proxy/ppapi_messages.h
index 959b93c..b5e04de 100644
--- a/ppapi/proxy/ppapi_messages.h
+++ b/ppapi/proxy/ppapi_messages.h
@@ -47,6 +47,8 @@
 #include "ppapi/proxy/serialized_flash_menu.h"
 #include "ppapi/proxy/serialized_structs.h"
 #include "ppapi/proxy/serialized_var.h"
+#include "ppapi/shared_impl/dir_contents.h"
+#include "ppapi/shared_impl/file_path.h"
 #include "ppapi/shared_impl/ppapi_preferences.h"
 #include "ppapi/shared_impl/ppb_device_ref_shared.h"
 #include "ppapi/shared_impl/ppb_input_event_shared.h"
@@ -162,6 +164,11 @@
   IPC_STRUCT_TRAITS_MEMBER(id)
 IPC_STRUCT_TRAITS_END()
 
+IPC_STRUCT_TRAITS_BEGIN(ppapi::DirEntry)
+  IPC_STRUCT_TRAITS_MEMBER(name)
+  IPC_STRUCT_TRAITS_MEMBER(is_dir)
+IPC_STRUCT_TRAITS_END()
+
 IPC_STRUCT_TRAITS_BEGIN(ppapi::FlashSiteSetting)
   IPC_STRUCT_TRAITS_MEMBER(site)
   IPC_STRUCT_TRAITS_MEMBER(permission)
@@ -1274,17 +1281,6 @@
                            PP_Instance /* instance */,
                            PP_Rect /* rect */,
                            PP_Bool /* result */)
-IPC_SYNC_MESSAGE_ROUTED3_2(PpapiHostMsg_PPBFlash_OpenFileRef,
-                           PP_Instance /* instance */,
-                           ppapi::HostResource /* file_ref */,
-                           int32_t /* mode */,
-                           IPC::PlatformFileForTransit /* file_handle */,
-                           int32_t /* result */)
-IPC_SYNC_MESSAGE_ROUTED2_2(PpapiHostMsg_PPBFlash_QueryFileRef,
-                           PP_Instance /* instance */,
-                           ppapi::HostResource /* file_ref */,
-                           PP_FileInfo /* info */,
-                           int32_t /* result */)
 IPC_SYNC_MESSAGE_ROUTED2_1(PpapiHostMsg_PPBFlash_GetSetting,
                            PP_Instance /* instance */,
                            PP_FlashSetting /* setting */,
@@ -1639,6 +1635,29 @@
                      std::vector<uint32_t> /* formats */,
                      std::vector<std::string> /* data */)
 
+// Flash file.
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_FlashFile_Create)
+IPC_MESSAGE_CONTROL2(PpapiHostMsg_FlashFile_OpenFile,
+                     ppapi::PepperFilePath /* path */,
+                     int /* flags */)
+IPC_MESSAGE_CONTROL2(PpapiHostMsg_FlashFile_RenameFile,
+                     ppapi::PepperFilePath /* from_path */,
+                     ppapi::PepperFilePath /* to_path */)
+IPC_MESSAGE_CONTROL2(PpapiHostMsg_FlashFile_DeleteFileOrDir,
+                     ppapi::PepperFilePath /* path */,
+                     bool /* recursive */)
+IPC_MESSAGE_CONTROL1(PpapiHostMsg_FlashFile_CreateDir,
+                     ppapi::PepperFilePath /* path */)
+IPC_MESSAGE_CONTROL1(PpapiHostMsg_FlashFile_QueryFile,
+                     ppapi::PepperFilePath /* path */)
+IPC_MESSAGE_CONTROL1(PpapiPluginMsg_FlashFile_QueryFileReply,
+                     base::PlatformFileInfo /* file_info */)
+IPC_MESSAGE_CONTROL1(PpapiHostMsg_FlashFile_GetDirContents,
+                     ppapi::PepperFilePath /* path */)
+IPC_MESSAGE_CONTROL1(PpapiPluginMsg_FlashFile_GetDirContentsReply,
+                     ppapi::DirContents /* entries */)
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_FlashFile_CreateTemporaryFile)
+
 // Flash font file.
 IPC_MESSAGE_CONTROL2(PpapiHostMsg_FlashFontFile_Create,
                      ppapi::proxy::SerializedFontDescription /* description */,
diff --git a/ppapi/proxy/ppapi_param_traits.cc b/ppapi/proxy/ppapi_param_traits.cc
index 763d05c..ea792e6 100644
--- a/ppapi/proxy/ppapi_param_traits.cc
+++ b/ppapi/proxy/ppapi_param_traits.cc
@@ -346,6 +346,7 @@
       break;
     case ppapi::proxy::SerializedHandle::SOCKET:
     case ppapi::proxy::SerializedHandle::CHANNEL_HANDLE:
+    case ppapi::proxy::SerializedHandle::FILE:
       ParamTraits<IPC::PlatformFileForTransit>::Write(m, p.descriptor());
       break;
     case ppapi::proxy::SerializedHandle::INVALID:
@@ -386,6 +387,14 @@
       }
       break;
     }
+    case ppapi::proxy::SerializedHandle::FILE: {
+      IPC::PlatformFileForTransit desc;
+      if (ParamTraits<IPC::PlatformFileForTransit>::Read(m, iter, &desc)) {
+        r->set_file_handle(desc);
+        return true;
+      }
+      break;
+    }
     case ppapi::proxy::SerializedHandle::INVALID:
       return true;
     // No default so the compiler will warn us if a new type is added.
@@ -552,6 +561,41 @@
     std::string* l) {
 }
 
+// ppapi::PepperFilePath -------------------------------------------------------
+
+// static
+void ParamTraits<ppapi::PepperFilePath>::Write(Message* m,
+                                               const param_type& p) {
+  WriteParam(m, static_cast<unsigned>(p.domain()));
+  WriteParam(m, p.path());
+}
+
+// static
+bool ParamTraits<ppapi::PepperFilePath>::Read(const Message* m,
+                                              PickleIterator* iter,
+                                              param_type* p) {
+  unsigned domain;
+  FilePath path;
+  if (!ReadParam(m, iter, &domain) || !ReadParam(m, iter, &path))
+    return false;
+  if (domain > ppapi::PepperFilePath::DOMAIN_MAX_VALID)
+    return false;
+
+  *p = ppapi::PepperFilePath(
+      static_cast<ppapi::PepperFilePath::Domain>(domain), path);
+  return true;
+}
+
+// static
+void ParamTraits<ppapi::PepperFilePath>::Log(const param_type& p,
+                                             std::string* l) {
+  l->append("(");
+  LogParam(static_cast<unsigned>(p.domain()), l);
+  l->append(", ");
+  LogParam(p.path(), l);
+  l->append(")");
+}
+
 // SerializedFlashMenu ---------------------------------------------------------
 
 // static
diff --git a/ppapi/proxy/ppapi_param_traits.h b/ppapi/proxy/ppapi_param_traits.h
index 13f7351..7556e35 100644
--- a/ppapi/proxy/ppapi_param_traits.h
+++ b/ppapi/proxy/ppapi_param_traits.h
@@ -14,6 +14,7 @@
 #include "ppapi/c/pp_rect.h"
 #include "ppapi/c/pp_var.h"
 #include "ppapi/proxy/ppapi_proxy_export.h"
+#include "ppapi/shared_impl/file_path.h"
 #include "ppapi/shared_impl/ppapi_permissions.h"
 #include "ppapi/shared_impl/ppb_file_ref_shared.h"
 
@@ -166,6 +167,14 @@
 };
 
 #if !defined(OS_NACL) && !defined(NACL_WIN64)
+template <>
+struct ParamTraits<ppapi::PepperFilePath> {
+  typedef ppapi::PepperFilePath param_type;
+  static void Write(Message* m, const param_type& p);
+  static bool Read(const Message* m, PickleIterator* iter, param_type* p);
+  static void Log(const param_type& p, std::string* l);
+};
+
 template<>
 struct PPAPI_PROXY_EXPORT ParamTraits<ppapi::proxy::SerializedFlashMenu> {
   typedef ppapi::proxy::SerializedFlashMenu param_type;
diff --git a/ppapi/proxy/ppb_flash_proxy.cc b/ppapi/proxy/ppb_flash_proxy.cc
index 05079107..9e06ede 100644
--- a/ppapi/proxy/ppb_flash_proxy.cc
+++ b/ppapi/proxy/ppb_flash_proxy.cc
@@ -21,14 +21,11 @@
 #include "ppapi/c/private/ppb_flash_print.h"
 #include "ppapi/c/trusted/ppb_browser_font_trusted.h"
 #include "ppapi/proxy/host_dispatcher.h"
-#include "ppapi/proxy/pepper_file_messages.h"
 #include "ppapi/proxy/plugin_dispatcher.h"
 #include "ppapi/proxy/plugin_globals.h"
 #include "ppapi/proxy/ppapi_messages.h"
 #include "ppapi/proxy/proxy_module.h"
 #include "ppapi/proxy/serialized_var.h"
-#include "ppapi/shared_impl/dir_contents.h"
-#include "ppapi/shared_impl/file_type_conversion.h"
 #include "ppapi/shared_impl/ppapi_globals.h"
 #include "ppapi/shared_impl/proxy_lock.h"
 #include "ppapi/shared_impl/resource.h"
@@ -67,19 +64,6 @@
 base::LazyInstance<LocalTimeZoneOffsetCache>::Leaky
     g_local_time_zone_offset_cache = LAZY_INSTANCE_INITIALIZER;
 
-IPC::PlatformFileForTransit PlatformFileToPlatformFileForTransit(
-    Dispatcher* dispatcher,
-    int32_t* error,
-    base::PlatformFile file) {
-  if (*error != PP_OK)
-    return IPC::InvalidPlatformFileForTransit();
-  IPC::PlatformFileForTransit out_handle =
-      dispatcher->ShareHandleWithRemote(file, true);
-  if (out_handle == IPC::InvalidPlatformFileForTransit())
-    *error = PP_ERROR_NOACCESS;
-  return out_handle;
-}
-
 void InvokePrinting(PP_Instance instance) {
   ProxyAutoLock lock;
 
@@ -125,10 +109,6 @@
                         OnHostMsgGetLocalTimeZoneOffset)
     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_IsRectTopmost,
                         OnHostMsgIsRectTopmost)
-    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_OpenFileRef,
-                        OnHostMsgOpenFileRef)
-    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_QueryFileRef,
-                        OnHostMsgQueryFileRef)
     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_InvokePrinting,
                         OnHostMsgInvokePrinting)
     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_GetSetting,
@@ -300,187 +280,6 @@
   return PP_MakeUndefined();
 }
 
-bool PPB_Flash_Proxy::CreateThreadAdapterForInstance(PP_Instance instance) {
-  return true;
-}
-
-void PPB_Flash_Proxy::ClearThreadAdapterForInstance(PP_Instance instance) {
-}
-
-int32_t PPB_Flash_Proxy::OpenFile(PP_Instance,
-                                  const char* path,
-                                  int32_t mode,
-                                  PP_FileHandle* file) {
-  int flags = 0;
-  if (!path ||
-      !ppapi::PepperFileOpenFlagsToPlatformFileFlags(mode, &flags) ||
-      !file)
-    return PP_ERROR_BADARGUMENT;
-
-  base::PlatformFileError error;
-  IPC::PlatformFileForTransit transit_file;
-  ppapi::PepperFilePath pepper_path(ppapi::PepperFilePath::DOMAIN_MODULE_LOCAL,
-                                    FilePath::FromUTF8Unsafe(path));
-
-  if (PluginGlobals::Get()->GetBrowserSender()->Send(
-          new PepperFileMsg_OpenFile(pepper_path, flags,
-                                     &error, &transit_file))) {
-    *file = IPC::PlatformFileForTransitToPlatformFile(transit_file);
-  } else {
-    *file = base::kInvalidPlatformFileValue;
-    error = base::PLATFORM_FILE_ERROR_FAILED;
-  }
-
-  return ppapi::PlatformFileErrorToPepperError(error);
-}
-
-int32_t PPB_Flash_Proxy::RenameFile(PP_Instance,
-                                    const char* from_path,
-                                    const char* to_path) {
-  base::PlatformFileError error = base::PLATFORM_FILE_ERROR_FAILED;
-  ppapi::PepperFilePath pepper_from(ppapi::PepperFilePath::DOMAIN_MODULE_LOCAL,
-                                    FilePath::FromUTF8Unsafe(from_path));
-  ppapi::PepperFilePath pepper_to(ppapi::PepperFilePath::DOMAIN_MODULE_LOCAL,
-                                  FilePath::FromUTF8Unsafe(to_path));
-
-  PluginGlobals::Get()->GetBrowserSender()->Send(
-      new PepperFileMsg_RenameFile(pepper_from, pepper_to, &error));
-
-  return ppapi::PlatformFileErrorToPepperError(error);
-}
-
-int32_t PPB_Flash_Proxy::DeleteFileOrDir(PP_Instance,
-                                         const char* path,
-                                         PP_Bool recursive) {
-  base::PlatformFileError error = base::PLATFORM_FILE_ERROR_FAILED;
-  ppapi::PepperFilePath pepper_path(ppapi::PepperFilePath::DOMAIN_MODULE_LOCAL,
-                                    FilePath::FromUTF8Unsafe(path));
-
-  PluginGlobals::Get()->GetBrowserSender()->Send(
-      new PepperFileMsg_DeleteFileOrDir(pepper_path,
-                                        PP_ToBool(recursive),
-                                        &error));
-
-  return ppapi::PlatformFileErrorToPepperError(error);
-}
-
-int32_t PPB_Flash_Proxy::CreateDir(PP_Instance, const char* path) {
-  base::PlatformFileError error = base::PLATFORM_FILE_ERROR_FAILED;
-  ppapi::PepperFilePath pepper_path(ppapi::PepperFilePath::DOMAIN_MODULE_LOCAL,
-                                    FilePath::FromUTF8Unsafe(path));
-
-  PluginGlobals::Get()->GetBrowserSender()->Send(
-      new PepperFileMsg_CreateDir(pepper_path, &error));
-
-  return ppapi::PlatformFileErrorToPepperError(error);
-}
-
-int32_t PPB_Flash_Proxy::QueryFile(PP_Instance,
-                                   const char* path,
-                                   PP_FileInfo* info) {
-  base::PlatformFileInfo file_info;
-  base::PlatformFileError error = base::PLATFORM_FILE_ERROR_FAILED;
-  ppapi::PepperFilePath pepper_path(ppapi::PepperFilePath::DOMAIN_MODULE_LOCAL,
-                                    FilePath::FromUTF8Unsafe(path));
-
-  PluginGlobals::Get()->GetBrowserSender()->Send(
-      new PepperFileMsg_QueryFile(pepper_path, &file_info, &error));
-
-  if (error == base::PLATFORM_FILE_OK) {
-    info->size = file_info.size;
-    info->creation_time = TimeToPPTime(file_info.creation_time);
-    info->last_access_time = TimeToPPTime(file_info.last_accessed);
-    info->last_modified_time = TimeToPPTime(file_info.last_modified);
-    info->system_type = PP_FILESYSTEMTYPE_EXTERNAL;
-    if (file_info.is_directory)
-        info->type = PP_FILETYPE_DIRECTORY;
-    else
-      info->type = PP_FILETYPE_REGULAR;
-  }
-
-  return ppapi::PlatformFileErrorToPepperError(error);
-}
-
-int32_t PPB_Flash_Proxy::GetDirContents(PP_Instance,
-                                        const char* path,
-                                        PP_DirContents_Dev** contents) {
-  ppapi::DirContents entries;
-  base::PlatformFileError error = base::PLATFORM_FILE_ERROR_FAILED;
-  ppapi::PepperFilePath pepper_path(ppapi::PepperFilePath::DOMAIN_MODULE_LOCAL,
-                                    FilePath::FromUTF8Unsafe(path));
-
-  PluginGlobals::Get()->GetBrowserSender()->Send(
-      new PepperFileMsg_GetDirContents(pepper_path, &entries, &error));
-
-  if (error == base::PLATFORM_FILE_OK) {
-    // Copy the serialized dir entries to the output struct.
-    *contents = new PP_DirContents_Dev;
-    (*contents)->count = static_cast<int32_t>(entries.size());
-    (*contents)->entries = new PP_DirEntry_Dev[entries.size()];
-    for (size_t i = 0; i < entries.size(); i++) {
-      const ppapi::DirEntry& source = entries[i];
-      PP_DirEntry_Dev* dest = &(*contents)->entries[i];
-      std::string name = source.name.AsUTF8Unsafe();
-      char* name_copy = new char[name.size() + 1];
-      memcpy(name_copy, name.c_str(), name.size() + 1);
-      dest->name = name_copy;
-      dest->is_dir = PP_FromBool(source.is_dir);
-    }
-  }
-
-  return ppapi::PlatformFileErrorToPepperError(error);
-}
-
-int32_t PPB_Flash_Proxy::CreateTemporaryFile(PP_Instance instance,
-                                             PP_FileHandle* file) {
-  if (!file)
-    return PP_ERROR_BADARGUMENT;
-
-  base::PlatformFileError error;
-  IPC::PlatformFileForTransit transit_file;
-
-  if (PluginGlobals::Get()->GetBrowserSender()->Send(
-          new PepperFileMsg_CreateTemporaryFile(&error, &transit_file))) {
-    *file = IPC::PlatformFileForTransitToPlatformFile(transit_file);
-  } else {
-    error = base::PLATFORM_FILE_ERROR_FAILED;
-    *file = base::kInvalidPlatformFileValue;
-  }
-
-  return ppapi::PlatformFileErrorToPepperError(error);
-}
-
-int32_t PPB_Flash_Proxy::OpenFileRef(PP_Instance instance,
-                                     PP_Resource file_ref_id,
-                                     int32_t mode,
-                                     PP_FileHandle* file) {
-  EnterResourceNoLock<thunk::PPB_FileRef_API> enter(file_ref_id, true);
-  if (enter.failed())
-    return PP_ERROR_BADRESOURCE;
-
-  int32_t result = PP_ERROR_FAILED;
-  IPC::PlatformFileForTransit transit;
-  dispatcher()->Send(new PpapiHostMsg_PPBFlash_OpenFileRef(
-      API_ID_PPB_FLASH, instance, enter.resource()->host_resource(), mode,
-      &transit, &result));
-  *file = IPC::PlatformFileForTransitToPlatformFile(transit);
-  return result;
-}
-
-int32_t PPB_Flash_Proxy::QueryFileRef(PP_Instance instance,
-                                      PP_Resource file_ref_id,
-                                      PP_FileInfo* info) {
-  EnterResourceNoLock<thunk::PPB_FileRef_API> enter(file_ref_id, true);
-  if (enter.failed())
-    return PP_ERROR_BADRESOURCE;
-
-  int32_t result = PP_ERROR_FAILED;
-  dispatcher()->Send(new PpapiHostMsg_PPBFlash_QueryFileRef(
-      API_ID_PPB_FLASH, instance, enter.resource()->host_resource(), info,
-      &result));
-  return result;
-}
-
 void PPB_Flash_Proxy::OnHostMsgSetInstanceAlwaysOnTop(PP_Instance instance,
                                                       PP_Bool on_top) {
   EnterInstanceNoLock enter(instance);
@@ -571,39 +370,6 @@
     *result = PP_FALSE;
 }
 
-void PPB_Flash_Proxy::OnHostMsgOpenFileRef(
-    PP_Instance instance,
-    const HostResource& host_resource,
-    int32_t mode,
-    IPC::PlatformFileForTransit* file_handle,
-    int32_t* result) {
-  EnterInstanceNoLock enter(instance);
-  if (enter.failed()) {
-    *result = PP_ERROR_BADARGUMENT;
-    return;
-  }
-
-  base::PlatformFile file;
-  *result = enter.functions()->GetFlashAPI()->OpenFileRef(
-      instance, host_resource.host_resource(), mode, &file);
-  *file_handle = PlatformFileToPlatformFileForTransit(dispatcher(),
-                                                      result, file);
-}
-
-void PPB_Flash_Proxy::OnHostMsgQueryFileRef(
-    PP_Instance instance,
-    const HostResource& host_resource,
-    PP_FileInfo* info,
-    int32_t* result) {
-  EnterInstanceNoLock enter(instance);
-  if (enter.failed()) {
-    *result = PP_ERROR_BADARGUMENT;
-    return;
-  }
-  *result = enter.functions()->GetFlashAPI()->QueryFileRef(
-      instance, host_resource.host_resource(), info);
-}
-
 void PPB_Flash_Proxy::OnHostMsgGetSetting(PP_Instance instance,
                                           PP_FlashSetting setting,
                                           SerializedVarReturnValue id) {
diff --git a/ppapi/proxy/ppb_flash_proxy.h b/ppapi/proxy/ppb_flash_proxy.h
index d9bea31..63cc5064 100644
--- a/ppapi/proxy/ppb_flash_proxy.h
+++ b/ppapi/proxy/ppb_flash_proxy.h
@@ -6,10 +6,8 @@
 #define PPAPI_PROXY_PPB_FLASH_PROXY_H_
 
 #include <string>
-#include <vector>
 
 #include "base/compiler_specific.h"
-#include "ipc/ipc_platform_file.h"
 #include "ppapi/c/pp_bool.h"
 #include "ppapi/c/pp_instance.h"
 #include "ppapi/c/pp_module.h"
@@ -18,7 +16,7 @@
 #include "ppapi/proxy/interface_proxy.h"
 #include "ppapi/proxy/serialized_var.h"
 #include "ppapi/shared_impl/host_resource.h"
-#include "ppapi/shared_impl/ppb_flash_shared.h"
+#include "ppapi/thunk/ppb_flash_api.h"
 
 struct PPB_Flash_Print_1_0;
 
@@ -37,7 +35,7 @@
 // implemented in the new-style resource proxy (see flash_resource.h).
 // TODO(raymes): All of these functions should be moved to the new-style proxy.
 ////////////////////////////////////////////////////////////////////////////////
-class PPB_Flash_Proxy : public InterfaceProxy, public PPB_Flash_Shared {
+class PPB_Flash_Proxy : public InterfaceProxy, public thunk::PPB_Flash_API {
  public:
   explicit PPB_Flash_Proxy(Dispatcher* dispatcher);
   virtual ~PPB_Flash_Proxy();
@@ -79,34 +77,6 @@
                                 const PP_Rect* rect) OVERRIDE;
   virtual PP_Var GetSetting(PP_Instance instance,
                             PP_FlashSetting setting) OVERRIDE;
-  virtual bool CreateThreadAdapterForInstance(PP_Instance instance) OVERRIDE;
-  virtual void ClearThreadAdapterForInstance(PP_Instance instance) OVERRIDE;
-  virtual int32_t OpenFile(PP_Instance instance,
-                           const char* path,
-                           int32_t mode,
-                           PP_FileHandle* file) OVERRIDE;
-  virtual int32_t RenameFile(PP_Instance instance,
-                             const char* path_from,
-                             const char* path_to) OVERRIDE;
-  virtual int32_t DeleteFileOrDir(PP_Instance instance,
-                                  const char* path,
-                                  PP_Bool recursive) OVERRIDE;
-  virtual int32_t CreateDir(PP_Instance instance, const char* path) OVERRIDE;
-  virtual int32_t QueryFile(PP_Instance instance,
-                            const char* path,
-                            PP_FileInfo* info) OVERRIDE;
-  virtual int32_t GetDirContents(PP_Instance instance,
-                                 const char* path,
-                                 PP_DirContents_Dev** contents) OVERRIDE;
-  virtual int32_t CreateTemporaryFile(PP_Instance instance,
-                                      PP_FileHandle* file) OVERRIDE;
-  virtual int32_t OpenFileRef(PP_Instance instance,
-                              PP_Resource file_ref,
-                              int32_t mode,
-                              PP_FileHandle* file) OVERRIDE;
-  virtual int32_t QueryFileRef(PP_Instance instance,
-                               PP_Resource file_ref,
-                               PP_FileInfo* info) OVERRIDE;
 
   static const ApiID kApiID = API_ID_PPB_FLASH;
 
@@ -127,15 +97,6 @@
   void OnHostMsgIsRectTopmost(PP_Instance instance,
                               PP_Rect rect,
                               PP_Bool* result);
-  void OnHostMsgOpenFileRef(PP_Instance instance,
-                            const ppapi::HostResource& host_resource,
-                            int32_t mode,
-                            IPC::PlatformFileForTransit* file_handle,
-                            int32_t* result);
-  void OnHostMsgQueryFileRef(PP_Instance instance,
-                             const ppapi::HostResource& host_resource,
-                             PP_FileInfo* info,
-                             int32_t* result);
   void OnHostMsgGetSetting(PP_Instance instance,
                            PP_FlashSetting setting,
                            SerializedVarReturnValue result);
diff --git a/ppapi/proxy/ppb_instance_proxy.cc b/ppapi/proxy/ppb_instance_proxy.cc
index 4e32822..d81fb8e 100644
--- a/ppapi/proxy/ppb_instance_proxy.cc
+++ b/ppapi/proxy/ppb_instance_proxy.cc
@@ -17,6 +17,7 @@
 #include "ppapi/proxy/content_decryptor_private_serializer.h"
 #include "ppapi/proxy/enter_proxy.h"
 #include "ppapi/proxy/flash_clipboard_resource.h"
+#include "ppapi/proxy/flash_file_resource.h"
 #include "ppapi/proxy/flash_fullscreen_resource.h"
 #include "ppapi/proxy/flash_resource.h"
 #include "ppapi/proxy/gamepad_resource.h"
@@ -382,6 +383,9 @@
     case FLASH_CLIPBOARD_SINGLETON_ID:
       new_singleton = new FlashClipboardResource(connection, instance);
       break;
+    case FLASH_FILE_SINGLETON_ID:
+      new_singleton = new FlashFileResource(connection, instance);
+      break;
     case FLASH_FULLSCREEN_SINGLETON_ID:
       new_singleton = new FlashFullscreenResource(connection, instance);
       break;
@@ -390,6 +394,7 @@
       break;
 #else
     case FLASH_CLIPBOARD_SINGLETON_ID:
+    case FLASH_FILE_SINGLETON_ID:
     case FLASH_FULLSCREEN_SINGLETON_ID:
     case FLASH_SINGLETON_ID:
       NOTREACHED();
diff --git a/ppapi/proxy/resource_message_params.cc b/ppapi/proxy/resource_message_params.cc
index aaca8c9a..49b6328b 100644
--- a/ppapi/proxy/resource_message_params.cc
+++ b/ppapi/proxy/resource_message_params.cc
@@ -91,6 +91,17 @@
   return true;
 }
 
+bool ResourceMessageParams::TakeFileHandleAtIndex(
+    size_t index,
+    IPC::PlatformFileForTransit* handle) const {
+  SerializedHandle serialized = TakeHandleOfTypeAtIndex(
+      index, SerializedHandle::FILE);
+  if (!serialized.is_file())
+    return false;
+  *handle = serialized.descriptor();
+  return true;
+}
+
 void ResourceMessageParams::TakeAllSharedMemoryHandles(
     std::vector<base::SharedMemoryHandle>* handles) const {
   for (size_t i = 0; i < handles_->data().size(); ++i) {
diff --git a/ppapi/proxy/resource_message_params.h b/ppapi/proxy/resource_message_params.h
index a414b87..6d0abea 100644
--- a/ppapi/proxy/resource_message_params.h
+++ b/ppapi/proxy/resource_message_params.h
@@ -38,8 +38,8 @@
   SerializedHandle TakeHandleOfTypeAtIndex(size_t index,
                                            SerializedHandle::Type type) const;
 
-  // Helper functions to return shared memory or socket handles passed in the
-  // params struct.
+  // Helper functions to return shared memory, socket or file handles passed in
+  // the params struct.
   // If the index has a valid handle of the given type, it will be placed in the
   // output parameter, the corresponding slot in the list will be set to an
   // invalid handle, and the function will return true. If the handle doesn't
@@ -54,6 +54,8 @@
                                      base::SharedMemoryHandle* handle) const;
   bool TakeSocketHandleAtIndex(size_t index,
                                IPC::PlatformFileForTransit* handle) const;
+  bool TakeFileHandleAtIndex(size_t index,
+                             IPC::PlatformFileForTransit* handle) const;
   void TakeAllSharedMemoryHandles(
       std::vector<base::SharedMemoryHandle>* handles) const;
 
diff --git a/ppapi/proxy/serialized_structs.cc b/ppapi/proxy/serialized_structs.cc
index 2904f9b8..fcd41a7b 100644
--- a/ppapi/proxy/serialized_structs.cc
+++ b/ppapi/proxy/serialized_structs.cc
@@ -134,10 +134,17 @@
 }
 
 bool SerializedHandle::IsHandleValid() const {
-  if (type_ == SHARED_MEMORY)
-    return base::SharedMemory::IsHandleValid(shm_handle_);
-  else if (type_ == SOCKET || type_ == CHANNEL_HANDLE)
-    return !(IPC::InvalidPlatformFileForTransit() == descriptor_);
+  switch (type_) {
+    case SHARED_MEMORY:
+      return base::SharedMemory::IsHandleValid(shm_handle_);
+    case SOCKET:
+    case CHANNEL_HANDLE:
+    case FILE:
+      return !(IPC::InvalidPlatformFileForTransit() == descriptor_);
+    case INVALID:
+      return false;
+    // No default so the compiler will warn us if a new type is added.
+  }
   return false;
 }
 
@@ -152,6 +159,7 @@
         break;
       case SOCKET:
       case CHANNEL_HANDLE:
+      case FILE:
         base::PlatformFile file =
             IPC::PlatformFileForTransitToPlatformFile(descriptor_);
 #if !defined(OS_NACL)
@@ -195,6 +203,7 @@
     }
     case SOCKET:
     case CHANNEL_HANDLE:
+    case FILE:
     case INVALID:
       valid_type = true;
       break;
diff --git a/ppapi/proxy/serialized_structs.h b/ppapi/proxy/serialized_structs.h
index 04d7f5d..bdc1b678 100644
--- a/ppapi/proxy/serialized_structs.h
+++ b/ppapi/proxy/serialized_structs.h
@@ -91,7 +91,7 @@
 // them in NaClIPCAdapter for use in NaCl.
 class PPAPI_PROXY_EXPORT SerializedHandle {
  public:
-  enum Type { INVALID, SHARED_MEMORY, SOCKET, CHANNEL_HANDLE };
+  enum Type { INVALID, SHARED_MEMORY, SOCKET, CHANNEL_HANDLE, FILE };
   struct Header {
     Header() : type(INVALID), size(0) {}
     Header(Type type_arg, uint32_t size_arg)
@@ -108,7 +108,7 @@
   // Create a shared memory handle.
   SerializedHandle(const base::SharedMemoryHandle& handle, uint32_t size);
 
-  // Create a socket or channel handle.
+  // Create a socket, channel or file handle.
   SerializedHandle(const Type type,
                    const IPC::PlatformFileForTransit& descriptor);
 
@@ -116,6 +116,7 @@
   bool is_shmem() const { return type_ == SHARED_MEMORY; }
   bool is_socket() const { return type_ == SOCKET; }
   bool is_channel_handle() const { return type_ == CHANNEL_HANDLE; }
+  bool is_file() const { return type_ == FILE; }
   const base::SharedMemoryHandle& shmem() const {
     DCHECK(is_shmem());
     return shm_handle_;
@@ -125,7 +126,7 @@
     return size_;
   }
   const IPC::PlatformFileForTransit& descriptor() const {
-    DCHECK(is_socket() || is_channel_handle());
+    DCHECK(is_socket() || is_channel_handle() || is_file());
     return descriptor_;
   }
   void set_shmem(const base::SharedMemoryHandle& handle, uint32_t size) {
@@ -149,6 +150,13 @@
     shm_handle_ = base::SharedMemory::NULLHandle();
     size_ = 0;
   }
+  void set_file_handle(const IPC::PlatformFileForTransit& descriptor) {
+    type_ = FILE;
+
+    descriptor_ = descriptor;
+    shm_handle_ = base::SharedMemory::NULLHandle();
+    size_ = 0;
+  }
   void set_null_shmem() {
     set_shmem(base::SharedMemory::NULLHandle(), 0);
   }
@@ -158,6 +166,9 @@
   void set_null_channel_handle() {
     set_channel_handle(IPC::InvalidPlatformFileForTransit());
   }
+  void set_null_file_handle() {
+    set_file_handle(IPC::InvalidPlatformFileForTransit());
+  }
   bool IsHandleValid() const;
 
   Header header() const {
diff --git a/ppapi/shared_impl/file_path.cc b/ppapi/shared_impl/file_path.cc
index 1208b08..1502d89 100644
--- a/ppapi/shared_impl/file_path.cc
+++ b/ppapi/shared_impl/file_path.cc
@@ -4,26 +4,8 @@
 
 #include "ppapi/shared_impl/file_path.h"
 
-#include <string>
-
-#if defined(OS_WIN)
-#include "base/utf_string_conversions.h"
-#endif
-
 namespace ppapi {
 
-namespace {
-
-FilePath GetFilePathFromUTF8(const std::string& utf8_path) {
-#if defined(OS_WIN)
-  return FilePath(UTF8ToUTF16(utf8_path));
-#else
-  return FilePath(utf8_path);
-#endif
-}
-
-}  // namespace
-
 PepperFilePath::PepperFilePath()
     : domain_(DOMAIN_INVALID),
       path_() {
@@ -35,17 +17,4 @@
   // TODO(viettrungluu): Should we DCHECK() some things here?
 }
 
-// static
-PepperFilePath PepperFilePath::MakeAbsolute(const FilePath& path) {
-  return PepperFilePath(DOMAIN_ABSOLUTE, path);
-}
-
-// static
-PepperFilePath PepperFilePath::MakeModuleLocal(const std::string& name,
-                                               const char* utf8_path) {
-  FilePath full_path = GetFilePathFromUTF8(name).Append(
-      GetFilePathFromUTF8(utf8_path));
-  return PepperFilePath(DOMAIN_MODULE_LOCAL, full_path);
-}
-
 }  // namespace ppapi
diff --git a/ppapi/shared_impl/file_path.h b/ppapi/shared_impl/file_path.h
index bcec9f8c..3d850f97 100644
--- a/ppapi/shared_impl/file_path.h
+++ b/ppapi/shared_impl/file_path.h
@@ -5,8 +5,6 @@
 #ifndef PPAPI_SHARED_IMPL_FILE_PATH_H_
 #define PPAPI_SHARED_IMPL_FILE_PATH_H_
 
-#include <string>
-
 #include "base/file_path.h"
 #include "ppapi/shared_impl/ppapi_shared_export.h"
 
@@ -30,10 +28,6 @@
   PepperFilePath();
   PepperFilePath(Domain d, const FilePath& p);
 
-  static PepperFilePath MakeAbsolute(const FilePath& path);
-  static PepperFilePath MakeModuleLocal(const std::string& name,
-                                        const char* utf8_path);
-
   Domain domain() const { return domain_; }
   const FilePath& path() const { return path_; }
 
diff --git a/ppapi/shared_impl/ppb_flash_shared.cc b/ppapi/shared_impl/ppb_flash_shared.cc
deleted file mode 100644
index c310e0e..0000000
--- a/ppapi/shared_impl/ppb_flash_shared.cc
+++ /dev/null
@@ -1,23 +0,0 @@
-// 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 "ppapi/shared_impl/ppb_flash_shared.h"
-
-namespace ppapi {
-
-PPB_Flash_Shared::PPB_Flash_Shared() {
-}
-
-PPB_Flash_Shared::~PPB_Flash_Shared() {
-}
-
-void PPB_Flash_Shared::FreeDirContents(PP_Instance instance,
-                                       PP_DirContents_Dev* contents) {
-  for (int32_t i = 0; i < contents->count; ++i)
-    delete[] contents->entries[i].name;
-  delete[] contents->entries;
-  delete contents;
-}
-
-}  // namespace ppapi
diff --git a/ppapi/shared_impl/ppb_flash_shared.h b/ppapi/shared_impl/ppb_flash_shared.h
deleted file mode 100644
index 29f8973..0000000
--- a/ppapi/shared_impl/ppb_flash_shared.h
+++ /dev/null
@@ -1,30 +0,0 @@
-// 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.
-
-#ifndef PPAPI_SHARED_IMPL_PPB_FLASH_SHARED_H_
-#define PPAPI_SHARED_IMPL_PPB_FLASH_SHARED_H_
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "ppapi/shared_impl/ppapi_shared_export.h"
-#include "ppapi/thunk/ppb_flash_api.h"
-
-namespace ppapi {
-
-class PPAPI_SHARED_EXPORT PPB_Flash_Shared : public thunk::PPB_Flash_API {
- public:
-  PPB_Flash_Shared();
-  virtual ~PPB_Flash_Shared();
-
-  // Shared implementation of PPB_Flash_API.
-  virtual void FreeDirContents(PP_Instance instance,
-                               PP_DirContents_Dev* contents) OVERRIDE;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(PPB_Flash_Shared);
-};
-
-}  // namespace ppapi
-
-#endif  // PPAPI_SHARED_IMPL_PPB_FLASH_SHARED_H_
diff --git a/ppapi/shared_impl/resource.h b/ppapi/shared_impl/resource.h
index dc1bf3f..6c86868 100644
--- a/ppapi/shared_impl/resource.h
+++ b/ppapi/shared_impl/resource.h
@@ -36,6 +36,7 @@
   F(PPB_Find_API) \
   F(PPB_Flash_Clipboard_API) \
   F(PPB_Flash_DeviceID_API) \
+  F(PPB_Flash_File_API) \
   F(PPB_Flash_FontFile_API) \
   F(PPB_Flash_Fullscreen_API) \
   F(PPB_Flash_Functions_API) \
diff --git a/ppapi/shared_impl/singleton_resource_id.h b/ppapi/shared_impl/singleton_resource_id.h
index 9558db6c..442611ab 100644
--- a/ppapi/shared_impl/singleton_resource_id.h
+++ b/ppapi/shared_impl/singleton_resource_id.h
@@ -11,6 +11,7 @@
 // PPB_Instance_API.GetSingletonResource.
 enum SingletonResourceID {
   FLASH_CLIPBOARD_SINGLETON_ID,
+  FLASH_FILE_SINGLETON_ID,
   FLASH_FULLSCREEN_SINGLETON_ID,
   FLASH_SINGLETON_ID,
   GAMEPAD_SINGLETON_ID,
diff --git a/ppapi/tests/test_flash_file.cc b/ppapi/tests/test_flash_file.cc
index a4a1169..86100d9 100644
--- a/ppapi/tests/test_flash_file.cc
+++ b/ppapi/tests/test_flash_file.cc
@@ -4,6 +4,11 @@
 
 #include "ppapi/tests/test_flash_file.h"
 
+#include <algorithm>
+#include <vector>
+
+#include "ppapi/c/pp_file_info.h"
+#include "ppapi/c/ppb_file_io.h"
 #include "ppapi/cpp/module.h"
 #include "ppapi/cpp/private/flash_file.h"
 #include "ppapi/tests/testing_instance.h"
@@ -74,6 +79,18 @@
   return result;
 }
 
+bool DirEntryEqual(FileModuleLocal::DirEntry i,
+                   FileModuleLocal::DirEntry j) {
+  return i.name == j.name && i.is_dir == j.is_dir;
+}
+
+bool DirEntryLessThan(FileModuleLocal::DirEntry i,
+                      FileModuleLocal::DirEntry j) {
+  if (i.name == j.name)
+    return i.is_dir < j.is_dir;
+  return i.name < j.name;
+}
+
 }  // namespace
 
 REGISTER_TEST_CASE(FlashFile);
@@ -90,13 +107,204 @@
 }
 
 void TestFlashFile::RunTests(const std::string& filter) {
+  RUN_TEST(OpenFile, filter);
+  RUN_TEST(RenameFile, filter);
+  RUN_TEST(DeleteFileOrDir, filter);
+  RUN_TEST(CreateDir, filter);
+  RUN_TEST(QueryFile, filter);
+  RUN_TEST(GetDirContents, filter);
   RUN_TEST(CreateTemporaryFile, filter);
 }
 
-std::string TestFlashFile::TestCreateTemporaryFile() {
+void TestFlashFile::SetUp() {
+  // Clear out existing test data.
+  FileModuleLocal::DeleteFileOrDir(instance_, std::string(), true);
   // Make sure that the root directory exists.
   FileModuleLocal::CreateDir(instance_, std::string());
+}
 
+std::string TestFlashFile::TestOpenFile() {
+  SetUp();
+  std::string filename = "abc.txt";
+  PP_FileHandle file_handle = FileModuleLocal::OpenFile(instance_,
+                                                        filename,
+                                                        PP_FILEOPENFLAG_WRITE |
+                                                        PP_FILEOPENFLAG_CREATE);
+  ASSERT_NE(PP_kInvalidFileHandle, file_handle);
+
+  std::string contents = "This is file.";
+  std::string read_contents;
+  ASSERT_TRUE(WriteFile(file_handle, contents));
+  ASSERT_FALSE(ReadFile(file_handle, &read_contents));
+  CloseFileHandle(file_handle);
+
+  file_handle = FileModuleLocal::OpenFile(instance_,
+                                          filename,
+                                          PP_FILEOPENFLAG_READ);
+  ASSERT_NE(PP_kInvalidFileHandle, file_handle);
+
+  ASSERT_FALSE(WriteFile(file_handle, contents));
+  ASSERT_TRUE(ReadFile(file_handle, &read_contents));
+  ASSERT_EQ(contents, read_contents);
+  CloseFileHandle(file_handle);
+
+  PASS();
+}
+
+std::string TestFlashFile::TestRenameFile() {
+  SetUp();
+  std::string filename = "abc.txt";
+  std::string new_filename = "abc_new.txt";
+  std::string contents = "This is file.";
+  std::string read_contents;
+
+  PP_FileHandle file_handle = FileModuleLocal::OpenFile(instance_,
+                                                        filename,
+                                                        PP_FILEOPENFLAG_WRITE |
+                                                        PP_FILEOPENFLAG_CREATE);
+  ASSERT_NE(PP_kInvalidFileHandle, file_handle);
+  ASSERT_TRUE(WriteFile(file_handle, contents));
+  CloseFileHandle(file_handle);
+
+  ASSERT_TRUE(FileModuleLocal::RenameFile(instance_, filename, new_filename));
+
+  file_handle = FileModuleLocal::OpenFile(instance_,
+                                          new_filename,
+                                          PP_FILEOPENFLAG_READ);
+  ASSERT_NE(PP_kInvalidFileHandle, file_handle);
+  ASSERT_TRUE(ReadFile(file_handle, &read_contents));
+  ASSERT_EQ(contents, read_contents);
+  CloseFileHandle(file_handle);
+
+  // Check that the old file no longer exists.
+  PP_FileInfo unused;
+  ASSERT_FALSE(FileModuleLocal::QueryFile(instance_, filename, &unused));
+
+  PASS();
+}
+
+std::string TestFlashFile::TestDeleteFileOrDir() {
+  SetUp();
+  std::string filename = "abc.txt";
+  std::string dirname = "def";
+  std::string contents = "This is file.";
+
+  // Test file deletion.
+  PP_FileHandle file_handle = FileModuleLocal::OpenFile(instance_,
+                                                        filename,
+                                                        PP_FILEOPENFLAG_WRITE |
+                                                        PP_FILEOPENFLAG_CREATE);
+  ASSERT_NE(PP_kInvalidFileHandle, file_handle);
+  ASSERT_TRUE(WriteFile(file_handle, contents));
+  CloseFileHandle(file_handle);
+  ASSERT_TRUE(FileModuleLocal::DeleteFileOrDir(instance_, filename, false));
+  PP_FileInfo unused;
+  ASSERT_FALSE(FileModuleLocal::QueryFile(instance_, filename, &unused));
+
+  // Test directory deletion.
+  ASSERT_TRUE(FileModuleLocal::CreateDir(instance_, dirname));
+  ASSERT_TRUE(FileModuleLocal::DeleteFileOrDir(instance_, dirname, false));
+  ASSERT_FALSE(FileModuleLocal::QueryFile(instance_, dirname, &unused));
+
+  // Test recursive directory deletion.
+  ASSERT_TRUE(FileModuleLocal::CreateDir(instance_, dirname));
+  file_handle = FileModuleLocal::OpenFile(
+      instance_, dirname + "/" + filename,
+      PP_FILEOPENFLAG_WRITE | PP_FILEOPENFLAG_CREATE);
+  ASSERT_NE(PP_kInvalidFileHandle, file_handle);
+  ASSERT_TRUE(WriteFile(file_handle, contents));
+  CloseFileHandle(file_handle);
+  ASSERT_FALSE(FileModuleLocal::DeleteFileOrDir(instance_, dirname, false));
+  ASSERT_TRUE(FileModuleLocal::DeleteFileOrDir(instance_, dirname, true));
+  ASSERT_FALSE(FileModuleLocal::QueryFile(instance_, filename, &unused));
+
+  PASS();
+}
+
+std::string TestFlashFile::TestCreateDir() {
+  SetUp();
+  std::string dirname = "abc";
+  PP_FileInfo info;
+  ASSERT_FALSE(FileModuleLocal::QueryFile(instance_, dirname, &info));
+  ASSERT_TRUE(FileModuleLocal::CreateDir(instance_, dirname));
+  ASSERT_TRUE(FileModuleLocal::QueryFile(instance_, dirname, &info));
+  ASSERT_EQ(info.type, PP_FILETYPE_DIRECTORY);
+
+  PASS();
+}
+
+std::string TestFlashFile::TestQueryFile() {
+  std::string filename = "abc.txt";
+  std::string dirname = "def";
+  std::string contents = "This is file.";
+  PP_FileInfo info;
+
+  // Test querying a file.
+  PP_FileHandle file_handle = FileModuleLocal::OpenFile(instance_,
+                                                        filename,
+                                                        PP_FILEOPENFLAG_WRITE |
+                                                        PP_FILEOPENFLAG_CREATE);
+  ASSERT_NE(PP_kInvalidFileHandle, file_handle);
+  ASSERT_TRUE(WriteFile(file_handle, contents));
+  CloseFileHandle(file_handle);
+  ASSERT_TRUE(FileModuleLocal::QueryFile(instance_, filename, &info));
+  ASSERT_EQ(static_cast<size_t>(info.size), contents.size());
+  ASSERT_EQ(info.type, PP_FILETYPE_REGULAR);
+  // TODO(raymes): Test the other fields.
+
+  // Test querying a directory.
+  ASSERT_TRUE(FileModuleLocal::CreateDir(instance_, dirname));
+  ASSERT_TRUE(FileModuleLocal::QueryFile(instance_, dirname, &info));
+  ASSERT_EQ(info.type, PP_FILETYPE_DIRECTORY);
+  // TODO(raymes): Test the other fields.
+
+  // Test querying a non-existent file.
+  ASSERT_FALSE(FileModuleLocal::QueryFile(instance_, "xx", &info));
+
+  PASS();
+}
+
+std::string TestFlashFile::TestGetDirContents() {
+  SetUp();
+  std::vector<FileModuleLocal::DirEntry> result;
+  ASSERT_TRUE(FileModuleLocal::GetDirContents(instance_, std::string(),
+                                              &result));
+  ASSERT_EQ(result.size(), 1);
+  ASSERT_EQ(result[0].name, "..");
+  ASSERT_EQ(result[0].is_dir, true);
+
+  std::string filename = "abc.txt";
+  std::string dirname = "def";
+  std::string contents = "This is file.";
+  PP_FileHandle file_handle = FileModuleLocal::OpenFile(instance_,
+                                                        filename,
+                                                        PP_FILEOPENFLAG_WRITE |
+                                                        PP_FILEOPENFLAG_CREATE);
+  ASSERT_NE(PP_kInvalidFileHandle, file_handle);
+  ASSERT_TRUE(WriteFile(file_handle, contents));
+  CloseFileHandle(file_handle);
+  ASSERT_TRUE(FileModuleLocal::CreateDir(instance_, dirname));
+
+  ASSERT_TRUE(FileModuleLocal::GetDirContents(instance_, "", &result));
+  FileModuleLocal::DirEntry expected[] =
+    { {"..", true},
+      {filename, false},
+      {dirname, true}
+    };
+  size_t expected_size = sizeof(expected) / sizeof(expected[0]);
+
+  std::sort(expected, expected + expected_size, DirEntryLessThan);
+  std::sort(result.begin(), result.end(), DirEntryLessThan);
+
+  ASSERT_EQ(expected_size, result.size());
+  ASSERT_TRUE(std::equal(expected, expected + expected_size, result.begin(),
+                         DirEntryEqual));
+
+  PASS();
+}
+
+std::string TestFlashFile::TestCreateTemporaryFile() {
+  SetUp();
   size_t before_create = 0;
   ASSERT_SUBTEST_SUCCESS(GetItemCountUnderModuleLocalRoot(&before_create));
 
diff --git a/ppapi/tests/test_flash_file.h b/ppapi/tests/test_flash_file.h
index b58890d..86055db 100644
--- a/ppapi/tests/test_flash_file.h
+++ b/ppapi/tests/test_flash_file.h
@@ -19,10 +19,21 @@
   virtual void RunTests(const std::string& filter);
 
  private:
-  // TODO(yzshen): Add more test cases for PPB_Flash_File_ModuleLocal and
-  // PPB_Flash_File_FileRef.
+  // TODO(raymes): We should have SetUp/TearDown methods for ppapi tests.
+  void SetUp();
+
+  std::string TestOpenFile();
+  std::string TestRenameFile();
+  std::string TestDeleteFileOrDir();
+  std::string TestCreateDir();
+  std::string TestQueryFile();
+  std::string TestGetDirContents();
   std::string TestCreateTemporaryFile();
 
+  // TODO(raymes): Add these when we can test file chooser properly.
+  // std::string TestOpenFileRef();
+  // std::string TestQueryFileRef();
+
   // Gets the number of files and directories under the module-local root
   // directory.
   std::string GetItemCountUnderModuleLocalRoot(size_t* item_count);
diff --git a/ppapi/thunk/ppb_file_ref_api.h b/ppapi/thunk/ppb_file_ref_api.h
index ed46098..0f9bbaa 100644
--- a/ppapi/thunk/ppb_file_ref_api.h
+++ b/ppapi/thunk/ppb_file_ref_api.h
@@ -33,7 +33,7 @@
   virtual int32_t Rename(PP_Resource new_file_ref,
                          scoped_refptr<TrackedCallback> callback) = 0;
 
-  // Intermal function for use in proxying. Returns the internal CreateInfo
+  // Internal function for use in proxying. Returns the internal CreateInfo
   // (the contained resource does not carry a ref on behalf of the caller).
   virtual const PPB_FileRef_CreateInfo& GetCreateInfo() const = 0;
 
diff --git a/ppapi/thunk/ppb_flash_api.h b/ppapi/thunk/ppb_flash_api.h
index 50a039d..d41acd9 100644
--- a/ppapi/thunk/ppb_flash_api.h
+++ b/ppapi/thunk/ppb_flash_api.h
@@ -57,40 +57,6 @@
   virtual double GetLocalTimeZoneOffset(PP_Instance instance, PP_Time t) = 0;
   virtual PP_Bool IsRectTopmost(PP_Instance instance, const PP_Rect* rect) = 0;
   virtual PP_Var GetSetting(PP_Instance instance, PP_FlashSetting setting) = 0;
-
-  // FlashFile_ModuleLocal.
-  virtual bool CreateThreadAdapterForInstance(PP_Instance instance) = 0;
-  virtual void ClearThreadAdapterForInstance(PP_Instance instance) = 0;
-  virtual int32_t OpenFile(PP_Instance instance,
-                           const char* path,
-                           int32_t mode,
-                           PP_FileHandle* file) = 0;
-  virtual int32_t RenameFile(PP_Instance instance,
-                             const char* path_from,
-                             const char* path_to) = 0;
-  virtual int32_t DeleteFileOrDir(PP_Instance instance,
-                                  const char* path,
-                                  PP_Bool recursive) = 0;
-  virtual int32_t CreateDir(PP_Instance instance, const char* path) = 0;
-  virtual int32_t QueryFile(PP_Instance instance,
-                            const char* path,
-                            PP_FileInfo* info) = 0;
-  virtual int32_t GetDirContents(PP_Instance instance,
-                                 const char* path,
-                                 PP_DirContents_Dev** contents) = 0;
-  virtual void FreeDirContents(PP_Instance instance,
-                               PP_DirContents_Dev* contents) = 0;
-  virtual int32_t CreateTemporaryFile(PP_Instance instance,
-                                      PP_FileHandle* file) = 0;
-
-  // FlashFile_FileRef.
-  virtual int32_t OpenFileRef(PP_Instance instance,
-                              PP_Resource file_ref,
-                              int32_t mode,
-                              PP_FileHandle* file) = 0;
-  virtual int32_t QueryFileRef(PP_Instance instance,
-                               PP_Resource file_ref,
-                               PP_FileInfo* info) = 0;
 };
 
 }  // namespace thunk
diff --git a/ppapi/thunk/ppb_flash_file_api.h b/ppapi/thunk/ppb_flash_file_api.h
new file mode 100644
index 0000000..d75725360
--- /dev/null
+++ b/ppapi/thunk/ppb_flash_file_api.h
@@ -0,0 +1,63 @@
+// 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.
+
+#ifndef PPAPI_THUNK_PPB_FLASH_FILE_API_H_
+#define PPAPI_THUNK_PPB_FLASH_FILE_API_H_
+
+#include "ppapi/c/pp_bool.h"
+#include "ppapi/c/pp_stdint.h"
+#include "ppapi/c/private/pp_file_handle.h"
+#include "ppapi/c/private/ppb_flash_file.h"
+#include "ppapi/shared_impl/singleton_resource_id.h"
+#include "ppapi/thunk/ppapi_thunk_export.h"
+
+struct PP_FileInfo;
+
+namespace ppapi {
+namespace thunk {
+
+class PPAPI_THUNK_EXPORT PPB_Flash_File_API {
+ public:
+  virtual ~PPB_Flash_File_API() {}
+
+  // FlashFile_ModuleLocal.
+  virtual int32_t OpenFile(PP_Instance instance,
+                           const char* path,
+                           int32_t mode,
+                           PP_FileHandle* file) = 0;
+  virtual int32_t RenameFile(PP_Instance instance,
+                             const char* path_from,
+                             const char* path_to) = 0;
+  virtual int32_t DeleteFileOrDir(PP_Instance instance,
+                                  const char* path,
+                                  PP_Bool recursive) = 0;
+  virtual int32_t CreateDir(PP_Instance instance, const char* path) = 0;
+  virtual int32_t QueryFile(PP_Instance instance,
+                            const char* path,
+                            PP_FileInfo* info) = 0;
+  virtual int32_t GetDirContents(PP_Instance instance,
+                                 const char* path,
+                                 PP_DirContents_Dev** contents) = 0;
+  virtual void FreeDirContents(PP_Instance instance,
+                               PP_DirContents_Dev* contents) = 0;
+  virtual int32_t CreateTemporaryFile(PP_Instance instance,
+                                      PP_FileHandle* file) = 0;
+
+  // FlashFile_FileRef.
+  virtual int32_t OpenFileRef(PP_Instance instance,
+                              PP_Resource file_ref,
+                              int32_t mode,
+                              PP_FileHandle* file) = 0;
+  virtual int32_t QueryFileRef(PP_Instance instance,
+                               PP_Resource file_ref,
+                               PP_FileInfo* info) = 0;
+
+  static const SingletonResourceID kSingletonResourceID =
+      FLASH_FILE_SINGLETON_ID;
+};
+
+}  // namespace thunk
+}  // namespace ppapi
+
+#endif // PPAPI_THUNK_PPB_FLASH_FILE_API_H_
diff --git a/ppapi/thunk/ppb_flash_file_fileref_thunk.cc b/ppapi/thunk/ppb_flash_file_fileref_thunk.cc
index 2b380c7..8ea0f24 100644
--- a/ppapi/thunk/ppb_flash_file_fileref_thunk.cc
+++ b/ppapi/thunk/ppb_flash_file_fileref_thunk.cc
@@ -6,8 +6,7 @@
 #include "ppapi/c/private/ppb_flash_file.h"
 #include "ppapi/thunk/enter.h"
 #include "ppapi/thunk/ppb_file_ref_api.h"
-#include "ppapi/thunk/ppb_flash_api.h"
-#include "ppapi/thunk/ppb_instance_api.h"
+#include "ppapi/thunk/ppb_flash_file_api.h"
 #include "ppapi/thunk/thunk.h"
 
 namespace ppapi {
@@ -27,22 +26,20 @@
   // TODO(brettw): this function should take an instance.
   // To work around this, use the PP_Instance from the resource.
   PP_Instance instance = GetInstanceFromFileRef(file_ref_id);
-  EnterInstance enter(instance);
+  EnterInstanceAPI<PPB_Flash_File_API> enter(instance);
   if (enter.failed())
     return PP_ERROR_BADARGUMENT;
-  return enter.functions()->GetFlashAPI()->OpenFileRef(instance, file_ref_id,
-                                                       mode, file);
+  return enter.functions()->OpenFileRef(instance, file_ref_id, mode, file);
 }
 
 int32_t QueryFile(PP_Resource file_ref_id, struct PP_FileInfo* info) {
   // TODO(brettw): this function should take an instance.
   // To work around this, use the PP_Instance from the resource.
   PP_Instance instance = GetInstanceFromFileRef(file_ref_id);
-  EnterInstance enter(instance);
+  EnterInstanceAPI<PPB_Flash_File_API> enter(instance);
   if (enter.failed())
     return PP_ERROR_BADARGUMENT;
-  return enter.functions()->GetFlashAPI()->QueryFileRef(instance, file_ref_id,
-                                                        info);
+  return enter.functions()->QueryFileRef(instance, file_ref_id, info);
 }
 
 const PPB_Flash_File_FileRef g_ppb_flash_file_fileref_thunk = {
diff --git a/ppapi/thunk/ppb_flash_file_modulelocal_thunk.cc b/ppapi/thunk/ppb_flash_file_modulelocal_thunk.cc
index 70c45d4..11962e41 100644
--- a/ppapi/thunk/ppb_flash_file_modulelocal_thunk.cc
+++ b/ppapi/thunk/ppb_flash_file_modulelocal_thunk.cc
@@ -5,8 +5,7 @@
 #include "ppapi/c/pp_errors.h"
 #include "ppapi/c/private/ppb_flash_file.h"
 #include "ppapi/thunk/enter.h"
-#include "ppapi/thunk/ppb_flash_api.h"
-#include "ppapi/thunk/ppb_instance_api.h"
+#include "ppapi/thunk/ppb_flash_file_api.h"
 #include "ppapi/thunk/thunk.h"
 
 namespace ppapi {
@@ -15,89 +14,77 @@
 namespace {
 
 bool CreateThreadAdapterForInstance(PP_Instance instance) {
-  EnterInstance enter(instance);
-  if (enter.failed())
-    return false;
-  return enter.functions()->GetFlashAPI()->CreateThreadAdapterForInstance(
-      instance);
+  return true;
 }
 
 void ClearThreadAdapterForInstance(PP_Instance instance) {
-  EnterInstance enter(instance);
-  if (enter.succeeded()) {
-    return enter.functions()->GetFlashAPI()->ClearThreadAdapterForInstance(
-        instance);
-  }
 }
 
 int32_t OpenFile(PP_Instance instance,
                  const char* path,
                  int32_t mode,
                  PP_FileHandle* file) {
-  EnterInstance enter(instance);
+  EnterInstanceAPI<PPB_Flash_File_API> enter(instance);
   if (enter.failed())
     return PP_ERROR_BADARGUMENT;
-  return enter.functions()->GetFlashAPI()->OpenFile(instance, path, mode, file);
+  return enter.functions()->OpenFile(instance, path, mode, file);
 }
 
 int32_t RenameFile(PP_Instance instance,
                    const char* path_from,
                    const char* path_to) {
-  EnterInstance enter(instance);
+  EnterInstanceAPI<PPB_Flash_File_API> enter(instance);
   if (enter.failed())
     return PP_ERROR_BADARGUMENT;
-  return enter.functions()->GetFlashAPI()->RenameFile(instance,
-                                                      path_from, path_to);
+  return enter.functions()->RenameFile(instance, path_from, path_to);
 }
 
 int32_t DeleteFileOrDir(PP_Instance instance,
                         const char* path,
                         PP_Bool recursive) {
-  EnterInstance enter(instance);
+  EnterInstanceAPI<PPB_Flash_File_API> enter(instance);
   if (enter.failed())
     return PP_ERROR_BADARGUMENT;
-  return enter.functions()->GetFlashAPI()->DeleteFileOrDir(instance, path,
-                                                           recursive);
+  return enter.functions()->DeleteFileOrDir(instance, path, recursive);
 }
 
 int32_t CreateDir(PP_Instance instance, const char* path) {
-  EnterInstance enter(instance);
+  EnterInstanceAPI<PPB_Flash_File_API> enter(instance);
   if (enter.failed())
     return PP_ERROR_BADARGUMENT;
-  return enter.functions()->GetFlashAPI()->CreateDir(instance, path);
+  return enter.functions()->CreateDir(instance, path);
 }
 
 int32_t QueryFile(PP_Instance instance, const char* path, PP_FileInfo* info) {
-  EnterInstance enter(instance);
+  EnterInstanceAPI<PPB_Flash_File_API> enter(instance);
   if (enter.failed())
     return PP_ERROR_BADARGUMENT;
-  return enter.functions()->GetFlashAPI()->QueryFile(instance, path, info);
+  return enter.functions()->QueryFile(instance, path, info);
 }
 
 int32_t GetDirContents(PP_Instance instance,
                        const char* path,
                        PP_DirContents_Dev** contents) {
-  EnterInstance enter(instance);
+  EnterInstanceAPI<PPB_Flash_File_API> enter(instance);
   if (enter.failed())
     return PP_ERROR_BADARGUMENT;
-  return enter.functions()->GetFlashAPI()->GetDirContents(instance, path,
-                                                          contents);
+  return enter.functions()->GetDirContents(instance, path, contents);
 }
 
 void FreeDirContents(PP_Instance instance,
                      PP_DirContents_Dev* contents) {
-  EnterInstance enter(instance);
+  EnterInstanceAPI<PPB_Flash_File_API> enter(instance);
   if (enter.succeeded())
-    enter.functions()->GetFlashAPI()->FreeDirContents(instance, contents);
+    enter.functions()->FreeDirContents(instance, contents);
 }
 
 int32_t CreateTemporaryFile(PP_Instance instance, PP_FileHandle* file) {
-  EnterInstance enter(instance);
+  EnterInstanceAPI<PPB_Flash_File_API> enter(instance);
   if (enter.failed())
     return PP_ERROR_BADARGUMENT;
 
   *file = PP_kInvalidFileHandle;
-  return enter.functions()->GetFlashAPI()->CreateTemporaryFile(instance, file);
+  return enter.functions()->CreateTemporaryFile(instance, file);
 }
 
 const PPB_Flash_File_ModuleLocal_3_0 g_ppb_flash_file_modulelocal_thunk_3_0 = {