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 15using ppapi::ArrayBufferVar; 16using ppapi::V8ObjectVar; 17 18namespace content { 19 20HostVarTracker::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 26HostVarTracker::V8ObjectVarKey::V8ObjectVarKey(PP_Instance instance, 27 v8::Handle<v8::Object> object) 28 : instance(instance), 29 hash(object.IsEmpty() ? 0 : object->GetIdentityHash()) {} 30 31HostVarTracker::V8ObjectVarKey::~V8ObjectVarKey() {} 32 33bool 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 40HostVarTracker::HostVarTracker() 41 : VarTracker(SINGLE_THREADED), last_shared_memory_map_id_(0) {} 42 43HostVarTracker::~HostVarTracker() {} 44 45ArrayBufferVar* HostVarTracker::CreateArrayBuffer(uint32 size_in_bytes) { 46 return new HostArrayBufferVar(size_in_bytes); 47} 48 49ArrayBufferVar* HostVarTracker::CreateShmArrayBuffer( 50 uint32 size_in_bytes, 51 base::SharedMemoryHandle handle) { 52 return new HostArrayBufferVar(size_in_bytes, handle); 53} 54 55void 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 63void 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 72PP_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 81int 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 95PP_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 106ppapi::ResourceVar* HostVarTracker::MakeResourceVar(PP_Resource pp_resource) { 107 return new HostResourceVar(pp_resource); 108} 109 110void 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 130void 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 142HostVarTracker::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 155int 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 172bool 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