15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#include "content/renderer/pepper/host_var_tracker.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
8bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#include "content/renderer/pepper/host_array_buffer_var.h"
91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "content/renderer/pepper/host_globals.h"
1068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "content/renderer/pepper/host_resource_var.h"
1158e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "content/renderer/pepper/v8object_var.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/pp_var.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ppapi::ArrayBufferVar;
161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciusing ppapi::V8ObjectVar;
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1858e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdochnamespace content {
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciHostVarTracker::V8ObjectVarKey::V8ObjectVarKey(V8ObjectVar* object_var)
211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    : instance(object_var->instance()->pp_instance()) {
221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  v8::Local<v8::Object> object = object_var->GetHandle();
231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  hash = object.IsEmpty() ? 0 : object->GetIdentityHash();
241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciHostVarTracker::V8ObjectVarKey::V8ObjectVarKey(PP_Instance instance,
271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                               v8::Handle<v8::Object> object)
281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    : instance(instance),
291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      hash(object.IsEmpty() ? 0 : object->GetIdentityHash()) {}
301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciHostVarTracker::V8ObjectVarKey::~V8ObjectVarKey() {}
321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool HostVarTracker::V8ObjectVarKey::operator<(
341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const V8ObjectVarKey& other) const {
351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (instance == other.instance)
361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return hash < other.hash;
371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return instance < other.instance;
381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)HostVarTracker::HostVarTracker()
41a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    : VarTracker(SINGLE_THREADED), last_shared_memory_map_id_(0) {}
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
43a02191e04bc25c4935f804f2c080ae28663d096dBen MurdochHostVarTracker::~HostVarTracker() {}
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ArrayBufferVar* HostVarTracker::CreateArrayBuffer(uint32 size_in_bytes) {
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new HostArrayBufferVar(size_in_bytes);
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ArrayBufferVar* HostVarTracker::CreateShmArrayBuffer(
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    uint32 size_in_bytes,
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::SharedMemoryHandle handle) {
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return new HostArrayBufferVar(size_in_bytes, handle);
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid HostVarTracker::AddV8ObjectVar(V8ObjectVar* object_var) {
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CheckThreadingPreconditions();
571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  v8::HandleScope handle_scope(object_var->instance()->GetIsolate());
581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(GetForV8Object(object_var->instance()->pp_instance(),
591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                        object_var->GetHandle()) == object_map_.end());
601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  object_map_.insert(std::make_pair(V8ObjectVarKey(object_var), object_var));
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid HostVarTracker::RemoveV8ObjectVar(V8ObjectVar* object_var) {
64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CheckThreadingPreconditions();
651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  v8::HandleScope handle_scope(object_var->instance()->GetIsolate());
661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ObjectMap::iterator it = GetForV8Object(
671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      object_var->instance()->pp_instance(), object_var->GetHandle());
681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(it != object_map_.end());
691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  object_map_.erase(it);
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciPP_Var HostVarTracker::V8ObjectVarForV8Object(PP_Instance instance,
731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                              v8::Handle<v8::Object> object) {
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CheckThreadingPreconditions();
751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ObjectMap::const_iterator it = GetForV8Object(instance, object);
761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (it == object_map_.end())
771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return (new V8ObjectVar(instance, object))->GetPPVar();
781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return it->second->GetPPVar();
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciint HostVarTracker::GetLiveV8ObjectVarsForTest(PP_Instance instance) {
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CheckThreadingPreconditions();
831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  int count = 0;
841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Use a key with an empty handle to find the v8 object var in the map with
851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // the given instance and the lowest hash.
861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  V8ObjectVarKey key(instance, v8::Handle<v8::Object>());
871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ObjectMap::const_iterator it = object_map_.lower_bound(key);
881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  while (it != object_map_.end() && it->first.instance == instance) {
891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    ++count;
901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    ++it;
911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return count;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
950f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)PP_Var HostVarTracker::MakeResourcePPVarFromMessage(
960f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    PP_Instance instance,
970f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    const IPC::Message& creation_message,
980f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    int pending_renderer_id,
990f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    int pending_browser_id) {
1000f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  // On the host side, the creation message is ignored when creating a resource.
1010f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  // Therefore, a call to this function indicates a null resource. Return the
1020f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  // resource 0.
1030f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  return MakeResourcePPVar(0);
1040f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}
1050f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
10668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)ppapi::ResourceVar* HostVarTracker::MakeResourceVar(PP_Resource pp_resource) {
10768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return new HostResourceVar(pp_resource);
10868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
10968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
1101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid HostVarTracker::DidDeleteInstance(PP_Instance pp_instance) {
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CheckThreadingPreconditions();
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  PepperPluginInstanceImpl* instance =
1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      HostGlobals::Get()->GetInstance(pp_instance);
1151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  v8::HandleScope handle_scope(instance->GetIsolate());
1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Force delete all var references. ForceReleaseV8Object() will cause
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // this object, and potentially others it references, to be removed from
1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // |live_vars_|.
1191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Use a key with an empty handle to find the v8 object var in the map with
1211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // the given instance and the lowest hash.
1221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  V8ObjectVarKey key(pp_instance, v8::Handle<v8::Object>());
1231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ObjectMap::iterator it = object_map_.lower_bound(key);
1241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  while (it != object_map_.end() && it->first.instance == pp_instance) {
1251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    ForceReleaseV8Object(it->second);
1261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    object_map_.erase(it++);
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid HostVarTracker::ForceReleaseV8Object(ppapi::V8ObjectVar* object_var) {
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  object_var->InstanceDeleted();
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  VarMap::iterator iter = live_vars_.find(object_var->GetExistingVarID());
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (iter == live_vars_.end()) {
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  iter->second.ref_count = 0;
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(iter->second.track_with_no_reference_count == 0);
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeleteObjectInfoIfNecessary(iter);
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciHostVarTracker::ObjectMap::iterator HostVarTracker::GetForV8Object(
1431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    PP_Instance instance,
1441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    v8::Handle<v8::Object> object) {
1451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  std::pair<ObjectMap::iterator, ObjectMap::iterator> range =
1461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      object_map_.equal_range(V8ObjectVarKey(instance, object));
1471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  for (ObjectMap::iterator it = range.first; it != range.second; ++it) {
1491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (object == it->second->GetHandle())
1501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return it;
1511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
1521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return object_map_.end();
1531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int HostVarTracker::TrackSharedMemoryHandle(PP_Instance instance,
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                            base::SharedMemoryHandle handle,
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                            uint32 size_in_bytes) {
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SharedMemoryMapEntry entry;
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  entry.instance = instance;
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  entry.handle = handle;
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  entry.size_in_bytes = size_in_bytes;
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Find a free id for our map.
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  while (shared_memory_map_.find(last_shared_memory_map_id_) !=
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         shared_memory_map_.end()) {
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ++last_shared_memory_map_id_;
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  shared_memory_map_[last_shared_memory_map_id_] = entry;
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return last_shared_memory_map_id_;
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool HostVarTracker::StopTrackingSharedMemoryHandle(
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int id,
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    PP_Instance instance,
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::SharedMemoryHandle* handle,
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    uint32* size_in_bytes) {
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SharedMemoryMap::iterator it = shared_memory_map_.find(id);
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (it == shared_memory_map_.end())
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (it->second.instance != instance)
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *handle = it->second.handle;
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *size_in_bytes = it->second.size_in_bytes;
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  shared_memory_map_.erase(it);
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18958e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch}  // namespace content
190