#include "native_client/src/shared/ppapi_proxy/browser_callback.h"
#include <new>
#include "native_client/src/include/nacl_macros.h"
#include "native_client/src/include/nacl_scoped_ptr.h"
#include "native_client/src/shared/platform/nacl_check.h"
#include "native_client/src/shared/ppapi_proxy/browser_globals.h"
#include "native_client/src/shared/ppapi_proxy/browser_ppp.h"
#include "native_client/src/shared/ppapi_proxy/object_serialize.h"
#include "native_client/src/shared/ppapi_proxy/utility.h"
#include "native_client/src/shared/srpc/nacl_srpc.h"
#include "ppapi/c/pp_completion_callback.h"
#include "native_client/src/trusted/plugin/plugin.h"
#include "srpcgen/ppp_rpc.h"
namespace ppapi_proxy {
namespace {
bool BytesWereRead(int32_t num_bytes) {
return (num_bytes > 0);
}
nacl_abi_size_t CastToNaClAbiSize(int32_t result) {
return static_cast<nacl_abi_size_t>(result);
}
struct RemoteCallbackInfo {
NaClSrpcChannel* srpc_channel;
int32_t callback_id;
char* read_buffer;
PP_Var read_var;
CheckResultFunc check_result_func;
GetReadSizeFunc get_size_read_func;
};
void RunRemoteCallback(void* user_data, int32_t result) {
CHECK(PPBCoreInterface()->IsMainThread());
DebugPrintf("RunRemoteCallback: result=%"NACL_PRId32"\n", result);
nacl::scoped_ptr<RemoteCallbackInfo> remote_callback(
reinterpret_cast<RemoteCallbackInfo*>(user_data));
nacl::scoped_array<char> read_buffer(remote_callback->read_buffer);
PP_Instance instance =
LookupInstanceIdForSrpcChannel(remote_callback->srpc_channel);
if (LookupBrowserPppForInstance(instance) == NULL) {
DebugPrintf("RunRemoteCallback: proxy=NULL\n", result);
return;
}
nacl_abi_size_t read_buffer_size = 0;
CheckResultFunc check_result_func = remote_callback->check_result_func;
GetReadSizeFunc get_size_read_func = remote_callback->get_size_read_func;
if ((*check_result_func)(result) && remote_callback->read_buffer != NULL)
read_buffer_size = (*get_size_read_func)(result);
if (remote_callback->read_var.type != PP_VARTYPE_NULL) {
read_buffer_size = kMaxReturnVarSize;
read_buffer.reset(
Serialize(&remote_callback->read_var, 1, &read_buffer_size));
PPBVarInterface()->Release(remote_callback->read_var);
}
NaClSrpcError srpc_result =
CompletionCallbackRpcClient::RunCompletionCallback(
remote_callback->srpc_channel,
remote_callback->callback_id,
result,
read_buffer_size,
read_buffer.get());
DebugPrintf("RunRemoteCallback: %s\n",
NaClSrpcErrorString(srpc_result));
if (srpc_result == NACL_SRPC_RESULT_INTERNAL)
CleanUpAfterDeadNexe(instance);
}
}
struct PP_CompletionCallback MakeRemoteCompletionCallback(
NaClSrpcChannel* srpc_channel,
int32_t callback_id,
int32_t bytes_to_read,
char** buffer,
PP_Var** var,
CheckResultFunc check_result_func,
GetReadSizeFunc get_size_read_func) {
nacl::scoped_ptr<RemoteCallbackInfo> remote_callback(
new(std::nothrow) RemoteCallbackInfo);
if (remote_callback.get() == NULL)
return PP_BlockUntilComplete();
remote_callback->srpc_channel = srpc_channel;
remote_callback->callback_id = callback_id;
remote_callback->read_buffer = NULL;
remote_callback->read_var = PP_MakeNull();
remote_callback->check_result_func = check_result_func;
remote_callback->get_size_read_func = get_size_read_func;
if (bytes_to_read > 0 && buffer != NULL) {
*buffer = new(std::nothrow) char[bytes_to_read];
if (*buffer == NULL)
return PP_BlockUntilComplete();
remote_callback->read_buffer = *buffer;
}
if (var)
*var = &remote_callback->read_var;
return PP_MakeOptionalCompletionCallback(
RunRemoteCallback, remote_callback.release());
}
struct PP_CompletionCallback MakeRemoteCompletionCallback(
NaClSrpcChannel* srpc_channel,
int32_t callback_id,
int32_t bytes_to_read,
char** buffer,
CheckResultFunc check_result_func,
GetReadSizeFunc get_size_read_func) {
return MakeRemoteCompletionCallback(srpc_channel, callback_id, bytes_to_read,
buffer, NULL, check_result_func,
get_size_read_func);
}
struct PP_CompletionCallback MakeRemoteCompletionCallback(
NaClSrpcChannel* srpc_channel,
int32_t callback_id,
int32_t bytes_to_read,
char** buffer) {
return MakeRemoteCompletionCallback(srpc_channel, callback_id, bytes_to_read,
buffer, BytesWereRead, CastToNaClAbiSize);
}
struct PP_CompletionCallback MakeRemoteCompletionCallback(
NaClSrpcChannel* srpc_channel,
int32_t callback_id,
PP_Var** var) {
return MakeRemoteCompletionCallback(srpc_channel, callback_id, 0, NULL, var,
BytesWereRead, CastToNaClAbiSize);
}
struct PP_CompletionCallback MakeRemoteCompletionCallback(
NaClSrpcChannel* srpc_channel,
int32_t callback_id) {
return MakeRemoteCompletionCallback(srpc_channel, callback_id, 0, NULL);
}
void DeleteRemoteCallbackInfo(struct PP_CompletionCallback callback) {
nacl::scoped_ptr<RemoteCallbackInfo> remote_callback(
reinterpret_cast<RemoteCallbackInfo*>(callback.user_data));
nacl::scoped_array<char> read_buffer(remote_callback->read_buffer);
}
}