// Copyright (c) 2012 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 "ppapi/proxy/ppb_file_system_proxy.h" #include "base/bind.h" #include "base/message_loop.h" #include "ppapi/c/pp_errors.h" #include "ppapi/c/ppb_file_system.h" #include "ppapi/proxy/enter_proxy.h" #include "ppapi/proxy/host_dispatcher.h" #include "ppapi/proxy/plugin_dispatcher.h" #include "ppapi/proxy/ppapi_messages.h" #include "ppapi/proxy/serialized_var.h" #include "ppapi/shared_impl/tracked_callback.h" #include "ppapi/thunk/enter.h" #include "ppapi/thunk/ppb_file_system_api.h" #include "ppapi/thunk/resource_creation_api.h" #include "ppapi/thunk/thunk.h" using ppapi::thunk::PPB_FileSystem_API; using ppapi::thunk::ResourceCreationAPI; namespace ppapi { namespace proxy { namespace { InterfaceProxy* CreateFileSystemProxy(Dispatcher* dispatcher) { return new PPB_FileSystem_Proxy(dispatcher); } } // namespace // This object maintains most of the state of the ref in the plugin for fast // querying. It's all set in the constructor from the "create info" sent from // the host. class FileSystem : public Resource, public PPB_FileSystem_API { public: FileSystem(const HostResource& host_resource, PP_FileSystemType type); virtual ~FileSystem(); // Resource override. virtual PPB_FileSystem_API* AsPPB_FileSystem_API() OVERRIDE; // PPB_FileSystem_APi implementation. virtual int32_t Open(int64_t expected_size, PP_CompletionCallback callback) OVERRIDE; virtual PP_FileSystemType GetType() OVERRIDE; // Called when the host has responded to our open request. void OpenComplete(int32_t result); private: PP_FileSystemType type_; bool called_open_; scoped_refptr current_open_callback_; DISALLOW_COPY_AND_ASSIGN(FileSystem); }; FileSystem::FileSystem(const HostResource& host_resource, PP_FileSystemType type) : Resource(OBJECT_IS_PROXY, host_resource), type_(type), called_open_(false) { } FileSystem::~FileSystem() { } PPB_FileSystem_API* FileSystem::AsPPB_FileSystem_API() { return this; } int32_t FileSystem::Open(int64_t expected_size, PP_CompletionCallback callback) { if (TrackedCallback::IsPending(current_open_callback_)) return PP_ERROR_INPROGRESS; if (called_open_) return PP_ERROR_FAILED; current_open_callback_ = new TrackedCallback(this, callback); called_open_ = true; PluginDispatcher::GetForResource(this)->Send( new PpapiHostMsg_PPBFileSystem_Open( API_ID_PPB_FILE_SYSTEM, host_resource(), expected_size)); return PP_OK_COMPLETIONPENDING; } PP_FileSystemType FileSystem::GetType() { return type_; } void FileSystem::OpenComplete(int32_t result) { TrackedCallback::ClearAndRun(¤t_open_callback_, result); } PPB_FileSystem_Proxy::PPB_FileSystem_Proxy(Dispatcher* dispatcher) : InterfaceProxy(dispatcher), callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { } PPB_FileSystem_Proxy::~PPB_FileSystem_Proxy() { } const InterfaceProxy::Info* PPB_FileSystem_Proxy::GetInfo() { static const Info info = { thunk::GetPPB_FileSystem_1_0_Thunk(), PPB_FILESYSTEM_INTERFACE_1_0, API_ID_PPB_FILE_SYSTEM, false, &CreateFileSystemProxy, }; return &info; } // static PP_Resource PPB_FileSystem_Proxy::CreateProxyResource( PP_Instance instance, PP_FileSystemType type) { PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance); if (!dispatcher) return PP_ERROR_BADARGUMENT; HostResource result; dispatcher->Send(new PpapiHostMsg_PPBFileSystem_Create( API_ID_PPB_FILE_SYSTEM, instance, type, &result)); if (result.is_null()) return 0; return (new FileSystem(result, type))->GetReference(); } bool PPB_FileSystem_Proxy::OnMessageReceived(const IPC::Message& msg) { bool handled = true; IPC_BEGIN_MESSAGE_MAP(PPB_FileSystem_Proxy, msg) IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileSystem_Create, OnMsgCreate) IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileSystem_Open, OnMsgOpen) IPC_MESSAGE_HANDLER(PpapiMsg_PPBFileSystem_OpenComplete, OnMsgOpenComplete) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() return handled; } void PPB_FileSystem_Proxy::OnMsgCreate(PP_Instance instance, int type, HostResource* result) { thunk::EnterResourceCreation enter(instance); if (enter.failed()) return; PP_Resource resource = enter.functions()->CreateFileSystem( instance, static_cast(type)); if (!resource) return; // CreateInfo default constructor initializes to 0. result->SetHostResource(instance, resource); } void PPB_FileSystem_Proxy::OnMsgOpen(const HostResource& host_resource, int64_t expected_size) { EnterHostFromHostResourceForceCallback enter( host_resource, callback_factory_, &PPB_FileSystem_Proxy::OpenCompleteInHost, host_resource); if (enter.succeeded()) enter.SetResult(enter.object()->Open(expected_size, enter.callback())); } // Called in the plugin to handle the open callback. void PPB_FileSystem_Proxy::OnMsgOpenComplete(const HostResource& host_resource, int32_t result) { EnterPluginFromHostResource enter(host_resource); if (enter.succeeded()) static_cast(enter.object())->OpenComplete(result); } void PPB_FileSystem_Proxy::OpenCompleteInHost( int32_t result, const HostResource& host_resource) { dispatcher()->Send(new PpapiMsg_PPBFileSystem_OpenComplete( API_ID_PPB_FILE_SYSTEM, host_resource, result)); } } // namespace proxy } // namespace ppapi