OLD | NEW |
---|---|
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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/singleton.h" | 8 #include "base/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" | 11 #include "ppapi/proxy/plugin_resource.h" |
12 #include "ppapi/proxy/serialized_var.h" | 12 #include "ppapi/proxy/serialized_var.h" |
13 | 13 |
14 namespace pp { | 14 namespace pp { |
15 namespace proxy { | 15 namespace proxy { |
16 | 16 |
17 namespace { | |
18 | |
19 // When non-NULL, this object overrides the ResourceTrackerSingleton. | |
20 PluginResourceTracker* resource_tracker_override = NULL; | |
viettrungluu
2011/01/27 16:52:58
Shouldn't its name be "g_..."?
| |
21 | |
22 } // namespace | |
23 | |
17 PluginResourceTracker::ResourceInfo::ResourceInfo() : ref_count(0) { | 24 PluginResourceTracker::ResourceInfo::ResourceInfo() : ref_count(0) { |
18 } | 25 } |
19 | 26 |
20 PluginResourceTracker::ResourceInfo::ResourceInfo(int rc, | 27 PluginResourceTracker::ResourceInfo::ResourceInfo(int rc, |
21 linked_ptr<PluginResource> r) | 28 linked_ptr<PluginResource> r) |
22 : ref_count(rc), | 29 : ref_count(rc), |
23 resource(r) { | 30 resource(r) { |
24 } | 31 } |
25 | 32 |
26 PluginResourceTracker::ResourceInfo::ResourceInfo(const ResourceInfo& other) | 33 PluginResourceTracker::ResourceInfo::ResourceInfo(const ResourceInfo& other) |
27 : ref_count(other.ref_count), | 34 : ref_count(other.ref_count), |
28 resource(other.resource) { | 35 resource(other.resource) { |
29 } | 36 } |
30 | 37 |
31 PluginResourceTracker::ResourceInfo::~ResourceInfo() { | 38 PluginResourceTracker::ResourceInfo::~ResourceInfo() { |
32 } | 39 } |
33 | 40 |
34 PluginResourceTracker::ResourceInfo& | 41 PluginResourceTracker::ResourceInfo& |
35 PluginResourceTracker::ResourceInfo::operator=( | 42 PluginResourceTracker::ResourceInfo::operator=( |
36 const ResourceInfo& other) { | 43 const ResourceInfo& other) { |
37 ref_count = other.ref_count; | 44 ref_count = other.ref_count; |
38 resource = other.resource; | 45 resource = other.resource; |
39 return *this; | 46 return *this; |
40 } | 47 } |
41 | 48 |
42 PluginResourceTracker::PluginResourceTracker() { | 49 // Start counting resources at a high number to avoid collisions with vars (to |
50 // help debugging). | |
51 PluginResourceTracker::PluginResourceTracker() | |
52 : last_resource_id_(0x00100000) { | |
43 } | 53 } |
44 | 54 |
45 PluginResourceTracker::~PluginResourceTracker() { | 55 PluginResourceTracker::~PluginResourceTracker() { |
46 } | 56 } |
47 | 57 |
48 // static | 58 // static |
59 void PluginResourceTracker::SetInstanceForTest(PluginResourceTracker* tracker) { | |
60 resource_tracker_override = tracker; | |
61 } | |
62 | |
63 // static | |
49 PluginResourceTracker* PluginResourceTracker::GetInstance() { | 64 PluginResourceTracker* PluginResourceTracker::GetInstance() { |
65 if (resource_tracker_override) | |
66 return resource_tracker_override; | |
50 return Singleton<PluginResourceTracker>::get(); | 67 return Singleton<PluginResourceTracker>::get(); |
51 } | 68 } |
52 | 69 |
53 PluginResource* PluginResourceTracker::GetResourceObject( | 70 PluginResource* PluginResourceTracker::GetResourceObject( |
54 PP_Resource pp_resource) { | 71 PP_Resource pp_resource) { |
55 ResourceMap::iterator found = resource_map_.find(pp_resource); | 72 ResourceMap::iterator found = resource_map_.find(pp_resource); |
56 if (found == resource_map_.end()) | 73 if (found == resource_map_.end()) |
57 return NULL; | 74 return NULL; |
58 return found->second.resource.get(); | 75 return found->second.resource.get(); |
59 } | 76 } |
60 | 77 |
61 void PluginResourceTracker::AddResource(PP_Resource pp_resource, | 78 PP_Resource PluginResourceTracker::AddResource( |
62 linked_ptr<PluginResource> object) { | 79 linked_ptr<PluginResource> object) { |
63 DCHECK(resource_map_.find(pp_resource) == resource_map_.end()); | 80 if (object->host_resource().is_null()) { |
64 resource_map_[pp_resource] = ResourceInfo(1, object); | 81 // Prevent adding null resources or GetResourceObject(0) will return a |
82 // valid pointer! | |
83 NOTREACHED(); | |
84 return 0; | |
85 } | |
86 | |
87 PP_Resource plugin_resource = ++last_resource_id_; | |
88 DCHECK(resource_map_.find(plugin_resource) == resource_map_.end()); | |
89 resource_map_[plugin_resource] = ResourceInfo(1, object); | |
90 host_resource_map_[HostResource(object->instance(), | |
91 object->host_resource().host_resource())] = | |
92 plugin_resource; | |
93 return plugin_resource; | |
65 } | 94 } |
66 | 95 |
67 void PluginResourceTracker::AddRefResource(PP_Resource resource) { | 96 void PluginResourceTracker::AddRefResource(PP_Resource resource) { |
68 resource_map_[resource].ref_count++; | 97 ResourceMap::iterator found = resource_map_.find(resource); |
98 if (found == resource_map_.end()) { | |
99 NOTREACHED(); | |
100 return; | |
101 } | |
102 found->second.ref_count++; | |
69 } | 103 } |
70 | 104 |
71 void PluginResourceTracker::ReleaseResource(PP_Resource resource) { | 105 void PluginResourceTracker::ReleaseResource(PP_Resource resource) { |
72 ReleasePluginResourceRef(resource, true); | 106 ReleasePluginResourceRef(resource, true); |
73 } | 107 } |
74 | 108 |
75 bool PluginResourceTracker::PreparePreviouslyTrackedResource( | 109 PP_Resource PluginResourceTracker::PluginResourceForHostResource( |
76 PP_Resource resource) { | 110 PP_Instance instance, |
77 ResourceMap::iterator found = resource_map_.find(resource); | 111 SerializedResource resource) const { |
78 if (found == resource_map_.end()) | 112 HostResourceMap::const_iterator found = host_resource_map_.find( |
79 return false; // We've not seen this resource before. | 113 HostResource(instance, resource.host_resource())); |
80 | 114 if (found == host_resource_map_.end()) |
81 // We have already seen this resource and the caller wants the plugin to | 115 return 0; |
82 // have one more ref to the object (this function is called when retuning | 116 return found->second; |
83 // a resource). | |
84 // | |
85 // This is like the PluginVarTracker::ReceiveObjectPassRef. We do an AddRef | |
86 // in the plugin for the additional ref, and then a Release in the renderer | |
87 // because the code in the renderer addrefed on behalf of the caller. | |
88 found->second.ref_count++; | |
89 | |
90 SendReleaseResourceToHost(resource, found->second.resource.get()); | |
91 return true; | |
92 } | 117 } |
93 | 118 |
94 void PluginResourceTracker::ReleasePluginResourceRef( | 119 void PluginResourceTracker::ReleasePluginResourceRef( |
95 const PP_Resource& resource, | 120 const PP_Resource& resource, |
96 bool notify_browser_on_release) { | 121 bool notify_browser_on_release) { |
97 ResourceMap::iterator found = resource_map_.find(resource); | 122 ResourceMap::iterator found = resource_map_.find(resource); |
98 if (found == resource_map_.end()) | 123 if (found == resource_map_.end()) |
99 return; | 124 return; |
100 found->second.ref_count--; | 125 found->second.ref_count--; |
101 if (found->second.ref_count == 0) { | 126 if (found->second.ref_count == 0) { |
127 PluginResource* plugin_resource = found->second.resource.get(); | |
102 if (notify_browser_on_release) | 128 if (notify_browser_on_release) |
103 SendReleaseResourceToHost(resource, found->second.resource.get()); | 129 SendReleaseResourceToHost(resource, plugin_resource); |
130 host_resource_map_.erase( | |
131 HostResource(plugin_resource->instance(), | |
132 plugin_resource->host_resource().host_resource())); | |
104 resource_map_.erase(found); | 133 resource_map_.erase(found); |
105 } | 134 } |
106 } | 135 } |
107 | 136 |
108 void PluginResourceTracker::SendReleaseResourceToHost( | 137 void PluginResourceTracker::SendReleaseResourceToHost( |
109 PP_Resource resource_id, | 138 PP_Resource resource_id, |
110 PluginResource* resource) { | 139 PluginResource* resource) { |
111 PluginDispatcher* dispatcher = | 140 PluginDispatcher* dispatcher = |
112 PluginDispatcher::GetForInstance(resource->instance()); | 141 PluginDispatcher::GetForInstance(resource->instance()); |
113 if (dispatcher) { | 142 if (dispatcher) { |
114 dispatcher->Send(new PpapiHostMsg_PPBCore_ReleaseResource( | 143 dispatcher->Send(new PpapiHostMsg_PPBCore_ReleaseResource( |
115 INTERFACE_ID_PPB_CORE, resource_id)); | 144 INTERFACE_ID_PPB_CORE, resource->host_resource())); |
116 } else { | 145 } else { |
117 NOTREACHED(); | 146 NOTREACHED(); |
118 } | 147 } |
119 } | 148 } |
120 | 149 |
121 } // namespace proxy | 150 } // namespace proxy |
122 } // namespace pp | 151 } // namespace pp |
OLD | NEW |