• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
FileRefResource(Connection connection,PP_Instance instance,const FileRefCreateInfo & create_info)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 
~FileRefResource()62 FileRefResource::~FileRefResource() {
63 }
64 
65 // static
CreateFileRef(Connection connection,PP_Instance instance,const FileRefCreateInfo & create_info)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 
AsPPB_FileRef_API()93 thunk::PPB_FileRef_API* FileRefResource::AsPPB_FileRef_API() {
94   return this;
95 }
96 
GetFileSystemType() const97 PP_FileSystemType FileRefResource::GetFileSystemType() const {
98   return create_info_.file_system_type;
99 }
100 
GetName() const101 PP_Var FileRefResource::GetName() const {
102   return name_var_->GetPPVar();
103 }
104 
GetPath() const105 PP_Var FileRefResource::GetPath() const {
106   if (!uses_internal_paths())
107     return PP_MakeUndefined();
108   return path_var_->GetPPVar();
109 }
110 
GetParent()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 
MakeDirectory(int32_t make_directory_flags,scoped_refptr<TrackedCallback> callback)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 
Touch(PP_Time last_access_time,PP_Time last_modified_time,scoped_refptr<TrackedCallback> callback)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 
Delete(scoped_refptr<TrackedCallback> callback)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 
Rename(PP_Resource new_file_ref,scoped_refptr<TrackedCallback> callback)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 
Query(PP_FileInfo * info,scoped_refptr<TrackedCallback> callback)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 
ReadDirectoryEntries(const PP_ArrayOutput & output,scoped_refptr<TrackedCallback> callback)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 
GetCreateInfo() const194 const FileRefCreateInfo& FileRefResource::GetCreateInfo() const {
195   return create_info_;
196 }
197 
GetAbsolutePath()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 
RunTrackedCallback(scoped_refptr<TrackedCallback> callback,const ResourceMessageReplyParams & params)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 
OnQueryReply(PP_FileInfo * out_info,scoped_refptr<TrackedCallback> callback,const ResourceMessageReplyParams & params,const PP_FileInfo & info)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 
OnDirectoryEntriesReply(const PP_ArrayOutput & output,scoped_refptr<TrackedCallback> callback,const ResourceMessageReplyParams & params,const std::vector<ppapi::FileRefCreateInfo> & infos,const std::vector<PP_FileType> & file_types)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 
uses_internal_paths() const261 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