blob: 24f68185d63e33f57a3605dddf04f998c6384071 [file] [log] [blame]
// 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_