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.
5 #ifndef PPAPI_PROXY_PLUGIN_VAR_TRACKER_H_
6 #define PPAPI_PROXY_PLUGIN_VAR_TRACKER_H_
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"
20 template<typename T
> struct DefaultSingletonTraits
;
21 struct PPP_Class_Deprecated
;
29 class PluginDispatcher
;
31 // Tracks live strings and objects in the plugin process.
32 class PPAPI_PROXY_EXPORT PluginVarTracker
: public VarTracker
{
35 ~PluginVarTracker() override
;
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
);
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
45 PP_Var
TrackObjectWithNoReference(const PP_Var
& host_var
,
46 PluginDispatcher
* dispatcher
);
47 void StopTrackingObjectWithNoReference(const PP_Var
& plugin_var
);
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;
53 PluginDispatcher
* DispatcherForPluginObject(
54 const PP_Var
& plugin_object
) const;
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
);
61 // VarTracker public overrides.
62 PP_Var
MakeResourcePPVarFromMessage(PP_Instance instance
,
63 const IPC::Message
& creation_message
,
64 int pending_renderer_id
,
65 int pending_browser_id
) override
;
66 ResourceVar
* MakeResourceVar(PP_Resource pp_resource
) override
;
67 void DidDeleteInstance(PP_Instance instance
) override
;
68 int TrackSharedMemoryHandle(PP_Instance instance
,
69 base::SharedMemoryHandle file
,
70 uint32 size_in_bytes
) override
;
71 bool StopTrackingSharedMemoryHandle(int id
,
73 base::SharedMemoryHandle
* handle
,
74 uint32
* size_in_bytes
) override
;
76 // Notification that a plugin-implemented object (PPP_Class) was created by
77 // the plugin or deallocated by WebKit over IPC.
78 void PluginImplementedObjectCreated(PP_Instance instance
,
79 const PP_Var
& created_var
,
80 const PPP_Class_Deprecated
* ppp_class
,
81 void* ppp_class_data
);
82 void PluginImplementedObjectDestroyed(void* ppp_class_data
);
84 // Returns true if there is an object implemented by the plugin with the
85 // given user_data that has not been deallocated yet. Call this when
86 // receiving a scripting call to the plugin to validate that the object
87 // receiving the call is still alive (see user_data_to_plugin_ below).
88 bool IsPluginImplementedObjectAlive(void* user_data
);
90 // Validates that the given class/user_data pair corresponds to a currently
91 // living plugin object.
92 bool ValidatePluginObjectCall(const PPP_Class_Deprecated
* ppp_class
,
95 void DidDeleteDispatcher(PluginDispatcher
* dispatcher
);
98 // VarTracker protected overrides.
99 int32
AddVarInternal(Var
* var
, AddVarRefMode mode
) override
;
100 void TrackedObjectGettingOneRef(VarMap::const_iterator iter
) override
;
101 void ObjectGettingZeroRef(VarMap::iterator iter
) override
;
102 bool DeleteObjectInfoIfNecessary(VarMap::iterator iter
) override
;
103 ArrayBufferVar
* CreateArrayBuffer(uint32 size_in_bytes
) override
;
104 ArrayBufferVar
* CreateShmArrayBuffer(
105 uint32 size_in_bytes
,
106 base::SharedMemoryHandle handle
) override
;
109 friend struct DefaultSingletonTraits
<PluginVarTracker
>;
110 friend class PluginProxyTestHarness
;
112 // Represents a var as received from the host.
114 HostVar(PluginDispatcher
* d
, int32 i
);
116 bool operator<(const HostVar
& other
) const;
118 // The dispatcher that sent us this object. This is used so we know how to
119 // send back requests on this object.
120 PluginDispatcher
* dispatcher
;
122 // The object ID that the host generated to identify the object. This is
123 // unique only within that host: different hosts could give us different
124 // objects with the same ID.
125 int32 host_object_id
;
128 struct PluginImplementedVar
{
129 const PPP_Class_Deprecated
* ppp_class
;
131 // The instance that created this Var. This will be 0 if the instance has
132 // been destroyed but the object is still alive.
133 PP_Instance instance
;
135 // Represents the plugin var ID for the var corresponding to this object.
136 // If the plugin does not have a ref to the object but it's still alive
137 // (the DOM could be holding a ref keeping it alive) this will be 0.
139 // There is an obscure corner case. If the plugin returns an object to the
140 // renderer and releases all of its refs, the object will still be alive
141 // but there will be no plugin refs. It's possible for the plugin to get
142 // this same object again through the DOM, and we'll lose the correlation
143 // between plugin implemented object and car. This means we won't know when
144 // the plugin releases its last refs and may call Deallocate when the
145 // plugin is still holding a ref.
147 // However, for the plugin to be depending on holding a ref to an object
148 // that it implements that it previously released but got again through
149 // indirect means would be extremely rare, and we only allow var scripting
150 // in limited cases anyway.
151 int32 plugin_object_id
;
154 // Returns the existing var ID for the given object var, creating and
155 // assigning an ID to it if necessary. This does not affect the reference
156 // count, so in the creation case the refcount will be 0. It's assumed in
157 // this case the caller will either adjust the refcount or the
158 // track_with_no_reference_count.
159 PP_Var
GetOrCreateObjectVarID(ProxyObjectVar
* object
);
161 // Sends an addref or release message to the browser for the given object ID.
162 void SendAddRefObjectMsg(const ProxyObjectVar
& proxy_object
);
163 void SendReleaseObjectMsg(const ProxyObjectVar
& proxy_object
);
165 // Looks up the given host var. If we already know about it, returns a
166 // reference to the already-tracked object. If it doesn't creates a new one
167 // and returns it. If it's created, it's not added to the map.
168 scoped_refptr
<ProxyObjectVar
> FindOrMakePluginVarFromHostVar(
170 PluginDispatcher
* dispatcher
);
172 // Maps host vars in the host to IDs in the plugin process.
173 typedef std::map
<HostVar
, int32
> HostVarToPluginVarMap
;
174 HostVarToPluginVarMap host_var_to_plugin_var_
;
176 // Maps "user data" for plugin implemented objects (PPP_Class) that are
177 // alive to various tracking info.
179 // This is tricky because there may not actually be any vars in the plugin
180 // associated with a plugin-implemented object, so they won't all have
181 // entries in our HostVarToPluginVarMap or the base class VarTracker's map.
183 // All objects that the plugin has created using CreateObject that have not
184 // yet been Deallocate()-ed by WebKit will be in this map. When the instance
185 // that created the object goes away, we know to call Deallocate on all
186 // remaining objects for that instance so that the data backing the object
187 // that the plugin owns is not leaked. We may not receive normal Deallocate
188 // calls from WebKit because the object could be leaked (attached to the DOM
189 // and outliving the plugin instance) or WebKit could send the deallocate
190 // after the out-of-process routing for that instance was torn down.
192 // There is an additional complexity. In WebKit, objects created by the
193 // plugin aren't actually bound to the plugin instance (for example, you
194 // could attach it to the DOM or send it to another plugin instance). It's
195 // possible that we could force deallocate an object when an instance id
196 // destroyed, but then another instance could get to that object somehow
197 // (like by reading it out of the DOM). We will then have deallocated the
198 // object and can't complete the call. We do not care about this case, and
199 // the calls will just fail.
200 typedef std::map
<void*, PluginImplementedVar
>
201 UserDataToPluginImplementedVarMap
;
202 UserDataToPluginImplementedVarMap user_data_to_plugin_
;
204 DISALLOW_COPY_AND_ASSIGN(PluginVarTracker
);
210 #endif // PPAPI_PROXY_PLUGIN_VAR_TRACKER_H_