Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1287)

Side by Side Diff: ppapi/proxy/plugin_var_tracker.cc

Issue 6282007: First pass at making the proxy handle multiple renderers. This associates the... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « ppapi/proxy/plugin_var_tracker.h ('k') | ppapi/proxy/ppapi_messages_internal.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ppapi/proxy/plugin_var_tracker.h" 5 #include "ppapi/proxy/plugin_var_tracker.h"
6 6
7 #include "base/ref_counted.h" 7 #include "base/ref_counted.h"
8 #include "base/singleton.h"
8 #include "ppapi/c/ppb_var.h" 9 #include "ppapi/c/ppb_var.h"
9 #include "ppapi/proxy/plugin_dispatcher.h"
10 #include "ppapi/proxy/ppapi_messages.h" 10 #include "ppapi/proxy/ppapi_messages.h"
11 #include "ppapi/proxy/interface_id.h"
11 12
12 namespace pp { 13 namespace pp {
13 namespace proxy { 14 namespace proxy {
14 15
15 namespace { 16 namespace {
16 17
17 class RefCountedString : public base::RefCounted<RefCountedString> { 18 class RefCountedString : public base::RefCounted<RefCountedString> {
18 public: 19 public:
19 RefCountedString() { 20 RefCountedString() {
20 } 21 }
21 RefCountedString(const std::string& str) : value_(str) { 22 RefCountedString(const std::string& str) : value_(str) {
22 } 23 }
23 RefCountedString(const char* data, size_t len) 24 RefCountedString(const char* data, size_t len)
24 : value_(data, len) { 25 : value_(data, len) {
25 } 26 }
26 27
27 const std::string& value() const { return value_; } 28 const std::string& value() const { return value_; }
28 29
29 private: 30 private:
30 std::string value_; 31 std::string value_;
31 }; 32 };
32 33
33 // When running in the plugin, this will convert the string ID to the object 34 // When running in the plugin, this will convert the string ID to the object
34 // using casting. No validity checking is done. 35 // using casting. No validity checking is done.
35 RefCountedString* PluginStringFromID(int64 id) { 36 RefCountedString* PluginStringFromID(PluginVarTracker::VarID id) {
36 return reinterpret_cast<RefCountedString*>(static_cast<intptr_t>(id)); 37 return reinterpret_cast<RefCountedString*>(static_cast<intptr_t>(id));
37 } 38 }
38 39
39 } // namespace 40 } // namespace
40 41
41 PluginVarTracker::PluginVarTracker(PluginDispatcher* dispatcher) 42 PluginVarTracker::HostVar::HostVar(Sender* d, VarID i)
42 : dispatcher_(dispatcher) { 43 : channel(d),
44 host_object_id(i) {
43 } 45 }
44 46
45 PluginVarTracker::~PluginVarTracker() {} 47 bool PluginVarTracker::HostVar::operator<(const HostVar& other) const {
48 if (channel < other.channel)
49 return true;
50 if (other.channel < channel)
51 return false;
52 return host_object_id < other.host_object_id;
53 }
46 54
47 int64 PluginVarTracker::MakeString(const std::string& str) { 55 PluginVarTracker::PluginVarInfo::PluginVarInfo(const HostVar& host_var)
56 : host_var(host_var),
57 ref_count(0),
58 track_with_no_reference_count(0) {
59 }
60
61 PluginVarTracker::PluginVarTracker() : last_plugin_object_id_(0) {
62 }
63
64 PluginVarTracker::~PluginVarTracker() {
65 }
66
67 PluginVarTracker* PluginVarTracker::GetInstance() {
68 return Singleton<PluginVarTracker>::get();
69 }
70
71 PluginVarTracker::VarID PluginVarTracker::MakeString(const std::string& str) {
48 RefCountedString* out = new RefCountedString(str); 72 RefCountedString* out = new RefCountedString(str);
49 out->AddRef(); 73 out->AddRef();
50 return static_cast<int64>(reinterpret_cast<intptr_t>(out)); 74 return static_cast<VarID>(reinterpret_cast<intptr_t>(out));
51 } 75 }
52 76
53 int64 PluginVarTracker::MakeString(const char* str, uint32_t len) { 77 PluginVarTracker::VarID PluginVarTracker::MakeString(const char* str,
78 uint32_t len) {
54 RefCountedString* out = new RefCountedString(str, len); 79 RefCountedString* out = new RefCountedString(str, len);
55 out->AddRef(); 80 out->AddRef();
56 return static_cast<int64>(reinterpret_cast<intptr_t>(out)); 81 return static_cast<VarID>(reinterpret_cast<intptr_t>(out));
57 } 82 }
58 83
59 std::string PluginVarTracker::GetString(const PP_Var& var) const { 84 std::string PluginVarTracker::GetString(const PP_Var& var) const {
60 return PluginStringFromID(var.value.as_id)->value(); 85 return PluginStringFromID(var.value.as_id)->value();
61 } 86 }
62 87
63 const std::string* PluginVarTracker::GetExistingString( 88 const std::string* PluginVarTracker::GetExistingString(
64 const PP_Var& var) const { 89 const PP_Var& var) const {
65 if (var.type != PP_VARTYPE_STRING) 90 if (var.type != PP_VARTYPE_STRING)
66 return NULL; 91 return NULL;
67 RefCountedString* str = PluginStringFromID(var.value.as_id); 92 RefCountedString* str = PluginStringFromID(var.value.as_id);
68 return &str->value(); 93 return &str->value();
69 } 94 }
70 95
71 void PluginVarTracker::AddRef(const PP_Var& var) { 96 void PluginVarTracker::AddRef(const PP_Var& var) {
72 if (var.type == PP_VARTYPE_STRING) { 97 if (var.type == PP_VARTYPE_STRING) {
73 PluginStringFromID(var.value.as_id)->AddRef(); 98 PluginStringFromID(var.value.as_id)->AddRef();
74 } else if (var.type == PP_VARTYPE_OBJECT && var.value.as_id != 0) { 99 } else if (var.type == PP_VARTYPE_OBJECT && var.value.as_id != 0) {
75 int& ref_count = object_ref_count_[var.value.as_id]; 100 PluginVarInfoMap::iterator found = plugin_var_info_.find(var.value.as_id);
76 ref_count++; 101 if (found == plugin_var_info_.end()) {
77 if (ref_count == 1) { 102 NOTREACHED() << "Requesting to addref an unknown object.";
78 // We must handle the case where we got requested to AddRef an object 103 return;
79 // that we've never seen before. This should tell the browser we've
80 // taken a ref. This comes up when the browser passes an object as an
81 // input param and holds a ref for us. We may not have seen that object
82 // and the plugin handler may want to AddRef and release it internally.
83 SendAddRefObjectMsg(var.value.as_id);
84 } 104 }
105
106 PluginVarInfo& info = found->second;
107 if (info.ref_count == 0) {
108 // Got an AddRef for an object we have no existing reference for.
109 // We need to tell the browser we've taken a ref. This comes up when the
110 // browser passes an object as an input param and holds a ref for us.
111 SendAddRefObjectMsg(info.host_var);
112 }
113 info.ref_count++;
85 } 114 }
86 } 115 }
87 116
88 void PluginVarTracker::Release(const PP_Var& var) { 117 void PluginVarTracker::Release(const PP_Var& var) {
89 if (var.type == PP_VARTYPE_STRING) { 118 if (var.type == PP_VARTYPE_STRING) {
90 PluginStringFromID(var.value.as_id)->Release(); 119 PluginStringFromID(var.value.as_id)->Release();
91 } else if (var.type == PP_VARTYPE_OBJECT) { 120 } else if (var.type == PP_VARTYPE_OBJECT) {
92 ObjectRefCount::iterator found = object_ref_count_.find(var.value.as_id); 121 PluginVarInfoMap::iterator found = plugin_var_info_.find(var.value.as_id);
93 if (found == object_ref_count_.end()) 122 if (found == plugin_var_info_.end()) {
94 return; // Invalid object. 123 NOTREACHED() << "Requesting to release an unknown object.";
95 found->second--; 124 return;
125 }
96 126
97 if (found->second == 0) { 127 PluginVarInfo& info = found->second;
98 // Plugin has released all of its refs, tell the browser. 128 if (info.ref_count == 0) {
99 object_ref_count_.erase(found); 129 NOTREACHED() << "Releasing an object with zero ref.";
100 SendReleaseObjectMsg(var.value.as_id); 130 return;
101 } 131 }
132
133 info.ref_count--;
134 if (info.ref_count == 0)
135 SendReleaseObjectMsg(info.host_var);
136 DeletePluginVarInfoIfNecessary(found);
102 } 137 }
103 } 138 }
104 139
105 void PluginVarTracker::ReceiveObjectPassRef(const PP_Var& var) { 140 PP_Var PluginVarTracker::ReceiveObjectPassRef(const PP_Var& var,
106 // We're the plugin and the renderer just sent us a ref. The renderer has 141 Sender* channel) {
107 // addrefed the var in its tracker for us since it's returning it. 142 DCHECK(var.type == PP_VARTYPE_OBJECT);
108 // 143
109 // - If We don't have a reference to this already, then we just add it to 144 // Find the plugin info.
110 // our tracker and use that one ref. 145 PluginVarInfoMap::iterator found =
111 // 146 FindOrMakePluginVarFromHostVar(var, channel);
112 // - If we do already have a reference to it, that means the renderer now 147 if (found == plugin_var_info_.end()) {
113 // has two references on our behalf. We want to transfer that extra 148 // The above code should have always made an entry in the map.
114 // reference to our list. This means we addref in the plugin, and release 149 NOTREACHED();
115 // the extra one in the renderer. 150 return PP_MakeUndefined();
116 ObjectRefCount::iterator found = object_ref_count_.find(var.value.as_id); 151 }
117 if (found == object_ref_count_.end()) { 152
118 object_ref_count_[var.value.as_id] = 1; 153 // Fix up the references. The host (renderer) just sent us a ref. The
154 // renderer has addrefed the var in its tracker for us since it's returning
155 // it.
156 PluginVarInfo& info = found->second;
157 if (info.ref_count == 0) {
158 // We don't have a reference to this already, then we just add it to our
159 // tracker and use that one ref.
160 info.ref_count = 1;
119 } else { 161 } else {
120 SendReleaseObjectMsg(var.value.as_id); 162 // We already have a reference to it, that means the renderer now has two
121 found->second++; 163 // references on our behalf. We want to transfer that extra reference to
164 // our list. This means we addref in the plugin, and release the extra one
165 // in the renderer.
166 SendReleaseObjectMsg(info.host_var);
167 info.ref_count++;
122 } 168 }
169
170 PP_Var ret;
171 ret.type = PP_VARTYPE_OBJECT;
172 ret.value.as_id = found->first;
173 return ret;
123 } 174 }
124 175
125 void PluginVarTracker::SendAddRefObjectMsg(int64_t id) { 176 PP_Var PluginVarTracker::TrackObjectWithNoReference(const PP_Var& host_var,
126 dispatcher_->Send(new PpapiHostMsg_PPBVar_AddRefObject( 177 Sender* channel) {
127 INTERFACE_ID_PPB_VAR_DEPRECATED, id)); 178 DCHECK(host_var.type == PP_VARTYPE_OBJECT);
179
180 PluginVarInfoMap::iterator found =
181 FindOrMakePluginVarFromHostVar(host_var, channel);
182 if (found == plugin_var_info_.end()) {
183 // The above code should have always made an entry in the map.
184 NOTREACHED();
185 return PP_MakeUndefined();
186 }
187
188 found->second.track_with_no_reference_count++;
189
190 PP_Var ret;
191 ret.type = PP_VARTYPE_OBJECT;
192 ret.value.as_id = found->first;
193 return ret;
128 } 194 }
129 195
130 void PluginVarTracker::SendReleaseObjectMsg(int64_t id) { 196 void PluginVarTracker::StopTrackingObjectWithNoReference(
131 dispatcher_->Send(new PpapiHostMsg_PPBVar_ReleaseObject( 197 const PP_Var& plugin_var) {
132 INTERFACE_ID_PPB_VAR_DEPRECATED, id)); 198 DCHECK(plugin_var.type == PP_VARTYPE_OBJECT);
199 PluginVarInfoMap::iterator found = plugin_var_info_.find(
200 plugin_var.value.as_id);
201 if (found == plugin_var_info_.end()) {
202 NOTREACHED();
203 return;
204 }
205
206 found->second.track_with_no_reference_count--;
207 DeletePluginVarInfoIfNecessary(found);
208 }
209
210 PP_Var PluginVarTracker::GetHostObject(const PP_Var& plugin_object) const {
211 DCHECK(plugin_object.type == PP_VARTYPE_OBJECT);
212 PluginVarInfoMap::const_iterator found = plugin_var_info_.find(
213 plugin_object.value.as_id);
214 if (found == plugin_var_info_.end()) {
215 NOTREACHED();
216 return PP_MakeUndefined();
217 }
218 PP_Var ret;
219 ret.type = PP_VARTYPE_OBJECT;
220 ret.value.as_id = found->second.host_var.host_object_id;
221 return ret;
222 }
223
224 int PluginVarTracker::GetRefCountForObject(const PP_Var& plugin_object) {
225 PluginVarInfoMap::iterator found = plugin_var_info_.find(
226 plugin_object.value.as_id);
227 if (found == plugin_var_info_.end())
228 return -1;
229 return found->second.ref_count;
230 }
231
232 int PluginVarTracker::GetTrackedWithNoReferenceCountForObject(
233 const PP_Var& plugin_object) {
234 PluginVarInfoMap::iterator found = plugin_var_info_.find(
235 plugin_object.value.as_id);
236 if (found == plugin_var_info_.end())
237 return -1;
238 return found->second.track_with_no_reference_count;
239 }
240
241 void PluginVarTracker::SendAddRefObjectMsg(const HostVar& host_var) {
242 host_var.channel->Send(new PpapiHostMsg_PPBVar_AddRefObject(
243 INTERFACE_ID_PPB_VAR_DEPRECATED, host_var.host_object_id));
244 }
245
246 void PluginVarTracker::SendReleaseObjectMsg(const HostVar& host_var) {
247 host_var.channel->Send(new PpapiHostMsg_PPBVar_ReleaseObject(
248 INTERFACE_ID_PPB_VAR_DEPRECATED, host_var.host_object_id));
249 }
250
251 PluginVarTracker::PluginVarInfoMap::iterator
252 PluginVarTracker::FindOrMakePluginVarFromHostVar(const PP_Var& var,
253 Sender* channel) {
254 DCHECK(var.type == PP_VARTYPE_OBJECT);
255 HostVar host_var(channel, var.value.as_id);
256
257 HostVarToPluginVarMap::iterator found =
258 host_var_to_plugin_var_.find(host_var);
259 if (found != host_var_to_plugin_var_.end()) {
260 PluginVarInfoMap::iterator ret = plugin_var_info_.find(found->second);
261 DCHECK(ret != plugin_var_info_.end());
262 return ret; // Already know about this var return the ID.
263 }
264
265 // Make a new var, adding references to both maps.
266 VarID new_plugin_var_id = ++last_plugin_object_id_;
267 host_var_to_plugin_var_[host_var] = new_plugin_var_id;
268 return plugin_var_info_.insert(
269 std::make_pair(new_plugin_var_id, PluginVarInfo(host_var))).first;
270 }
271
272 void PluginVarTracker::DeletePluginVarInfoIfNecessary(
273 PluginVarInfoMap::iterator iter) {
274 if (iter->second.ref_count != 0 ||
275 iter->second.track_with_no_reference_count != 0)
276 return; // Object still alive.
277
278 // Object ref counts are all zero, delete from both maps.
279 DCHECK(host_var_to_plugin_var_.find(iter->second.host_var) !=
280 host_var_to_plugin_var_.end());
281 host_var_to_plugin_var_.erase(iter->second.host_var);
282 plugin_var_info_.erase(iter);
133 } 283 }
134 284
135 } // namesace proxy 285 } // namesace proxy
136 } // namespace pp 286 } // namespace pp
OLDNEW
« no previous file with comments | « ppapi/proxy/plugin_var_tracker.h ('k') | ppapi/proxy/ppapi_messages_internal.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698