OLD | NEW |
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 Loading... |
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 |
OLD | NEW |