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 FileRef_CreateInfo
& 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
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
);
38 create_info_
.display_name
= GetNameForInternalFilePath(
39 create_info_
.internal_path
);
41 name_var_
= new StringVar(create_info_
.display_name
);
43 if (create_info_
.pending_host_resource_id
!= 0) {
44 AttachToPendingHost(BROWSER
, create_info_
.pending_host_resource_id
);
46 CHECK(create_info_
.file_system_type
!= PP_FILESYSTEMTYPE_EXTERNAL
);
47 SendCreate(BROWSER
, PpapiHostMsg_FileRef_CreateInternal(
48 create_info
.file_system_plugin_resource
,
49 create_info
.internal_path
));
53 FileRefResource::~FileRefResource() {
57 PP_Resource
FileRefResource::CreateFileRef(
58 Connection connection
,
60 const FileRef_CreateInfo
& create_info
) {
61 // If we have a valid file_system resource, ensure that its type matches that
62 // of the fs_type parameter.
63 if (create_info
.file_system_plugin_resource
!= 0) {
64 thunk::EnterResourceNoLock
<thunk::PPB_FileSystem_API
> enter(
65 create_info
.file_system_plugin_resource
, true);
68 if (enter
.object()->GetType() != create_info
.file_system_type
) {
69 NOTREACHED() << "file system type mismatch with resource";
74 if (create_info
.file_system_type
== PP_FILESYSTEMTYPE_LOCALPERSISTENT
||
75 create_info
.file_system_type
== PP_FILESYSTEMTYPE_LOCALTEMPORARY
) {
76 if (!IsValidInternalPath(create_info
.internal_path
))
79 return (new FileRefResource(connection
,
81 create_info
))->GetReference();
84 thunk::PPB_FileRef_API
* FileRefResource::AsPPB_FileRef_API() {
85 // TODO: return "this" once we update PPB_FileRef_API.
90 PP_FileSystemType
FileRefResource::GetFileSystemType() const {
91 return create_info_
.file_system_type
;
94 PP_Var
FileRefResource::GetName() const {
95 return name_var_
->GetPPVar();
98 PP_Var
FileRefResource::GetPath() const {
99 if (create_info_
.file_system_type
== PP_FILESYSTEMTYPE_EXTERNAL
)
100 return PP_MakeUndefined();
101 return path_var_
->GetPPVar();
104 PP_Resource
FileRefResource::GetParent() {
105 if (create_info_
.file_system_type
== PP_FILESYSTEMTYPE_EXTERNAL
)
108 size_t pos
= create_info_
.internal_path
.rfind('/');
109 CHECK(pos
!= std::string::npos
);
112 std::string parent_path
= create_info_
.internal_path
.substr(0, pos
);
114 ppapi::FileRef_CreateInfo parent_info
;
115 parent_info
.file_system_type
= create_info_
.file_system_type
;
116 parent_info
.internal_path
= parent_path
;
117 parent_info
.display_name
= GetNameForInternalFilePath(parent_path
);
118 parent_info
.file_system_plugin_resource
=
119 create_info_
.file_system_plugin_resource
;
121 return (new FileRefResource(connection(),
123 parent_info
))->GetReference();
126 int32_t FileRefResource::MakeDirectory(
127 PP_Bool make_ancestors
,
128 scoped_refptr
<TrackedCallback
> callback
) {
129 Call
<PpapiPluginMsg_FileRef_MakeDirectoryReply
>(
131 PpapiHostMsg_FileRef_MakeDirectory(PP_TRUE
== make_ancestors
),
132 base::Bind(&FileRefResource::RunTrackedCallback
, this, callback
));
133 return PP_OK_COMPLETIONPENDING
;
136 int32_t FileRefResource::Touch(PP_Time last_access_time
,
137 PP_Time last_modified_time
,
138 scoped_refptr
<TrackedCallback
> callback
) {
139 Call
<PpapiPluginMsg_FileRef_TouchReply
>(
141 PpapiHostMsg_FileRef_Touch(last_access_time
,
143 base::Bind(&FileRefResource::RunTrackedCallback
, this, callback
));
144 return PP_OK_COMPLETIONPENDING
;
147 int32_t FileRefResource::Delete(scoped_refptr
<TrackedCallback
> callback
) {
148 Call
<PpapiPluginMsg_FileRef_DeleteReply
>(
150 PpapiHostMsg_FileRef_Delete(),
151 base::Bind(&FileRefResource::RunTrackedCallback
, this, callback
));
152 return PP_OK_COMPLETIONPENDING
;
155 int32_t FileRefResource::Rename(PP_Resource new_file_ref
,
156 scoped_refptr
<TrackedCallback
> callback
) {
157 Call
<PpapiPluginMsg_FileRef_RenameReply
>(
159 PpapiHostMsg_FileRef_Rename(new_file_ref
),
160 base::Bind(&FileRefResource::RunTrackedCallback
, this, callback
));
161 return PP_OK_COMPLETIONPENDING
;
164 int32_t FileRefResource::Query(PP_FileInfo
* info
,
165 scoped_refptr
<TrackedCallback
> callback
) {
167 return PP_ERROR_BADARGUMENT
;
169 Call
<PpapiPluginMsg_FileRef_QueryReply
>(
171 PpapiHostMsg_FileRef_Query(),
172 base::Bind(&FileRefResource::OnQueryReply
, this, info
, callback
));
173 return PP_OK_COMPLETIONPENDING
;
176 int32_t FileRefResource::ReadDirectoryEntries(
177 const PP_ArrayOutput
& output
,
178 scoped_refptr
<TrackedCallback
> callback
) {
179 Call
<PpapiPluginMsg_FileRef_ReadDirectoryEntriesReply
>(
181 PpapiHostMsg_FileRef_ReadDirectoryEntries(),
182 base::Bind(&FileRefResource::OnDirectoryEntriesReply
,
183 this, output
, callback
));
184 return PP_OK_COMPLETIONPENDING
;
188 const FileRef_CreateInfo& FileRefResource::GetCreateInfo() const {
192 const PPB_FileRef_CreateInfo
& FileRefResource::GetCreateInfo() const {
195 PPB_FileRef_CreateInfo
*info
= new PPB_FileRef_CreateInfo();
199 // TODO(teravest): Remove this when we are finished moving to the new proxy.
200 int32_t FileRefResource::QueryInHost(linked_ptr
<PP_FileInfo
> info
,
201 scoped_refptr
<TrackedCallback
> callback
) {
203 return PP_ERROR_FAILED
;
206 // TODO(teravest): Remove this when we are finished moving to the new proxy.
207 int32_t FileRefResource::ReadDirectoryEntriesInHost(
208 linked_ptr
<std::vector
<ppapi::PPB_FileRef_CreateInfo
> > files
,
209 linked_ptr
<std::vector
<PP_FileType
> > file_types
,
210 scoped_refptr
<TrackedCallback
> callback
) {
212 return PP_ERROR_FAILED
;
215 PP_Var
FileRefResource::GetAbsolutePath() {
216 if (!absolute_path_var_
.get()) {
217 std::string absolute_path
;
218 int32_t result
= SyncCall
<PpapiPluginMsg_FileRef_GetAbsolutePathReply
>(
219 BROWSER
, PpapiHostMsg_FileRef_GetAbsolutePath(), &absolute_path
);
221 return PP_MakeUndefined();
222 absolute_path_var_
= new StringVar(absolute_path
);
224 return absolute_path_var_
->GetPPVar();
227 void FileRefResource::RunTrackedCallback(
228 scoped_refptr
<TrackedCallback
> callback
,
229 const ResourceMessageReplyParams
& params
) {
230 if (TrackedCallback::IsPending(callback
))
231 callback
->Run(params
.result());
234 void FileRefResource::OnQueryReply(
235 PP_FileInfo
* out_info
,
236 scoped_refptr
<TrackedCallback
> callback
,
237 const ResourceMessageReplyParams
& params
,
238 const PP_FileInfo
& info
) {
239 if (!TrackedCallback::IsPending(callback
))
242 if (params
.result() == PP_OK
)
244 callback
->Run(params
.result());
247 void FileRefResource::OnDirectoryEntriesReply(
248 const PP_ArrayOutput
& output
,
249 scoped_refptr
<TrackedCallback
> callback
,
250 const ResourceMessageReplyParams
& params
,
251 const std::vector
<ppapi::FileRef_CreateInfo
>& infos
,
252 const std::vector
<PP_FileType
>& file_types
) {
253 if (!TrackedCallback::IsPending(callback
))
256 if (params
.result() == PP_OK
) {
257 ArrayWriter
writer(output
);
258 if (!writer
.is_valid()) {
259 callback
->Run(PP_ERROR_BADARGUMENT
);
263 std::vector
<PP_DirectoryEntry
> entries
;
264 for (size_t i
= 0; i
< infos
.size(); ++i
) {
265 PP_DirectoryEntry entry
;
266 entry
.file_ref
= FileRefResource::CreateFileRef(connection(),
269 entry
.file_type
= file_types
[i
];
270 entries
.push_back(entry
);
273 writer
.StoreVector(entries
);
275 callback
->Run(params
.result());