summaryrefslogtreecommitdiffstats
path: root/ppapi/proxy/plugin_var_tracker.h
diff options
context:
space:
mode:
Diffstat (limited to 'ppapi/proxy/plugin_var_tracker.h')
-rw-r--r--ppapi/proxy/plugin_var_tracker.h196
1 files changed, 196 insertions, 0 deletions
diff --git a/ppapi/proxy/plugin_var_tracker.h b/ppapi/proxy/plugin_var_tracker.h
new file mode 100644
index 0000000..748ec2d
--- /dev/null
+++ b/ppapi/proxy/plugin_var_tracker.h
@@ -0,0 +1,196 @@
+// Copyright (c) 2011 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 "base/memory/ref_counted.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.
+//
+// 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 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 PluginProxyTestHarness;
+
+ class RefCountedString : public base::RefCounted<RefCountedString> {
+ public:
+ RefCountedString() {
+ }
+ RefCountedString(const std::string& str) : value_(str) {
+ }
+ RefCountedString(const char* data, size_t len)
+ : value_(data, len) {
+ }
+
+ const std::string& value() const { return value_; }
+
+ private:
+ std::string value_;
+
+ // Ensure only base::RefCounted can delete a RefCountedString.
+ friend void base::RefCounted<RefCountedString>::Release() const;
+ virtual ~RefCountedString() {}
+ };
+ typedef scoped_refptr<RefCountedString> RefCountedStringPtr;
+
+ // 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_;
+
+ // Maps plugin var IDs to ref counted strings.
+ typedef std::map<VarID, RefCountedStringPtr> VarIDStringMap;
+ VarIDStringMap var_id_to_string_;
+
+ // The last plugin PP_Var ID we've handed out. This must be unique for the
+ // process.
+ VarID last_plugin_var_id_;
+
+ // Get a new Var ID and increment last_plugin_var_id_.
+ VarID GetNewVarID();
+};
+
+} // namespace proxy
+} // namespace pp
+
+#endif // PPAPI_PROXY_PLUGIN_VAR_TRACKER_H_