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