summaryrefslogtreecommitdiffstats
path: root/ppapi/proxy/plugin_var_tracker.h
blob: 24f68185d63e33f57a3605dddf04f998c6384071 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
// 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_