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 (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
);
37 create_info_
.display_name
= GetNameForInternalFilePath(
38 create_info_
.internal_path
);
40 name_var_
= new StringVar(create_info_
.display_name
);
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
);
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
));
60 FileRefResource::~FileRefResource() {
64 PP_Resource
FileRefResource::CreateFileRef(
65 Connection connection
,
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);
75 if (enter
.object()->GetType() != create_info
.file_system_type
) {
76 NOTREACHED() << "file system type mismatch with resource";
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
))
86 return (new FileRefResource(connection
,
88 create_info
))->GetReference();
91 thunk::PPB_FileRef_API
* FileRefResource::AsPPB_FileRef_API() {
95 PP_FileSystemType
FileRefResource::GetFileSystemType() const {
96 return create_info_
.file_system_type
;
99 PP_Var
FileRefResource::GetName() const {
100 return name_var_
->GetPPVar();
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();
109 PP_Resource
FileRefResource::GetParent() {
110 if (create_info_
.file_system_type
== PP_FILESYSTEMTYPE_EXTERNAL
)
113 size_t pos
= create_info_
.internal_path
.rfind('/');
114 CHECK(pos
!= std::string::npos
);
117 std::string parent_path
= create_info_
.internal_path
.substr(0, pos
);
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
;
126 return (new FileRefResource(connection(),
128 parent_info
))->GetReference();
131 int32_t FileRefResource::MakeDirectory(
132 PP_Bool make_ancestors
,
133 scoped_refptr
<TrackedCallback
> callback
) {
134 Call
<PpapiPluginMsg_FileRef_MakeDirectoryReply
>(
136 PpapiHostMsg_FileRef_MakeDirectory(PP_TRUE
== make_ancestors
),
137 base::Bind(&FileRefResource::RunTrackedCallback
, this, callback
));
138 return PP_OK_COMPLETIONPENDING
;
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
>(
146 PpapiHostMsg_FileRef_Touch(last_access_time
,
148 base::Bind(&FileRefResource::RunTrackedCallback
, this, callback
));
149 return PP_OK_COMPLETIONPENDING
;
152 int32_t FileRefResource::Delete(scoped_refptr
<TrackedCallback
> callback
) {
153 Call
<PpapiPluginMsg_FileRef_DeleteReply
>(
155 PpapiHostMsg_FileRef_Delete(),
156 base::Bind(&FileRefResource::RunTrackedCallback
, this, callback
));
157 return PP_OK_COMPLETIONPENDING
;
160 int32_t FileRefResource::Rename(PP_Resource new_file_ref
,
161 scoped_refptr
<TrackedCallback
> callback
) {
162 Call
<PpapiPluginMsg_FileRef_RenameReply
>(
164 PpapiHostMsg_FileRef_Rename(new_file_ref
),
165 base::Bind(&FileRefResource::RunTrackedCallback
, this, callback
));
166 return PP_OK_COMPLETIONPENDING
;
169 int32_t FileRefResource::Query(PP_FileInfo
* info
,
170 scoped_refptr
<TrackedCallback
> callback
) {
172 return PP_ERROR_BADARGUMENT
;
174 Call
<PpapiPluginMsg_FileRef_QueryReply
>(
176 PpapiHostMsg_FileRef_Query(),
177 base::Bind(&FileRefResource::OnQueryReply
, this, info
, callback
));
178 return PP_OK_COMPLETIONPENDING
;
181 int32_t FileRefResource::ReadDirectoryEntries(
182 const PP_ArrayOutput
& output
,
183 scoped_refptr
<TrackedCallback
> callback
) {
184 Call
<PpapiPluginMsg_FileRef_ReadDirectoryEntriesReply
>(
186 PpapiHostMsg_FileRef_ReadDirectoryEntries(),
187 base::Bind(&FileRefResource::OnDirectoryEntriesReply
,
188 this, output
, callback
));
189 return PP_OK_COMPLETIONPENDING
;
192 const FileRefCreateInfo
& FileRefResource::GetCreateInfo() const {
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
);
202 return PP_MakeUndefined();
203 absolute_path_var_
= new StringVar(absolute_path
);
205 return absolute_path_var_
->GetPPVar();
208 void FileRefResource::RunTrackedCallback(
209 scoped_refptr
<TrackedCallback
> callback
,
210 const ResourceMessageReplyParams
& params
) {
211 if (TrackedCallback::IsPending(callback
))
212 callback
->Run(params
.result());
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
))
223 if (params
.result() == PP_OK
)
225 callback
->Run(params
.result());
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
))
237 if (params
.result() == PP_OK
) {
238 ArrayWriter
writer(output
);
239 if (!writer
.is_valid()) {
240 callback
->Run(PP_ERROR_BADARGUMENT
);
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(),
250 entry
.file_type
= file_types
[i
];
251 entries
.push_back(entry
);
254 writer
.StoreVector(entries
);
256 callback
->Run(params
.result());