Home | History | Annotate | Download | only in pepper
      1 // Copyright 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "content/browser/renderer_host/pepper/pepper_file_system_browser_host.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/callback.h"
      9 #include "content/public/browser/browser_ppapi_host.h"
     10 #include "content/public/browser/browser_thread.h"
     11 #include "content/public/browser/render_process_host.h"
     12 #include "content/public/browser/storage_partition.h"
     13 #include "ppapi/c/pp_errors.h"
     14 #include "ppapi/host/dispatch_host_message.h"
     15 #include "ppapi/host/ppapi_host.h"
     16 #include "ppapi/proxy/ppapi_messages.h"
     17 #include "ppapi/shared_impl/file_type_conversion.h"
     18 #include "webkit/browser/fileapi/file_system_context.h"
     19 #include "webkit/browser/fileapi/file_system_operation_runner.h"
     20 #include "webkit/common/fileapi/file_system_util.h"
     21 
     22 namespace content {
     23 
     24 namespace {
     25 
     26 // TODO(teravest): Move this function to be shared and public in fileapi.
     27 bool LooksLikeAGuid(const std::string& fsid) {
     28   const size_t kExpectedFsIdSize = 32;
     29   if (fsid.size() != kExpectedFsIdSize)
     30     return false;
     31   for (std::string::const_iterator it = fsid.begin(); it != fsid.end(); ++it) {
     32     if (('A' <= *it && *it <= 'F') || ('0' <= *it && *it <= '9'))
     33       continue;
     34     return false;
     35   }
     36   return true;
     37 }
     38 
     39 scoped_refptr<fileapi::FileSystemContext>
     40 GetFileSystemContextFromRenderId(int render_process_id) {
     41   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     42   RenderProcessHost* render_process_host =
     43       RenderProcessHost::FromID(render_process_id);
     44   if (!render_process_host)
     45     return NULL;
     46   StoragePartition* storage_partition =
     47       render_process_host->GetStoragePartition();
     48   if (!storage_partition)
     49     return NULL;
     50   return storage_partition->GetFileSystemContext();
     51 }
     52 
     53 }  // namespace
     54 
     55 PepperFileSystemBrowserHost::PepperFileSystemBrowserHost(BrowserPpapiHost* host,
     56                                                          PP_Instance instance,
     57                                                          PP_Resource resource,
     58                                                          PP_FileSystemType type)
     59     : ResourceHost(host->GetPpapiHost(), instance, resource),
     60       browser_ppapi_host_(host),
     61       weak_factory_(this),
     62       type_(type),
     63       opened_(false),
     64       fs_context_(NULL),
     65       called_open_(false) {
     66 }
     67 
     68 PepperFileSystemBrowserHost::~PepperFileSystemBrowserHost() {
     69   if (fs_context_.get())
     70     fs_context_->operation_runner()->Shutdown();
     71 }
     72 
     73 int32_t PepperFileSystemBrowserHost::OnResourceMessageReceived(
     74     const IPC::Message& msg,
     75     ppapi::host::HostMessageContext* context) {
     76   IPC_BEGIN_MESSAGE_MAP(PepperFileSystemBrowserHost, msg)
     77     PPAPI_DISPATCH_HOST_RESOURCE_CALL(
     78         PpapiHostMsg_FileSystem_Open,
     79         OnHostMsgOpen)
     80     PPAPI_DISPATCH_HOST_RESOURCE_CALL(
     81         PpapiHostMsg_FileSystem_InitIsolatedFileSystem,
     82         OnHostMsgInitIsolatedFileSystem)
     83   IPC_END_MESSAGE_MAP()
     84   return PP_ERROR_FAILED;
     85 }
     86 
     87 bool PepperFileSystemBrowserHost::IsFileSystemHost() {
     88   return true;
     89 }
     90 
     91 int32_t PepperFileSystemBrowserHost::OnHostMsgOpen(
     92     ppapi::host::HostMessageContext* context,
     93     int64_t /* unused */) {
     94   // TODO(raymes): The file system size is now unused by FileSystemDispatcher.
     95   // Figure out why. Why is the file system size signed?
     96 
     97   // Not allow multiple opens.
     98   if (called_open_)
     99     return PP_ERROR_INPROGRESS;
    100   called_open_ = true;
    101 
    102   fileapi::FileSystemType file_system_type;
    103   switch (type_) {
    104     case PP_FILESYSTEMTYPE_LOCALTEMPORARY:
    105       file_system_type = fileapi::kFileSystemTypeTemporary;
    106       break;
    107     case PP_FILESYSTEMTYPE_LOCALPERSISTENT:
    108       file_system_type = fileapi::kFileSystemTypePersistent;
    109       break;
    110     case PP_FILESYSTEMTYPE_EXTERNAL:
    111       file_system_type = fileapi::kFileSystemTypeExternal;
    112       break;
    113     default:
    114       return PP_ERROR_FAILED;
    115   }
    116 
    117   int render_process_id = 0;
    118   int unused;
    119   if (!browser_ppapi_host_->GetRenderViewIDsForInstance(pp_instance(),
    120                                                         &render_process_id,
    121                                                         &unused)) {
    122       return PP_ERROR_FAILED;
    123   }
    124   BrowserThread::PostTaskAndReplyWithResult(
    125       BrowserThread::UI,
    126       FROM_HERE,
    127       base::Bind(&GetFileSystemContextFromRenderId, render_process_id),
    128       base::Bind(&PepperFileSystemBrowserHost::GotFileSystemContext,
    129                  weak_factory_.GetWeakPtr(),
    130                  context->MakeReplyMessageContext(),
    131                  file_system_type));
    132   return PP_OK_COMPLETIONPENDING;
    133 }
    134 
    135 void PepperFileSystemBrowserHost::GotFileSystemContext(
    136     ppapi::host::ReplyMessageContext reply_context,
    137     fileapi::FileSystemType file_system_type,
    138     scoped_refptr<fileapi::FileSystemContext> fs_context) {
    139   if (!fs_context.get()) {
    140     OpenFileSystemComplete(
    141         reply_context, base::PLATFORM_FILE_ERROR_FAILED, std::string(), GURL());
    142     return;
    143   }
    144   GURL origin = browser_ppapi_host_->GetDocumentURLForInstance(
    145       pp_instance()).GetOrigin();
    146   fs_context->OpenFileSystem(origin, file_system_type,
    147       fileapi::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
    148       base::Bind(&PepperFileSystemBrowserHost::OpenFileSystemComplete,
    149                  weak_factory_.GetWeakPtr(),
    150                  reply_context));
    151   fs_context_ = fs_context;
    152 }
    153 
    154 void PepperFileSystemBrowserHost::OpenFileSystemComplete(
    155     ppapi::host::ReplyMessageContext reply_context,
    156     base::PlatformFileError error,
    157     const std::string& /* unused */,
    158     const GURL& root) {
    159   int32 pp_error = ppapi::PlatformFileErrorToPepperError(error);
    160   if (pp_error == PP_OK) {
    161     opened_ = true;
    162     root_url_ = root;
    163   }
    164   reply_context.params.set_result(pp_error);
    165   host()->SendReply(reply_context, PpapiPluginMsg_FileSystem_OpenReply());
    166 }
    167 
    168 int32_t PepperFileSystemBrowserHost::OnHostMsgInitIsolatedFileSystem(
    169     ppapi::host::HostMessageContext* context,
    170     const std::string& fsid) {
    171   called_open_ = true;
    172   // Do a sanity check.
    173   if (!LooksLikeAGuid(fsid))
    174     return PP_ERROR_BADARGUMENT;
    175   const GURL& url =
    176       browser_ppapi_host_->GetDocumentURLForInstance(pp_instance());
    177   root_url_ = GURL(fileapi::GetIsolatedFileSystemRootURIString(
    178       url.GetOrigin(), fsid, "crxfs"));
    179   opened_ = true;
    180   return PP_OK;
    181 }
    182 
    183 }  // namespace content
    184