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.
4
5 #include "content/renderer/pepper/host_var_tracker.h"
6
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"
14
15 using ppapi::ArrayBufferVar;
16 using ppapi::V8ObjectVar;
17
18 namespace content {
19
V8ObjectVarKey(V8ObjectVar * object_var)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();
24 }
25
V8ObjectVarKey(PP_Instance instance,v8::Handle<v8::Object> object)26 HostVarTracker::V8ObjectVarKey::V8ObjectVarKey(PP_Instance instance,
27 v8::Handle<v8::Object> object)
28 : instance(instance),
29 hash(object.IsEmpty() ? 0 : object->GetIdentityHash()) {}
30
~V8ObjectVarKey()31 HostVarTracker::V8ObjectVarKey::~V8ObjectVarKey() {}
32
operator <(const V8ObjectVarKey & other) const33 bool HostVarTracker::V8ObjectVarKey::operator<(
34 const V8ObjectVarKey& other) const {
35 if (instance == other.instance)
36 return hash < other.hash;
37 return instance < other.instance;
38 }
39
HostVarTracker()40 HostVarTracker::HostVarTracker()
41 : VarTracker(SINGLE_THREADED), last_shared_memory_map_id_(0) {}
42
~HostVarTracker()43 HostVarTracker::~HostVarTracker() {}
44
CreateArrayBuffer(uint32 size_in_bytes)45 ArrayBufferVar* HostVarTracker::CreateArrayBuffer(uint32 size_in_bytes) {
46 return new HostArrayBufferVar(size_in_bytes);
47 }
48
CreateShmArrayBuffer(uint32 size_in_bytes,base::SharedMemoryHandle handle)49 ArrayBufferVar* HostVarTracker::CreateShmArrayBuffer(
50 uint32 size_in_bytes,
51 base::SharedMemoryHandle handle) {
52 return new HostArrayBufferVar(size_in_bytes, handle);
53 }
54
AddV8ObjectVar(V8ObjectVar * object_var)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));
61 }
62
RemoveV8ObjectVar(V8ObjectVar * 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);
70 }
71
V8ObjectVarForV8Object(PP_Instance instance,v8::Handle<v8::Object> object)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();
79 }
80
GetLiveV8ObjectVarsForTest(PP_Instance instance)81 int HostVarTracker::GetLiveV8ObjectVarsForTest(PP_Instance instance) {
82 CheckThreadingPreconditions();
83 int count = 0;
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) {
89 ++count;
90 ++it;
91 }
92 return count;
93 }
94
MakeResourcePPVarFromMessage(PP_Instance instance,const IPC::Message & creation_message,int pending_renderer_id,int pending_browser_id)95 PP_Var HostVarTracker::MakeResourcePPVarFromMessage(
96 PP_Instance instance,
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
102 // resource 0.
103 return MakeResourcePPVar(0);
104 }
105
MakeResourceVar(PP_Resource pp_resource)106 ppapi::ResourceVar* HostVarTracker::MakeResourceVar(PP_Resource pp_resource) {
107 return new HostResourceVar(pp_resource);
108 }
109
DidDeleteInstance(PP_Instance pp_instance)110 void HostVarTracker::DidDeleteInstance(PP_Instance pp_instance) {
111 CheckThreadingPreconditions();
112
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
118 // |live_vars_|.
119
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++);
127 }
128 }
129
ForceReleaseV8Object(ppapi::V8ObjectVar * object_var)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()) {
134 NOTREACHED();
135 return;
136 }
137 iter->second.ref_count = 0;
138 DCHECK(iter->second.track_with_no_reference_count == 0);
139 DeleteObjectInfoIfNecessary(iter);
140 }
141
GetForV8Object(PP_Instance instance,v8::Handle<v8::Object> object)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));
147
148 for (ObjectMap::iterator it = range.first; it != range.second; ++it) {
149 if (object == it->second->GetHandle())
150 return it;
151 }
152 return object_map_.end();
153 }
154
TrackSharedMemoryHandle(PP_Instance instance,base::SharedMemoryHandle handle,uint32 size_in_bytes)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;
162
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_;
167 }
168 shared_memory_map_[last_shared_memory_map_id_] = entry;
169 return last_shared_memory_map_id_;
170 }
171
StopTrackingSharedMemoryHandle(int id,PP_Instance instance,base::SharedMemoryHandle * handle,uint32 * size_in_bytes)172 bool HostVarTracker::StopTrackingSharedMemoryHandle(
173 int id,
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())
179 return false;
180 if (it->second.instance != instance)
181 return false;
182
183 *handle = it->second.handle;
184 *size_in_bytes = it->second.size_in_bytes;
185 shared_memory_map_.erase(it);
186 return true;
187 }
188
189 } // namespace content
190