OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2010 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 "ppapi/proxy/plugin_var_tracker.h" |
| 6 |
| 7 #include "base/ref_counted.h" |
| 8 #include "ppapi/c/ppb_var.h" |
| 9 #include "ppapi/proxy/plugin_dispatcher.h" |
| 10 #include "ppapi/proxy/ppapi_messages.h" |
| 11 |
| 12 namespace pp { |
| 13 namespace proxy { |
| 14 |
| 15 namespace { |
| 16 |
| 17 class RefCountedString : public base::RefCounted<RefCountedString> { |
| 18 public: |
| 19 RefCountedString() { |
| 20 } |
| 21 RefCountedString(const std::string& str) : value_(str) { |
| 22 } |
| 23 RefCountedString(const char* data, size_t len) |
| 24 : value_(data, len) { |
| 25 } |
| 26 |
| 27 const std::string& value() const { return value_; } |
| 28 |
| 29 private: |
| 30 std::string value_; |
| 31 }; |
| 32 |
| 33 // When running in the plugin, this will convert the string ID to the object |
| 34 // using casting. No validity checking is done. |
| 35 RefCountedString* PluginStringFromID(int64 id) { |
| 36 return reinterpret_cast<RefCountedString*>(static_cast<intptr_t>(id)); |
| 37 } |
| 38 |
| 39 } // namespace |
| 40 |
| 41 PluginVarTracker::PluginVarTracker(PluginDispatcher* dispatcher) |
| 42 : dispatcher_(dispatcher), |
| 43 browser_var_interface_(NULL) { |
| 44 } |
| 45 |
| 46 void PluginVarTracker::Init() { |
| 47 browser_var_interface_ = reinterpret_cast<const PPB_Var*>( |
| 48 dispatcher_->GetLocalInterface(PPB_VAR_INTERFACE)); |
| 49 } |
| 50 |
| 51 int64 PluginVarTracker::MakeString(const std::string& str) { |
| 52 RefCountedString* out = new RefCountedString(str); |
| 53 out->AddRef(); |
| 54 return static_cast<int64>(reinterpret_cast<intptr_t>(out)); |
| 55 } |
| 56 |
| 57 std::string PluginVarTracker::GetString(const PP_Var& var) const { |
| 58 return PluginStringFromID(var.value.as_id)->value(); |
| 59 } |
| 60 |
| 61 const std::string* PluginVarTracker::GetExistingString( |
| 62 const PP_Var& var) const { |
| 63 if (var.type != PP_VARTYPE_STRING) |
| 64 return NULL; |
| 65 RefCountedString* str = PluginStringFromID(var.value.as_id); |
| 66 return &str->value(); |
| 67 } |
| 68 |
| 69 void PluginVarTracker::AddRef(const PP_Var& var) { |
| 70 if (var.type == PP_VARTYPE_STRING) { |
| 71 PluginStringFromID(var.value.as_id)->AddRef(); |
| 72 } else if (var.type == PP_VARTYPE_OBJECT && var.value.as_id != 0) { |
| 73 int& ref_count = object_ref_count_[var.value.as_id]; |
| 74 ref_count++; |
| 75 if (ref_count == 1) { |
| 76 // We must handle the case where we got requested to AddRef an object |
| 77 // that we've never seen before. This should tell the browser we've |
| 78 // taken a ref. This comes up when the browser passes an object as an |
| 79 // input param and holds a ref for us. We may not have seen that object |
| 80 // and the plugin handler may want to AddRef and release it internally. |
| 81 SendAddRefObjectMsg(var.value.as_id); |
| 82 } |
| 83 } |
| 84 } |
| 85 |
| 86 void PluginVarTracker::Release(const PP_Var& var) { |
| 87 if (var.type == PP_VARTYPE_STRING) { |
| 88 PluginStringFromID(var.value.as_id)->Release(); |
| 89 } else if (var.type == PP_VARTYPE_OBJECT) { |
| 90 ObjectRefCount::iterator found = object_ref_count_.find(var.value.as_id); |
| 91 if (found == object_ref_count_.end()) |
| 92 return; // Invalid object. |
| 93 found->second--; |
| 94 |
| 95 if (found->second == 0) { |
| 96 // Plugin has released all of its refs, tell the browser. |
| 97 object_ref_count_.erase(found); |
| 98 SendReleaseObjectMsg(var.value.as_id); |
| 99 } |
| 100 } |
| 101 } |
| 102 |
| 103 void PluginVarTracker::ReceiveObjectPassRef(const PP_Var& var) { |
| 104 // We're the plugin and the renderer just sent us a ref. The renderer has |
| 105 // addrefed the var in its tracker for us since it's returning it. |
| 106 // |
| 107 // - If We don't have a reference to this already, then we just add it to |
| 108 // our tracker and use that one ref. |
| 109 // |
| 110 // - If we do already have a reference to it, that means the renderer now |
| 111 // has two references on our behalf. We want to transfer that extra |
| 112 // reference to our list. This means we addref in the plugin, and release |
| 113 // the extra one in the renderer. |
| 114 ObjectRefCount::iterator found = object_ref_count_.find(var.value.as_id); |
| 115 if (found == object_ref_count_.end()) { |
| 116 object_ref_count_[var.value.as_id] = 1; |
| 117 } else { |
| 118 SendReleaseObjectMsg(var.value.as_id); |
| 119 found->second++; |
| 120 } |
| 121 } |
| 122 |
| 123 void PluginVarTracker::SendAddRefObjectMsg(int64_t id) { |
| 124 dispatcher_->Send(new PpapiHostMsg_PPBVar_AddRefObject( |
| 125 INTERFACE_ID_PPB_VAR_DEPRECATED, id)); |
| 126 } |
| 127 |
| 128 void PluginVarTracker::SendReleaseObjectMsg(int64_t id) { |
| 129 dispatcher_->Send(new PpapiHostMsg_PPBVar_ReleaseObject( |
| 130 INTERFACE_ID_PPB_VAR_DEPRECATED, id)); |
| 131 } |
| 132 |
| 133 } // namesace proxy |
| 134 } // namespace pp |
OLD | NEW |