blob: 54e8dd3cd1c43f2ef0b1681f9268de25cce762de [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 "native_client/src/shared/ppapi_proxy/plugin_callback.h"
#include <string.h>
#include "native_client/src/shared/ppapi_proxy/object_serialize.h"
#include "native_client/src/shared/ppapi_proxy/utility.h"
#include "ppapi/c/pp_errors.h"
#include "srpcgen/ppp_rpc.h"
namespace ppapi_proxy {
int32_t MayForceCallback(PP_CompletionCallback callback, int32_t result) {
if (result == PP_OK_COMPLETIONPENDING)
return result;
if (callback.func == NULL ||
(callback.flags & PP_COMPLETIONCALLBACK_FLAG_OPTIONAL) != 0)
return result;
PPBCoreInterface()->CallOnMainThread(0, callback, result);
return PP_OK_COMPLETIONPENDING;
}
// Initialize static mutex used as critical section for all callback tables.
pthread_mutex_t CompletionCallbackTable::mutex_ = PTHREAD_MUTEX_INITIALIZER;
int32_t CompletionCallbackTable::AddCallback(
const PP_CompletionCallback& callback,
void* read_buffer,
PP_Var* read_var) {
CallbackTableCriticalSection guard;
DCHECK (!read_buffer || !read_var);
if (callback.func == NULL) {
DebugPrintf("CompletionCallbackTable attempted to add NULL func!!\n");
return 0;
}
int32_t callback_id = next_id_;
++next_id_;
CallbackInfo info = { callback, read_buffer, read_var };
table_.insert(std::pair<int32_t, CallbackInfo>(callback_id, info));
return callback_id;
}
int32_t CompletionCallbackTable::AddCallback(
const PP_CompletionCallback& callback) {
return AddCallback(callback, NULL, NULL);
}
int32_t CompletionCallbackTable::AddCallback(
const PP_CompletionCallback& callback,
void* read_buffer) {
return AddCallback(callback, read_buffer, NULL);
}
int32_t CompletionCallbackTable::AddCallback(
const PP_CompletionCallback& callback,
PP_Var* read_var) {
return AddCallback(callback, NULL, read_var);
}
PP_CompletionCallback CompletionCallbackTable::RemoveCallback(
int32_t callback_id, void** read_buffer, PP_Var** read_var) {
CallbackTableCriticalSection guard;
CallbackTable::iterator it = table_.find(callback_id);
DebugPrintf("CompletionCallbackTable::RemoveCallback id: %"NACL_PRId32"\n",
callback_id);
if (table_.end() != it) {
CallbackInfo info = it->second;
table_.erase(it);
if (read_buffer != NULL)
*read_buffer = info.read_buffer;
if (read_var != NULL)
*read_var = info.read_var;
return info.callback;
}
*read_buffer = NULL;
return PP_BlockUntilComplete();
}
} // namespace ppapi_proxy
// SRPC-abstraction wrapper around a PP_CompletionCallback.
void CompletionCallbackRpcServer::RunCompletionCallback(
NaClSrpcRpc* rpc,
NaClSrpcClosure* done,
// inputs
int32_t callback_id,
int32_t result,
// TODO(polina): use shm for read buffer
nacl_abi_size_t read_buffer_size, char* read_buffer) {
NaClSrpcClosureRunner runner(done);
rpc->result = NACL_SRPC_RESULT_APP_ERROR;
void* user_buffer;
PP_Var* user_var;
PP_CompletionCallback callback =
ppapi_proxy::CompletionCallbackTable::Get()->RemoveCallback(
callback_id, &user_buffer, &user_var);
if (callback.func == NULL) {
ppapi_proxy::DebugPrintf(
"CompletionCallbackRpcServer: id of %"NACL_PRId32" is NULL callback!\n",
callback_id);
return;
}
if (user_buffer != NULL && read_buffer_size > 0)
memcpy(user_buffer, read_buffer, read_buffer_size);
else if (user_var != NULL && read_buffer_size > 0)
ppapi_proxy::DeserializeTo(read_buffer, read_buffer_size, 1, user_var);
PP_RunCompletionCallback(&callback, result);
rpc->result = NACL_SRPC_RESULT_OK;
}