This source file includes following definitions.
- GetConnectionForInstance
- host_object_id
- ReceiveObjectPassRef
- TrackObjectWithNoReference
- StopTrackingObjectWithNoReference
- GetHostObject
- DispatcherForPluginObject
- ReleaseHostObject
- MakeResourcePPVarFromMessage
- MakeResourceVar
- DidDeleteInstance
- DidDeleteDispatcher
- CreateArrayBuffer
- CreateShmArrayBuffer
- PluginImplementedObjectCreated
- PluginImplementedObjectDestroyed
- IsPluginImplementedObjectAlive
- ValidatePluginObjectCall
- AddVarInternal
- TrackedObjectGettingOneRef
- ObjectGettingZeroRef
- DeleteObjectInfoIfNecessary
- GetOrCreateObjectVarID
- SendAddRefObjectMsg
- SendReleaseObjectMsg
- FindOrMakePluginVarFromHostVar
- TrackSharedMemoryHandle
- StopTrackingSharedMemoryHandle
#include "ppapi/proxy/plugin_var_tracker.h"
#include "base/memory/ref_counted.h"
#include "base/memory/singleton.h"
#include "ipc/ipc_message.h"
#include "ppapi/c/dev/ppp_class_deprecated.h"
#include "ppapi/c/ppb_var.h"
#include "ppapi/proxy/file_system_resource.h"
#include "ppapi/proxy/media_stream_audio_track_resource.h"
#include "ppapi/proxy/media_stream_video_track_resource.h"
#include "ppapi/proxy/plugin_array_buffer_var.h"
#include "ppapi/proxy/plugin_dispatcher.h"
#include "ppapi/proxy/plugin_globals.h"
#include "ppapi/proxy/plugin_resource_var.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/proxy/proxy_object_var.h"
#include "ppapi/shared_impl/api_id.h"
#include "ppapi/shared_impl/ppapi_globals.h"
#include "ppapi/shared_impl/proxy_lock.h"
#include "ppapi/shared_impl/resource_tracker.h"
#include "ppapi/shared_impl/var.h"
namespace ppapi {
namespace proxy {
namespace {
Connection GetConnectionForInstance(PP_Instance instance) {
PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
DCHECK(dispatcher);
return Connection(PluginGlobals::Get()->GetBrowserSender(), dispatcher);
}
}
PluginVarTracker::HostVar::HostVar(PluginDispatcher* d, int32 i)
: dispatcher(d),
host_object_id(i) {
}
bool PluginVarTracker::HostVar::operator<(const HostVar& other) const {
if (dispatcher < other.dispatcher)
return true;
if (other.dispatcher < dispatcher)
return false;
return host_object_id < other.host_object_id;
}
PluginVarTracker::PluginVarTracker() : VarTracker(THREAD_SAFE) {
}
PluginVarTracker::~PluginVarTracker() {
}
PP_Var PluginVarTracker::ReceiveObjectPassRef(const PP_Var& host_var,
PluginDispatcher* dispatcher) {
CheckThreadingPreconditions();
DCHECK(host_var.type == PP_VARTYPE_OBJECT);
scoped_refptr<ProxyObjectVar> object(
FindOrMakePluginVarFromHostVar(host_var, dispatcher));
PP_Var ret = GetOrCreateObjectVarID(object.get());
VarInfo& info = GetLiveVar(ret)->second;
if (info.ref_count > 0) {
SendReleaseObjectMsg(*object.get());
}
info.ref_count++;
return ret;
}
PP_Var PluginVarTracker::TrackObjectWithNoReference(
const PP_Var& host_var,
PluginDispatcher* dispatcher) {
CheckThreadingPreconditions();
DCHECK(host_var.type == PP_VARTYPE_OBJECT);
scoped_refptr<ProxyObjectVar> object(
FindOrMakePluginVarFromHostVar(host_var, dispatcher));
PP_Var ret = GetOrCreateObjectVarID(object.get());
VarInfo& info = GetLiveVar(ret)->second;
info.track_with_no_reference_count++;
return ret;
}
void PluginVarTracker::StopTrackingObjectWithNoReference(
const PP_Var& plugin_var) {
CheckThreadingPreconditions();
DCHECK(plugin_var.type == PP_VARTYPE_OBJECT);
VarMap::iterator found = GetLiveVar(plugin_var);
if (found == live_vars_.end()) {
NOTREACHED();
return;
}
DCHECK(found->second.track_with_no_reference_count > 0);
found->second.track_with_no_reference_count--;
DeleteObjectInfoIfNecessary(found);
}
PP_Var PluginVarTracker::GetHostObject(const PP_Var& plugin_object) const {
CheckThreadingPreconditions();
if (plugin_object.type != PP_VARTYPE_OBJECT) {
NOTREACHED();
return PP_MakeUndefined();
}
Var* var = GetVar(plugin_object);
ProxyObjectVar* object = var->AsProxyObjectVar();
if (!object) {
NOTREACHED();
return PP_MakeUndefined();
}
PP_Var ret = { PP_VARTYPE_OBJECT };
ret.value.as_id = object->host_var_id();
return ret;
}
PluginDispatcher* PluginVarTracker::DispatcherForPluginObject(
const PP_Var& plugin_object) const {
CheckThreadingPreconditions();
if (plugin_object.type != PP_VARTYPE_OBJECT)
return NULL;
VarMap::const_iterator found = GetLiveVar(plugin_object);
if (found == live_vars_.end())
return NULL;
ProxyObjectVar* object = found->second.var->AsProxyObjectVar();
if (!object)
return NULL;
return object->dispatcher();
}
void PluginVarTracker::ReleaseHostObject(PluginDispatcher* dispatcher,
const PP_Var& host_object) {
CheckThreadingPreconditions();
DCHECK(host_object.type == PP_VARTYPE_OBJECT);
HostVarToPluginVarMap::iterator found = host_var_to_plugin_var_.find(
HostVar(dispatcher, static_cast<int32>(host_object.value.as_id)));
if (found == host_var_to_plugin_var_.end()) {
NOTREACHED();
return;
}
ReleaseVar(found->second);
}
PP_Var PluginVarTracker::MakeResourcePPVarFromMessage(
PP_Instance instance,
const IPC::Message& creation_message,
int pending_renderer_id,
int pending_browser_id) {
switch (creation_message.type()) {
case PpapiPluginMsg_FileSystem_CreateFromPendingHost::ID: {
DCHECK(pending_renderer_id);
DCHECK(pending_browser_id);
PP_FileSystemType file_system_type;
if (!UnpackMessage<PpapiPluginMsg_FileSystem_CreateFromPendingHost>(
creation_message, &file_system_type)) {
NOTREACHED() << "Invalid message of type "
"PpapiPluginMsg_FileSystem_CreateFromPendingHost";
return PP_MakeNull();
}
PP_Resource pp_resource =
(new FileSystemResource(GetConnectionForInstance(instance),
instance,
pending_renderer_id,
pending_browser_id,
file_system_type))->GetReference();
return MakeResourcePPVar(pp_resource);
}
case PpapiPluginMsg_MediaStreamAudioTrack_CreateFromPendingHost::ID: {
DCHECK(pending_renderer_id);
std::string track_id;
if (!UnpackMessage<
PpapiPluginMsg_MediaStreamAudioTrack_CreateFromPendingHost>(
creation_message, &track_id)) {
NOTREACHED() <<
"Invalid message of type "
"PpapiPluginMsg_MediaStreamAudioTrack_CreateFromPendingHost";
return PP_MakeNull();
}
PP_Resource pp_resource =
(new MediaStreamAudioTrackResource(GetConnectionForInstance(instance),
instance,
pending_renderer_id,
track_id))->GetReference();
return MakeResourcePPVar(pp_resource);
}
case PpapiPluginMsg_MediaStreamVideoTrack_CreateFromPendingHost::ID: {
DCHECK(pending_renderer_id);
std::string track_id;
if (!UnpackMessage<
PpapiPluginMsg_MediaStreamVideoTrack_CreateFromPendingHost>(
creation_message, &track_id)) {
NOTREACHED() <<
"Invalid message of type "
"PpapiPluginMsg_MediaStreamVideoTrack_CreateFromPendingHost";
return PP_MakeNull();
}
PP_Resource pp_resource =
(new MediaStreamVideoTrackResource(GetConnectionForInstance(instance),
instance,
pending_renderer_id,
track_id))->GetReference();
return MakeResourcePPVar(pp_resource);
}
default: {
NOTREACHED() << "Creation message has unexpected type "
<< creation_message.type();
return PP_MakeNull();
}
}
}
ResourceVar* PluginVarTracker::MakeResourceVar(PP_Resource pp_resource) {
if (!pp_resource)
return new PluginResourceVar();
ResourceTracker* resource_tracker = PpapiGlobals::Get()->GetResourceTracker();
ppapi::Resource* resource = resource_tracker->GetResource(pp_resource);
if (!resource)
return NULL;
return new PluginResourceVar(resource);
}
void PluginVarTracker::DidDeleteInstance(PP_Instance instance) {
std::vector<void*> user_data_to_delete;
for (UserDataToPluginImplementedVarMap::const_iterator i =
user_data_to_plugin_.begin();
i != user_data_to_plugin_.end();
++i) {
if (i->second.instance == instance)
user_data_to_delete.push_back(i->first);
}
for (size_t i = 0; i < user_data_to_delete.size(); i++) {
UserDataToPluginImplementedVarMap::iterator found =
user_data_to_plugin_.find(user_data_to_delete[i]);
if (found == user_data_to_plugin_.end())
continue;
if (!found->second.plugin_object_id) {
CallWhileUnlocked(found->second.ppp_class->Deallocate, found->first);
user_data_to_plugin_.erase(found);
} else {
found->second.instance = 0;
}
}
}
void PluginVarTracker::DidDeleteDispatcher(PluginDispatcher* dispatcher) {
for (VarMap::iterator it = live_vars_.begin();
it != live_vars_.end();
++it) {
if (it->second.var.get() == NULL)
continue;
ProxyObjectVar* object = it->second.var->AsProxyObjectVar();
if (object && object->dispatcher() == dispatcher)
object->clear_dispatcher();
}
}
ArrayBufferVar* PluginVarTracker::CreateArrayBuffer(uint32 size_in_bytes) {
return new PluginArrayBufferVar(size_in_bytes);
}
ArrayBufferVar* PluginVarTracker::CreateShmArrayBuffer(
uint32 size_in_bytes,
base::SharedMemoryHandle handle) {
return new PluginArrayBufferVar(size_in_bytes, handle);
}
void PluginVarTracker::PluginImplementedObjectCreated(
PP_Instance instance,
const PP_Var& created_var,
const PPP_Class_Deprecated* ppp_class,
void* ppp_class_data) {
PluginImplementedVar p;
p.ppp_class = ppp_class;
p.instance = instance;
p.plugin_object_id = created_var.value.as_id;
user_data_to_plugin_[ppp_class_data] = p;
ProxyObjectVar* object = GetVar(created_var)->AsProxyObjectVar();
object->set_user_data(ppp_class_data);
}
void PluginVarTracker::PluginImplementedObjectDestroyed(void* user_data) {
UserDataToPluginImplementedVarMap::iterator found =
user_data_to_plugin_.find(user_data);
if (found == user_data_to_plugin_.end()) {
NOTREACHED();
return;
}
user_data_to_plugin_.erase(found);
}
bool PluginVarTracker::IsPluginImplementedObjectAlive(void* user_data) {
return user_data_to_plugin_.find(user_data) != user_data_to_plugin_.end();
}
bool PluginVarTracker::ValidatePluginObjectCall(
const PPP_Class_Deprecated* ppp_class,
void* user_data) {
UserDataToPluginImplementedVarMap::iterator found =
user_data_to_plugin_.find(user_data);
if (found == user_data_to_plugin_.end())
return false;
return found->second.ppp_class == ppp_class;
}
int32 PluginVarTracker::AddVarInternal(Var* var, AddVarRefMode mode) {
int32 new_id = VarTracker::AddVarInternal(var, mode);
ProxyObjectVar* proxy_object = var->AsProxyObjectVar();
if (proxy_object) {
HostVar host_var(proxy_object->dispatcher(), proxy_object->host_var_id());
CHECK(host_var_to_plugin_var_.find(host_var) ==
host_var_to_plugin_var_.end());
host_var_to_plugin_var_[host_var] = new_id;
}
return new_id;
}
void PluginVarTracker::TrackedObjectGettingOneRef(VarMap::const_iterator iter) {
ProxyObjectVar* object = iter->second.var->AsProxyObjectVar();
if (!object) {
NOTREACHED();
return;
}
DCHECK(iter->second.ref_count == 0);
SendAddRefObjectMsg(*object);
}
void PluginVarTracker::ObjectGettingZeroRef(VarMap::iterator iter) {
ProxyObjectVar* object = iter->second.var->AsProxyObjectVar();
if (!object) {
NOTREACHED();
return;
}
DCHECK(iter->second.ref_count == 0);
SendReleaseObjectMsg(*object);
UserDataToPluginImplementedVarMap::iterator found =
user_data_to_plugin_.find(object->user_data());
if (found != user_data_to_plugin_.end()) {
if (found->second.instance == 0) {
found->second.ppp_class->Deallocate(found->first);
user_data_to_plugin_.erase(found);
} else {
found->second.plugin_object_id = 0;
}
}
VarTracker::ObjectGettingZeroRef(iter);
}
bool PluginVarTracker::DeleteObjectInfoIfNecessary(VarMap::iterator iter) {
ProxyObjectVar* object = iter->second.var->AsProxyObjectVar();
HostVar host_var(object->dispatcher(), object->host_var_id());
if (!VarTracker::DeleteObjectInfoIfNecessary(iter))
return false;
DCHECK(host_var_to_plugin_var_.find(host_var) !=
host_var_to_plugin_var_.end());
host_var_to_plugin_var_.erase(host_var);
return true;
}
PP_Var PluginVarTracker::GetOrCreateObjectVarID(ProxyObjectVar* object) {
int32 var_id = object->GetExistingVarID();
if (!var_id) {
var_id = AddVarInternal(object, ADD_VAR_CREATE_WITH_NO_REFERENCE);
object->AssignVarID(var_id);
}
PP_Var ret = { PP_VARTYPE_OBJECT };
ret.value.as_id = var_id;
return ret;
}
void PluginVarTracker::SendAddRefObjectMsg(
const ProxyObjectVar& proxy_object) {
int unused;
if (proxy_object.dispatcher()) {
proxy_object.dispatcher()->Send(new PpapiHostMsg_PPBVar_AddRefObject(
API_ID_PPB_VAR_DEPRECATED, proxy_object.host_var_id(), &unused));
}
}
void PluginVarTracker::SendReleaseObjectMsg(
const ProxyObjectVar& proxy_object) {
if (proxy_object.dispatcher()) {
proxy_object.dispatcher()->Send(new PpapiHostMsg_PPBVar_ReleaseObject(
API_ID_PPB_VAR_DEPRECATED, proxy_object.host_var_id()));
}
}
scoped_refptr<ProxyObjectVar> PluginVarTracker::FindOrMakePluginVarFromHostVar(
const PP_Var& var,
PluginDispatcher* dispatcher) {
DCHECK(var.type == PP_VARTYPE_OBJECT);
HostVar host_var(dispatcher, var.value.as_id);
HostVarToPluginVarMap::iterator found =
host_var_to_plugin_var_.find(host_var);
if (found == host_var_to_plugin_var_.end()) {
return scoped_refptr<ProxyObjectVar>(
new ProxyObjectVar(dispatcher, static_cast<int32>(var.value.as_id)));
}
VarMap::iterator ret = live_vars_.find(found->second);
CHECK(ret != live_vars_.end());
DCHECK(ret->second.var->AsProxyObjectVar());
return scoped_refptr<ProxyObjectVar>(ret->second.var->AsProxyObjectVar());
}
int PluginVarTracker::TrackSharedMemoryHandle(PP_Instance instance,
base::SharedMemoryHandle handle,
uint32 size_in_bytes) {
NOTREACHED();
return -1;
}
bool PluginVarTracker::StopTrackingSharedMemoryHandle(
int id,
PP_Instance instance,
base::SharedMemoryHandle* handle,
uint32* size_in_bytes) {
NOTREACHED();
return false;
}
}
}