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.
4
5 #include "content/browser/renderer_host/pepper/pepper_file_ref_host.h"
6
7 #include <string>
8
9 #include "content/browser/renderer_host/pepper/pepper_external_file_ref_backend.h"
10 #include "content/browser/renderer_host/pepper/pepper_file_system_browser_host.h"
11 #include "content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.h"
12 #include "ppapi/c/pp_errors.h"
13 #include "ppapi/c/pp_file_info.h"
14 #include "ppapi/c/pp_instance.h"
15 #include "ppapi/c/pp_resource.h"
16 #include "ppapi/host/dispatch_host_message.h"
17 #include "ppapi/host/ppapi_host.h"
18 #include "ppapi/proxy/ppapi_messages.h"
19 #include "ppapi/shared_impl/file_ref_util.h"
20 #include "webkit/browser/fileapi/file_permission_policy.h"
21
22 using ppapi::host::ResourceHost;
23
24 namespace content {
25
~PepperFileRefBackend()26 PepperFileRefBackend::~PepperFileRefBackend() {
27 }
28
PepperFileRefHost(BrowserPpapiHost * host,PP_Instance instance,PP_Resource resource,PP_Resource file_system,const std::string & path)29 PepperFileRefHost::PepperFileRefHost(BrowserPpapiHost* host,
30 PP_Instance instance,
31 PP_Resource resource,
32 PP_Resource file_system,
33 const std::string& path)
34 : ResourceHost(host->GetPpapiHost(), instance, resource),
35 host_(host),
36 fs_type_(PP_FILESYSTEMTYPE_INVALID) {
37 if (!ppapi::IsValidInternalPath(path))
38 return;
39
40 int render_process_id;
41 int unused;
42 if (!host->GetRenderViewIDsForInstance(instance,
43 &render_process_id,
44 &unused)) {
45 return;
46 }
47
48 ResourceHost* fs_resource_host =
49 host->GetPpapiHost()->GetResourceHost(file_system);
50 if (fs_resource_host == NULL) {
51 DLOG(ERROR) << "Couldn't find FileSystem host: " << resource
52 << " path: " << path;
53 return;
54 }
55
56 if (!fs_resource_host->IsFileSystemHost()) {
57 DLOG(ERROR) << "Filesystem PP_Resource is not PepperFileSystemBrowserHost";
58 return;
59 }
60
61 PepperFileSystemBrowserHost* file_system_host =
62 static_cast<PepperFileSystemBrowserHost*>(fs_resource_host);
63 file_system_host_ = file_system_host->AsWeakPtr();
64 fs_type_ = file_system_host->GetType();
65 if ((fs_type_ != PP_FILESYSTEMTYPE_LOCALPERSISTENT) &&
66 (fs_type_ != PP_FILESYSTEMTYPE_LOCALTEMPORARY) &&
67 (fs_type_ != PP_FILESYSTEMTYPE_ISOLATED)) {
68 DLOG(ERROR) << "Unsupported filesystem type: " << fs_type_;
69 return;
70 }
71
72 backend_.reset(new PepperInternalFileRefBackend(
73 host->GetPpapiHost(),
74 render_process_id,
75 file_system_host->AsWeakPtr(),
76 path));
77 }
78
PepperFileRefHost(BrowserPpapiHost * host,PP_Instance instance,PP_Resource resource,const base::FilePath & external_path)79 PepperFileRefHost::PepperFileRefHost(BrowserPpapiHost* host,
80 PP_Instance instance,
81 PP_Resource resource,
82 const base::FilePath& external_path)
83 : ResourceHost(host->GetPpapiHost(), instance, resource),
84 host_(host),
85 fs_type_(PP_FILESYSTEMTYPE_EXTERNAL) {
86 if (!ppapi::IsValidExternalPath(external_path))
87 return;
88
89 int render_process_id;
90 int unused;
91 if (!host->GetRenderViewIDsForInstance(instance,
92 &render_process_id,
93 &unused)) {
94 return;
95 }
96
97 backend_.reset(new PepperExternalFileRefBackend(host->GetPpapiHost(),
98 render_process_id,
99 external_path));
100 }
101
~PepperFileRefHost()102 PepperFileRefHost::~PepperFileRefHost() {
103 }
104
IsFileRefHost()105 bool PepperFileRefHost::IsFileRefHost() {
106 return true;
107 }
108
GetFileSystemType() const109 PP_FileSystemType PepperFileRefHost::GetFileSystemType() const {
110 return fs_type_;
111 }
112
GetFileSystemURL() const113 fileapi::FileSystemURL PepperFileRefHost::GetFileSystemURL() const {
114 if (backend_)
115 return backend_->GetFileSystemURL();
116 return fileapi::FileSystemURL();
117 }
118
GetExternalFilePath() const119 base::FilePath PepperFileRefHost::GetExternalFilePath() const {
120 if (backend_)
121 return backend_->GetExternalFilePath();
122 return base::FilePath();
123 }
124
125 base::WeakPtr<PepperFileSystemBrowserHost>
GetFileSystemHost() const126 PepperFileRefHost::GetFileSystemHost() const {
127 return file_system_host_;
128 }
129
CanRead() const130 int32_t PepperFileRefHost::CanRead() const {
131 if (backend_)
132 return backend_->CanRead();
133 return PP_ERROR_FAILED;
134 }
135
CanWrite() const136 int32_t PepperFileRefHost::CanWrite() const {
137 if (backend_)
138 return backend_->CanWrite();
139 return PP_ERROR_FAILED;
140 }
141
CanCreate() const142 int32_t PepperFileRefHost::CanCreate() const {
143 if (backend_)
144 return backend_->CanCreate();
145 return PP_ERROR_FAILED;
146 }
147
CanReadWrite() const148 int32_t PepperFileRefHost::CanReadWrite() const {
149 if (backend_)
150 return backend_->CanReadWrite();
151 return PP_ERROR_FAILED;
152 }
153
OnResourceMessageReceived(const IPC::Message & msg,ppapi::host::HostMessageContext * context)154 int32_t PepperFileRefHost::OnResourceMessageReceived(
155 const IPC::Message& msg,
156 ppapi::host::HostMessageContext* context) {
157 if (!backend_)
158 return PP_ERROR_FAILED;
159
160 IPC_BEGIN_MESSAGE_MAP(PepperFileRefHost, msg)
161 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileRef_MakeDirectory,
162 OnMakeDirectory);
163 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileRef_Touch,
164 OnTouch);
165 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_FileRef_Delete,
166 OnDelete);
167 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileRef_Rename,
168 OnRename);
169 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_FileRef_Query,
170 OnQuery);
171 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(
172 PpapiHostMsg_FileRef_ReadDirectoryEntries,
173 OnReadDirectoryEntries);
174 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_FileRef_GetAbsolutePath,
175 OnGetAbsolutePath);
176
177 IPC_END_MESSAGE_MAP()
178 return PP_ERROR_FAILED;
179 }
180
OnMakeDirectory(ppapi::host::HostMessageContext * context,bool make_ancestors)181 int32_t PepperFileRefHost::OnMakeDirectory(
182 ppapi::host::HostMessageContext* context,
183 bool make_ancestors) {
184 int32_t rv = CanCreate();
185 if (rv != PP_OK)
186 return rv;
187 return backend_->MakeDirectory(context->MakeReplyMessageContext(),
188 make_ancestors);
189 }
190
OnTouch(ppapi::host::HostMessageContext * context,PP_Time last_access_time,PP_Time last_modified_time)191 int32_t PepperFileRefHost::OnTouch(ppapi::host::HostMessageContext* context,
192 PP_Time last_access_time,
193 PP_Time last_modified_time) {
194 // TODO(teravest): Change this to be kWriteFilePermissions here and in
195 // fileapi_message_filter.
196 int32_t rv = CanCreate();
197 if (rv != PP_OK)
198 return rv;
199 return backend_->Touch(context->MakeReplyMessageContext(),
200 last_access_time,
201 last_modified_time);
202 }
203
OnDelete(ppapi::host::HostMessageContext * context)204 int32_t PepperFileRefHost::OnDelete(ppapi::host::HostMessageContext* context) {
205 int32_t rv = CanWrite();
206 if (rv != PP_OK)
207 return rv;
208 return backend_->Delete(context->MakeReplyMessageContext());
209 }
210
OnRename(ppapi::host::HostMessageContext * context,PP_Resource new_file_ref)211 int32_t PepperFileRefHost::OnRename(ppapi::host::HostMessageContext* context,
212 PP_Resource new_file_ref) {
213 int32_t rv = CanReadWrite();
214 if (rv != PP_OK)
215 return rv;
216
217 ResourceHost* resource_host =
218 host_->GetPpapiHost()->GetResourceHost(new_file_ref);
219 if (!resource_host)
220 return PP_ERROR_BADRESOURCE;
221
222 PepperFileRefHost* file_ref_host = NULL;
223 if (resource_host->IsFileRefHost())
224 file_ref_host = static_cast<PepperFileRefHost*>(resource_host);
225 if (!file_ref_host)
226 return PP_ERROR_BADRESOURCE;
227
228 rv = file_ref_host->CanCreate();
229 if (rv != PP_OK)
230 return rv;
231
232 return backend_->Rename(context->MakeReplyMessageContext(),
233 file_ref_host);
234 }
235
OnQuery(ppapi::host::HostMessageContext * context)236 int32_t PepperFileRefHost::OnQuery(ppapi::host::HostMessageContext* context) {
237 int32_t rv = CanRead();
238 if (rv != PP_OK)
239 return rv;
240 return backend_->Query(context->MakeReplyMessageContext());
241 }
242
OnReadDirectoryEntries(ppapi::host::HostMessageContext * context)243 int32_t PepperFileRefHost::OnReadDirectoryEntries(
244 ppapi::host::HostMessageContext* context) {
245 int32_t rv = CanRead();
246 if (rv != PP_OK)
247 return rv;
248 return backend_->ReadDirectoryEntries(context->MakeReplyMessageContext());
249 }
250
OnGetAbsolutePath(ppapi::host::HostMessageContext * context)251 int32_t PepperFileRefHost::OnGetAbsolutePath(
252 ppapi::host::HostMessageContext* context) {
253 if (!host_->GetPpapiHost()->permissions().HasPermission(
254 ppapi::PERMISSION_PRIVATE))
255 return PP_ERROR_NOACCESS;
256 return backend_->GetAbsolutePath(context->MakeReplyMessageContext());
257 }
258
259 } // namespace content
260