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"
9 #include "base/callback.h"
10 #include "base/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/browser_thread.h"
17 #include "content/public/browser/render_process_host.h"
18 #include "content/public/browser/storage_partition.h"
19 #include "net/base/escape.h"
20 #include "ppapi/c/pp_errors.h"
21 #include "ppapi/c/pp_file_info.h"
22 #include "ppapi/c/pp_instance.h"
23 #include "ppapi/c/pp_resource.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 "webkit/browser/fileapi/file_system_operation.h"
37 #include "webkit/browser/fileapi/file_system_operation_runner.h"
38 #include "webkit/browser/fileapi/file_system_url.h"
39 #include "webkit/common/fileapi/file_system_util.h"
41 using ppapi::host::PpapiHost
;
42 using ppapi::host::ResourceHost
;
46 PepperInternalFileRefBackend::PepperInternalFileRefBackend(
48 int render_process_id
,
49 base::WeakPtr
<PepperFileSystemBrowserHost
> fs_host
,
50 const std::string
& path
) : host_(host
),
51 render_process_id_(render_process_id
),
53 fs_type_(fs_host
->GetType()),
56 ppapi::NormalizeInternalPath(&path_
);
59 PepperInternalFileRefBackend::~PepperInternalFileRefBackend() {
62 fileapi::FileSystemURL
PepperInternalFileRefBackend::GetFileSystemURL() const {
63 if (!fs_url_
.is_valid() && fs_host_
.get() && fs_host_
->IsOpened()) {
64 GURL fs_path
= fs_host_
->GetRootUrl().Resolve(
65 net::EscapePath(path_
.substr(1)));
66 scoped_refptr
<fileapi::FileSystemContext
> fs_context
=
67 GetFileSystemContext();
69 fs_url_
= fs_context
->CrackURL(fs_path
);
74 base::FilePath
PepperInternalFileRefBackend::GetExternalFilePath() const {
75 return base::FilePath();
78 scoped_refptr
<fileapi::FileSystemContext
>
79 PepperInternalFileRefBackend::GetFileSystemContext() const {
82 return fs_host_
->GetFileSystemContext();
85 void PepperInternalFileRefBackend::DidFinish(
86 ppapi::host::ReplyMessageContext context
,
87 const IPC::Message
& msg
,
88 base::PlatformFileError error
) {
89 context
.params
.set_result(ppapi::PlatformFileErrorToPepperError(error
));
90 host_
->SendReply(context
, msg
);
93 int32_t PepperInternalFileRefBackend::MakeDirectory(
94 ppapi::host::ReplyMessageContext reply_context
,
95 bool make_ancestors
) {
96 if (!GetFileSystemURL().is_valid())
97 return PP_ERROR_FAILED
;
99 GetFileSystemContext()->operation_runner()->CreateDirectory(
103 base::Bind(&PepperInternalFileRefBackend::DidFinish
,
104 weak_factory_
.GetWeakPtr(),
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(
119 ppapi::PPTimeToTime(last_access_time
),
120 ppapi::PPTimeToTime(last_modified_time
),
121 base::Bind(&PepperInternalFileRefBackend::DidFinish
,
122 weak_factory_
.GetWeakPtr(),
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(
136 base::Bind(&PepperInternalFileRefBackend::DidFinish
,
137 weak_factory_
.GetWeakPtr(),
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 fileapi::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(
158 fileapi::FileSystemOperation::OPTION_NONE
,
159 base::Bind(&PepperInternalFileRefBackend::DidFinish
,
160 weak_factory_
.GetWeakPtr(),
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(
173 base::Bind(&PepperInternalFileRefBackend::GetMetadataComplete
,
174 weak_factory_
.GetWeakPtr(),
176 return PP_OK_COMPLETIONPENDING
;
179 void PepperInternalFileRefBackend::GetMetadataComplete(
180 ppapi::host::ReplyMessageContext reply_context
,
181 base::PlatformFileError error
,
182 const base::PlatformFileInfo
& file_info
) {
183 reply_context
.params
.set_result(ppapi::PlatformFileErrorToPepperError(error
));
185 PP_FileInfo pp_file_info
;
186 if (error
== base::PLATFORM_FILE_OK
)
187 ppapi::PlatformFileInfoToPepperFileInfo(file_info
, fs_type_
, &pp_file_info
);
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 GetFileSystemContext()->operation_runner()->ReadDirectory(
202 base::Bind(&PepperInternalFileRefBackend::ReadDirectoryComplete
,
203 weak_factory_
.GetWeakPtr(),
205 return PP_OK_COMPLETIONPENDING
;
208 void PepperInternalFileRefBackend::ReadDirectoryComplete(
209 ppapi::host::ReplyMessageContext context
,
210 base::PlatformFileError error
,
211 const fileapi::FileSystemOperation::FileEntryList
& file_list
,
213 // The current filesystem backend always returns false.
216 context
.params
.set_result(ppapi::PlatformFileErrorToPepperError(error
));
218 std::vector
<ppapi::FileRefCreateInfo
> infos
;
219 std::vector
<PP_FileType
> file_types
;
220 if (error
== base::PLATFORM_FILE_OK
&& fs_host_
.get()) {
221 std::string dir_path
= path_
;
222 if (dir_path
.empty() || dir_path
[dir_path
.size() - 1] != '/')
225 for (fileapi::FileSystemOperation::FileEntryList::const_iterator it
=
226 file_list
.begin(); it
!= file_list
.end(); ++it
) {
227 if (it
->is_directory
)
228 file_types
.push_back(PP_FILETYPE_DIRECTORY
);
230 file_types
.push_back(PP_FILETYPE_REGULAR
);
232 ppapi::FileRefCreateInfo info
;
233 info
.file_system_type
= fs_type_
;
234 info
.file_system_plugin_resource
= fs_host_
->pp_resource();
236 dir_path
+ fileapi::FilePathToString(base::FilePath(it
->name
));
237 info
.internal_path
= path
;
238 info
.display_name
= ppapi::GetNameForInternalFilePath(path
);
239 infos
.push_back(info
);
243 host_
->SendReply(context
,
244 PpapiPluginMsg_FileRef_ReadDirectoryEntriesReply(infos
, file_types
));
247 int32_t PepperInternalFileRefBackend::GetAbsolutePath(
248 ppapi::host::ReplyMessageContext reply_context
) {
249 host_
->SendReply(reply_context
,
250 PpapiPluginMsg_FileRef_GetAbsolutePathReply(path_
));
251 return PP_OK_COMPLETIONPENDING
;
254 int32_t PepperInternalFileRefBackend::CanRead() const {
255 fileapi::FileSystemURL url
= GetFileSystemURL();
256 if (!FileSystemURLIsValid(GetFileSystemContext().get(), url
))
257 return PP_ERROR_FAILED
;
258 if (!ChildProcessSecurityPolicyImpl::GetInstance()->
259 CanReadFileSystemFile(render_process_id_
, url
)) {
260 return PP_ERROR_NOACCESS
;
265 int32_t PepperInternalFileRefBackend::CanWrite() const {
266 fileapi::FileSystemURL url
= GetFileSystemURL();
267 if (!FileSystemURLIsValid(GetFileSystemContext().get(), url
))
268 return PP_ERROR_FAILED
;
269 if (!ChildProcessSecurityPolicyImpl::GetInstance()->
270 CanWriteFileSystemFile(render_process_id_
, url
)) {
271 return PP_ERROR_NOACCESS
;
276 int32_t PepperInternalFileRefBackend::CanCreate() const {
277 fileapi::FileSystemURL url
= GetFileSystemURL();
278 if (!FileSystemURLIsValid(GetFileSystemContext().get(), url
))
279 return PP_ERROR_FAILED
;
280 if (!ChildProcessSecurityPolicyImpl::GetInstance()->
281 CanCreateFileSystemFile(render_process_id_
, url
)) {
282 return PP_ERROR_NOACCESS
;
287 int32_t PepperInternalFileRefBackend::CanReadWrite() const {
288 fileapi::FileSystemURL url
= GetFileSystemURL();
289 if (!FileSystemURLIsValid(GetFileSystemContext().get(), url
))
290 return PP_ERROR_FAILED
;
291 ChildProcessSecurityPolicyImpl
* policy
=
292 ChildProcessSecurityPolicyImpl::GetInstance();
293 if (!policy
->CanReadFileSystemFile(render_process_id_
, url
) ||
294 !policy
->CanWriteFileSystemFile(render_process_id_
, url
)) {
295 return PP_ERROR_NOACCESS
;
300 } // namespace content