1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/renderer/pepper/host_var_tracker.h"
7 #include "base/logging.h"
8 #include "content/renderer/pepper/host_array_buffer_var.h"
9 #include "content/renderer/pepper/host_resource_var.h"
10 #include "content/renderer/pepper/npobject_var.h"
11 #include "content/renderer/pepper/pepper_plugin_instance_impl.h"
12 #include "ppapi/c/pp_var.h"
14 using ppapi::ArrayBufferVar;
15 using ppapi::NPObjectVar;
19 HostVarTracker::HostVarTracker()
20 : VarTracker(SINGLE_THREADED),
21 last_shared_memory_map_id_(0) {
24 HostVarTracker::~HostVarTracker() {
27 ArrayBufferVar* HostVarTracker::CreateArrayBuffer(uint32 size_in_bytes) {
28 return new HostArrayBufferVar(size_in_bytes);
31 ArrayBufferVar* HostVarTracker::CreateShmArrayBuffer(
33 base::SharedMemoryHandle handle) {
34 return new HostArrayBufferVar(size_in_bytes, handle);
37 void HostVarTracker::AddNPObjectVar(NPObjectVar* object_var) {
38 CheckThreadingPreconditions();
40 InstanceMap::iterator found_instance = instance_map_.find(
41 object_var->pp_instance());
42 if (found_instance == instance_map_.end()) {
43 // Lazily create the instance map.
44 DCHECK(object_var->pp_instance() != 0);
45 found_instance = instance_map_.insert(std::make_pair(
46 object_var->pp_instance(),
47 linked_ptr<NPObjectToNPObjectVarMap>(new NPObjectToNPObjectVarMap))).
50 NPObjectToNPObjectVarMap* np_object_map = found_instance->second.get();
52 DCHECK(np_object_map->find(object_var->np_object()) ==
53 np_object_map->end()) << "NPObjectVar already in map";
54 np_object_map->insert(std::make_pair(object_var->np_object(), object_var));
57 void HostVarTracker::RemoveNPObjectVar(NPObjectVar* object_var) {
58 CheckThreadingPreconditions();
60 InstanceMap::iterator found_instance = instance_map_.find(
61 object_var->pp_instance());
62 if (found_instance == instance_map_.end()) {
63 NOTREACHED() << "NPObjectVar has invalid instance.";
66 NPObjectToNPObjectVarMap* np_object_map = found_instance->second.get();
68 NPObjectToNPObjectVarMap::iterator found_object =
69 np_object_map->find(object_var->np_object());
70 if (found_object == np_object_map->end()) {
71 NOTREACHED() << "NPObjectVar not registered.";
74 if (found_object->second != object_var) {
75 NOTREACHED() << "NPObjectVar doesn't match.";
78 np_object_map->erase(found_object);
81 NPObjectVar* HostVarTracker::NPObjectVarForNPObject(PP_Instance instance,
82 NPObject* np_object) {
83 CheckThreadingPreconditions();
85 InstanceMap::iterator found_instance = instance_map_.find(instance);
86 if (found_instance == instance_map_.end())
87 return NULL; // No such instance.
88 NPObjectToNPObjectVarMap* np_object_map = found_instance->second.get();
90 NPObjectToNPObjectVarMap::iterator found_object =
91 np_object_map->find(np_object);
92 if (found_object == np_object_map->end())
93 return NULL; // No such object.
94 return found_object->second;
97 int HostVarTracker::GetLiveNPObjectVarsForInstance(PP_Instance instance) const {
98 CheckThreadingPreconditions();
100 InstanceMap::const_iterator found = instance_map_.find(instance);
101 if (found == instance_map_.end())
103 return static_cast<int>(found->second->size());
106 PP_Var HostVarTracker::MakeResourcePPVarFromMessage(
107 PP_Instance instance,
108 const IPC::Message& creation_message,
109 int pending_renderer_id,
110 int pending_browser_id) {
111 // On the host side, the creation message is ignored when creating a resource.
112 // Therefore, a call to this function indicates a null resource. Return the
114 return MakeResourcePPVar(0);
117 ppapi::ResourceVar* HostVarTracker::MakeResourceVar(PP_Resource pp_resource) {
118 return new HostResourceVar(pp_resource);
121 void HostVarTracker::DidDeleteInstance(PP_Instance instance) {
122 CheckThreadingPreconditions();
124 InstanceMap::iterator found_instance = instance_map_.find(instance);
125 if (found_instance == instance_map_.end())
126 return; // Nothing to do.
127 NPObjectToNPObjectVarMap* np_object_map = found_instance->second.get();
129 // Force delete all var references. ForceReleaseNPObject() will cause
130 // this object, and potentially others it references, to be removed from
132 while (!np_object_map->empty()) {
133 ForceReleaseNPObject(np_object_map->begin()->second);
136 // Remove the record for this instance since it should be empty.
137 DCHECK(np_object_map->empty());
138 instance_map_.erase(found_instance);
141 void HostVarTracker::ForceReleaseNPObject(ppapi::NPObjectVar* object_var) {
142 object_var->InstanceDeleted();
143 VarMap::iterator iter = live_vars_.find(object_var->GetExistingVarID());
144 if (iter == live_vars_.end()) {
148 iter->second.ref_count = 0;
149 DCHECK(iter->second.track_with_no_reference_count == 0);
150 DeleteObjectInfoIfNecessary(iter);
153 int HostVarTracker::TrackSharedMemoryHandle(PP_Instance instance,
154 base::SharedMemoryHandle handle,
155 uint32 size_in_bytes) {
156 SharedMemoryMapEntry entry;
157 entry.instance = instance;
158 entry.handle = handle;
159 entry.size_in_bytes = size_in_bytes;
161 // Find a free id for our map.
162 while (shared_memory_map_.find(last_shared_memory_map_id_) !=
163 shared_memory_map_.end()) {
164 ++last_shared_memory_map_id_;
166 shared_memory_map_[last_shared_memory_map_id_] = entry;
167 return last_shared_memory_map_id_;
170 bool HostVarTracker::StopTrackingSharedMemoryHandle(
172 PP_Instance instance,
173 base::SharedMemoryHandle* handle,
174 uint32* size_in_bytes) {
175 SharedMemoryMap::iterator it = shared_memory_map_.find(id);
176 if (it == shared_memory_map_.end())
178 if (it->second.instance != instance)
181 *handle = it->second.handle;
182 *size_in_bytes = it->second.size_in_bytes;
183 shared_memory_map_.erase(it);
187 } // namespace content