blob: 48942eecd6b0eb4d5106f73ab6d116eb885a2e22 [file] [log] [blame]
// 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::EnterFunctionNoLock;
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<TrackedCallback> current_open_callback_;
DISALLOW_COPY_AND_ASSIGN(FileSystem);
};
FileSystem::FileSystem(const HostResource& host_resource,
PP_FileSystemType type)
: Resource(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(&current_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<PP_FileSystemType>(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<PPB_FileSystem_API> 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<PPB_FileSystem_API> enter(host_resource);
if (enter.succeeded())
static_cast<FileSystem*>(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