| // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef PPAPI_PROXY_PLUGIN_VAR_TRACKER_H_ |
| #define PPAPI_PROXY_PLUGIN_VAR_TRACKER_H_ |
| |
| #include <map> |
| #include <string> |
| |
| #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. |
| // |
| // 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: |
| typedef int64_t VarID; |
| |
| // Called by tests that want to specify a specific VarTracker. This allows |
| // them to use a unique one each time and avoids singletons sticking around |
| // across tests. |
| static void SetInstanceForTest(PluginVarTracker* tracker); |
| |
| // 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. |
| 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& 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& plugin_var) const; |
| |
| 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. |
| PP_Var ReceiveObjectPassRef(const PP_Var& var, PluginDispatcher* dispatcher); |
| |
| PP_Var TrackObjectWithNoReference(const PP_Var& host_var, |
| PluginDispatcher* dispatcher); |
| 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; |
| |
| PluginDispatcher* DispatcherForPluginObject( |
| const PP_Var& plugin_object) const; |
| |
| // Like Release() but the var is identified by its host object ID (as |
| // returned by GetHostObject). |
| void ReleaseHostObject(PluginDispatcher* dispatcher, |
| const PP_Var& host_object); |
| |
| // 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>; |
| friend class PluginProxyTest; |
| |
| // Represents a var as received from the host. |
| struct HostVar { |
| HostVar(PluginDispatcher* d, int64_t i); |
| |
| bool operator<(const HostVar& other) const; |
| |
| // The dispatcher that sent us this object. This is used so we know how to |
| // send back requests on this object. |
| PluginDispatcher* dispatcher; |
| |
| // 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(const HostVar& host_var); |
| void SendReleaseObjectMsg(const HostVar& host_var); |
| |
| PluginVarInfoMap::iterator FindOrMakePluginVarFromHostVar( |
| const PP_Var& var, |
| PluginDispatcher* dispatcher); |
| |
| // 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 |
| } // namespace pp |
| |
| #endif // PPAPI_PROXY_PLUGIN_VAR_TRACKER_H_ |