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