OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ppapi/proxy/plugin_resource_tracker.h" | 5 #include "ppapi/proxy/plugin_resource_tracker.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "base/memory/singleton.h" | 8 #include "base/memory/singleton.h" |
9 #include "ppapi/proxy/plugin_dispatcher.h" | 9 #include "ppapi/proxy/plugin_dispatcher.h" |
10 #include "ppapi/proxy/ppapi_messages.h" | 10 #include "ppapi/proxy/ppapi_messages.h" |
11 #include "ppapi/proxy/plugin_resource.h" | |
12 #include "ppapi/proxy/serialized_var.h" | 11 #include "ppapi/proxy/serialized_var.h" |
| 12 #include "ppapi/shared_impl/resource.h" |
13 #include "ppapi/shared_impl/tracker_base.h" | 13 #include "ppapi/shared_impl/tracker_base.h" |
14 #include "ppapi/shared_impl/var.h" | 14 #include "ppapi/shared_impl/var.h" |
15 | 15 |
16 using ppapi::HostResource; | 16 using ppapi::HostResource; |
| 17 using ppapi::Resource; |
17 | 18 |
18 namespace pp { | 19 namespace pp { |
19 namespace proxy { | 20 namespace proxy { |
20 | 21 |
21 namespace { | 22 namespace { |
22 | 23 |
23 // When non-NULL, this object overrides the ResourceTrackerSingleton. | 24 // When non-NULL, this object overrides the ResourceTrackerSingleton. |
24 PluginResourceTracker* g_resource_tracker_override = NULL; | 25 PluginResourceTracker* g_resource_tracker_override = NULL; |
25 | 26 |
26 ::ppapi::TrackerBase* GetTrackerBase() { | 27 ::ppapi::TrackerBase* GetTrackerBase() { |
27 return PluginResourceTracker::GetInstance(); | 28 return PluginResourceTracker::GetInstance(); |
28 } | 29 } |
29 | 30 |
30 } // namespace | 31 } // namespace |
31 | 32 |
32 PluginResourceTracker::ResourceInfo::ResourceInfo() : ref_count(0) { | |
33 } | |
34 | |
35 PluginResourceTracker::ResourceInfo::ResourceInfo(int rc, PluginResource* r) | |
36 : ref_count(rc), | |
37 resource(r) { | |
38 } | |
39 | |
40 PluginResourceTracker::ResourceInfo::ResourceInfo(const ResourceInfo& other) | |
41 : ref_count(other.ref_count), | |
42 resource(other.resource) { | |
43 // Wire up the new shared resource tracker base to use our implementation. | |
44 ::ppapi::TrackerBase::Init(&GetTrackerBase); | |
45 } | |
46 | |
47 PluginResourceTracker::ResourceInfo::~ResourceInfo() { | |
48 } | |
49 | |
50 PluginResourceTracker::ResourceInfo& | |
51 PluginResourceTracker::ResourceInfo::operator=( | |
52 const ResourceInfo& other) { | |
53 ref_count = other.ref_count; | |
54 resource = other.resource; | |
55 return *this; | |
56 } | |
57 | |
58 // Start counting resources at a high number to avoid collisions with vars (to | |
59 // help debugging). | |
60 PluginResourceTracker::PluginResourceTracker() | 33 PluginResourceTracker::PluginResourceTracker() |
61 : var_tracker_test_override_(NULL), | 34 : var_tracker_test_override_(NULL) { |
62 last_resource_id_(0x00100000) { | |
63 } | 35 } |
64 | 36 |
65 PluginResourceTracker::~PluginResourceTracker() { | 37 PluginResourceTracker::~PluginResourceTracker() { |
66 } | 38 } |
67 | 39 |
68 // static | 40 // static |
69 void PluginResourceTracker::SetInstanceForTest(PluginResourceTracker* tracker) { | 41 void PluginResourceTracker::SetInstanceForTest(PluginResourceTracker* tracker) { |
70 g_resource_tracker_override = tracker; | 42 g_resource_tracker_override = tracker; |
71 } | 43 } |
72 | 44 |
73 // static | 45 // static |
74 PluginResourceTracker* PluginResourceTracker::GetInstance() { | 46 PluginResourceTracker* PluginResourceTracker::GetInstance() { |
75 if (g_resource_tracker_override) | 47 if (g_resource_tracker_override) |
76 return g_resource_tracker_override; | 48 return g_resource_tracker_override; |
77 return Singleton<PluginResourceTracker>::get(); | 49 return Singleton<PluginResourceTracker>::get(); |
78 } | 50 } |
79 | 51 |
80 // static | 52 // static |
81 ::ppapi::TrackerBase* | 53 ::ppapi::TrackerBase* |
82 PluginResourceTracker::GetTrackerBaseInstance() { | 54 PluginResourceTracker::GetTrackerBaseInstance() { |
83 return GetInstance(); | 55 return GetInstance(); |
84 } | 56 } |
85 | 57 |
86 PluginResource* PluginResourceTracker::GetResourceObject( | |
87 PP_Resource pp_resource) { | |
88 ResourceMap::iterator found = resource_map_.find(pp_resource); | |
89 if (found == resource_map_.end()) | |
90 return NULL; | |
91 return found->second.resource.get(); | |
92 } | |
93 | |
94 PP_Resource PluginResourceTracker::AddResource(PluginResource* object) { | |
95 PP_Resource plugin_resource = ++last_resource_id_; | |
96 DCHECK(resource_map_.find(plugin_resource) == resource_map_.end()); | |
97 resource_map_[plugin_resource] = ResourceInfo(1, object); | |
98 if (!object->host_resource().is_null()) { | |
99 // The host resource ID will be 0 for resources that only exist in the | |
100 // plugin process. Don't add those to the list. | |
101 host_resource_map_[object->host_resource()] = plugin_resource; | |
102 } | |
103 return plugin_resource; | |
104 } | |
105 | |
106 void PluginResourceTracker::AddRefResource(PP_Resource resource) { | |
107 ResourceMap::iterator found = resource_map_.find(resource); | |
108 if (found == resource_map_.end()) { | |
109 NOTREACHED(); | |
110 return; | |
111 } | |
112 found->second.ref_count++; | |
113 } | |
114 | |
115 void PluginResourceTracker::ReleaseResource(PP_Resource resource) { | |
116 ReleasePluginResourceRef(resource, true); | |
117 } | |
118 | |
119 PP_Resource PluginResourceTracker::PluginResourceForHostResource( | 58 PP_Resource PluginResourceTracker::PluginResourceForHostResource( |
120 const HostResource& resource) const { | 59 const HostResource& resource) const { |
121 HostResourceMap::const_iterator found = host_resource_map_.find(resource); | 60 HostResourceMap::const_iterator found = host_resource_map_.find(resource); |
122 if (found == host_resource_map_.end()) | 61 if (found == host_resource_map_.end()) |
123 return 0; | 62 return 0; |
124 return found->second; | 63 return found->second; |
125 } | 64 } |
126 | 65 |
127 ::ppapi::ResourceObjectBase* PluginResourceTracker::GetResourceAPI( | |
128 PP_Resource res) { | |
129 ResourceMap::iterator found = resource_map_.find(res); | |
130 if (found == resource_map_.end()) | |
131 return NULL; | |
132 return found->second.resource.get(); | |
133 } | |
134 | |
135 ::ppapi::FunctionGroupBase* PluginResourceTracker::GetFunctionAPI( | 66 ::ppapi::FunctionGroupBase* PluginResourceTracker::GetFunctionAPI( |
136 PP_Instance inst, | 67 PP_Instance inst, |
137 pp::proxy::InterfaceID id) { | 68 pp::proxy::InterfaceID id) { |
138 PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(inst); | 69 PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(inst); |
139 if (dispatcher) | 70 if (dispatcher) |
140 return dispatcher->GetFunctionAPI(id); | 71 return dispatcher->GetFunctionAPI(id); |
141 return NULL; | 72 return NULL; |
142 } | 73 } |
143 | 74 |
144 PP_Instance PluginResourceTracker::GetInstanceForResource( | |
145 PP_Resource resource) { | |
146 ResourceMap::iterator found = resource_map_.find(resource); | |
147 if (found == resource_map_.end()) | |
148 return 0; | |
149 return found->second.resource->instance(); | |
150 } | |
151 | |
152 ppapi::VarTracker* PluginResourceTracker::GetVarTracker() { | 75 ppapi::VarTracker* PluginResourceTracker::GetVarTracker() { |
153 return &var_tracker(); | 76 return &var_tracker(); |
154 } | 77 } |
155 | 78 |
156 void PluginResourceTracker::ReleasePluginResourceRef( | 79 ppapi::ResourceTracker* PluginResourceTracker::GetResourceTracker() { |
157 const PP_Resource& resource, | 80 return this; |
158 bool notify_browser_on_release) { | 81 } |
159 ResourceMap::iterator found = resource_map_.find(resource); | 82 |
160 if (found == resource_map_.end()) | 83 PP_Resource PluginResourceTracker::AddResource(Resource* object) { |
161 return; | 84 PP_Resource ret = ResourceTracker::AddResource(object); |
162 found->second.ref_count--; | 85 |
163 if (found->second.ref_count == 0) { | 86 // Some resources are plugin-only, so they don't have a host resource. |
164 // Keep a reference while removing in case the destructor ends up | 87 if (object->host_resource().host_resource()) |
165 // re-entering. That way, when the destructor is called, it's out of the | 88 host_resource_map_.insert(std::make_pair(object->host_resource(), ret)); |
166 // maps. | 89 return ret; |
167 scoped_refptr<PluginResource> plugin_resource = found->second.resource; | 90 } |
| 91 |
| 92 void PluginResourceTracker::RemoveResource(Resource* object) { |
| 93 ResourceTracker::RemoveResource(object); |
| 94 |
| 95 if (!object->host_resource().is_null()) { |
| 96 // The host_resource will be NULL for proxy-only resources, which we |
| 97 // obviously don't need to tell the host about. |
| 98 DCHECK(host_resource_map_.find(object->host_resource()) != |
| 99 host_resource_map_.end()); |
| 100 host_resource_map_.erase(object->host_resource()); |
| 101 |
168 PluginDispatcher* dispatcher = | 102 PluginDispatcher* dispatcher = |
169 PluginDispatcher::GetForInstance(plugin_resource->instance()); | 103 PluginDispatcher::GetForInstance(object->pp_instance()); |
170 HostResource host_resource = plugin_resource->host_resource(); | 104 if (dispatcher) { |
171 if (!host_resource.is_null()) | 105 // The dispatcher can be NULL if the plugin held on to a resource after |
172 host_resource_map_.erase(host_resource); | 106 // the instance was destroyed. In that case the browser-side resource has |
173 resource_map_.erase(found); | 107 // already been freed correctly on the browser side. |
174 plugin_resource = NULL; | |
175 | |
176 // dispatcher can be NULL if the plugin held on to a resource after the | |
177 // instance was destroyed. In that case the browser-side resource has | |
178 // already been freed correctly on the browser side. The host_resource | |
179 // will be NULL for proxy-only resources, which we obviously don't need to | |
180 // tell the host about. | |
181 if (notify_browser_on_release && dispatcher && !host_resource.is_null()) { | |
182 dispatcher->Send(new PpapiHostMsg_PPBCore_ReleaseResource( | 108 dispatcher->Send(new PpapiHostMsg_PPBCore_ReleaseResource( |
183 INTERFACE_ID_PPB_CORE, host_resource)); | 109 INTERFACE_ID_PPB_CORE, object->host_resource())); |
184 } | 110 } |
185 } | 111 } |
186 } | 112 } |
187 | 113 |
188 } // namespace proxy | 114 } // namespace proxy |
189 } // namespace pp | 115 } // namespace pp |
OLD | NEW |