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 #ifndef PPAPI_PROXY_PLUGIN_VAR_TRACKER_H_ 6 #define PPAPI_PROXY_PLUGIN_VAR_TRACKER_H_ 7 8 #include <map> 9 #include <string> 10 11 #include "base/basictypes.h" 12 #include "base/compiler_specific.h" 13 #include "base/memory/ref_counted.h" 14 #include "base/memory/shared_memory.h" 15 #include "ppapi/c/pp_stdint.h" 16 #include "ppapi/c/pp_var.h" 17 #include "ppapi/proxy/ppapi_proxy_export.h" 18 #include "ppapi/shared_impl/var_tracker.h" 19 20 template<typename T> struct DefaultSingletonTraits; 21 struct PPP_Class_Deprecated; 22 23 namespace ppapi { 24 25 class ProxyObjectVar; 26 27 namespace proxy { 28 29 class PluginDispatcher; 30 31 // Tracks live strings and objects in the plugin process. 32 class PPAPI_PROXY_EXPORT PluginVarTracker : public VarTracker { 33 public: 34 PluginVarTracker(); 35 ~PluginVarTracker(); 36 37 // Manages tracking for receiving a VARTYPE_OBJECT from the remote side 38 // (either the plugin or the renderer) that has already had its reference 39 // count incremented on behalf of the caller. 40 PP_Var ReceiveObjectPassRef(const PP_Var& var, PluginDispatcher* dispatcher); 41 42 // See the comment in var_tracker.h for more about what a tracked object is. 43 // This adds and releases the "track_with_no_reference_count" for a given 44 // object. 45 PP_Var TrackObjectWithNoReference(const PP_Var& host_var, 46 PluginDispatcher* dispatcher); 47 void StopTrackingObjectWithNoReference(const PP_Var& plugin_var); 48 49 // Returns the host var for the corresponding plugin object var. The object 50 // should be a VARTYPE_OBJECT. The reference count is not affeceted. 51 PP_Var GetHostObject(const PP_Var& plugin_object) const; 52 53 PluginDispatcher* DispatcherForPluginObject( 54 const PP_Var& plugin_object) const; 55 56 // Like Release() but the var is identified by its host object ID (as 57 // returned by GetHostObject). 58 void ReleaseHostObject(PluginDispatcher* dispatcher, 59 const PP_Var& host_object); 60 61 // VarTracker public overrides. 62 virtual PP_Var MakeResourcePPVarFromMessage( 63 PP_Instance instance, 64 const IPC::Message& creation_message, 65 int pending_renderer_id, 66 int pending_browser_id) OVERRIDE; 67 virtual ResourceVar* MakeResourceVar(PP_Resource pp_resource) OVERRIDE; 68 virtual void DidDeleteInstance(PP_Instance instance) OVERRIDE; 69 virtual int TrackSharedMemoryHandle(PP_Instance instance, 70 base::SharedMemoryHandle file, 71 uint32 size_in_bytes) OVERRIDE; 72 virtual bool StopTrackingSharedMemoryHandle(int id, 73 PP_Instance instance, 74 base::SharedMemoryHandle* handle, 75 uint32* size_in_bytes) OVERRIDE; 76 77 // Notification that a plugin-implemented object (PPP_Class) was created by 78 // the plugin or deallocated by WebKit over IPC. 79 void PluginImplementedObjectCreated(PP_Instance instance, 80 const PP_Var& created_var, 81 const PPP_Class_Deprecated* ppp_class, 82 void* ppp_class_data); 83 void PluginImplementedObjectDestroyed(void* ppp_class_data); 84 85 // Returns true if there is an object implemented by the plugin with the 86 // given user_data that has not been deallocated yet. Call this when 87 // receiving a scripting call to the plugin to validate that the object 88 // receiving the call is still alive (see user_data_to_plugin_ below). 89 bool IsPluginImplementedObjectAlive(void* user_data); 90 91 // Validates that the given class/user_data pair corresponds to a currently 92 // living plugin object. 93 bool ValidatePluginObjectCall(const PPP_Class_Deprecated* ppp_class, 94 void* user_data); 95 96 void DidDeleteDispatcher(PluginDispatcher* dispatcher); 97 98 private: 99 // VarTracker protected overrides. 100 virtual int32 AddVarInternal(Var* var, AddVarRefMode mode) OVERRIDE; 101 virtual void TrackedObjectGettingOneRef(VarMap::const_iterator iter) OVERRIDE; 102 virtual void ObjectGettingZeroRef(VarMap::iterator iter) OVERRIDE; 103 virtual bool DeleteObjectInfoIfNecessary(VarMap::iterator iter) OVERRIDE; 104 virtual ArrayBufferVar* CreateArrayBuffer(uint32 size_in_bytes) OVERRIDE; 105 virtual ArrayBufferVar* CreateShmArrayBuffer( 106 uint32 size_in_bytes, 107 base::SharedMemoryHandle handle) OVERRIDE; 108 109 private: 110 friend struct DefaultSingletonTraits<PluginVarTracker>; 111 friend class PluginProxyTestHarness; 112 113 // Represents a var as received from the host. 114 struct HostVar { 115 HostVar(PluginDispatcher* d, int32 i); 116 117 bool operator<(const HostVar& other) const; 118 119 // The dispatcher that sent us this object. This is used so we know how to 120 // send back requests on this object. 121 PluginDispatcher* dispatcher; 122 123 // The object ID that the host generated to identify the object. This is 124 // unique only within that host: different hosts could give us different 125 // objects with the same ID. 126 int32 host_object_id; 127 }; 128 129 struct PluginImplementedVar { 130 const PPP_Class_Deprecated* ppp_class; 131 132 // The instance that created this Var. This will be 0 if the instance has 133 // been destroyed but the object is still alive. 134 PP_Instance instance; 135 136 // Represents the plugin var ID for the var corresponding to this object. 137 // If the plugin does not have a ref to the object but it's still alive 138 // (the DOM could be holding a ref keeping it alive) this will be 0. 139 // 140 // There is an obscure corner case. If the plugin returns an object to the 141 // renderer and releases all of its refs, the object will still be alive 142 // but there will be no plugin refs. It's possible for the plugin to get 143 // this same object again through the DOM, and we'll lose the correlation 144 // between plugin implemented object and car. This means we won't know when 145 // the plugin releases its last refs and may call Deallocate when the 146 // plugin is still holding a ref. 147 // 148 // However, for the plugin to be depending on holding a ref to an object 149 // that it implements that it previously released but got again through 150 // indirect means would be extremely rare, and we only allow var scripting 151 // in limited cases anyway. 152 int32 plugin_object_id; 153 }; 154 155 // Returns the existing var ID for the given object var, creating and 156 // assigning an ID to it if necessary. This does not affect the reference 157 // count, so in the creation case the refcount will be 0. It's assumed in 158 // this case the caller will either adjust the refcount or the 159 // track_with_no_reference_count. 160 PP_Var GetOrCreateObjectVarID(ProxyObjectVar* object); 161 162 // Sends an addref or release message to the browser for the given object ID. 163 void SendAddRefObjectMsg(const ProxyObjectVar& proxy_object); 164 void SendReleaseObjectMsg(const ProxyObjectVar& proxy_object); 165 166 // Looks up the given host var. If we already know about it, returns a 167 // reference to the already-tracked object. If it doesn't creates a new one 168 // and returns it. If it's created, it's not added to the map. 169 scoped_refptr<ProxyObjectVar> FindOrMakePluginVarFromHostVar( 170 const PP_Var& var, 171 PluginDispatcher* dispatcher); 172 173 // Maps host vars in the host to IDs in the plugin process. 174 typedef std::map<HostVar, int32> HostVarToPluginVarMap; 175 HostVarToPluginVarMap host_var_to_plugin_var_; 176 177 // Maps "user data" for plugin implemented objects (PPP_Class) that are 178 // alive to various tracking info. 179 // 180 // This is tricky because there may not actually be any vars in the plugin 181 // associated with a plugin-implemented object, so they won't all have 182 // entries in our HostVarToPluginVarMap or the base class VarTracker's map. 183 // 184 // All objects that the plugin has created using CreateObject that have not 185 // yet been Deallocate()-ed by WebKit will be in this map. When the instance 186 // that created the object goes away, we know to call Deallocate on all 187 // remaining objects for that instance so that the data backing the object 188 // that the plugin owns is not leaked. We may not receive normal Deallocate 189 // calls from WebKit because the object could be leaked (attached to the DOM 190 // and outliving the plugin instance) or WebKit could send the deallocate 191 // after the out-of-process routing for that instance was torn down. 192 // 193 // There is an additional complexity. In WebKit, objects created by the 194 // plugin aren't actually bound to the plugin instance (for example, you 195 // could attach it to the DOM or send it to another plugin instance). It's 196 // possible that we could force deallocate an object when an instance id 197 // destroyed, but then another instance could get to that object somehow 198 // (like by reading it out of the DOM). We will then have deallocated the 199 // object and can't complete the call. We do not care about this case, and 200 // the calls will just fail. 201 typedef std::map<void*, PluginImplementedVar> 202 UserDataToPluginImplementedVarMap; 203 UserDataToPluginImplementedVarMap user_data_to_plugin_; 204 205 DISALLOW_COPY_AND_ASSIGN(PluginVarTracker); 206 }; 207 208 } // namespace proxy 209 } // namespace ppapi 210 211 #endif // PPAPI_PROXY_PLUGIN_VAR_TRACKER_H_ 212