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_ref_host.h"
      6 
      7 #include <string>
      8 
      9 #include "content/browser/renderer_host/pepper/pepper_external_file_ref_backend.h"
     10 #include "content/browser/renderer_host/pepper/pepper_file_system_browser_host.h"
     11 #include "content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.h"
     12 #include "ppapi/c/pp_errors.h"
     13 #include "ppapi/c/pp_file_info.h"
     14 #include "ppapi/c/pp_instance.h"
     15 #include "ppapi/c/pp_resource.h"
     16 #include "ppapi/host/dispatch_host_message.h"
     17 #include "ppapi/host/ppapi_host.h"
     18 #include "ppapi/proxy/ppapi_messages.h"
     19 #include "ppapi/shared_impl/file_ref_util.h"
     20 #include "webkit/browser/fileapi/file_permission_policy.h"
     21 
     22 using ppapi::host::ResourceHost;
     23 
     24 namespace content {
     25 
     26 PepperFileRefBackend::~PepperFileRefBackend() {
     27 }
     28 
     29 PepperFileRefHost::PepperFileRefHost(BrowserPpapiHost* host,
     30                                      PP_Instance instance,
     31                                      PP_Resource resource,
     32                                      PP_Resource file_system,
     33                                      const std::string& path)
     34     : ResourceHost(host->GetPpapiHost(), instance, resource),
     35       host_(host),
     36       fs_type_(PP_FILESYSTEMTYPE_INVALID) {
     37   if (!ppapi::IsValidInternalPath(path))
     38     return;
     39 
     40   int render_process_id;
     41   int unused;
     42   if (!host->GetRenderViewIDsForInstance(instance,
     43                                          &render_process_id,
     44                                          &unused)) {
     45     return;
     46   }
     47 
     48   ResourceHost* fs_resource_host =
     49       host->GetPpapiHost()->GetResourceHost(file_system);
     50   if (fs_resource_host == NULL) {
     51     DLOG(ERROR) << "Couldn't find FileSystem host: " << resource
     52                 << " path: " << path;
     53     return;
     54   }
     55 
     56   PepperFileSystemBrowserHost* fs_host = NULL;
     57   if (fs_resource_host->IsFileSystemHost())
     58     fs_host = static_cast<PepperFileSystemBrowserHost*>(fs_resource_host);
     59   if (fs_host == NULL) {
     60     DLOG(ERROR) << "Filesystem PP_Resource is not PepperFileSystemBrowserHost";
     61     return;
     62   }
     63 
     64   fs_type_ = fs_host->GetType();
     65   // TODO(teravest): Add support for isolated filesystems.
     66   if ((fs_type_ != PP_FILESYSTEMTYPE_LOCALPERSISTENT) &&
     67       (fs_type_ != PP_FILESYSTEMTYPE_LOCALTEMPORARY)) {
     68     DLOG(ERROR) << "Unsupported filesystem type: " << fs_type_;
     69     return;
     70   }
     71 
     72   backend_.reset(new PepperInternalFileRefBackend(
     73       host->GetPpapiHost(),
     74       render_process_id,
     75       base::AsWeakPtr(fs_host),
     76       path));
     77 }
     78 
     79 PepperFileRefHost::PepperFileRefHost(BrowserPpapiHost* host,
     80                                      PP_Instance instance,
     81                                      PP_Resource resource,
     82                                      const base::FilePath& external_path)
     83     : ResourceHost(host->GetPpapiHost(), instance, resource),
     84       host_(host),
     85       fs_type_(PP_FILESYSTEMTYPE_EXTERNAL) {
     86   if (!ppapi::IsValidExternalPath(external_path))
     87     return;
     88 
     89   int render_process_id;
     90   int unused;
     91   if (!host->GetRenderViewIDsForInstance(instance,
     92                                          &render_process_id,
     93                                          &unused)) {
     94     return;
     95   }
     96 
     97   backend_.reset(new PepperExternalFileRefBackend(host->GetPpapiHost(),
     98                                                   render_process_id,
     99                                                   external_path));
    100 }
    101 
    102 PepperFileRefHost::~PepperFileRefHost() {
    103 }
    104 
    105 bool PepperFileRefHost::IsFileRefHost() {
    106   return true;
    107 }
    108 
    109 PP_FileSystemType PepperFileRefHost::GetFileSystemType() const {
    110   return fs_type_;
    111 }
    112 
    113 fileapi::FileSystemURL PepperFileRefHost::GetFileSystemURL() const {
    114   if (backend_)
    115     return backend_->GetFileSystemURL();
    116   return fileapi::FileSystemURL();
    117 }
    118 
    119 std::string PepperFileRefHost::GetFileSystemURLSpec() const {
    120   if (backend_)
    121     return backend_->GetFileSystemURLSpec();
    122   return std::string();
    123 }
    124 
    125 base::FilePath PepperFileRefHost::GetExternalPath() const {
    126   if (backend_)
    127     return backend_->GetExternalPath();
    128   return base::FilePath();
    129 }
    130 
    131 int32_t PepperFileRefHost::CanRead() const {
    132   if (backend_)
    133     return backend_->CanRead();
    134   return PP_ERROR_FAILED;
    135 }
    136 
    137 int32_t PepperFileRefHost::CanWrite() const {
    138   if (backend_)
    139     return backend_->CanWrite();
    140   return PP_ERROR_FAILED;
    141 }
    142 
    143 int32_t PepperFileRefHost::CanCreate() const {
    144   if (backend_)
    145     return backend_->CanCreate();
    146   return PP_ERROR_FAILED;
    147 }
    148 
    149 int32_t PepperFileRefHost::CanReadWrite() const {
    150   if (backend_)
    151     return backend_->CanReadWrite();
    152   return PP_ERROR_FAILED;
    153 }
    154 
    155 int32_t PepperFileRefHost::OnResourceMessageReceived(
    156     const IPC::Message& msg,
    157     ppapi::host::HostMessageContext* context) {
    158   if (!backend_)
    159     return PP_ERROR_FAILED;
    160 
    161   IPC_BEGIN_MESSAGE_MAP(PepperFileRefHost, msg)
    162     PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileRef_MakeDirectory,
    163                                       OnMakeDirectory);
    164     PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileRef_Touch,
    165                                       OnTouch);
    166     PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_FileRef_Delete,
    167                                         OnDelete);
    168     PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileRef_Rename,
    169                                       OnRename);
    170     PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_FileRef_Query,
    171                                         OnQuery);
    172     PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(
    173         PpapiHostMsg_FileRef_ReadDirectoryEntries,
    174         OnReadDirectoryEntries);
    175     PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_FileRef_GetAbsolutePath,
    176                                         OnGetAbsolutePath);
    177 
    178   IPC_END_MESSAGE_MAP()
    179   return PP_ERROR_FAILED;
    180 }
    181 
    182 int32_t PepperFileRefHost::OnMakeDirectory(
    183     ppapi::host::HostMessageContext* context,
    184     bool make_ancestors) {
    185   int32_t rv = CanCreate();
    186   if (rv != PP_OK)
    187     return rv;
    188   return backend_->MakeDirectory(context->MakeReplyMessageContext(),
    189                                  make_ancestors);
    190 }
    191 
    192 int32_t PepperFileRefHost::OnTouch(ppapi::host::HostMessageContext* context,
    193                                    PP_Time last_access_time,
    194                                    PP_Time last_modified_time) {
    195   // TODO(teravest): Change this to be kWriteFilePermissions here and in
    196   // fileapi_message_filter.
    197   int32_t rv = CanCreate();
    198   if (rv != PP_OK)
    199     return rv;
    200   return backend_->Touch(context->MakeReplyMessageContext(),
    201                          last_access_time,
    202                          last_modified_time);
    203 }
    204 
    205 int32_t PepperFileRefHost::OnDelete(ppapi::host::HostMessageContext* context) {
    206   int32_t rv = CanWrite();
    207   if (rv != PP_OK)
    208     return rv;
    209   return backend_->Delete(context->MakeReplyMessageContext());
    210 }
    211 
    212 int32_t PepperFileRefHost::OnRename(ppapi::host::HostMessageContext* context,
    213                                     PP_Resource new_file_ref) {
    214   int32_t rv = CanReadWrite();
    215   if (rv != PP_OK)
    216     return rv;
    217 
    218   ResourceHost* resource_host =
    219       host_->GetPpapiHost()->GetResourceHost(new_file_ref);
    220   if (!resource_host)
    221     return PP_ERROR_BADRESOURCE;
    222 
    223   PepperFileRefHost* file_ref_host = NULL;
    224   if (resource_host->IsFileRefHost())
    225     file_ref_host = static_cast<PepperFileRefHost*>(resource_host);
    226   if (!file_ref_host)
    227     return PP_ERROR_BADRESOURCE;
    228 
    229   rv = file_ref_host->CanCreate();
    230   if (rv != PP_OK)
    231     return rv;
    232 
    233   return backend_->Rename(context->MakeReplyMessageContext(),
    234                           file_ref_host);
    235 }
    236 
    237 int32_t PepperFileRefHost::OnQuery(ppapi::host::HostMessageContext* context) {
    238   int32_t rv = CanRead();
    239   if (rv != PP_OK)
    240     return rv;
    241   return backend_->Query(context->MakeReplyMessageContext());
    242 }
    243 
    244 int32_t PepperFileRefHost::OnReadDirectoryEntries(
    245     ppapi::host::HostMessageContext* context) {
    246   int32_t rv = CanRead();
    247   if (rv != PP_OK)
    248     return rv;
    249   return backend_->ReadDirectoryEntries(context->MakeReplyMessageContext());
    250 }
    251 
    252 int32_t PepperFileRefHost::OnGetAbsolutePath(
    253     ppapi::host::HostMessageContext* context) {
    254   if (!host_->GetPpapiHost()->permissions().HasPermission(
    255       ppapi::PERMISSION_PRIVATE))
    256     return PP_ERROR_NOACCESS;
    257   return backend_->GetAbsolutePath(context->MakeReplyMessageContext());
    258 }
    259 
    260 }  // namespace content
    261