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