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

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

Issue 6995083: Proxy PPB_Var, fix o-o-p string var id tracking. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Updated copyright header Created 9 years, 6 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/plugin_var_tracker_unittest.cc » ('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) 2011 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/memory/ref_counted.h" 7 #include "base/memory/ref_counted.h"
8 #include "base/memory/singleton.h" 8 #include "base/memory/singleton.h"
9 #include "ppapi/c/ppb_var.h" 9 #include "ppapi/c/ppb_var.h"
10 #include "ppapi/proxy/plugin_dispatcher.h" 10 #include "ppapi/proxy/plugin_dispatcher.h"
11 #include "ppapi/proxy/ppapi_messages.h" 11 #include "ppapi/proxy/ppapi_messages.h"
12 #include "ppapi/proxy/interface_id.h" 12 #include "ppapi/proxy/interface_id.h"
13 13
14 namespace pp { 14 namespace pp {
15 namespace proxy { 15 namespace proxy {
16 16
17 namespace { 17 namespace {
18 18
19 // When non-NULL, this object overrides the VarTrackerSingleton. 19 // When non-NULL, this object overrides the VarTrackerSingleton.
20 PluginVarTracker* var_tracker_override = NULL; 20 PluginVarTracker* var_tracker_override = NULL;
21 21
22 class RefCountedString : public base::RefCounted<RefCountedString> {
23 public:
24 RefCountedString() {
25 }
26 RefCountedString(const std::string& str) : value_(str) {
27 }
28 RefCountedString(const char* data, size_t len)
29 : value_(data, len) {
30 }
31
32 const std::string& value() const { return value_; }
33
34 private:
35 std::string value_;
36 };
37
38 // When running in the plugin, this will convert the string ID to the object
39 // using casting. No validity checking is done.
40 RefCountedString* PluginStringFromID(PluginVarTracker::VarID id) {
41 return reinterpret_cast<RefCountedString*>(static_cast<intptr_t>(id));
42 }
43
44 } // namespace 22 } // namespace
45 23
46 PluginVarTracker::HostVar::HostVar(PluginDispatcher* d, VarID i) 24 PluginVarTracker::HostVar::HostVar(PluginDispatcher* d, VarID i)
47 : dispatcher(d), 25 : dispatcher(d),
48 host_object_id(i) { 26 host_object_id(i) {
49 } 27 }
50 28
51 bool PluginVarTracker::HostVar::operator<(const HostVar& other) const { 29 bool PluginVarTracker::HostVar::operator<(const HostVar& other) const {
52 if (dispatcher < other.dispatcher) 30 if (dispatcher < other.dispatcher)
53 return true; 31 return true;
54 if (other.dispatcher < dispatcher) 32 if (other.dispatcher < dispatcher)
55 return false; 33 return false;
56 return host_object_id < other.host_object_id; 34 return host_object_id < other.host_object_id;
57 } 35 }
58 36
59 PluginVarTracker::PluginVarInfo::PluginVarInfo(const HostVar& host_var) 37 PluginVarTracker::PluginVarInfo::PluginVarInfo(const HostVar& host_var)
60 : host_var(host_var), 38 : host_var(host_var),
61 ref_count(0), 39 ref_count(0),
62 track_with_no_reference_count(0) { 40 track_with_no_reference_count(0) {
63 } 41 }
64 42
65 PluginVarTracker::PluginVarTracker() : last_plugin_object_id_(0) { 43 PluginVarTracker::PluginVarTracker() : last_plugin_var_id_(0) {
66 } 44 }
67 45
68 PluginVarTracker::~PluginVarTracker() { 46 PluginVarTracker::~PluginVarTracker() {
69 } 47 }
70 48
71 // static 49 // static
72 void PluginVarTracker::SetInstanceForTest(PluginVarTracker* tracker) { 50 void PluginVarTracker::SetInstanceForTest(PluginVarTracker* tracker) {
73 var_tracker_override = tracker; 51 var_tracker_override = tracker;
74 } 52 }
75 53
76 // static 54 // static
77 PluginVarTracker* PluginVarTracker::GetInstance() { 55 PluginVarTracker* PluginVarTracker::GetInstance() {
78 if (var_tracker_override) 56 if (var_tracker_override)
79 return var_tracker_override; 57 return var_tracker_override;
80 return Singleton<PluginVarTracker>::get(); 58 return Singleton<PluginVarTracker>::get();
81 } 59 }
82 60
83 PluginVarTracker::VarID PluginVarTracker::MakeString(const std::string& str) { 61 PluginVarTracker::VarID PluginVarTracker::MakeString(const std::string& str) {
84 RefCountedString* out = new RefCountedString(str); 62 return MakeString(str.c_str(), str.length());
85 out->AddRef();
86 return static_cast<VarID>(reinterpret_cast<intptr_t>(out));
87 } 63 }
88 64
89 PluginVarTracker::VarID PluginVarTracker::MakeString(const char* str, 65 PluginVarTracker::VarID PluginVarTracker::MakeString(const char* str,
90 uint32_t len) { 66 uint32_t len) {
91 RefCountedString* out = new RefCountedString(str, len); 67 std::pair<VarIDStringMap::iterator, bool>
92 out->AddRef(); 68 iter_success_pair(var_id_to_string_.end(), false);
93 return static_cast<VarID>(reinterpret_cast<intptr_t>(out)); 69 VarID new_id(0);
94 } 70 RefCountedStringPtr str_ptr(new RefCountedString(str, len));
95 71 // Pick new IDs until one is successfully inserted. This loop is very unlikely
96 std::string PluginVarTracker::GetString(const PP_Var& var) const { 72 // to ever run a 2nd time, since we have ~2^63 possible IDs to exhaust.
97 return PluginStringFromID(var.value.as_id)->value(); 73 while (!iter_success_pair.second) {
74 new_id = GetNewVarID();
75 iter_success_pair =
76 var_id_to_string_.insert(VarIDStringMap::value_type(new_id, str_ptr));
77 }
78 iter_success_pair.first->second->AddRef();
79 return new_id;
98 } 80 }
99 81
100 const std::string* PluginVarTracker::GetExistingString( 82 const std::string* PluginVarTracker::GetExistingString(
101 const PP_Var& var) const { 83 const PP_Var& var) const {
102 if (var.type != PP_VARTYPE_STRING) 84 if (var.type != PP_VARTYPE_STRING)
103 return NULL; 85 return NULL;
104 RefCountedString* str = PluginStringFromID(var.value.as_id); 86 VarIDStringMap::const_iterator found =
105 return &str->value(); 87 var_id_to_string_.find(var.value.as_id);
88 if (found != var_id_to_string_.end())
89 return &found->second->value();
90 return NULL;
106 } 91 }
107 92
108 void PluginVarTracker::AddRef(const PP_Var& var) { 93 void PluginVarTracker::AddRef(const PP_Var& var) {
109 if (var.type == PP_VARTYPE_STRING) { 94 if (var.type == PP_VARTYPE_STRING) {
110 PluginStringFromID(var.value.as_id)->AddRef(); 95 VarIDStringMap::iterator found = var_id_to_string_.find(var.value.as_id);
96 if (found == var_id_to_string_.end()) {
97 NOTREACHED() << "Requesting to addref an unknown string.";
98 return;
99 }
100 found->second->AddRef();
111 } else if (var.type == PP_VARTYPE_OBJECT && var.value.as_id != 0) { 101 } else if (var.type == PP_VARTYPE_OBJECT && var.value.as_id != 0) {
112 PluginVarInfoMap::iterator found = plugin_var_info_.find(var.value.as_id); 102 PluginVarInfoMap::iterator found = plugin_var_info_.find(var.value.as_id);
113 if (found == plugin_var_info_.end()) { 103 if (found == plugin_var_info_.end()) {
114 NOTREACHED() << "Requesting to addref an unknown object."; 104 NOTREACHED() << "Requesting to addref an unknown object.";
115 return; 105 return;
116 } 106 }
117 107
118 PluginVarInfo& info = found->second; 108 PluginVarInfo& info = found->second;
119 if (info.ref_count == 0) { 109 if (info.ref_count == 0) {
120 // Got an AddRef for an object we have no existing reference for. 110 // Got an AddRef for an object we have no existing reference for.
121 // We need to tell the browser we've taken a ref. This comes up when the 111 // We need to tell the browser we've taken a ref. This comes up when the
122 // browser passes an object as an input param and holds a ref for us. 112 // browser passes an object as an input param and holds a ref for us.
123 // This must be a sync message since otherwise the "addref" will actually 113 // This must be a sync message since otherwise the "addref" will actually
124 // occur after the return to the browser of the sync function that 114 // occur after the return to the browser of the sync function that
125 // presumably sent the object. 115 // presumably sent the object.
126 SendAddRefObjectMsg(info.host_var); 116 SendAddRefObjectMsg(info.host_var);
127 } 117 }
128 info.ref_count++; 118 info.ref_count++;
129 } 119 }
130 } 120 }
131 121
132 void PluginVarTracker::Release(const PP_Var& var) { 122 void PluginVarTracker::Release(const PP_Var& var) {
133 if (var.type == PP_VARTYPE_STRING) { 123 if (var.type == PP_VARTYPE_STRING) {
134 PluginStringFromID(var.value.as_id)->Release(); 124 VarIDStringMap::iterator found = var_id_to_string_.find(var.value.as_id);
125 if (found == var_id_to_string_.end()) {
126 NOTREACHED() << "Requesting to release an unknown string.";
127 return;
128 }
129 found->second->Release();
130 // If there is only 1 reference left, it's the map's reference. Erase it
131 // from the map, which will delete the string.
132 if (found->second->HasOneRef())
133 var_id_to_string_.erase(found);
135 } else if (var.type == PP_VARTYPE_OBJECT) { 134 } else if (var.type == PP_VARTYPE_OBJECT) {
136 PluginVarInfoMap::iterator found = plugin_var_info_.find(var.value.as_id); 135 PluginVarInfoMap::iterator found = plugin_var_info_.find(var.value.as_id);
137 if (found == plugin_var_info_.end()) { 136 if (found == plugin_var_info_.end()) {
138 NOTREACHED() << "Requesting to release an unknown object."; 137 NOTREACHED() << "Requesting to release an unknown object.";
139 return; 138 return;
140 } 139 }
141 140
142 PluginVarInfo& info = found->second; 141 PluginVarInfo& info = found->second;
143 if (info.ref_count == 0) { 142 if (info.ref_count == 0) {
144 NOTREACHED() << "Releasing an object with zero ref."; 143 NOTREACHED() << "Releasing an object with zero ref.";
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
301 300
302 HostVarToPluginVarMap::iterator found = 301 HostVarToPluginVarMap::iterator found =
303 host_var_to_plugin_var_.find(host_var); 302 host_var_to_plugin_var_.find(host_var);
304 if (found != host_var_to_plugin_var_.end()) { 303 if (found != host_var_to_plugin_var_.end()) {
305 PluginVarInfoMap::iterator ret = plugin_var_info_.find(found->second); 304 PluginVarInfoMap::iterator ret = plugin_var_info_.find(found->second);
306 DCHECK(ret != plugin_var_info_.end()); 305 DCHECK(ret != plugin_var_info_.end());
307 return ret; // Already know about this var return the ID. 306 return ret; // Already know about this var return the ID.
308 } 307 }
309 308
310 // Make a new var, adding references to both maps. 309 // Make a new var, adding references to both maps.
311 VarID new_plugin_var_id = ++last_plugin_object_id_; 310 VarID new_plugin_var_id = GetNewVarID();
312 host_var_to_plugin_var_[host_var] = new_plugin_var_id; 311 host_var_to_plugin_var_[host_var] = new_plugin_var_id;
313 return plugin_var_info_.insert( 312 return plugin_var_info_.insert(
314 std::make_pair(new_plugin_var_id, PluginVarInfo(host_var))).first; 313 std::make_pair(new_plugin_var_id, PluginVarInfo(host_var))).first;
315 } 314 }
316 315
317 void PluginVarTracker::DeletePluginVarInfoIfNecessary( 316 void PluginVarTracker::DeletePluginVarInfoIfNecessary(
318 PluginVarInfoMap::iterator iter) { 317 PluginVarInfoMap::iterator iter) {
319 if (iter->second.ref_count != 0 || 318 if (iter->second.ref_count != 0 ||
320 iter->second.track_with_no_reference_count != 0) 319 iter->second.track_with_no_reference_count != 0)
321 return; // Object still alive. 320 return; // Object still alive.
322 321
323 // Object ref counts are all zero, delete from both maps. 322 // Object ref counts are all zero, delete from both maps.
324 DCHECK(host_var_to_plugin_var_.find(iter->second.host_var) != 323 DCHECK(host_var_to_plugin_var_.find(iter->second.host_var) !=
325 host_var_to_plugin_var_.end()); 324 host_var_to_plugin_var_.end());
326 host_var_to_plugin_var_.erase(iter->second.host_var); 325 host_var_to_plugin_var_.erase(iter->second.host_var);
327 plugin_var_info_.erase(iter); 326 plugin_var_info_.erase(iter);
328 } 327 }
329 328
329 PluginVarTracker::VarID PluginVarTracker::GetNewVarID() {
330 if (last_plugin_var_id_ == std::numeric_limits<VarID>::max())
331 last_plugin_var_id_ = 0;
332 return ++last_plugin_var_id_;
333 }
334
330 } // namesace proxy 335 } // namesace proxy
331 } // namespace pp 336 } // namespace pp
OLDNEW
« no previous file with comments | « ppapi/proxy/plugin_var_tracker.h ('k') | ppapi/proxy/plugin_var_tracker_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698