// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "content/renderer/pepper/host_var_tracker.h" #include #include "base/logging.h" #include "content/renderer/pepper/host_array_buffer_var.h" #include "content/renderer/pepper/host_globals.h" #include "content/renderer/pepper/host_resource_var.h" #include "content/renderer/pepper/pepper_plugin_instance_impl.h" #include "content/renderer/pepper/v8object_var.h" #include "ppapi/c/pp_var.h" using ppapi::ArrayBufferVar; using ppapi::V8ObjectVar; namespace content { HostVarTracker::V8ObjectVarKey::V8ObjectVarKey(V8ObjectVar* object_var) : instance(object_var->instance()->pp_instance()) { v8::Local object = object_var->GetHandle(); hash = object.IsEmpty() ? 0 : object->GetIdentityHash(); } HostVarTracker::V8ObjectVarKey::V8ObjectVarKey(PP_Instance instance, v8::Local object) : instance(instance), hash(object.IsEmpty() ? 0 : object->GetIdentityHash()) {} HostVarTracker::V8ObjectVarKey::~V8ObjectVarKey() {} bool HostVarTracker::V8ObjectVarKey::operator<( const V8ObjectVarKey& other) const { return std::tie(instance, hash) < std::tie(other.instance, other.hash); } HostVarTracker::HostVarTracker() : VarTracker(SINGLE_THREADED), last_shared_memory_map_id_(0) {} HostVarTracker::~HostVarTracker() {} ArrayBufferVar* HostVarTracker::CreateArrayBuffer(uint32_t size_in_bytes) { return new HostArrayBufferVar(size_in_bytes); } ArrayBufferVar* HostVarTracker::CreateShmArrayBuffer( uint32_t size_in_bytes, base::SharedMemoryHandle handle) { return new HostArrayBufferVar(size_in_bytes, handle); } void HostVarTracker::AddV8ObjectVar(V8ObjectVar* object_var) { CheckThreadingPreconditions(); v8::HandleScope handle_scope(object_var->instance()->GetIsolate()); DCHECK(GetForV8Object(object_var->instance()->pp_instance(), object_var->GetHandle()) == object_map_.end()); object_map_.insert(std::make_pair(V8ObjectVarKey(object_var), object_var)); } void HostVarTracker::RemoveV8ObjectVar(V8ObjectVar* object_var) { CheckThreadingPreconditions(); v8::HandleScope handle_scope(object_var->instance()->GetIsolate()); ObjectMap::iterator it = GetForV8Object( object_var->instance()->pp_instance(), object_var->GetHandle()); DCHECK(it != object_map_.end()); object_map_.erase(it); } PP_Var HostVarTracker::V8ObjectVarForV8Object(PP_Instance instance, v8::Local object) { CheckThreadingPreconditions(); ObjectMap::const_iterator it = GetForV8Object(instance, object); if (it == object_map_.end()) return (new V8ObjectVar(instance, object))->GetPPVar(); return it->second->GetPPVar(); } int HostVarTracker::GetLiveV8ObjectVarsForTest(PP_Instance instance) { CheckThreadingPreconditions(); int count = 0; // Use a key with an empty handle to find the v8 object var in the map with // the given instance and the lowest hash. V8ObjectVarKey key(instance, v8::Local()); ObjectMap::const_iterator it = object_map_.lower_bound(key); while (it != object_map_.end() && it->first.instance == instance) { ++count; ++it; } return count; } PP_Var HostVarTracker::MakeResourcePPVarFromMessage( PP_Instance instance, const IPC::Message& creation_message, int pending_renderer_id, int pending_browser_id) { // On the host side, the creation message is ignored when creating a resource. // Therefore, a call to this function indicates a null resource. Return the // resource 0. return MakeResourcePPVar(0); } ppapi::ResourceVar* HostVarTracker::MakeResourceVar(PP_Resource pp_resource) { return new HostResourceVar(pp_resource); } void HostVarTracker::DidDeleteInstance(PP_Instance pp_instance) { CheckThreadingPreconditions(); PepperPluginInstanceImpl* instance = HostGlobals::Get()->GetInstance(pp_instance); v8::HandleScope handle_scope(instance->GetIsolate()); // Force delete all var references. ForceReleaseV8Object() will cause // this object, and potentially others it references, to be removed from // |live_vars_|. // Use a key with an empty handle to find the v8 object var in the map with // the given instance and the lowest hash. V8ObjectVarKey key(pp_instance, v8::Local()); ObjectMap::iterator it = object_map_.lower_bound(key); while (it != object_map_.end() && it->first.instance == pp_instance) { ForceReleaseV8Object(it->second); object_map_.erase(it++); } } void HostVarTracker::ForceReleaseV8Object(ppapi::V8ObjectVar* object_var) { object_var->InstanceDeleted(); VarMap::iterator iter = live_vars_.find(object_var->GetExistingVarID()); if (iter == live_vars_.end()) { NOTREACHED(); return; } iter->second.ref_count = 0; DCHECK(iter->second.track_with_no_reference_count == 0); DeleteObjectInfoIfNecessary(iter); } HostVarTracker::ObjectMap::iterator HostVarTracker::GetForV8Object( PP_Instance instance, v8::Local object) { std::pair range = object_map_.equal_range(V8ObjectVarKey(instance, object)); for (ObjectMap::iterator it = range.first; it != range.second; ++it) { if (object == it->second->GetHandle()) return it; } return object_map_.end(); } int HostVarTracker::TrackSharedMemoryHandle(PP_Instance instance, base::SharedMemoryHandle handle, uint32_t size_in_bytes) { SharedMemoryMapEntry entry; entry.instance = instance; entry.handle = handle; entry.size_in_bytes = size_in_bytes; // Find a free id for our map. while (shared_memory_map_.find(last_shared_memory_map_id_) != shared_memory_map_.end()) { ++last_shared_memory_map_id_; } shared_memory_map_[last_shared_memory_map_id_] = entry; return last_shared_memory_map_id_; } bool HostVarTracker::StopTrackingSharedMemoryHandle( int id, PP_Instance instance, base::SharedMemoryHandle* handle, uint32_t* size_in_bytes) { SharedMemoryMap::iterator it = shared_memory_map_.find(id); if (it == shared_memory_map_.end()) return false; if (it->second.instance != instance) return false; *handle = it->second.handle; *size_in_bytes = it->second.size_in_bytes; shared_memory_map_.erase(it); return true; } } // namespace content