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 26 PepperFileRefBackend::~PepperFileRefBackend() { 27 } 28 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 PepperFileSystemBrowserHost* fs_host = NULL; 57 if (fs_resource_host->IsFileSystemHost()) 58 fs_host = static_cast<PepperFileSystemBrowserHost*>(fs_resource_host); 59 if (fs_host == NULL) { 60 DLOG(ERROR) << "Filesystem PP_Resource is not PepperFileSystemBrowserHost"; 61 return; 62 } 63 64 fs_type_ = fs_host->GetType(); 65 // TODO(teravest): Add support for isolated filesystems. 66 if ((fs_type_ != PP_FILESYSTEMTYPE_LOCALPERSISTENT) && 67 (fs_type_ != PP_FILESYSTEMTYPE_LOCALTEMPORARY)) { 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 base::AsWeakPtr(fs_host), 76 path)); 77 } 78 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 102 PepperFileRefHost::~PepperFileRefHost() { 103 } 104 105 bool PepperFileRefHost::IsFileRefHost() { 106 return true; 107 } 108 109 PP_FileSystemType PepperFileRefHost::GetFileSystemType() const { 110 return fs_type_; 111 } 112 113 fileapi::FileSystemURL PepperFileRefHost::GetFileSystemURL() const { 114 if (backend_) 115 return backend_->GetFileSystemURL(); 116 return fileapi::FileSystemURL(); 117 } 118 119 std::string PepperFileRefHost::GetFileSystemURLSpec() const { 120 if (backend_) 121 return backend_->GetFileSystemURLSpec(); 122 return std::string(); 123 } 124 125 base::FilePath PepperFileRefHost::GetExternalPath() const { 126 if (backend_) 127 return backend_->GetExternalPath(); 128 return base::FilePath(); 129 } 130 131 int32_t PepperFileRefHost::CanRead() const { 132 if (backend_) 133 return backend_->CanRead(); 134 return PP_ERROR_FAILED; 135 } 136 137 int32_t PepperFileRefHost::CanWrite() const { 138 if (backend_) 139 return backend_->CanWrite(); 140 return PP_ERROR_FAILED; 141 } 142 143 int32_t PepperFileRefHost::CanCreate() const { 144 if (backend_) 145 return backend_->CanCreate(); 146 return PP_ERROR_FAILED; 147 } 148 149 int32_t PepperFileRefHost::CanReadWrite() const { 150 if (backend_) 151 return backend_->CanReadWrite(); 152 return PP_ERROR_FAILED; 153 } 154 155 int32_t PepperFileRefHost::OnResourceMessageReceived( 156 const IPC::Message& msg, 157 ppapi::host::HostMessageContext* context) { 158 if (!backend_) 159 return PP_ERROR_FAILED; 160 161 IPC_BEGIN_MESSAGE_MAP(PepperFileRefHost, msg) 162 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileRef_MakeDirectory, 163 OnMakeDirectory); 164 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileRef_Touch, 165 OnTouch); 166 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_FileRef_Delete, 167 OnDelete); 168 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileRef_Rename, 169 OnRename); 170 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_FileRef_Query, 171 OnQuery); 172 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0( 173 PpapiHostMsg_FileRef_ReadDirectoryEntries, 174 OnReadDirectoryEntries); 175 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_FileRef_GetAbsolutePath, 176 OnGetAbsolutePath); 177 178 IPC_END_MESSAGE_MAP() 179 return PP_ERROR_FAILED; 180 } 181 182 int32_t PepperFileRefHost::OnMakeDirectory( 183 ppapi::host::HostMessageContext* context, 184 bool make_ancestors) { 185 int32_t rv = CanCreate(); 186 if (rv != PP_OK) 187 return rv; 188 return backend_->MakeDirectory(context->MakeReplyMessageContext(), 189 make_ancestors); 190 } 191 192 int32_t PepperFileRefHost::OnTouch(ppapi::host::HostMessageContext* context, 193 PP_Time last_access_time, 194 PP_Time last_modified_time) { 195 // TODO(teravest): Change this to be kWriteFilePermissions here and in 196 // fileapi_message_filter. 197 int32_t rv = CanCreate(); 198 if (rv != PP_OK) 199 return rv; 200 return backend_->Touch(context->MakeReplyMessageContext(), 201 last_access_time, 202 last_modified_time); 203 } 204 205 int32_t PepperFileRefHost::OnDelete(ppapi::host::HostMessageContext* context) { 206 int32_t rv = CanWrite(); 207 if (rv != PP_OK) 208 return rv; 209 return backend_->Delete(context->MakeReplyMessageContext()); 210 } 211 212 int32_t PepperFileRefHost::OnRename(ppapi::host::HostMessageContext* context, 213 PP_Resource new_file_ref) { 214 int32_t rv = CanReadWrite(); 215 if (rv != PP_OK) 216 return rv; 217 218 ResourceHost* resource_host = 219 host_->GetPpapiHost()->GetResourceHost(new_file_ref); 220 if (!resource_host) 221 return PP_ERROR_BADRESOURCE; 222 223 PepperFileRefHost* file_ref_host = NULL; 224 if (resource_host->IsFileRefHost()) 225 file_ref_host = static_cast<PepperFileRefHost*>(resource_host); 226 if (!file_ref_host) 227 return PP_ERROR_BADRESOURCE; 228 229 rv = file_ref_host->CanCreate(); 230 if (rv != PP_OK) 231 return rv; 232 233 return backend_->Rename(context->MakeReplyMessageContext(), 234 file_ref_host); 235 } 236 237 int32_t PepperFileRefHost::OnQuery(ppapi::host::HostMessageContext* context) { 238 int32_t rv = CanRead(); 239 if (rv != PP_OK) 240 return rv; 241 return backend_->Query(context->MakeReplyMessageContext()); 242 } 243 244 int32_t PepperFileRefHost::OnReadDirectoryEntries( 245 ppapi::host::HostMessageContext* context) { 246 int32_t rv = CanRead(); 247 if (rv != PP_OK) 248 return rv; 249 return backend_->ReadDirectoryEntries(context->MakeReplyMessageContext()); 250 } 251 252 int32_t PepperFileRefHost::OnGetAbsolutePath( 253 ppapi::host::HostMessageContext* context) { 254 if (!host_->GetPpapiHost()->permissions().HasPermission( 255 ppapi::PERMISSION_PRIVATE)) 256 return PP_ERROR_NOACCESS; 257 return backend_->GetAbsolutePath(context->MakeReplyMessageContext()); 258 } 259 260 } // namespace content 261