Index: ppapi/proxy/plugin_var_tracker.h |
=================================================================== |
--- ppapi/proxy/plugin_var_tracker.h (revision 71973) |
+++ ppapi/proxy/plugin_var_tracker.h (working copy) |
@@ -8,64 +8,152 @@ |
#include <map> |
#include <string> |
+#include "ipc/ipc_channel.h" |
#include "ppapi/c/pp_stdint.h" |
#include "ppapi/c/pp_var.h" |
struct PPB_Var; |
+template<typename T> struct DefaultSingletonTraits; |
+ |
namespace pp { |
namespace proxy { |
-class PluginDispatcher; |
- |
-// Tracks live strings and objects in the plugin process. We maintain our own |
-// reference count for these objects. In the case of JS objects, we maintain |
-// a single ref in the renderer process whenever we have a nonzero refcount |
-// in the plugin process. This allows AddRef and Release to not initiate too |
-// much IPC chat. |
+// Tracks live strings and objects in the plugin process. |
+// |
+// This object maintains its own object IDs that are used by the plugin. These |
+// IDs can be mapped to the renderer that created them, and that renderer's ID. |
+// This way, we can maintain multiple renderers each giving us objects, and the |
+// plugin can work with them using a uniform set of unique IDs. |
+// |
+// We maintain our own reference count for objects. a single ref in the |
+// renderer process whenever we have a nonzero refcount in the plugin process. |
+// This allows AddRef and Release to not initiate too much IPC chat. |
+// |
+// In addition to the local reference count, we also maintain "tracked objects" |
+// which are objects that the plugin is aware of, but doesn't hold a reference |
+// to. This will happen when the plugin is passed an object as an argument from |
+// the host (renderer) but where a reference is not passed. |
class PluginVarTracker { |
public: |
- // You must call Init() after creation to set up the correct interfaces. We |
- // do this to avoid having to depend on the dispatcher in the constructor, |
- // which is probably just being created from our constructor. |
- PluginVarTracker(PluginDispatcher* dispatcher); |
+ typedef int64_t VarID; |
- ~PluginVarTracker(); |
+ // This uses the PluginDispatcher to identify the source of vars so that |
+ // the proper messages can be sent back. However, since all we need is the |
+ // ability to send messages, we can always use the Sender base class of |
+ // Dispatcher in this class, which makes it easy to unit test. |
+ typedef IPC::Channel::Sender Sender; |
- // Must be called after construction. |
- void Init(); |
+ // Returns the global var tracker for the plugin object. |
+ static PluginVarTracker* GetInstance(); |
// Allocates a string and returns the ID of it. The refcount will be 1. |
- int64_t MakeString(const std::string& str); |
- int64_t MakeString(const char* str, uint32_t len); |
+ VarID MakeString(const std::string& str); |
+ VarID MakeString(const char* str, uint32_t len); |
// Returns the string associated with the given string var. The var must be |
// of type string and must be valid or this function will crash. |
- std::string GetString(const PP_Var& var) const; |
+ std::string GetString(const PP_Var& plugin_var) const; |
// Returns a pointer to the given string if it exists, or NULL if the var |
// isn't a string var. |
- const std::string* GetExistingString(const PP_Var& var) const; |
+ const std::string* GetExistingString(const PP_Var& plugin_var) const; |
- void AddRef(const PP_Var& var); |
- void Release(const PP_Var& var); |
+ void AddRef(const PP_Var& plugin_var); |
+ void Release(const PP_Var& plugin_var); |
// Manages tracking for receiving a VARTYPE_OBJECT from the remote side |
// (either the plugin or the renderer) that has already had its reference |
// count incremented on behalf of the caller. |
- void ReceiveObjectPassRef(const PP_Var& var); |
+ PP_Var ReceiveObjectPassRef(const PP_Var& var, Sender* channel); |
+ PP_Var TrackObjectWithNoReference(const PP_Var& host_var, |
+ Sender* channel); |
+ void StopTrackingObjectWithNoReference(const PP_Var& plugin_var); |
+ |
+ // Returns the host var for the corresponding plugin object var. The object |
+ // should be a VARTYPE_OBJECT |
+ PP_Var GetHostObject(const PP_Var& plugin_object) const; |
+ |
+ // Retrieves the internal reference counts for testing. Returns 0 if we |
+ // know about the object but the corresponding value is 0, or -1 if the |
+ // given object ID isn't in our map. |
+ int GetRefCountForObject(const PP_Var& plugin_object); |
+ int GetTrackedWithNoReferenceCountForObject(const PP_Var& plugin_object); |
+ |
private: |
+ friend struct DefaultSingletonTraits<PluginVarTracker>; |
+ |
+ // Represents a var as received from the host. |
+ struct HostVar { |
+ HostVar(Sender* s, int64_t i); |
+ |
+ bool operator<(const HostVar& other) const; |
+ |
+ // The host that sent us this object. This is used so we know how to send |
+ // back requests on this object. |
+ Sender* channel; |
+ |
+ // The object ID that the host generated to identify the object. This is |
+ // unique only within that host: different hosts could give us different |
+ // objects with the same ID. |
+ VarID host_object_id; |
+ }; |
+ |
+ // The information associated with a var object in the plugin. |
+ struct PluginVarInfo { |
+ PluginVarInfo(const HostVar& host_var); |
+ |
+ // Maps back to the original var in the host. |
+ HostVar host_var; |
+ |
+ // Explicit reference count. This value is affected by the renderer calling |
+ // AddRef and Release. A nonzero value here is represented by a single |
+ // reference in the host on our behalf (this reduces IPC traffic). |
+ int32_t ref_count; |
+ |
+ // Tracked object count (see class comment above). |
+ // |
+ // "TrackObjectWithNoReference" might be called recursively in rare cases. |
+ // For example, say the host calls a plugin function with an object as an |
+ // argument, and in response, the plugin calls a host function that then |
+ // calls another (or the same) plugin function with the same object. |
+ // |
+ // This value tracks the number of calls to TrackObjectWithNoReference so |
+ // we know when we can stop tracking this object. |
+ int32_t track_with_no_reference_count; |
+ }; |
+ |
+ typedef std::map<int64_t, PluginVarInfo> PluginVarInfoMap; |
+ |
+ PluginVarTracker(); |
+ ~PluginVarTracker(); |
+ |
// Sends an addref or release message to the browser for the given object ID. |
- void SendAddRefObjectMsg(int64_t id); |
- void SendReleaseObjectMsg(int64_t id); |
+ void SendAddRefObjectMsg(const HostVar& host_var); |
+ void SendReleaseObjectMsg(const HostVar& host_var); |
- PluginDispatcher* dispatcher_; |
+ PluginVarInfoMap::iterator FindOrMakePluginVarFromHostVar( |
+ const PP_Var& var, |
+ Sender* channel); |
- // Tracks object references to the reference count of that object on the |
- // plugin side. |
- typedef std::map<int64_t, int> ObjectRefCount; |
- ObjectRefCount object_ref_count_; |
+ // Checks the reference counds of the given plugin var info and removes the |
+ // tracking information if necessary. We're done with the object when its |
+ // explicit reference count and its "tracked with no reference" count both |
+ // reach zero. |
+ void DeletePluginVarInfoIfNecessary(PluginVarInfoMap::iterator iter); |
+ |
+ // Tracks all information about plugin vars. |
+ PluginVarInfoMap plugin_var_info_; |
+ |
+ // Maps host vars to plugin vars. This allows us to know if we've previously |
+ // seen a host var and re-use the information. |
+ typedef std::map<HostVar, VarID> HostVarToPluginVarMap; |
+ HostVarToPluginVarMap host_var_to_plugin_var_; |
+ |
+ // The last plugin object ID we've handed out. This must be unique for the |
+ // process. |
+ VarID last_plugin_object_id_; |
}; |
} // namespace proxy |