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