Chromium Code Reviews| 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 |