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/c/ppb_file_ref.h"
25 #include "ppapi/host/dispatch_host_message.h"
26 #include "ppapi/host/ppapi_host.h"
27 #include "ppapi/proxy/ppapi_messages.h"
28 #include "ppapi/shared_impl/file_ref_create_info.h"
29 #include "ppapi/shared_impl/file_ref_util.h"
30 #include "ppapi/shared_impl/file_type_conversion.h"
31 #include "ppapi/shared_impl/scoped_pp_var.h"
32 #include "ppapi/shared_impl/time_conversion.h"
33 #include "ppapi/shared_impl/var.h"
34 #include "ppapi/thunk/enter.h"
35 #include "ppapi/thunk/ppb_file_ref_api.h"
36 #include "ppapi/thunk/ppb_file_system_api.h"
37 #include "webkit/browser/fileapi/file_system_operation.h"
38 #include "webkit/browser/fileapi/file_system_operation_runner.h"
39 #include "webkit/browser/fileapi/file_system_url.h"
40 #include "webkit/common/fileapi/file_system_util.h"
42 using ppapi::host::PpapiHost
;
43 using ppapi::host::ResourceHost
;
47 PepperInternalFileRefBackend::PepperInternalFileRefBackend(
49 int render_process_id
,
50 base::WeakPtr
<PepperFileSystemBrowserHost
> fs_host
,
51 const std::string
& path
) : host_(host
),
52 render_process_id_(render_process_id
),
54 fs_type_(fs_host
->GetType()),
57 ppapi::NormalizeInternalPath(&path_
);
60 PepperInternalFileRefBackend::~PepperInternalFileRefBackend() {
63 fileapi::FileSystemURL
PepperInternalFileRefBackend::GetFileSystemURL() const {
64 if (!fs_url_
.is_valid() && fs_host_
.get() && fs_host_
->IsOpened()) {
65 GURL fs_path
= fs_host_
->GetRootUrl().Resolve(
66 net::EscapePath(path_
.substr(1)));
67 scoped_refptr
<fileapi::FileSystemContext
> fs_context
=
68 GetFileSystemContext();
70 fs_url_
= fs_context
->CrackURL(fs_path
);
75 base::FilePath
PepperInternalFileRefBackend::GetExternalFilePath() const {
76 return base::FilePath();
79 scoped_refptr
<fileapi::FileSystemContext
>
80 PepperInternalFileRefBackend::GetFileSystemContext() const {
83 return fs_host_
->GetFileSystemContext();
86 void PepperInternalFileRefBackend::DidFinish(
87 ppapi::host::ReplyMessageContext context
,
88 const IPC::Message
& msg
,
89 base::PlatformFileError error
) {
90 context
.params
.set_result(ppapi::PlatformFileErrorToPepperError(error
));
91 host_
->SendReply(context
, msg
);
94 int32_t PepperInternalFileRefBackend::MakeDirectory(
95 ppapi::host::ReplyMessageContext reply_context
,
96 int32_t make_directory_flags
) {
97 if (!GetFileSystemURL().is_valid())
98 return PP_ERROR_FAILED
;
100 GetFileSystemContext()->operation_runner()->CreateDirectory(
102 !!(make_directory_flags
& PP_MAKEDIRECTORYFLAG_EXCLUSIVE
),
103 !!(make_directory_flags
& PP_MAKEDIRECTORYFLAG_WITH_ANCESTORS
),
104 base::Bind(&PepperInternalFileRefBackend::DidFinish
,
105 weak_factory_
.GetWeakPtr(),
107 PpapiPluginMsg_FileRef_MakeDirectoryReply()));
108 return PP_OK_COMPLETIONPENDING
;
111 int32_t PepperInternalFileRefBackend::Touch(
112 ppapi::host::ReplyMessageContext reply_context
,
113 PP_Time last_access_time
,
114 PP_Time last_modified_time
) {
115 if (!GetFileSystemURL().is_valid())
116 return PP_ERROR_FAILED
;
118 GetFileSystemContext()->operation_runner()->TouchFile(
120 ppapi::PPTimeToTime(last_access_time
),
121 ppapi::PPTimeToTime(last_modified_time
),
122 base::Bind(&PepperInternalFileRefBackend::DidFinish
,
123 weak_factory_
.GetWeakPtr(),
125 PpapiPluginMsg_FileRef_TouchReply()));
126 return PP_OK_COMPLETIONPENDING
;
129 int32_t PepperInternalFileRefBackend::Delete(
130 ppapi::host::ReplyMessageContext reply_context
) {
131 if (!GetFileSystemURL().is_valid())
132 return PP_ERROR_FAILED
;
134 GetFileSystemContext()->operation_runner()->Remove(
137 base::Bind(&PepperInternalFileRefBackend::DidFinish
,
138 weak_factory_
.GetWeakPtr(),
140 PpapiPluginMsg_FileRef_DeleteReply()));
141 return PP_OK_COMPLETIONPENDING
;
144 int32_t PepperInternalFileRefBackend::Rename(
145 ppapi::host::ReplyMessageContext reply_context
,
146 PepperFileRefHost
* new_file_ref
) {
147 if (!GetFileSystemURL().is_valid())
148 return PP_ERROR_FAILED
;
150 fileapi::FileSystemURL new_url
= new_file_ref
->GetFileSystemURL();
151 if (!new_url
.is_valid())
152 return PP_ERROR_FAILED
;
153 if (!new_url
.IsInSameFileSystem(GetFileSystemURL()))
154 return PP_ERROR_FAILED
;
156 GetFileSystemContext()->operation_runner()->Move(
159 fileapi::FileSystemOperation::OPTION_NONE
,
160 base::Bind(&PepperInternalFileRefBackend::DidFinish
,
161 weak_factory_
.GetWeakPtr(),
163 PpapiPluginMsg_FileRef_RenameReply()));
164 return PP_OK_COMPLETIONPENDING
;
167 int32_t PepperInternalFileRefBackend::Query(
168 ppapi::host::ReplyMessageContext reply_context
) {
169 if (!GetFileSystemURL().is_valid())
170 return PP_ERROR_FAILED
;
172 GetFileSystemContext()->operation_runner()->GetMetadata(
174 base::Bind(&PepperInternalFileRefBackend::GetMetadataComplete
,
175 weak_factory_
.GetWeakPtr(),
177 return PP_OK_COMPLETIONPENDING
;
180 void PepperInternalFileRefBackend::GetMetadataComplete(
181 ppapi::host::ReplyMessageContext reply_context
,
182 base::PlatformFileError error
,
183 const base::PlatformFileInfo
& file_info
) {
184 reply_context
.params
.set_result(ppapi::PlatformFileErrorToPepperError(error
));
186 PP_FileInfo pp_file_info
;
187 if (error
== base::PLATFORM_FILE_OK
)
188 ppapi::PlatformFileInfoToPepperFileInfo(file_info
, fs_type_
, &pp_file_info
);
190 memset(&pp_file_info
, 0, sizeof(pp_file_info
));
192 host_
->SendReply(reply_context
,
193 PpapiPluginMsg_FileRef_QueryReply(pp_file_info
));
196 int32_t PepperInternalFileRefBackend::ReadDirectoryEntries(
197 ppapi::host::ReplyMessageContext reply_context
) {
198 if (!GetFileSystemURL().is_valid())
199 return PP_ERROR_FAILED
;
201 GetFileSystemContext()->operation_runner()->ReadDirectory(
203 base::Bind(&PepperInternalFileRefBackend::ReadDirectoryComplete
,
204 weak_factory_
.GetWeakPtr(),
206 return PP_OK_COMPLETIONPENDING
;
209 void PepperInternalFileRefBackend::ReadDirectoryComplete(
210 ppapi::host::ReplyMessageContext context
,
211 base::PlatformFileError error
,
212 const fileapi::FileSystemOperation::FileEntryList
& file_list
,
214 // The current filesystem backend always returns false.
217 context
.params
.set_result(ppapi::PlatformFileErrorToPepperError(error
));
219 std::vector
<ppapi::FileRefCreateInfo
> infos
;
220 std::vector
<PP_FileType
> file_types
;
221 if (error
== base::PLATFORM_FILE_OK
&& fs_host_
.get()) {
222 std::string dir_path
= path_
;
223 if (dir_path
.empty() || dir_path
[dir_path
.size() - 1] != '/')
226 for (fileapi::FileSystemOperation::FileEntryList::const_iterator it
=
227 file_list
.begin(); it
!= file_list
.end(); ++it
) {
228 if (it
->is_directory
)
229 file_types
.push_back(PP_FILETYPE_DIRECTORY
);
231 file_types
.push_back(PP_FILETYPE_REGULAR
);
233 ppapi::FileRefCreateInfo info
;
234 info
.file_system_type
= fs_type_
;
235 info
.file_system_plugin_resource
= fs_host_
->pp_resource();
237 dir_path
+ fileapi::FilePathToString(base::FilePath(it
->name
));
238 info
.internal_path
= path
;
239 info
.display_name
= ppapi::GetNameForInternalFilePath(path
);
240 infos
.push_back(info
);
244 host_
->SendReply(context
,
245 PpapiPluginMsg_FileRef_ReadDirectoryEntriesReply(infos
, file_types
));
248 int32_t PepperInternalFileRefBackend::GetAbsolutePath(
249 ppapi::host::ReplyMessageContext reply_context
) {
250 host_
->SendReply(reply_context
,
251 PpapiPluginMsg_FileRef_GetAbsolutePathReply(path_
));
252 return PP_OK_COMPLETIONPENDING
;
255 int32_t PepperInternalFileRefBackend::CanRead() const {
256 fileapi::FileSystemURL url
= GetFileSystemURL();
257 if (!FileSystemURLIsValid(GetFileSystemContext().get(), url
))
258 return PP_ERROR_FAILED
;
259 if (!ChildProcessSecurityPolicyImpl::GetInstance()->
260 CanReadFileSystemFile(render_process_id_
, url
)) {
261 return PP_ERROR_NOACCESS
;
266 int32_t PepperInternalFileRefBackend::CanWrite() const {
267 fileapi::FileSystemURL url
= GetFileSystemURL();
268 if (!FileSystemURLIsValid(GetFileSystemContext().get(), url
))
269 return PP_ERROR_FAILED
;
270 if (!ChildProcessSecurityPolicyImpl::GetInstance()->
271 CanWriteFileSystemFile(render_process_id_
, url
)) {
272 return PP_ERROR_NOACCESS
;
277 int32_t PepperInternalFileRefBackend::CanCreate() const {
278 fileapi::FileSystemURL url
= GetFileSystemURL();
279 if (!FileSystemURLIsValid(GetFileSystemContext().get(), url
))
280 return PP_ERROR_FAILED
;
281 if (!ChildProcessSecurityPolicyImpl::GetInstance()->
282 CanCreateFileSystemFile(render_process_id_
, url
)) {
283 return PP_ERROR_NOACCESS
;
288 int32_t PepperInternalFileRefBackend::CanReadWrite() const {
289 fileapi::FileSystemURL url
= GetFileSystemURL();
290 if (!FileSystemURLIsValid(GetFileSystemContext().get(), url
))
291 return PP_ERROR_FAILED
;
292 ChildProcessSecurityPolicyImpl
* policy
=
293 ChildProcessSecurityPolicyImpl::GetInstance();
294 if (!policy
->CanReadFileSystemFile(render_process_id_
, url
) ||
295 !policy
->CanWriteFileSystemFile(render_process_id_
, url
)) {
296 return PP_ERROR_NOACCESS
;
301 } // namespace content