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), last_shared_memory_map_id_(0) {} 21 22 HostVarTracker::~HostVarTracker() {} 23 24 ArrayBufferVar* HostVarTracker::CreateArrayBuffer(uint32 size_in_bytes) { 25 return new HostArrayBufferVar(size_in_bytes); 26 } 27 28 ArrayBufferVar* HostVarTracker::CreateShmArrayBuffer( 29 uint32 size_in_bytes, 30 base::SharedMemoryHandle handle) { 31 return new HostArrayBufferVar(size_in_bytes, handle); 32 } 33 34 void HostVarTracker::AddNPObjectVar(NPObjectVar* object_var) { 35 CheckThreadingPreconditions(); 36 37 InstanceMap::iterator found_instance = 38 instance_map_.find(object_var->pp_instance()); 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)); 53 } 54 55 void HostVarTracker::RemoveNPObjectVar(NPObjectVar* object_var) { 56 CheckThreadingPreconditions(); 57 58 InstanceMap::iterator found_instance = 59 instance_map_.find(object_var->pp_instance()); 60 if (found_instance == instance_map_.end()) { 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); 77 } 78 79 NPObjectVar* HostVarTracker::NPObjectVarForNPObject(PP_Instance instance, 80 NPObject* np_object) { 81 CheckThreadingPreconditions(); 82 83 InstanceMap::iterator found_instance = instance_map_.find(instance); 84 if (found_instance == instance_map_.end()) 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; 93 } 94 95 int HostVarTracker::GetLiveNPObjectVarsForInstance(PP_Instance instance) const { 96 CheckThreadingPreconditions(); 97 98 InstanceMap::const_iterator found = instance_map_.find(instance); 99 if (found == instance_map_.end()) 100 return 0; 101 return static_cast<int>(found->second->size()); 102 } 103 104 PP_Var HostVarTracker::MakeResourcePPVarFromMessage( 105 PP_Instance instance, 106 const IPC::Message& creation_message, 107 int pending_renderer_id, 108 int pending_browser_id) { 109 // 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 111 // resource 0. 112 return MakeResourcePPVar(0); 113 } 114 115 ppapi::ResourceVar* HostVarTracker::MakeResourceVar(PP_Resource pp_resource) { 116 return new HostResourceVar(pp_resource); 117 } 118 119 void HostVarTracker::DidDeleteInstance(PP_Instance instance) { 120 CheckThreadingPreconditions(); 121 122 InstanceMap::iterator found_instance = instance_map_.find(instance); 123 if (found_instance == instance_map_.end()) 124 return; // Nothing to do. 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 129 // |np_object_map|. 130 while (!np_object_map->empty()) { 131 ForceReleaseNPObject(np_object_map->begin()->second); 132 } 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 } 138 139 void HostVarTracker::ForceReleaseNPObject(ppapi::NPObjectVar* object_var) { 140 object_var->InstanceDeleted(); 141 VarMap::iterator iter = live_vars_.find(object_var->GetExistingVarID()); 142 if (iter == live_vars_.end()) { 143 NOTREACHED(); 144 return; 145 } 146 iter->second.ref_count = 0; 147 DCHECK(iter->second.track_with_no_reference_count == 0); 148 DeleteObjectInfoIfNecessary(iter); 149 } 150 151 int HostVarTracker::TrackSharedMemoryHandle(PP_Instance instance, 152 base::SharedMemoryHandle handle, 153 uint32 size_in_bytes) { 154 SharedMemoryMapEntry entry; 155 entry.instance = instance; 156 entry.handle = handle; 157 entry.size_in_bytes = size_in_bytes; 158 159 // Find a free id for our map. 160 while (shared_memory_map_.find(last_shared_memory_map_id_) != 161 shared_memory_map_.end()) { 162 ++last_shared_memory_map_id_; 163 } 164 shared_memory_map_[last_shared_memory_map_id_] = entry; 165 return last_shared_memory_map_id_; 166 } 167 168 bool HostVarTracker::StopTrackingSharedMemoryHandle( 169 int id, 170 PP_Instance instance, 171 base::SharedMemoryHandle* handle, 172 uint32* size_in_bytes) { 173 SharedMemoryMap::iterator it = shared_memory_map_.find(id); 174 if (it == shared_memory_map_.end()) 175 return false; 176 if (it->second.instance != instance) 177 return false; 178 179 *handle = it->second.handle; 180 *size_in_bytes = it->second.size_in_bytes; 181 shared_memory_map_.erase(it); 182 return true; 183 } 184 185 } // namespace content 186