host_var_tracker.cc revision 58e6fbe4ee35d65e14b626c557d37565bf8ad179
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/npobject_var.h"
10#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
11#include "ppapi/c/pp_var.h"
12
13using ppapi::ArrayBufferVar;
14using ppapi::NPObjectVar;
15
16namespace content {
17
18HostVarTracker::HostVarTracker()
19  : VarTracker(SINGLE_THREADED),
20    last_shared_memory_map_id_(0) {
21}
22
23HostVarTracker::~HostVarTracker() {
24}
25
26ArrayBufferVar* HostVarTracker::CreateArrayBuffer(uint32 size_in_bytes) {
27  return new HostArrayBufferVar(size_in_bytes);
28}
29
30ArrayBufferVar* HostVarTracker::CreateShmArrayBuffer(
31    uint32 size_in_bytes,
32    base::SharedMemoryHandle handle) {
33  return new HostArrayBufferVar(size_in_bytes, handle);
34}
35
36void HostVarTracker::AddNPObjectVar(NPObjectVar* object_var) {
37  CheckThreadingPreconditions();
38
39  InstanceMap::iterator found_instance = instance_map_.find(
40      object_var->pp_instance());
41  if (found_instance == instance_map_.end()) {
42    // Lazily create the instance map.
43    DCHECK(object_var->pp_instance() != 0);
44    found_instance = instance_map_.insert(std::make_pair(
45        object_var->pp_instance(),
46        linked_ptr<NPObjectToNPObjectVarMap>(new NPObjectToNPObjectVarMap))).
47            first;
48  }
49  NPObjectToNPObjectVarMap* np_object_map = found_instance->second.get();
50
51  DCHECK(np_object_map->find(object_var->np_object()) ==
52         np_object_map->end()) << "NPObjectVar already in map";
53  np_object_map->insert(std::make_pair(object_var->np_object(), object_var));
54}
55
56void HostVarTracker::RemoveNPObjectVar(NPObjectVar* object_var) {
57  CheckThreadingPreconditions();
58
59  InstanceMap::iterator found_instance = instance_map_.find(
60      object_var->pp_instance());
61  if (found_instance == instance_map_.end()) {
62    NOTREACHED() << "NPObjectVar has invalid instance.";
63    return;
64  }
65  NPObjectToNPObjectVarMap* np_object_map = found_instance->second.get();
66
67  NPObjectToNPObjectVarMap::iterator found_object =
68      np_object_map->find(object_var->np_object());
69  if (found_object == np_object_map->end()) {
70    NOTREACHED() << "NPObjectVar not registered.";
71    return;
72  }
73  if (found_object->second != object_var) {
74    NOTREACHED() << "NPObjectVar doesn't match.";
75    return;
76  }
77  np_object_map->erase(found_object);
78}
79
80NPObjectVar* HostVarTracker::NPObjectVarForNPObject(PP_Instance instance,
81                                                    NPObject* np_object) {
82  CheckThreadingPreconditions();
83
84  InstanceMap::iterator found_instance = instance_map_.find(instance);
85  if (found_instance == instance_map_.end())
86    return NULL;  // No such instance.
87  NPObjectToNPObjectVarMap* np_object_map = found_instance->second.get();
88
89  NPObjectToNPObjectVarMap::iterator found_object =
90      np_object_map->find(np_object);
91  if (found_object == np_object_map->end())
92    return NULL;  // No such object.
93  return found_object->second;
94}
95
96int HostVarTracker::GetLiveNPObjectVarsForInstance(PP_Instance instance) const {
97  CheckThreadingPreconditions();
98
99  InstanceMap::const_iterator found = instance_map_.find(instance);
100  if (found == instance_map_.end())
101    return 0;
102  return static_cast<int>(found->second->size());
103}
104
105void HostVarTracker::DidDeleteInstance(PP_Instance instance) {
106  CheckThreadingPreconditions();
107
108  InstanceMap::iterator found_instance = instance_map_.find(instance);
109  if (found_instance == instance_map_.end())
110    return;  // Nothing to do.
111  NPObjectToNPObjectVarMap* np_object_map = found_instance->second.get();
112
113  // Force delete all var references. ForceReleaseNPObject() will cause
114  // this object, and potentially others it references, to be removed from
115  // |np_object_map|.
116  while (!np_object_map->empty()) {
117    ForceReleaseNPObject(np_object_map->begin()->second);
118  }
119
120  // Remove the record for this instance since it should be empty.
121  DCHECK(np_object_map->empty());
122  instance_map_.erase(found_instance);
123}
124
125void HostVarTracker::ForceReleaseNPObject(::ppapi::NPObjectVar* object_var) {
126  object_var->InstanceDeleted();
127  VarMap::iterator iter = live_vars_.find(object_var->GetExistingVarID());
128  if (iter == live_vars_.end()) {
129    NOTREACHED();
130    return;
131  }
132  iter->second.ref_count = 0;
133  DCHECK(iter->second.track_with_no_reference_count == 0);
134  DeleteObjectInfoIfNecessary(iter);
135}
136
137int HostVarTracker::TrackSharedMemoryHandle(PP_Instance instance,
138                                            base::SharedMemoryHandle handle,
139                                            uint32 size_in_bytes) {
140  SharedMemoryMapEntry entry;
141  entry.instance = instance;
142  entry.handle = handle;
143  entry.size_in_bytes = size_in_bytes;
144
145  // Find a free id for our map.
146  while (shared_memory_map_.find(last_shared_memory_map_id_) !=
147         shared_memory_map_.end()) {
148    ++last_shared_memory_map_id_;
149  }
150  shared_memory_map_[last_shared_memory_map_id_] = entry;
151  return last_shared_memory_map_id_;
152}
153
154bool HostVarTracker::StopTrackingSharedMemoryHandle(
155    int id,
156    PP_Instance instance,
157    base::SharedMemoryHandle* handle,
158    uint32* size_in_bytes) {
159  SharedMemoryMap::iterator it = shared_memory_map_.find(id);
160  if (it == shared_memory_map_.end())
161    return false;
162  if (it->second.instance != instance)
163    return false;
164
165  *handle = it->second.handle;
166  *size_in_bytes = it->second.size_in_bytes;
167  shared_memory_map_.erase(it);
168  return true;
169}
170
171}  // namespace content
172