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_globals.h"
10 #include "content/renderer/pepper/host_resource_var.h"
11 #include "content/renderer/pepper/pepper_plugin_instance_impl.h"
12 #include "content/renderer/pepper/v8object_var.h"
13 #include "ppapi/c/pp_var.h"
15 using ppapi::ArrayBufferVar
;
16 using ppapi::V8ObjectVar
;
20 HostVarTracker::V8ObjectVarKey::V8ObjectVarKey(V8ObjectVar
* object_var
)
21 : instance(object_var
->instance()->pp_instance()) {
22 v8::Local
<v8::Object
> object
= object_var
->GetHandle();
23 hash
= object
.IsEmpty() ? 0 : object
->GetIdentityHash();
26 HostVarTracker::V8ObjectVarKey::V8ObjectVarKey(PP_Instance instance
,
27 v8::Handle
<v8::Object
> object
)
29 hash(object
.IsEmpty() ? 0 : object
->GetIdentityHash()) {}
31 HostVarTracker::V8ObjectVarKey::~V8ObjectVarKey() {}
33 bool HostVarTracker::V8ObjectVarKey::operator<(
34 const V8ObjectVarKey
& other
) const {
35 if (instance
== other
.instance
)
36 return hash
< other
.hash
;
37 return instance
< other
.instance
;
40 HostVarTracker::HostVarTracker()
41 : VarTracker(SINGLE_THREADED
), last_shared_memory_map_id_(0) {}
43 HostVarTracker::~HostVarTracker() {}
45 ArrayBufferVar
* HostVarTracker::CreateArrayBuffer(uint32 size_in_bytes
) {
46 return new HostArrayBufferVar(size_in_bytes
);
49 ArrayBufferVar
* HostVarTracker::CreateShmArrayBuffer(
51 base::SharedMemoryHandle handle
) {
52 return new HostArrayBufferVar(size_in_bytes
, handle
);
55 void HostVarTracker::AddV8ObjectVar(V8ObjectVar
* object_var
) {
56 CheckThreadingPreconditions();
57 v8::HandleScope
handle_scope(object_var
->instance()->GetIsolate());
58 DCHECK(GetForV8Object(object_var
->instance()->pp_instance(),
59 object_var
->GetHandle()) == object_map_
.end());
60 object_map_
.insert(std::make_pair(V8ObjectVarKey(object_var
), object_var
));
63 void HostVarTracker::RemoveV8ObjectVar(V8ObjectVar
* object_var
) {
64 CheckThreadingPreconditions();
65 v8::HandleScope
handle_scope(object_var
->instance()->GetIsolate());
66 ObjectMap::iterator it
= GetForV8Object(
67 object_var
->instance()->pp_instance(), object_var
->GetHandle());
68 DCHECK(it
!= object_map_
.end());
69 object_map_
.erase(it
);
72 PP_Var
HostVarTracker::V8ObjectVarForV8Object(PP_Instance instance
,
73 v8::Handle
<v8::Object
> object
) {
74 CheckThreadingPreconditions();
75 ObjectMap::const_iterator it
= GetForV8Object(instance
, object
);
76 if (it
== object_map_
.end())
77 return (new V8ObjectVar(instance
, object
))->GetPPVar();
78 return it
->second
->GetPPVar();
81 int HostVarTracker::GetLiveV8ObjectVarsForTest(PP_Instance instance
) {
82 CheckThreadingPreconditions();
84 // Use a key with an empty handle to find the v8 object var in the map with
85 // the given instance and the lowest hash.
86 V8ObjectVarKey
key(instance
, v8::Handle
<v8::Object
>());
87 ObjectMap::const_iterator it
= object_map_
.lower_bound(key
);
88 while (it
!= object_map_
.end() && it
->first
.instance
== instance
) {
95 PP_Var
HostVarTracker::MakeResourcePPVarFromMessage(
97 const IPC::Message
& creation_message
,
98 int pending_renderer_id
,
99 int pending_browser_id
) {
100 // On the host side, the creation message is ignored when creating a resource.
101 // Therefore, a call to this function indicates a null resource. Return the
103 return MakeResourcePPVar(0);
106 ppapi::ResourceVar
* HostVarTracker::MakeResourceVar(PP_Resource pp_resource
) {
107 return new HostResourceVar(pp_resource
);
110 void HostVarTracker::DidDeleteInstance(PP_Instance pp_instance
) {
111 CheckThreadingPreconditions();
113 PepperPluginInstanceImpl
* instance
=
114 HostGlobals::Get()->GetInstance(pp_instance
);
115 v8::HandleScope
handle_scope(instance
->GetIsolate());
116 // Force delete all var references. ForceReleaseV8Object() will cause
117 // this object, and potentially others it references, to be removed from
120 // Use a key with an empty handle to find the v8 object var in the map with
121 // the given instance and the lowest hash.
122 V8ObjectVarKey
key(pp_instance
, v8::Handle
<v8::Object
>());
123 ObjectMap::iterator it
= object_map_
.lower_bound(key
);
124 while (it
!= object_map_
.end() && it
->first
.instance
== pp_instance
) {
125 ForceReleaseV8Object(it
->second
);
126 object_map_
.erase(it
++);
130 void HostVarTracker::ForceReleaseV8Object(ppapi::V8ObjectVar
* object_var
) {
131 object_var
->InstanceDeleted();
132 VarMap::iterator iter
= live_vars_
.find(object_var
->GetExistingVarID());
133 if (iter
== live_vars_
.end()) {
137 iter
->second
.ref_count
= 0;
138 DCHECK(iter
->second
.track_with_no_reference_count
== 0);
139 DeleteObjectInfoIfNecessary(iter
);
142 HostVarTracker::ObjectMap::iterator
HostVarTracker::GetForV8Object(
143 PP_Instance instance
,
144 v8::Handle
<v8::Object
> object
) {
145 std::pair
<ObjectMap::iterator
, ObjectMap::iterator
> range
=
146 object_map_
.equal_range(V8ObjectVarKey(instance
, object
));
148 for (ObjectMap::iterator it
= range
.first
; it
!= range
.second
; ++it
) {
149 if (object
== it
->second
->GetHandle())
152 return object_map_
.end();
155 int HostVarTracker::TrackSharedMemoryHandle(PP_Instance instance
,
156 base::SharedMemoryHandle handle
,
157 uint32 size_in_bytes
) {
158 SharedMemoryMapEntry entry
;
159 entry
.instance
= instance
;
160 entry
.handle
= handle
;
161 entry
.size_in_bytes
= size_in_bytes
;
163 // Find a free id for our map.
164 while (shared_memory_map_
.find(last_shared_memory_map_id_
) !=
165 shared_memory_map_
.end()) {
166 ++last_shared_memory_map_id_
;
168 shared_memory_map_
[last_shared_memory_map_id_
] = entry
;
169 return last_shared_memory_map_id_
;
172 bool HostVarTracker::StopTrackingSharedMemoryHandle(
174 PP_Instance instance
,
175 base::SharedMemoryHandle
* handle
,
176 uint32
* size_in_bytes
) {
177 SharedMemoryMap::iterator it
= shared_memory_map_
.find(id
);
178 if (it
== shared_memory_map_
.end())
180 if (it
->second
.instance
!= instance
)
183 *handle
= it
->second
.handle
;
184 *size_in_bytes
= it
->second
.size_in_bytes
;
185 shared_memory_map_
.erase(it
);
189 } // namespace content