OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/renderer/pepper/host_var_tracker.h" | 5 #include "content/renderer/pepper/host_var_tracker.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "content/renderer/pepper/host_array_buffer_var.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" | 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" | 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" | 12 #include "ppapi/c/pp_var.h" |
14 | 13 |
15 using ppapi::ArrayBufferVar; | 14 using ppapi::ArrayBufferVar; |
16 using ppapi::V8ObjectVar; | 15 using ppapi::NPObjectVar; |
17 | 16 |
18 namespace content { | 17 namespace content { |
19 | 18 |
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 | |
26 HostVarTracker::V8ObjectVarKey::V8ObjectVarKey(PP_Instance instance, | |
27 v8::Handle<v8::Object> object) | |
28 : instance(instance), | |
29 hash(object.IsEmpty() ? 0 : object->GetIdentityHash()) {} | |
30 | |
31 HostVarTracker::V8ObjectVarKey::~V8ObjectVarKey() {} | |
32 | |
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; | |
38 } | |
39 | |
40 HostVarTracker::HostVarTracker() | 19 HostVarTracker::HostVarTracker() |
41 : VarTracker(SINGLE_THREADED), last_shared_memory_map_id_(0) {} | 20 : VarTracker(SINGLE_THREADED), last_shared_memory_map_id_(0) {} |
42 | 21 |
43 HostVarTracker::~HostVarTracker() {} | 22 HostVarTracker::~HostVarTracker() {} |
44 | 23 |
45 ArrayBufferVar* HostVarTracker::CreateArrayBuffer(uint32 size_in_bytes) { | 24 ArrayBufferVar* HostVarTracker::CreateArrayBuffer(uint32 size_in_bytes) { |
46 return new HostArrayBufferVar(size_in_bytes); | 25 return new HostArrayBufferVar(size_in_bytes); |
47 } | 26 } |
48 | 27 |
49 ArrayBufferVar* HostVarTracker::CreateShmArrayBuffer( | 28 ArrayBufferVar* HostVarTracker::CreateShmArrayBuffer( |
50 uint32 size_in_bytes, | 29 uint32 size_in_bytes, |
51 base::SharedMemoryHandle handle) { | 30 base::SharedMemoryHandle handle) { |
52 return new HostArrayBufferVar(size_in_bytes, handle); | 31 return new HostArrayBufferVar(size_in_bytes, handle); |
53 } | 32 } |
54 | 33 |
55 void HostVarTracker::AddV8ObjectVar(V8ObjectVar* object_var) { | 34 void HostVarTracker::AddNPObjectVar(NPObjectVar* object_var) { |
56 CheckThreadingPreconditions(); | 35 CheckThreadingPreconditions(); |
57 v8::HandleScope handle_scope(object_var->instance()->GetIsolate()); | 36 |
58 DCHECK(GetForV8Object(object_var->instance()->pp_instance(), | 37 InstanceMap::iterator found_instance = |
59 object_var->GetHandle()) == object_map_.end()); | 38 instance_map_.find(object_var->pp_instance()); |
60 object_map_.insert(std::make_pair(V8ObjectVarKey(object_var), object_var)); | 39 if (found_instance == instance_map_.end()) { |
| 40 // Lazily create the instance map. |
| 41 DCHECK(object_var->pp_instance() != 0); |
| 42 found_instance = |
| 43 instance_map_.insert(std::make_pair( |
| 44 object_var->pp_instance(), |
| 45 linked_ptr<NPObjectToNPObjectVarMap>( |
| 46 new NPObjectToNPObjectVarMap))).first; |
| 47 } |
| 48 NPObjectToNPObjectVarMap* np_object_map = found_instance->second.get(); |
| 49 |
| 50 DCHECK(np_object_map->find(object_var->np_object()) == np_object_map->end()) |
| 51 << "NPObjectVar already in map"; |
| 52 np_object_map->insert(std::make_pair(object_var->np_object(), object_var)); |
61 } | 53 } |
62 | 54 |
63 void HostVarTracker::RemoveV8ObjectVar(V8ObjectVar* object_var) { | 55 void HostVarTracker::RemoveNPObjectVar(NPObjectVar* object_var) { |
64 CheckThreadingPreconditions(); | 56 CheckThreadingPreconditions(); |
65 v8::HandleScope handle_scope(object_var->instance()->GetIsolate()); | 57 |
66 ObjectMap::iterator it = GetForV8Object( | 58 InstanceMap::iterator found_instance = |
67 object_var->instance()->pp_instance(), object_var->GetHandle()); | 59 instance_map_.find(object_var->pp_instance()); |
68 DCHECK(it != object_map_.end()); | 60 if (found_instance == instance_map_.end()) { |
69 object_map_.erase(it); | 61 NOTREACHED() << "NPObjectVar has invalid instance."; |
| 62 return; |
| 63 } |
| 64 NPObjectToNPObjectVarMap* np_object_map = found_instance->second.get(); |
| 65 |
| 66 NPObjectToNPObjectVarMap::iterator found_object = |
| 67 np_object_map->find(object_var->np_object()); |
| 68 if (found_object == np_object_map->end()) { |
| 69 NOTREACHED() << "NPObjectVar not registered."; |
| 70 return; |
| 71 } |
| 72 if (found_object->second != object_var) { |
| 73 NOTREACHED() << "NPObjectVar doesn't match."; |
| 74 return; |
| 75 } |
| 76 np_object_map->erase(found_object); |
70 } | 77 } |
71 | 78 |
72 PP_Var HostVarTracker::V8ObjectVarForV8Object(PP_Instance instance, | 79 NPObjectVar* HostVarTracker::NPObjectVarForNPObject(PP_Instance instance, |
73 v8::Handle<v8::Object> object) { | 80 NPObject* np_object) { |
74 CheckThreadingPreconditions(); | 81 CheckThreadingPreconditions(); |
75 ObjectMap::const_iterator it = GetForV8Object(instance, object); | 82 |
76 if (it == object_map_.end()) | 83 InstanceMap::iterator found_instance = instance_map_.find(instance); |
77 return (new V8ObjectVar(instance, object))->GetPPVar(); | 84 if (found_instance == instance_map_.end()) |
78 return it->second->GetPPVar(); | 85 return NULL; // No such instance. |
| 86 NPObjectToNPObjectVarMap* np_object_map = found_instance->second.get(); |
| 87 |
| 88 NPObjectToNPObjectVarMap::iterator found_object = |
| 89 np_object_map->find(np_object); |
| 90 if (found_object == np_object_map->end()) |
| 91 return NULL; // No such object. |
| 92 return found_object->second; |
79 } | 93 } |
80 | 94 |
81 int HostVarTracker::GetLiveV8ObjectVarsForTest(PP_Instance instance) { | 95 int HostVarTracker::GetLiveNPObjectVarsForInstance(PP_Instance instance) const { |
82 CheckThreadingPreconditions(); | 96 CheckThreadingPreconditions(); |
83 int count = 0; | 97 |
84 // Use a key with an empty handle to find the v8 object var in the map with | 98 InstanceMap::const_iterator found = instance_map_.find(instance); |
85 // the given instance and the lowest hash. | 99 if (found == instance_map_.end()) |
86 V8ObjectVarKey key(instance, v8::Handle<v8::Object>()); | 100 return 0; |
87 ObjectMap::const_iterator it = object_map_.lower_bound(key); | 101 return static_cast<int>(found->second->size()); |
88 while (it != object_map_.end() && it->first.instance == instance) { | |
89 ++count; | |
90 ++it; | |
91 } | |
92 return count; | |
93 } | 102 } |
94 | 103 |
95 PP_Var HostVarTracker::MakeResourcePPVarFromMessage( | 104 PP_Var HostVarTracker::MakeResourcePPVarFromMessage( |
96 PP_Instance instance, | 105 PP_Instance instance, |
97 const IPC::Message& creation_message, | 106 const IPC::Message& creation_message, |
98 int pending_renderer_id, | 107 int pending_renderer_id, |
99 int pending_browser_id) { | 108 int pending_browser_id) { |
100 // On the host side, the creation message is ignored when creating a resource. | 109 // 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 | 110 // Therefore, a call to this function indicates a null resource. Return the |
102 // resource 0. | 111 // resource 0. |
103 return MakeResourcePPVar(0); | 112 return MakeResourcePPVar(0); |
104 } | 113 } |
105 | 114 |
106 ppapi::ResourceVar* HostVarTracker::MakeResourceVar(PP_Resource pp_resource) { | 115 ppapi::ResourceVar* HostVarTracker::MakeResourceVar(PP_Resource pp_resource) { |
107 return new HostResourceVar(pp_resource); | 116 return new HostResourceVar(pp_resource); |
108 } | 117 } |
109 | 118 |
110 void HostVarTracker::DidDeleteInstance(PP_Instance pp_instance) { | 119 void HostVarTracker::DidDeleteInstance(PP_Instance instance) { |
111 CheckThreadingPreconditions(); | 120 CheckThreadingPreconditions(); |
112 | 121 |
113 PepperPluginInstanceImpl* instance = | 122 InstanceMap::iterator found_instance = instance_map_.find(instance); |
114 HostGlobals::Get()->GetInstance(pp_instance); | 123 if (found_instance == instance_map_.end()) |
115 v8::HandleScope handle_scope(instance->GetIsolate()); | 124 return; // Nothing to do. |
116 // Force delete all var references. ForceReleaseV8Object() will cause | 125 NPObjectToNPObjectVarMap* np_object_map = found_instance->second.get(); |
| 126 |
| 127 // Force delete all var references. ForceReleaseNPObject() will cause |
117 // this object, and potentially others it references, to be removed from | 128 // this object, and potentially others it references, to be removed from |
118 // |live_vars_|. | 129 // |np_object_map|. |
| 130 while (!np_object_map->empty()) { |
| 131 ForceReleaseNPObject(np_object_map->begin()->second); |
| 132 } |
119 | 133 |
120 // Use a key with an empty handle to find the v8 object var in the map with | 134 // Remove the record for this instance since it should be empty. |
121 // the given instance and the lowest hash. | 135 DCHECK(np_object_map->empty()); |
122 V8ObjectVarKey key(pp_instance, v8::Handle<v8::Object>()); | 136 instance_map_.erase(found_instance); |
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 } | 137 } |
129 | 138 |
130 void HostVarTracker::ForceReleaseV8Object(ppapi::V8ObjectVar* object_var) { | 139 void HostVarTracker::ForceReleaseNPObject(ppapi::NPObjectVar* object_var) { |
131 object_var->InstanceDeleted(); | 140 object_var->InstanceDeleted(); |
132 VarMap::iterator iter = live_vars_.find(object_var->GetExistingVarID()); | 141 VarMap::iterator iter = live_vars_.find(object_var->GetExistingVarID()); |
133 if (iter == live_vars_.end()) { | 142 if (iter == live_vars_.end()) { |
134 NOTREACHED(); | 143 NOTREACHED(); |
135 return; | 144 return; |
136 } | 145 } |
137 iter->second.ref_count = 0; | 146 iter->second.ref_count = 0; |
138 DCHECK(iter->second.track_with_no_reference_count == 0); | 147 DCHECK(iter->second.track_with_no_reference_count == 0); |
139 DeleteObjectInfoIfNecessary(iter); | 148 DeleteObjectInfoIfNecessary(iter); |
140 } | 149 } |
141 | 150 |
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 | |
155 int HostVarTracker::TrackSharedMemoryHandle(PP_Instance instance, | 151 int HostVarTracker::TrackSharedMemoryHandle(PP_Instance instance, |
156 base::SharedMemoryHandle handle, | 152 base::SharedMemoryHandle handle, |
157 uint32 size_in_bytes) { | 153 uint32 size_in_bytes) { |
158 SharedMemoryMapEntry entry; | 154 SharedMemoryMapEntry entry; |
159 entry.instance = instance; | 155 entry.instance = instance; |
160 entry.handle = handle; | 156 entry.handle = handle; |
161 entry.size_in_bytes = size_in_bytes; | 157 entry.size_in_bytes = size_in_bytes; |
162 | 158 |
163 // Find a free id for our map. | 159 // Find a free id for our map. |
164 while (shared_memory_map_.find(last_shared_memory_map_id_) != | 160 while (shared_memory_map_.find(last_shared_memory_map_id_) != |
(...skipping 15 matching lines...) Expand all Loading... |
180 if (it->second.instance != instance) | 176 if (it->second.instance != instance) |
181 return false; | 177 return false; |
182 | 178 |
183 *handle = it->second.handle; | 179 *handle = it->second.handle; |
184 *size_in_bytes = it->second.size_in_bytes; | 180 *size_in_bytes = it->second.size_in_bytes; |
185 shared_memory_map_.erase(it); | 181 shared_memory_map_.erase(it); |
186 return true; | 182 return true; |
187 } | 183 } |
188 | 184 |
189 } // namespace content | 185 } // namespace content |
OLD | NEW |