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 "base/numerics/safe_conversions.h"
8 #include "ppapi/c/pp_directory_entry.h"
9 #include "ppapi/c/pp_instance.h"
10 #include "ppapi/c/pp_resource.h"
11 #include "ppapi/proxy/ppapi_messages.h"
12 #include "ppapi/shared_impl/array_writer.h"
13 #include "ppapi/shared_impl/file_ref_util.h"
14 #include "ppapi/shared_impl/resource.h"
15 #include "ppapi/shared_impl/resource_tracker.h"
16 #include "ppapi/shared_impl/var.h"
17 #include "ppapi/thunk/enter.h"
18 #include "ppapi/thunk/ppb_file_system_api.h"
23 FileRefResource::FileRefResource(
24 Connection connection
,
26 const FileRefCreateInfo
& create_info
)
27 : PluginResource(connection
, instance
),
28 create_info_(create_info
),
29 file_system_resource_(create_info
.file_system_plugin_resource
) {
30 if (uses_internal_paths()) {
31 // If path ends with a slash, then normalize it away unless path is
33 int path_size
= base::checked_cast
<int>(create_info_
.internal_path
.size());
34 if (path_size
> 1 && create_info_
.internal_path
.at(path_size
- 1) == '/')
35 create_info_
.internal_path
.erase(path_size
- 1, 1);
37 path_var_
= new StringVar(create_info_
.internal_path
);
38 create_info_
.display_name
= GetNameForInternalFilePath(
39 create_info_
.internal_path
);
41 DCHECK(!create_info_
.display_name
.empty());
43 name_var_
= new StringVar(create_info_
.display_name
);
45 if (create_info_
.browser_pending_host_resource_id
!= 0 &&
46 create_info_
.renderer_pending_host_resource_id
!= 0) {
47 AttachToPendingHost(BROWSER
, create_info_
.browser_pending_host_resource_id
);
48 AttachToPendingHost(RENDERER
,
49 create_info_
.renderer_pending_host_resource_id
);
51 CHECK_EQ(0, create_info_
.browser_pending_host_resource_id
);
52 CHECK_EQ(0, create_info_
.renderer_pending_host_resource_id
);
53 CHECK(uses_internal_paths());
54 SendCreate(BROWSER
, PpapiHostMsg_FileRef_CreateForFileAPI(
55 create_info
.file_system_plugin_resource
,
56 create_info
.internal_path
));
57 SendCreate(RENDERER
, PpapiHostMsg_FileRef_CreateForFileAPI(
58 create_info
.file_system_plugin_resource
,
59 create_info
.internal_path
));
63 FileRefResource::~FileRefResource() {
67 PP_Resource
FileRefResource::CreateFileRef(
68 Connection connection
,
70 const FileRefCreateInfo
& create_info
) {
71 // If we have a valid file_system resource, ensure that its type matches that
72 // of the fs_type parameter.
73 if (create_info
.file_system_plugin_resource
!= 0) {
74 thunk::EnterResourceNoLock
<thunk::PPB_FileSystem_API
> enter(
75 create_info
.file_system_plugin_resource
, true);
78 if (enter
.object()->GetType() != create_info
.file_system_type
) {
79 NOTREACHED() << "file system type mismatch with resource";
84 if (create_info
.file_system_type
== PP_FILESYSTEMTYPE_LOCALPERSISTENT
||
85 create_info
.file_system_type
== PP_FILESYSTEMTYPE_LOCALTEMPORARY
) {
86 if (!IsValidInternalPath(create_info
.internal_path
))
89 return (new FileRefResource(connection
,
91 create_info
))->GetReference();
94 thunk::PPB_FileRef_API
* FileRefResource::AsPPB_FileRef_API() {
98 PP_FileSystemType
FileRefResource::GetFileSystemType() const {
99 return create_info_
.file_system_type
;
102 PP_Var
FileRefResource::GetName() const {
103 return name_var_
->GetPPVar();
106 PP_Var
FileRefResource::GetPath() const {
107 if (!uses_internal_paths())
108 return PP_MakeUndefined();
109 return path_var_
->GetPPVar();
112 PP_Resource
FileRefResource::GetParent() {
113 if (!uses_internal_paths())
116 size_t pos
= create_info_
.internal_path
.rfind('/');
117 CHECK(pos
!= std::string::npos
);
120 std::string parent_path
= create_info_
.internal_path
.substr(0, pos
);
122 ppapi::FileRefCreateInfo parent_info
;
123 parent_info
.file_system_type
= create_info_
.file_system_type
;
124 parent_info
.internal_path
= parent_path
;
125 parent_info
.display_name
= GetNameForInternalFilePath(parent_path
);
126 parent_info
.file_system_plugin_resource
=
127 create_info_
.file_system_plugin_resource
;
129 return (new FileRefResource(connection(),
131 parent_info
))->GetReference();
134 int32_t FileRefResource::MakeDirectory(
135 int32_t make_directory_flags
,
136 scoped_refptr
<TrackedCallback
> callback
) {
137 Call
<PpapiPluginMsg_FileRef_MakeDirectoryReply
>(
139 PpapiHostMsg_FileRef_MakeDirectory(make_directory_flags
),
140 base::Bind(&FileRefResource::RunTrackedCallback
, this, callback
));
141 return PP_OK_COMPLETIONPENDING
;
144 int32_t FileRefResource::Touch(PP_Time last_access_time
,
145 PP_Time last_modified_time
,
146 scoped_refptr
<TrackedCallback
> callback
) {
147 Call
<PpapiPluginMsg_FileRef_TouchReply
>(
149 PpapiHostMsg_FileRef_Touch(last_access_time
,
151 base::Bind(&FileRefResource::RunTrackedCallback
, this, callback
));
152 return PP_OK_COMPLETIONPENDING
;
155 int32_t FileRefResource::Delete(scoped_refptr
<TrackedCallback
> callback
) {
156 Call
<PpapiPluginMsg_FileRef_DeleteReply
>(
158 PpapiHostMsg_FileRef_Delete(),
159 base::Bind(&FileRefResource::RunTrackedCallback
, this, callback
));
160 return PP_OK_COMPLETIONPENDING
;
163 int32_t FileRefResource::Rename(PP_Resource new_file_ref
,
164 scoped_refptr
<TrackedCallback
> callback
) {
165 Call
<PpapiPluginMsg_FileRef_RenameReply
>(
167 PpapiHostMsg_FileRef_Rename(new_file_ref
),
168 base::Bind(&FileRefResource::RunTrackedCallback
, this, callback
));
169 return PP_OK_COMPLETIONPENDING
;
172 int32_t FileRefResource::Query(PP_FileInfo
* info
,
173 scoped_refptr
<TrackedCallback
> callback
) {
175 return PP_ERROR_BADARGUMENT
;
177 Call
<PpapiPluginMsg_FileRef_QueryReply
>(
179 PpapiHostMsg_FileRef_Query(),
180 base::Bind(&FileRefResource::OnQueryReply
, this, info
, callback
));
181 return PP_OK_COMPLETIONPENDING
;
184 int32_t FileRefResource::ReadDirectoryEntries(
185 const PP_ArrayOutput
& output
,
186 scoped_refptr
<TrackedCallback
> callback
) {
187 Call
<PpapiPluginMsg_FileRef_ReadDirectoryEntriesReply
>(
189 PpapiHostMsg_FileRef_ReadDirectoryEntries(),
190 base::Bind(&FileRefResource::OnDirectoryEntriesReply
,
191 this, output
, callback
));
192 return PP_OK_COMPLETIONPENDING
;
195 const FileRefCreateInfo
& FileRefResource::GetCreateInfo() const {
199 PP_Var
FileRefResource::GetAbsolutePath() {
200 if (!absolute_path_var_
.get()) {
201 std::string absolute_path
;
202 int32_t result
= SyncCall
<PpapiPluginMsg_FileRef_GetAbsolutePathReply
>(
203 BROWSER
, PpapiHostMsg_FileRef_GetAbsolutePath(), &absolute_path
);
205 return PP_MakeUndefined();
206 absolute_path_var_
= new StringVar(absolute_path
);
208 return absolute_path_var_
->GetPPVar();
211 void FileRefResource::RunTrackedCallback(
212 scoped_refptr
<TrackedCallback
> callback
,
213 const ResourceMessageReplyParams
& params
) {
214 if (TrackedCallback::IsPending(callback
))
215 callback
->Run(params
.result());
218 void FileRefResource::OnQueryReply(
219 PP_FileInfo
* out_info
,
220 scoped_refptr
<TrackedCallback
> callback
,
221 const ResourceMessageReplyParams
& params
,
222 const PP_FileInfo
& info
) {
223 if (!TrackedCallback::IsPending(callback
))
226 if (params
.result() == PP_OK
)
228 callback
->Run(params
.result());
231 void FileRefResource::OnDirectoryEntriesReply(
232 const PP_ArrayOutput
& output
,
233 scoped_refptr
<TrackedCallback
> callback
,
234 const ResourceMessageReplyParams
& params
,
235 const std::vector
<ppapi::FileRefCreateInfo
>& infos
,
236 const std::vector
<PP_FileType
>& file_types
) {
237 if (!TrackedCallback::IsPending(callback
))
240 if (params
.result() == PP_OK
) {
241 ArrayWriter
writer(output
);
242 if (!writer
.is_valid()) {
243 callback
->Run(PP_ERROR_BADARGUMENT
);
247 std::vector
<PP_DirectoryEntry
> entries
;
248 for (size_t i
= 0; i
< infos
.size(); ++i
) {
249 PP_DirectoryEntry entry
;
250 entry
.file_ref
= FileRefResource::CreateFileRef(connection(),
253 entry
.file_type
= file_types
[i
];
254 entries
.push_back(entry
);
257 writer
.StoreVector(entries
);
259 callback
->Run(params
.result());
262 bool FileRefResource::uses_internal_paths() const {
263 return (create_info_
.file_system_type
!= PP_FILESYSTEMTYPE_EXTERNAL
) ||
264 !create_info_
.internal_path
.empty();