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
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
|
// 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 WEBKIT_PLUGINS_PPAPI_RESOURCE_TRACKER_H_
#define WEBKIT_PLUGINS_PPAPI_RESOURCE_TRACKER_H_
#include <map>
#include <set>
#include <utility>
#include "base/basictypes.h"
#include "base/gtest_prod_util.h"
#include "base/hash_tables.h"
#include "base/memory/ref_counted.h"
#include "ppapi/c/pp_instance.h"
#include "ppapi/c/pp_module.h"
#include "ppapi/c/pp_resource.h"
namespace webkit {
namespace ppapi {
class PluginInstance;
class PluginModule;
class Resource;
class ResourceTrackerTest;
class Var;
// This class maintains a global list of all live pepper resources. It allows
// us to check resource ID validity and to map them to a specific module.
//
// This object is NOT threadsafe.
class ResourceTracker {
public:
// Returns the pointer to the singleton object.
static ResourceTracker* Get();
// PP_Resources --------------------------------------------------------------
// The returned pointer will be NULL if there is no resource. Note that this
// return value is a scoped_refptr so that we ensure the resource is valid
// from the point of the lookup to the point that the calling code needs it.
// Otherwise, the plugin could Release() the resource on another thread and
// the object will get deleted out from under us.
scoped_refptr<Resource> GetResource(PP_Resource res) const;
// Increment resource's plugin refcount. See ResourceAndRefCount comments
// below.
bool AddRefResource(PP_Resource res);
bool UnrefResource(PP_Resource res);
// Returns the number of resources associated with this module.
uint32 GetLiveObjectsForInstance(PP_Instance instance) const;
// PP_Vars -------------------------------------------------------------------
scoped_refptr<Var> GetVar(int32 var_id) const;
bool AddRefVar(int32 var_id);
bool UnrefVar(int32 var_id);
// PP_Modules ----------------------------------------------------------------
// Adds a new plugin module to the list of tracked module, and returns a new
// module handle to identify it.
PP_Module AddModule(PluginModule* module);
// Called when a plugin modulde was deleted and should no longer be tracked.
// The given handle should be one generated by AddModule.
void ModuleDeleted(PP_Module module);
// Returns a pointer to the plugin modulde object associated with the given
// modulde handle. The return value will be NULL if the handle is invalid.
PluginModule* GetModule(PP_Module module);
// PP_Instances --------------------------------------------------------------
// Adds a new plugin instance to the list of tracked instances, and returns a
// new instance handle to identify it.
PP_Instance AddInstance(PluginInstance* instance);
// Called when a plugin instance was deleted and should no longer be tracked.
// The given handle should be one generated by AddInstance.
void InstanceDeleted(PP_Instance instance);
void InstanceCrashed(PP_Instance instance);
// Returns a pointer to the plugin instance object associated with the given
// instance handle. The return value will be NULL if the handle is invalid or
// if the instance has crashed.
PluginInstance* GetInstance(PP_Instance instance);
private:
friend class Resource;
friend class ResourceTrackerTest;
friend class Var;
typedef std::set<PP_Resource> ResourceSet;
// Indexed by the var ID.
typedef std::set<int32> VarSet;
// Per-instance data we track.
struct InstanceData;
// Prohibit creation other then by the Singleton class.
ResourceTracker();
~ResourceTracker();
// Adds the given resource to the tracker and assigns it a resource ID and
// refcount of 1. The assigned resource ID will be returned. Used only by the
// Resource class.
PP_Resource AddResource(Resource* resource);
// The same as AddResource but for Var, and returns the new Var ID.
int32 AddVar(Var* var);
// Force frees all vars and resources associated with the given instance.
// If delete_instance is true, the instance tracking information will also
// be deleted.
void CleanupInstanceData(PP_Instance instance, bool delete_instance);
// Overrides the singleton object. This is used for tests which want to
// specify their own tracker (otherwise, you can get cross-talk between
// tests since the data will live into the subsequent tests).
static void SetSingletonOverride(ResourceTracker* tracker);
static void ClearSingletonOverride();
// The lazy-initialized global instance of this object. This is created in
// ::Get() if there is no singleton_override_ specified.
//
// It would be nice to use LazyInstance for this since it manages the
// creation properly, and also cleans up on shutdown. However, the shutdown
// cleanup causes problems in some cases.
//
// For example, say the browser crashes or is killed. The renderer then
// decides to exit. Normally resources are bound to an instance and are
// cleaned up when WebKit deletes the instance (when you go to a different
// page or close that view). In this case, WebKit doesn't clean up. If the
// ResourceTracker was cleaned up by the AtExitManager (which would be the
// case with LazyInstance/Singleton) then we'd try to call up to the renderer
// layer via the delegate, which may be in a random state of shutdown.
//
// So effectively our rule is: any resources still around at shutdown are
// associated with leaked plugins in WebKit, so it's also OK to leak those
// resources from here (avoiding the shutdown race).
static ResourceTracker* global_tracker_;
// See SetSingletonOverride above.
static ResourceTracker* singleton_override_;
// Last assigned resource & var ID.
PP_Resource last_resource_id_;
int32 last_var_id_;
// For each PP_Resource, keep the Resource* (as refptr) and plugin use count.
// This use count is different then Resource's RefCount, and is manipulated
// using this RefResource/UnrefResource. When it drops to zero, we just remove
// the resource from this resource tracker, but the resource object will be
// alive so long as some scoped_refptr still holds it's reference. This
// prevents plugins from forcing destruction of Resource objects.
typedef std::pair<scoped_refptr<Resource>, size_t> ResourceAndRefCount;
typedef base::hash_map<PP_Resource, ResourceAndRefCount> ResourceMap;
ResourceMap live_resources_;
// Like ResourceAndRefCount but for vars, which are associated with modules.
typedef std::pair<scoped_refptr<Var>, size_t> VarAndRefCount;
typedef base::hash_map<int32, VarAndRefCount> VarMap;
VarMap live_vars_;
// Tracks all live instances and their associated data.
typedef std::map<PP_Instance, InstanceData> InstanceMap;
InstanceMap instance_map_;
// Tracks all live modules. The pointers are non-owning, the PluginModule
// destructor will notify us when the module is deleted.
typedef std::map<PP_Module, PluginModule*> ModuleMap;
ModuleMap module_map_;
DISALLOW_COPY_AND_ASSIGN(ResourceTracker);
};
} // namespace ppapi
} // namespace webkit
#endif // WEBKIT_PLUGINS_PPAPI_RESOURCE_TRACKER_H_
|