Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / ppapi / proxy / file_ref_resource.cc
blobee56969cd82068b83e0b17d18ac73f3d7ae29b96
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"
20 namespace ppapi {
21 namespace proxy {
23 FileRefResource::FileRefResource(
24 Connection connection,
25 PP_Instance instance,
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
32 // the root path.
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);
40 } else {
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);
50 } else {
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() {
66 // static
67 PP_Resource FileRefResource::CreateFileRef(
68 Connection connection,
69 PP_Instance instance,
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);
76 if (enter.failed())
77 return 0;
78 if (enter.object()->GetType() != create_info.file_system_type) {
79 NOTREACHED() << "file system type mismatch with resource";
80 return 0;
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))
87 return 0;
89 return (new FileRefResource(connection,
90 instance,
91 create_info))->GetReference();
94 thunk::PPB_FileRef_API* FileRefResource::AsPPB_FileRef_API() {
95 return this;
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())
114 return 0;
116 size_t pos = create_info_.internal_path.rfind('/');
117 CHECK(pos != std::string::npos);
118 if (pos == 0)
119 pos++;
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(),
130 pp_instance(),
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>(
138 BROWSER,
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>(
148 BROWSER,
149 PpapiHostMsg_FileRef_Touch(last_access_time,
150 last_modified_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>(
157 BROWSER,
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>(
166 BROWSER,
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) {
174 if (info == NULL)
175 return PP_ERROR_BADARGUMENT;
177 Call<PpapiPluginMsg_FileRef_QueryReply>(
178 BROWSER,
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>(
188 BROWSER,
189 PpapiHostMsg_FileRef_ReadDirectoryEntries(),
190 base::Bind(&FileRefResource::OnDirectoryEntriesReply,
191 this, output, callback));
192 return PP_OK_COMPLETIONPENDING;
195 const FileRefCreateInfo& FileRefResource::GetCreateInfo() const {
196 return create_info_;
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);
204 if (result != PP_OK)
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))
224 return;
226 if (params.result() == PP_OK)
227 *out_info = info;
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))
238 return;
240 if (params.result() == PP_OK) {
241 ArrayWriter writer(output);
242 if (!writer.is_valid()) {
243 callback->Run(PP_ERROR_BADARGUMENT);
244 return;
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(),
251 pp_instance(),
252 infos[i]);
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();
267 } // namespace proxy
268 } // namespace ppapi