// Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "content/browser/renderer_host/pepper/pepper_file_ref_host.h" #include #include "content/browser/renderer_host/pepper/pepper_external_file_ref_backend.h" #include "content/browser/renderer_host/pepper/pepper_file_system_browser_host.h" #include "content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.h" #include "ppapi/c/pp_errors.h" #include "ppapi/c/pp_file_info.h" #include "ppapi/c/pp_instance.h" #include "ppapi/c/pp_resource.h" #include "ppapi/host/dispatch_host_message.h" #include "ppapi/host/ppapi_host.h" #include "ppapi/proxy/ppapi_messages.h" #include "ppapi/shared_impl/file_ref_util.h" #include "webkit/browser/fileapi/file_permission_policy.h" using ppapi::host::ResourceHost; namespace content { PepperFileRefBackend::~PepperFileRefBackend() {} PepperFileRefHost::PepperFileRefHost(BrowserPpapiHost* host, PP_Instance instance, PP_Resource resource, PP_Resource file_system, const std::string& path) : ResourceHost(host->GetPpapiHost(), instance, resource), host_(host), fs_type_(PP_FILESYSTEMTYPE_INVALID) { if (!ppapi::IsValidInternalPath(path)) return; int render_process_id; int unused; if (!host->GetRenderFrameIDsForInstance( instance, &render_process_id, &unused)) { return; } ResourceHost* fs_resource_host = host->GetPpapiHost()->GetResourceHost(file_system); if (fs_resource_host == NULL) { DLOG(ERROR) << "Couldn't find FileSystem host: " << resource << " path: " << path; return; } if (!fs_resource_host->IsFileSystemHost()) { DLOG(ERROR) << "Filesystem PP_Resource is not PepperFileSystemBrowserHost"; return; } PepperFileSystemBrowserHost* file_system_host = static_cast(fs_resource_host); file_system_host_ = file_system_host->AsWeakPtr(); fs_type_ = file_system_host->GetType(); if ((fs_type_ != PP_FILESYSTEMTYPE_LOCALPERSISTENT) && (fs_type_ != PP_FILESYSTEMTYPE_LOCALTEMPORARY) && (fs_type_ != PP_FILESYSTEMTYPE_EXTERNAL) && (fs_type_ != PP_FILESYSTEMTYPE_ISOLATED)) { DLOG(ERROR) << "Unsupported filesystem type: " << fs_type_; return; } if ((fs_type_ == PP_FILESYSTEMTYPE_EXTERNAL) && (!file_system_host->GetRootUrl().is_valid())) { DLOG(ERROR) << "Native external filesystems are not supported by this " << "constructor."; return; } backend_.reset(new PepperInternalFileRefBackend(host->GetPpapiHost(), render_process_id, file_system_host->AsWeakPtr(), path)); } PepperFileRefHost::PepperFileRefHost(BrowserPpapiHost* host, PP_Instance instance, PP_Resource resource, const base::FilePath& external_path) : ResourceHost(host->GetPpapiHost(), instance, resource), host_(host), fs_type_(PP_FILESYSTEMTYPE_EXTERNAL) { if (!ppapi::IsValidExternalPath(external_path)) return; int render_process_id; int unused; if (!host->GetRenderFrameIDsForInstance( instance, &render_process_id, &unused)) { return; } backend_.reset(new PepperExternalFileRefBackend( host->GetPpapiHost(), render_process_id, external_path)); } PepperFileRefHost::~PepperFileRefHost() {} bool PepperFileRefHost::IsFileRefHost() { return true; } PP_FileSystemType PepperFileRefHost::GetFileSystemType() const { return fs_type_; } fileapi::FileSystemURL PepperFileRefHost::GetFileSystemURL() const { if (backend_) return backend_->GetFileSystemURL(); return fileapi::FileSystemURL(); } base::FilePath PepperFileRefHost::GetExternalFilePath() const { if (backend_) return backend_->GetExternalFilePath(); return base::FilePath(); } base::WeakPtr PepperFileRefHost::GetFileSystemHost() const { return file_system_host_; } int32_t PepperFileRefHost::CanRead() const { if (backend_) return backend_->CanRead(); return PP_ERROR_FAILED; } int32_t PepperFileRefHost::CanWrite() const { if (backend_) return backend_->CanWrite(); return PP_ERROR_FAILED; } int32_t PepperFileRefHost::CanCreate() const { if (backend_) return backend_->CanCreate(); return PP_ERROR_FAILED; } int32_t PepperFileRefHost::CanReadWrite() const { if (backend_) return backend_->CanReadWrite(); return PP_ERROR_FAILED; } int32_t PepperFileRefHost::OnResourceMessageReceived( const IPC::Message& msg, ppapi::host::HostMessageContext* context) { if (!backend_) return PP_ERROR_FAILED; PPAPI_BEGIN_MESSAGE_MAP(PepperFileRefHost, msg) PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileRef_MakeDirectory, OnMakeDirectory) PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileRef_Touch, OnTouch) PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_FileRef_Delete, OnDelete) PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileRef_Rename, OnRename) PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_FileRef_Query, OnQuery) PPAPI_DISPATCH_HOST_RESOURCE_CALL_0( PpapiHostMsg_FileRef_ReadDirectoryEntries, OnReadDirectoryEntries) PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_FileRef_GetAbsolutePath, OnGetAbsolutePath) PPAPI_END_MESSAGE_MAP() return PP_ERROR_FAILED; } int32_t PepperFileRefHost::OnMakeDirectory( ppapi::host::HostMessageContext* context, int32_t make_directory_flags) { int32_t rv = CanCreate(); if (rv != PP_OK) return rv; return backend_->MakeDirectory(context->MakeReplyMessageContext(), make_directory_flags); } int32_t PepperFileRefHost::OnTouch(ppapi::host::HostMessageContext* context, PP_Time last_access_time, PP_Time last_modified_time) { // TODO(teravest): Change this to be kWriteFilePermissions here and in // fileapi_message_filter. int32_t rv = CanCreate(); if (rv != PP_OK) return rv; return backend_->Touch( context->MakeReplyMessageContext(), last_access_time, last_modified_time); } int32_t PepperFileRefHost::OnDelete(ppapi::host::HostMessageContext* context) { int32_t rv = CanWrite(); if (rv != PP_OK) return rv; return backend_->Delete(context->MakeReplyMessageContext()); } int32_t PepperFileRefHost::OnRename(ppapi::host::HostMessageContext* context, PP_Resource new_file_ref) { int32_t rv = CanReadWrite(); if (rv != PP_OK) return rv; ResourceHost* resource_host = host_->GetPpapiHost()->GetResourceHost(new_file_ref); if (!resource_host) return PP_ERROR_BADRESOURCE; PepperFileRefHost* file_ref_host = NULL; if (resource_host->IsFileRefHost()) file_ref_host = static_cast(resource_host); if (!file_ref_host) return PP_ERROR_BADRESOURCE; rv = file_ref_host->CanCreate(); if (rv != PP_OK) return rv; return backend_->Rename(context->MakeReplyMessageContext(), file_ref_host); } int32_t PepperFileRefHost::OnQuery(ppapi::host::HostMessageContext* context) { int32_t rv = CanRead(); if (rv != PP_OK) return rv; return backend_->Query(context->MakeReplyMessageContext()); } int32_t PepperFileRefHost::OnReadDirectoryEntries( ppapi::host::HostMessageContext* context) { int32_t rv = CanRead(); if (rv != PP_OK) return rv; return backend_->ReadDirectoryEntries(context->MakeReplyMessageContext()); } int32_t PepperFileRefHost::OnGetAbsolutePath( ppapi::host::HostMessageContext* context) { if (!host_->GetPpapiHost()->permissions().HasPermission( ppapi::PERMISSION_PRIVATE)) return PP_ERROR_NOACCESS; return backend_->GetAbsolutePath(context->MakeReplyMessageContext()); } } // namespace content