| Index: ppapi/host/ppapi_host.cc
|
| diff --git a/ppapi/host/ppapi_host.cc b/ppapi/host/ppapi_host.cc
|
| index 130bc875569dcd61fe1d318ea682f5db927431a6..f24eb01935f2cadede3a56f29a85c5e07c3000cf 100644
|
| --- a/ppapi/host/ppapi_host.cc
|
| +++ b/ppapi/host/ppapi_host.cc
|
| @@ -44,6 +44,9 @@ PpapiHost::~PpapiHost() {
|
| // The resources may also want to use us in their destructors.
|
| resources_.clear();
|
| pending_resource_hosts_.clear();
|
| + // At this point, all hosts should have Unpinned anything they depend on in
|
| + // their destructors, so this map should be empty.
|
| + DCHECK(owner_to_owned_map_.empty()) << "A ResourceHost forgot to Unpin";
|
| }
|
|
|
| bool PpapiHost::Send(IPC::Message* msg) {
|
| @@ -164,6 +167,35 @@ void PpapiHost::AddInstanceMessageFilter(
|
| instance_message_filters_.push_back(filter.release());
|
| }
|
|
|
| +ResourceHost* PpapiHost::GetResourceHost(PP_Resource resource) const {
|
| + ResourceMap::const_iterator found = resources_.find(resource);
|
| + return found == resources_.end() ? NULL : found->second.get();
|
| +}
|
| +
|
| +void PpapiHost::PinHost(ResourceHost* owner_host, ResourceHost* owned_host) {
|
| + // Only allow a ResourceHost to be "owned" or be an "owner", but not both.
|
| + // This prevents graphs that are >1 level deep and also prevents cycles.
|
| + DCHECK(owner_to_owned_map_.count(owned_host) == 0)
|
| + << "A ResourceHost is not allowed to own and also be owned.";
|
| + linked_ptr<ResourceHost> owned_linked_ptr = RawToLinkedPtr(owned_host);
|
| + DCHECK(owned_linked_ptr.get());
|
| + DCHECK(owner_to_owned_map_[owner_host].count(owned_linked_ptr) == 0);
|
| + owner_to_owned_map_[owner_host][owned_linked_ptr]++;
|
| +}
|
| +
|
| +void PpapiHost::UnpinHost(ResourceHost* owner_host, ResourceHost* owned_host) {
|
| + OwnerToOwnedHostMap::iterator iter = owner_to_owned_map_.find(owner_host);
|
| + DCHECK(iter != owner_to_owned_map_.end());
|
| + if (iter != owner_to_owned_map_.end()) {
|
| + linked_ptr<ResourceHost> owned_linked_ptr = RawToLinkedPtr(owned_host);
|
| + PinCountMap::iterator count_iter = iter->second.find(owned_linked_ptr);
|
| + if (--count_iter->second == 0)
|
| + iter->second.erase(count_iter);
|
| + if (iter->second.empty())
|
| + owner_to_owned_map_.erase(iter);
|
| + }
|
| +}
|
| +
|
| void PpapiHost::OnHostMsgResourceCall(
|
| const proxy::ResourceMessageCallParams& params,
|
| const IPC::Message& nested_msg) {
|
| @@ -276,9 +308,22 @@ void PpapiHost::OnHostMsgResourceDestroyed(PP_Resource resource) {
|
| resources_.erase(found);
|
| }
|
|
|
| -ResourceHost* PpapiHost::GetResourceHost(PP_Resource resource) const {
|
| - ResourceMap::const_iterator found = resources_.find(resource);
|
| - return found == resources_.end() ? NULL : found->second.get();
|
| +linked_ptr<ResourceHost> PpapiHost::RawToLinkedPtr(ResourceHost* host) {
|
| + if (host->pp_resource()) {
|
| + // If it has a valid PP_Resource, it's not "pending" and therefore should
|
| + // be in resources_.
|
| + DCHECK(resources_.count(host->pp_resource()));
|
| + return resources_[host->pp_resource()];
|
| + } else {
|
| + // It's a pending host. This map should be small, so a linear search is OK.
|
| + PendingHostResourceMap::iterator iter = pending_resource_hosts_.begin();
|
| + for (; iter != pending_resource_hosts_.end(); ++iter) {
|
| + if (host == iter->second.get())
|
| + return iter->second;
|
| + }
|
| + }
|
| + NOTREACHED();
|
| + return linked_ptr<ResourceHost>();
|
| }
|
|
|
| } // namespace host
|
|
|