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 "webkit/plugins/ppapi/host_var_tracker.h"
7 #include "base/logging.h"
8 #include "ppapi/c/pp_var.h"
9 #include "webkit/plugins/ppapi/host_array_buffer_var.h"
10 #include "webkit/plugins/ppapi/npobject_var.h"
11 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
13 using ppapi::ArrayBufferVar
;
14 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 void HostVarTracker::DidDeleteInstance(PP_Instance instance
) {
107 CheckThreadingPreconditions();
109 InstanceMap::iterator found_instance
= instance_map_
.find(instance
);
110 if (found_instance
== instance_map_
.end())
111 return; // Nothing to do.
112 NPObjectToNPObjectVarMap
* np_object_map
= found_instance
->second
.get();
114 // Force delete all var references. ForceReleaseNPObject() will cause
115 // this object, and potentially others it references, to be removed from
117 while (!np_object_map
->empty()) {
118 ForceReleaseNPObject(np_object_map
->begin()->second
);
121 // Remove the record for this instance since it should be empty.
122 DCHECK(np_object_map
->empty());
123 instance_map_
.erase(found_instance
);
126 void HostVarTracker::ForceReleaseNPObject(::ppapi::NPObjectVar
* object_var
) {
127 object_var
->InstanceDeleted();
128 VarMap::iterator iter
= live_vars_
.find(object_var
->GetExistingVarID());
129 if (iter
== live_vars_
.end()) {
133 iter
->second
.ref_count
= 0;
134 DCHECK(iter
->second
.track_with_no_reference_count
== 0);
135 DeleteObjectInfoIfNecessary(iter
);
138 int HostVarTracker::TrackSharedMemoryHandle(PP_Instance instance
,
139 base::SharedMemoryHandle handle
,
140 uint32 size_in_bytes
) {
141 SharedMemoryMapEntry entry
;
142 entry
.instance
= instance
;
143 entry
.handle
= handle
;
144 entry
.size_in_bytes
= size_in_bytes
;
146 // Find a free id for our map.
147 while (shared_memory_map_
.find(last_shared_memory_map_id_
) !=
148 shared_memory_map_
.end()) {
149 ++last_shared_memory_map_id_
;
151 shared_memory_map_
[last_shared_memory_map_id_
] = entry
;
152 return last_shared_memory_map_id_
;
155 bool HostVarTracker::StopTrackingSharedMemoryHandle(
157 PP_Instance instance
,
158 base::SharedMemoryHandle
* handle
,
159 uint32
* size_in_bytes
) {
160 SharedMemoryMap::iterator it
= shared_memory_map_
.find(id
);
161 if (it
== shared_memory_map_
.end())
163 if (it
->second
.instance
!= instance
)
166 *handle
= it
->second
.handle
;
167 *size_in_bytes
= it
->second
.size_in_bytes
;
168 shared_memory_map_
.erase(it
);
173 } // namespace webkit