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_resource_var.h" 10 #include "content/renderer/pepper/npobject_var.h" 11 #include "content/renderer/pepper/pepper_plugin_instance_impl.h" 12 #include "ppapi/c/pp_var.h" 13 14 using ppapi::ArrayBufferVar; 15 using ppapi::NPObjectVar; 16 17 namespace content { 18 19 HostVarTracker::HostVarTracker() 20 : VarTracker(SINGLE_THREADED), 21 last_shared_memory_map_id_(0) { 22 } 23 24 HostVarTracker::~HostVarTracker() { 25 } 26 27 ArrayBufferVar* HostVarTracker::CreateArrayBuffer(uint32 size_in_bytes) { 28 return new HostArrayBufferVar(size_in_bytes); 29 } 30 31 ArrayBufferVar* HostVarTracker::CreateShmArrayBuffer( 32 uint32 size_in_bytes, 33 base::SharedMemoryHandle handle) { 34 return new HostArrayBufferVar(size_in_bytes, handle); 35 } 36 37 void HostVarTracker::AddNPObjectVar(NPObjectVar* object_var) { 38 CheckThreadingPreconditions(); 39 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))). 48 first; 49 } 50 NPObjectToNPObjectVarMap* np_object_map = found_instance->second.get(); 51 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)); 55 } 56 57 void HostVarTracker::RemoveNPObjectVar(NPObjectVar* object_var) { 58 CheckThreadingPreconditions(); 59 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."; 64 return; 65 } 66 NPObjectToNPObjectVarMap* np_object_map = found_instance->second.get(); 67 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."; 72 return; 73 } 74 if (found_object->second != object_var) { 75 NOTREACHED() << "NPObjectVar doesn't match."; 76 return; 77 } 78 np_object_map->erase(found_object); 79 } 80 81 NPObjectVar* HostVarTracker::NPObjectVarForNPObject(PP_Instance instance, 82 NPObject* np_object) { 83 CheckThreadingPreconditions(); 84 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(); 89 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; 95 } 96 97 int HostVarTracker::GetLiveNPObjectVarsForInstance(PP_Instance instance) const { 98 CheckThreadingPreconditions(); 99 100 InstanceMap::const_iterator found = instance_map_.find(instance); 101 if (found == instance_map_.end()) 102 return 0; 103 return static_cast<int>(found->second->size()); 104 } 105 106 PP_Var HostVarTracker::MakeResourcePPVarFromMessage( 107 PP_Instance instance, 108 const IPC::Message& creation_message, 109 int pending_renderer_id, 110 int pending_browser_id) { 111 // On the host side, the creation message is ignored when creating a resource. 112 // Therefore, a call to this function indicates a null resource. Return the 113 // resource 0. 114 return MakeResourcePPVar(0); 115 } 116 117 ppapi::ResourceVar* HostVarTracker::MakeResourceVar(PP_Resource pp_resource) { 118 return new HostResourceVar(pp_resource); 119 } 120 121 void HostVarTracker::DidDeleteInstance(PP_Instance instance) { 122 CheckThreadingPreconditions(); 123 124 InstanceMap::iterator found_instance = instance_map_.find(instance); 125 if (found_instance == instance_map_.end()) 126 return; // Nothing to do. 127 NPObjectToNPObjectVarMap* np_object_map = found_instance->second.get(); 128 129 // Force delete all var references. ForceReleaseNPObject() will cause 130 // this object, and potentially others it references, to be removed from 131 // |np_object_map|. 132 while (!np_object_map->empty()) { 133 ForceReleaseNPObject(np_object_map->begin()->second); 134 } 135 136 // Remove the record for this instance since it should be empty. 137 DCHECK(np_object_map->empty()); 138 instance_map_.erase(found_instance); 139 } 140 141 void HostVarTracker::ForceReleaseNPObject(ppapi::NPObjectVar* object_var) { 142 object_var->InstanceDeleted(); 143 VarMap::iterator iter = live_vars_.find(object_var->GetExistingVarID()); 144 if (iter == live_vars_.end()) { 145 NOTREACHED(); 146 return; 147 } 148 iter->second.ref_count = 0; 149 DCHECK(iter->second.track_with_no_reference_count == 0); 150 DeleteObjectInfoIfNecessary(iter); 151 } 152 153 int HostVarTracker::TrackSharedMemoryHandle(PP_Instance instance, 154 base::SharedMemoryHandle handle, 155 uint32 size_in_bytes) { 156 SharedMemoryMapEntry entry; 157 entry.instance = instance; 158 entry.handle = handle; 159 entry.size_in_bytes = size_in_bytes; 160 161 // Find a free id for our map. 162 while (shared_memory_map_.find(last_shared_memory_map_id_) != 163 shared_memory_map_.end()) { 164 ++last_shared_memory_map_id_; 165 } 166 shared_memory_map_[last_shared_memory_map_id_] = entry; 167 return last_shared_memory_map_id_; 168 } 169 170 bool HostVarTracker::StopTrackingSharedMemoryHandle( 171 int id, 172 PP_Instance instance, 173 base::SharedMemoryHandle* handle, 174 uint32* size_in_bytes) { 175 SharedMemoryMap::iterator it = shared_memory_map_.find(id); 176 if (it == shared_memory_map_.end()) 177 return false; 178 if (it->second.instance != instance) 179 return false; 180 181 *handle = it->second.handle; 182 *size_in_bytes = it->second.size_in_bytes; 183 shared_memory_map_.erase(it); 184 return true; 185 } 186 187 } // namespace content 188