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.
5 #include "ppapi/proxy/file_ref_resource.h"
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"
22 FileRefResource::FileRefResource(
23 Connection connection
,
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
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);
36 path_var_
= new StringVar(create_info_
.internal_path
);
37 create_info_
.display_name
= GetNameForInternalFilePath(
38 create_info_
.internal_path
);
40 DCHECK(!create_info_
.display_name
.empty());
42 name_var_
= new StringVar(create_info_
.display_name
);
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
);
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
));
62 FileRefResource::~FileRefResource() {
66 PP_Resource
FileRefResource::CreateFileRef(
67 Connection connection
,
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);
77 if (enter
.object()->GetType() != create_info
.file_system_type
) {
78 NOTREACHED() << "file system type mismatch with resource";
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
))
88 return (new FileRefResource(connection
,
90 create_info
))->GetReference();
93 thunk::PPB_FileRef_API
* FileRefResource::AsPPB_FileRef_API() {
97 PP_FileSystemType
FileRefResource::GetFileSystemType() const {
98 return create_info_
.file_system_type
;
101 PP_Var
FileRefResource::GetName() const {
102 return name_var_
->GetPPVar();
105 PP_Var
FileRefResource::GetPath() const {
106 if (!uses_internal_paths())
107 return PP_MakeUndefined();
108 return path_var_
->GetPPVar();
111 PP_Resource
FileRefResource::GetParent() {
112 if (!uses_internal_paths())
115 size_t pos
= create_info_
.internal_path
.rfind('/');
116 CHECK(pos
!= std::string::npos
);
119 std::string parent_path
= create_info_
.internal_path
.substr(0, pos
);
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
;
128 return (new FileRefResource(connection(),
130 parent_info
))->GetReference();
133 int32_t FileRefResource::MakeDirectory(
134 int32_t make_directory_flags
,
135 scoped_refptr
<TrackedCallback
> callback
) {
136 Call
<PpapiPluginMsg_FileRef_MakeDirectoryReply
>(
138 PpapiHostMsg_FileRef_MakeDirectory(make_directory_flags
),
139 base::Bind(&FileRefResource::RunTrackedCallback
, this, callback
));
140 return PP_OK_COMPLETIONPENDING
;
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
>(
148 PpapiHostMsg_FileRef_Touch(last_access_time
,
150 base::Bind(&FileRefResource::RunTrackedCallback
, this, callback
));
151 return PP_OK_COMPLETIONPENDING
;
154 int32_t FileRefResource::Delete(scoped_refptr
<TrackedCallback
> callback
) {
155 Call
<PpapiPluginMsg_FileRef_DeleteReply
>(
157 PpapiHostMsg_FileRef_Delete(),
158 base::Bind(&FileRefResource::RunTrackedCallback
, this, callback
));
159 return PP_OK_COMPLETIONPENDING
;
162 int32_t FileRefResource::Rename(PP_Resource new_file_ref
,
163 scoped_refptr
<TrackedCallback
> callback
) {
164 Call
<PpapiPluginMsg_FileRef_RenameReply
>(
166 PpapiHostMsg_FileRef_Rename(new_file_ref
),
167 base::Bind(&FileRefResource::RunTrackedCallback
, this, callback
));
168 return PP_OK_COMPLETIONPENDING
;
171 int32_t FileRefResource::Query(PP_FileInfo
* info
,
172 scoped_refptr
<TrackedCallback
> callback
) {
174 return PP_ERROR_BADARGUMENT
;
176 Call
<PpapiPluginMsg_FileRef_QueryReply
>(
178 PpapiHostMsg_FileRef_Query(),
179 base::Bind(&FileRefResource::OnQueryReply
, this, info
, callback
));
180 return PP_OK_COMPLETIONPENDING
;
183 int32_t FileRefResource::ReadDirectoryEntries(
184 const PP_ArrayOutput
& output
,
185 scoped_refptr
<TrackedCallback
> callback
) {
186 Call
<PpapiPluginMsg_FileRef_ReadDirectoryEntriesReply
>(
188 PpapiHostMsg_FileRef_ReadDirectoryEntries(),
189 base::Bind(&FileRefResource::OnDirectoryEntriesReply
,
190 this, output
, callback
));
191 return PP_OK_COMPLETIONPENDING
;
194 const FileRefCreateInfo
& FileRefResource::GetCreateInfo() const {
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
);
204 return PP_MakeUndefined();
205 absolute_path_var_
= new StringVar(absolute_path
);
207 return absolute_path_var_
->GetPPVar();
210 void FileRefResource::RunTrackedCallback(
211 scoped_refptr
<TrackedCallback
> callback
,
212 const ResourceMessageReplyParams
& params
) {
213 if (TrackedCallback::IsPending(callback
))
214 callback
->Run(params
.result());
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
))
225 if (params
.result() == PP_OK
)
227 callback
->Run(params
.result());
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
))
239 if (params
.result() == PP_OK
) {
240 ArrayWriter
writer(output
);
241 if (!writer
.is_valid()) {
242 callback
->Run(PP_ERROR_BADARGUMENT
);
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(),
252 entry
.file_type
= file_types
[i
];
253 entries
.push_back(entry
);
256 writer
.StoreVector(entries
);
258 callback
->Run(params
.result());
261 bool FileRefResource::uses_internal_paths() const {
262 return (create_info_
.file_system_type
!= PP_FILESYSTEMTYPE_EXTERNAL
) ||
263 !create_info_
.internal_path
.empty();