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