Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / content / browser / renderer_host / pepper / pepper_internal_file_ref_backend.cc
blobddab7c00822ba878cc334932c64e223757b8443e
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 "content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.h"
7 #include <string>
9 #include "base/callback.h"
10 #include "base/files/file_util.h"
11 #include "base/files/file_util_proxy.h"
12 #include "content/browser/child_process_security_policy_impl.h"
13 #include "content/browser/fileapi/browser_file_system_helper.h"
14 #include "content/browser/renderer_host/pepper/pepper_file_system_browser_host.h"
15 #include "content/public/browser/browser_context.h"
16 #include "content/public/browser/render_process_host.h"
17 #include "content/public/browser/storage_partition.h"
18 #include "net/base/escape.h"
19 #include "ppapi/c/pp_errors.h"
20 #include "ppapi/c/pp_file_info.h"
21 #include "ppapi/c/pp_instance.h"
22 #include "ppapi/c/pp_resource.h"
23 #include "ppapi/c/ppb_file_ref.h"
24 #include "ppapi/host/dispatch_host_message.h"
25 #include "ppapi/host/ppapi_host.h"
26 #include "ppapi/proxy/ppapi_messages.h"
27 #include "ppapi/shared_impl/file_ref_create_info.h"
28 #include "ppapi/shared_impl/file_ref_util.h"
29 #include "ppapi/shared_impl/file_type_conversion.h"
30 #include "ppapi/shared_impl/scoped_pp_var.h"
31 #include "ppapi/shared_impl/time_conversion.h"
32 #include "ppapi/shared_impl/var.h"
33 #include "ppapi/thunk/enter.h"
34 #include "ppapi/thunk/ppb_file_ref_api.h"
35 #include "ppapi/thunk/ppb_file_system_api.h"
36 #include "storage/browser/fileapi/file_system_operation.h"
37 #include "storage/browser/fileapi/file_system_operation_runner.h"
38 #include "storage/browser/fileapi/file_system_url.h"
39 #include "storage/common/fileapi/file_system_util.h"
41 using ppapi::host::PpapiHost;
42 using ppapi::host::ResourceHost;
44 namespace content {
46 PepperInternalFileRefBackend::PepperInternalFileRefBackend(
47 PpapiHost* host,
48 int render_process_id,
49 base::WeakPtr<PepperFileSystemBrowserHost> fs_host,
50 const std::string& path)
51 : host_(host),
52 render_process_id_(render_process_id),
53 fs_host_(fs_host),
54 fs_type_(fs_host->GetType()),
55 path_(path),
56 weak_factory_(this) {
57 ppapi::NormalizeInternalPath(&path_);
60 PepperInternalFileRefBackend::~PepperInternalFileRefBackend() {}
62 storage::FileSystemURL PepperInternalFileRefBackend::GetFileSystemURL() const {
63 if (!fs_url_.is_valid() && fs_host_.get() && fs_host_->IsOpened()) {
64 GURL fs_path =
65 fs_host_->GetRootUrl().Resolve(net::EscapePath(path_.substr(1)));
66 scoped_refptr<storage::FileSystemContext> fs_context =
67 GetFileSystemContext();
68 if (fs_context.get())
69 fs_url_ = fs_context->CrackURL(fs_path);
71 return fs_url_;
74 base::FilePath PepperInternalFileRefBackend::GetExternalFilePath() const {
75 return base::FilePath();
78 scoped_refptr<storage::FileSystemContext>
79 PepperInternalFileRefBackend::GetFileSystemContext() const {
80 if (!fs_host_.get())
81 return NULL;
82 return fs_host_->GetFileSystemContext();
85 void PepperInternalFileRefBackend::DidFinish(
86 ppapi::host::ReplyMessageContext context,
87 const IPC::Message& msg,
88 base::File::Error error) {
89 context.params.set_result(ppapi::FileErrorToPepperError(error));
90 host_->SendReply(context, msg);
93 int32_t PepperInternalFileRefBackend::MakeDirectory(
94 ppapi::host::ReplyMessageContext reply_context,
95 int32_t make_directory_flags) {
96 if (!GetFileSystemURL().is_valid())
97 return PP_ERROR_FAILED;
99 GetFileSystemContext()->operation_runner()->CreateDirectory(
100 GetFileSystemURL(),
101 !!(make_directory_flags & PP_MAKEDIRECTORYFLAG_EXCLUSIVE),
102 !!(make_directory_flags & PP_MAKEDIRECTORYFLAG_WITH_ANCESTORS),
103 base::Bind(&PepperInternalFileRefBackend::DidFinish,
104 weak_factory_.GetWeakPtr(),
105 reply_context,
106 PpapiPluginMsg_FileRef_MakeDirectoryReply()));
107 return PP_OK_COMPLETIONPENDING;
110 int32_t PepperInternalFileRefBackend::Touch(
111 ppapi::host::ReplyMessageContext reply_context,
112 PP_Time last_access_time,
113 PP_Time last_modified_time) {
114 if (!GetFileSystemURL().is_valid())
115 return PP_ERROR_FAILED;
117 GetFileSystemContext()->operation_runner()->TouchFile(
118 GetFileSystemURL(),
119 ppapi::PPTimeToTime(last_access_time),
120 ppapi::PPTimeToTime(last_modified_time),
121 base::Bind(&PepperInternalFileRefBackend::DidFinish,
122 weak_factory_.GetWeakPtr(),
123 reply_context,
124 PpapiPluginMsg_FileRef_TouchReply()));
125 return PP_OK_COMPLETIONPENDING;
128 int32_t PepperInternalFileRefBackend::Delete(
129 ppapi::host::ReplyMessageContext reply_context) {
130 if (!GetFileSystemURL().is_valid())
131 return PP_ERROR_FAILED;
133 GetFileSystemContext()->operation_runner()->Remove(
134 GetFileSystemURL(),
135 false,
136 base::Bind(&PepperInternalFileRefBackend::DidFinish,
137 weak_factory_.GetWeakPtr(),
138 reply_context,
139 PpapiPluginMsg_FileRef_DeleteReply()));
140 return PP_OK_COMPLETIONPENDING;
143 int32_t PepperInternalFileRefBackend::Rename(
144 ppapi::host::ReplyMessageContext reply_context,
145 PepperFileRefHost* new_file_ref) {
146 if (!GetFileSystemURL().is_valid())
147 return PP_ERROR_FAILED;
149 storage::FileSystemURL new_url = new_file_ref->GetFileSystemURL();
150 if (!new_url.is_valid())
151 return PP_ERROR_FAILED;
152 if (!new_url.IsInSameFileSystem(GetFileSystemURL()))
153 return PP_ERROR_FAILED;
155 GetFileSystemContext()->operation_runner()->Move(
156 GetFileSystemURL(),
157 new_url,
158 storage::FileSystemOperation::OPTION_NONE,
159 base::Bind(&PepperInternalFileRefBackend::DidFinish,
160 weak_factory_.GetWeakPtr(),
161 reply_context,
162 PpapiPluginMsg_FileRef_RenameReply()));
163 return PP_OK_COMPLETIONPENDING;
166 int32_t PepperInternalFileRefBackend::Query(
167 ppapi::host::ReplyMessageContext reply_context) {
168 if (!GetFileSystemURL().is_valid())
169 return PP_ERROR_FAILED;
171 GetFileSystemContext()->operation_runner()->GetMetadata(
172 GetFileSystemURL(),
173 base::Bind(&PepperInternalFileRefBackend::GetMetadataComplete,
174 weak_factory_.GetWeakPtr(),
175 reply_context));
176 return PP_OK_COMPLETIONPENDING;
179 void PepperInternalFileRefBackend::GetMetadataComplete(
180 ppapi::host::ReplyMessageContext reply_context,
181 base::File::Error error,
182 const base::File::Info& file_info) {
183 reply_context.params.set_result(ppapi::FileErrorToPepperError(error));
185 PP_FileInfo pp_file_info;
186 if (error == base::File::FILE_OK)
187 ppapi::FileInfoToPepperFileInfo(file_info, fs_type_, &pp_file_info);
188 else
189 memset(&pp_file_info, 0, sizeof(pp_file_info));
191 host_->SendReply(reply_context,
192 PpapiPluginMsg_FileRef_QueryReply(pp_file_info));
195 int32_t PepperInternalFileRefBackend::ReadDirectoryEntries(
196 ppapi::host::ReplyMessageContext reply_context) {
197 if (!GetFileSystemURL().is_valid())
198 return PP_ERROR_FAILED;
200 storage::FileSystemOperation::FileEntryList* accumulated_file_list =
201 new storage::FileSystemOperation::FileEntryList;
202 GetFileSystemContext()->operation_runner()->ReadDirectory(
203 GetFileSystemURL(),
204 base::Bind(&PepperInternalFileRefBackend::ReadDirectoryComplete,
205 weak_factory_.GetWeakPtr(),
206 reply_context,
207 base::Owned(accumulated_file_list)));
208 return PP_OK_COMPLETIONPENDING;
211 void PepperInternalFileRefBackend::ReadDirectoryComplete(
212 ppapi::host::ReplyMessageContext context,
213 storage::FileSystemOperation::FileEntryList* accumulated_file_list,
214 base::File::Error error,
215 const storage::FileSystemOperation::FileEntryList& file_list,
216 bool has_more) {
217 accumulated_file_list->insert(
218 accumulated_file_list->end(), file_list.begin(), file_list.end());
219 if (has_more)
220 return;
222 context.params.set_result(ppapi::FileErrorToPepperError(error));
224 std::vector<ppapi::FileRefCreateInfo> infos;
225 std::vector<PP_FileType> file_types;
226 if (error == base::File::FILE_OK && fs_host_.get()) {
227 std::string dir_path = path_;
228 if (dir_path.empty() || dir_path[dir_path.size() - 1] != '/')
229 dir_path += '/';
231 for (storage::FileSystemOperation::FileEntryList::const_iterator it =
232 accumulated_file_list->begin();
233 it != accumulated_file_list->end();
234 ++it) {
235 if (it->is_directory)
236 file_types.push_back(PP_FILETYPE_DIRECTORY);
237 else
238 file_types.push_back(PP_FILETYPE_REGULAR);
240 ppapi::FileRefCreateInfo info;
241 info.file_system_type = fs_type_;
242 info.file_system_plugin_resource = fs_host_->pp_resource();
243 std::string path =
244 dir_path + storage::FilePathToString(base::FilePath(it->name));
245 info.internal_path = path;
246 info.display_name = ppapi::GetNameForInternalFilePath(path);
247 infos.push_back(info);
251 host_->SendReply(
252 context,
253 PpapiPluginMsg_FileRef_ReadDirectoryEntriesReply(infos, file_types));
256 int32_t PepperInternalFileRefBackend::GetAbsolutePath(
257 ppapi::host::ReplyMessageContext reply_context) {
258 host_->SendReply(reply_context,
259 PpapiPluginMsg_FileRef_GetAbsolutePathReply(path_));
260 return PP_OK_COMPLETIONPENDING;
263 int32_t PepperInternalFileRefBackend::CanRead() const {
264 storage::FileSystemURL url = GetFileSystemURL();
265 if (!FileSystemURLIsValid(GetFileSystemContext().get(), url))
266 return PP_ERROR_FAILED;
267 if (!ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFileSystemFile(
268 render_process_id_, url)) {
269 return PP_ERROR_NOACCESS;
271 return PP_OK;
274 int32_t PepperInternalFileRefBackend::CanWrite() const {
275 storage::FileSystemURL url = GetFileSystemURL();
276 if (!FileSystemURLIsValid(GetFileSystemContext().get(), url))
277 return PP_ERROR_FAILED;
278 if (!ChildProcessSecurityPolicyImpl::GetInstance()->CanWriteFileSystemFile(
279 render_process_id_, url)) {
280 return PP_ERROR_NOACCESS;
282 return PP_OK;
285 int32_t PepperInternalFileRefBackend::CanCreate() const {
286 storage::FileSystemURL url = GetFileSystemURL();
287 if (!FileSystemURLIsValid(GetFileSystemContext().get(), url))
288 return PP_ERROR_FAILED;
289 if (!ChildProcessSecurityPolicyImpl::GetInstance()->CanCreateFileSystemFile(
290 render_process_id_, url)) {
291 return PP_ERROR_NOACCESS;
293 return PP_OK;
296 int32_t PepperInternalFileRefBackend::CanReadWrite() const {
297 storage::FileSystemURL url = GetFileSystemURL();
298 if (!FileSystemURLIsValid(GetFileSystemContext().get(), url))
299 return PP_ERROR_FAILED;
300 ChildProcessSecurityPolicyImpl* policy =
301 ChildProcessSecurityPolicyImpl::GetInstance();
302 if (!policy->CanReadFileSystemFile(render_process_id_, url) ||
303 !policy->CanWriteFileSystemFile(render_process_id_, url)) {
304 return PP_ERROR_NOACCESS;
306 return PP_OK;
309 } // namespace content