Home | History | Annotate | Download | only in proxy
      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 "ppapi/proxy/file_ref_resource.h"
      6 
      7 #include "ppapi/c/pp_directory_entry.h"
      8 #include "ppapi/c/pp_instance.h"
      9 #include "ppapi/c/pp_resource.h"
     10 #include "ppapi/proxy/ppapi_messages.h"
     11 #include "ppapi/shared_impl/array_writer.h"
     12 #include "ppapi/shared_impl/file_ref_util.h"
     13 #include "ppapi/shared_impl/resource.h"
     14 #include "ppapi/shared_impl/resource_tracker.h"
     15 #include "ppapi/shared_impl/var.h"
     16 #include "ppapi/thunk/enter.h"
     17 #include "ppapi/thunk/ppb_file_system_api.h"
     18 
     19 namespace ppapi {
     20 namespace proxy {
     21 
     22 FileRefResource::FileRefResource(
     23     Connection connection,
     24     PP_Instance instance,
     25     const FileRefCreateInfo& create_info)
     26     : PluginResource(connection, instance),
     27       create_info_(create_info),
     28       file_system_resource_(create_info.file_system_plugin_resource) {
     29   if (create_info_.file_system_type != PP_FILESYSTEMTYPE_EXTERNAL) {
     30     // If path ends with a slash, then normalize it away unless path is
     31     // the root path.
     32     int path_size = create_info_.internal_path.size();
     33     if (path_size > 1 && create_info_.internal_path.at(path_size - 1) == '/')
     34       create_info_.internal_path.erase(path_size - 1, 1);
     35 
     36     path_var_ = new StringVar(create_info_.internal_path);
     37     create_info_.display_name = GetNameForInternalFilePath(
     38         create_info_.internal_path);
     39   }
     40   name_var_ = new StringVar(create_info_.display_name);
     41 
     42   if (create_info_.browser_pending_host_resource_id != 0 &&
     43       create_info_.renderer_pending_host_resource_id != 0) {
     44     AttachToPendingHost(BROWSER, create_info_.browser_pending_host_resource_id);
     45     AttachToPendingHost(RENDERER,
     46                         create_info_.renderer_pending_host_resource_id);
     47   } else {
     48     CHECK(create_info_.browser_pending_host_resource_id == 0);
     49     CHECK(create_info_.renderer_pending_host_resource_id == 0);
     50     CHECK(create_info_.file_system_type != PP_FILESYSTEMTYPE_EXTERNAL);
     51     SendCreate(BROWSER, PpapiHostMsg_FileRef_CreateInternal(
     52         create_info.file_system_plugin_resource,
     53         create_info.internal_path));
     54     SendCreate(RENDERER, PpapiHostMsg_FileRef_CreateInternal(
     55         create_info.file_system_plugin_resource,
     56         create_info.internal_path));
     57   }
     58 }
     59 
     60 FileRefResource::~FileRefResource() {
     61 }
     62 
     63 //static
     64 PP_Resource FileRefResource::CreateFileRef(
     65     Connection connection,
     66     PP_Instance instance,
     67     const FileRefCreateInfo& create_info) {
     68   // If we have a valid file_system resource, ensure that its type matches that
     69   // of the fs_type parameter.
     70   if (create_info.file_system_plugin_resource != 0) {
     71     thunk::EnterResourceNoLock<thunk::PPB_FileSystem_API> enter(
     72         create_info.file_system_plugin_resource, true);
     73     if (enter.failed())
     74       return 0;
     75     if (enter.object()->GetType() != create_info.file_system_type) {
     76       NOTREACHED() << "file system type mismatch with resource";
     77       return 0;
     78     }
     79   }
     80 
     81   if (create_info.file_system_type == PP_FILESYSTEMTYPE_LOCALPERSISTENT ||
     82       create_info.file_system_type == PP_FILESYSTEMTYPE_LOCALTEMPORARY) {
     83     if (!IsValidInternalPath(create_info.internal_path))
     84       return 0;
     85   }
     86   return (new FileRefResource(connection,
     87                               instance,
     88                               create_info))->GetReference();
     89 }
     90 
     91 thunk::PPB_FileRef_API* FileRefResource::AsPPB_FileRef_API() {
     92   return this;
     93 }
     94 
     95 PP_FileSystemType FileRefResource::GetFileSystemType() const {
     96   return create_info_.file_system_type;
     97 }
     98 
     99 PP_Var FileRefResource::GetName() const {
    100   return name_var_->GetPPVar();
    101 }
    102 
    103 PP_Var FileRefResource::GetPath() const {
    104   if (create_info_.file_system_type == PP_FILESYSTEMTYPE_EXTERNAL)
    105     return PP_MakeUndefined();
    106   return path_var_->GetPPVar();
    107 }
    108 
    109 PP_Resource FileRefResource::GetParent() {
    110   if (create_info_.file_system_type == PP_FILESYSTEMTYPE_EXTERNAL)
    111     return 0;
    112 
    113   size_t pos = create_info_.internal_path.rfind('/');
    114   CHECK(pos != std::string::npos);
    115   if (pos == 0)
    116     pos++;
    117   std::string parent_path = create_info_.internal_path.substr(0, pos);
    118 
    119   ppapi::FileRefCreateInfo parent_info;
    120   parent_info.file_system_type = create_info_.file_system_type;
    121   parent_info.internal_path = parent_path;
    122   parent_info.display_name = GetNameForInternalFilePath(parent_path);
    123   parent_info.file_system_plugin_resource =
    124       create_info_.file_system_plugin_resource;
    125 
    126   return (new FileRefResource(connection(),
    127                               pp_instance(),
    128                               parent_info))->GetReference();
    129 }
    130 
    131 int32_t FileRefResource::MakeDirectory(
    132     PP_Bool make_ancestors,
    133     scoped_refptr<TrackedCallback> callback) {
    134   Call<PpapiPluginMsg_FileRef_MakeDirectoryReply>(
    135       BROWSER,
    136       PpapiHostMsg_FileRef_MakeDirectory(PP_TRUE == make_ancestors),
    137       base::Bind(&FileRefResource::RunTrackedCallback, this, callback));
    138   return PP_OK_COMPLETIONPENDING;
    139 }
    140 
    141 int32_t FileRefResource::Touch(PP_Time last_access_time,
    142                                PP_Time last_modified_time,
    143                                scoped_refptr<TrackedCallback> callback) {
    144   Call<PpapiPluginMsg_FileRef_TouchReply>(
    145       BROWSER,
    146       PpapiHostMsg_FileRef_Touch(last_access_time,
    147                                  last_modified_time),
    148       base::Bind(&FileRefResource::RunTrackedCallback, this, callback));
    149   return PP_OK_COMPLETIONPENDING;
    150 }
    151 
    152 int32_t FileRefResource::Delete(scoped_refptr<TrackedCallback> callback) {
    153   Call<PpapiPluginMsg_FileRef_DeleteReply>(
    154       BROWSER,
    155       PpapiHostMsg_FileRef_Delete(),
    156       base::Bind(&FileRefResource::RunTrackedCallback, this, callback));
    157   return PP_OK_COMPLETIONPENDING;
    158 }
    159 
    160 int32_t FileRefResource::Rename(PP_Resource new_file_ref,
    161                                 scoped_refptr<TrackedCallback> callback) {
    162   Call<PpapiPluginMsg_FileRef_RenameReply>(
    163       BROWSER,
    164       PpapiHostMsg_FileRef_Rename(new_file_ref),
    165       base::Bind(&FileRefResource::RunTrackedCallback, this, callback));
    166   return PP_OK_COMPLETIONPENDING;
    167 }
    168 
    169 int32_t FileRefResource::Query(PP_FileInfo* info,
    170                                scoped_refptr<TrackedCallback> callback) {
    171   if (info == NULL)
    172     return PP_ERROR_BADARGUMENT;
    173 
    174   Call<PpapiPluginMsg_FileRef_QueryReply>(
    175       BROWSER,
    176       PpapiHostMsg_FileRef_Query(),
    177       base::Bind(&FileRefResource::OnQueryReply, this, info, callback));
    178   return PP_OK_COMPLETIONPENDING;
    179 }
    180 
    181 int32_t FileRefResource::ReadDirectoryEntries(
    182     const PP_ArrayOutput& output,
    183     scoped_refptr<TrackedCallback> callback) {
    184   Call<PpapiPluginMsg_FileRef_ReadDirectoryEntriesReply>(
    185       BROWSER,
    186       PpapiHostMsg_FileRef_ReadDirectoryEntries(),
    187       base::Bind(&FileRefResource::OnDirectoryEntriesReply,
    188                  this, output, callback));
    189   return PP_OK_COMPLETIONPENDING;
    190 }
    191 
    192 const FileRefCreateInfo& FileRefResource::GetCreateInfo() const {
    193   return create_info_;
    194 }
    195 
    196 PP_Var FileRefResource::GetAbsolutePath() {
    197   if (!absolute_path_var_.get()) {
    198     std::string absolute_path;
    199     int32_t result = SyncCall<PpapiPluginMsg_FileRef_GetAbsolutePathReply>(
    200         BROWSER, PpapiHostMsg_FileRef_GetAbsolutePath(), &absolute_path);
    201     if (result != PP_OK)
    202       return PP_MakeUndefined();
    203     absolute_path_var_ = new StringVar(absolute_path);
    204   }
    205   return absolute_path_var_->GetPPVar();
    206 }
    207 
    208 void FileRefResource::RunTrackedCallback(
    209     scoped_refptr<TrackedCallback> callback,
    210     const ResourceMessageReplyParams& params) {
    211   if (TrackedCallback::IsPending(callback))
    212     callback->Run(params.result());
    213 }
    214 
    215 void FileRefResource::OnQueryReply(
    216     PP_FileInfo* out_info,
    217     scoped_refptr<TrackedCallback> callback,
    218     const ResourceMessageReplyParams& params,
    219     const PP_FileInfo& info) {
    220   if (!TrackedCallback::IsPending(callback))
    221     return;
    222 
    223   if (params.result() == PP_OK)
    224     *out_info = info;
    225   callback->Run(params.result());
    226 }
    227 
    228 void FileRefResource::OnDirectoryEntriesReply(
    229     const PP_ArrayOutput& output,
    230     scoped_refptr<TrackedCallback> callback,
    231     const ResourceMessageReplyParams& params,
    232     const std::vector<ppapi::FileRefCreateInfo>& infos,
    233     const std::vector<PP_FileType>& file_types) {
    234   if (!TrackedCallback::IsPending(callback))
    235     return;
    236 
    237   if (params.result() == PP_OK) {
    238     ArrayWriter writer(output);
    239     if (!writer.is_valid()) {
    240       callback->Run(PP_ERROR_BADARGUMENT);
    241       return;
    242     }
    243 
    244     std::vector<PP_DirectoryEntry> entries;
    245     for (size_t i = 0; i < infos.size(); ++i) {
    246       PP_DirectoryEntry entry;
    247       entry.file_ref = FileRefResource::CreateFileRef(connection(),
    248                                                       pp_instance(),
    249                                                       infos[i]);
    250       entry.file_type = file_types[i];
    251       entries.push_back(entry);
    252     }
    253 
    254     writer.StoreVector(entries);
    255   }
    256   callback->Run(params.result());
    257 }
    258 
    259 }  // namespace proxy
    260 }  // namespace ppapi
    261