15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/shared_impl/resource_tracker.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h" 99ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/shared_impl/callback_tracker.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/shared_impl/id_assignment.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/shared_impl/ppapi_globals.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ppapi/shared_impl/proxy_lock.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/shared_impl/resource.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ppapi { 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)ResourceTracker::ResourceTracker(ThreadMode thread_mode) 19a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) : last_resource_value_(0), weak_ptr_factory_(this) { 20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (thread_mode == SINGLE_THREADED) 21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) thread_checker_.reset(new base::ThreadChecker); 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)ResourceTracker::~ResourceTracker() {} 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ResourceTracker::CheckThreadingPreconditions() const { 27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(!thread_checker_ || thread_checker_->CalledOnValidThread()); 28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#ifndef NDEBUG 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ProxyLock::AssertAcquired(); 30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif 31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)Resource* ResourceTracker::GetResource(PP_Resource res) const { 34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CheckThreadingPreconditions(); 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ResourceMap::const_iterator i = live_resources_.find(res); 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i == live_resources_.end()) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return i->second.first; 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceTracker::AddRefResource(PP_Resource res) { 42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CheckThreadingPreconditions(); 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DLOG_IF(ERROR, !CheckIdType(res, PP_ID_TYPE_RESOURCE)) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << res << " is not a PP_Resource."; 453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DCHECK(CanOperateOnResource(res)); 473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ResourceMap::iterator i = live_resources_.find(res); 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i == live_resources_.end()) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Prevent overflow of refcount. 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i->second.second == 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::numeric_limits<ResourceAndRefCount::second_type>::max()) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // When we go from 0 to 1 plugin ref count, keep an additional "real" ref 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // on its behalf. 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i->second.second == 0) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i->second.first->AddRef(); 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i->second.second++; 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceTracker::ReleaseResource(PP_Resource res) { 67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CheckThreadingPreconditions(); 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DLOG_IF(ERROR, !CheckIdType(res, PP_ID_TYPE_RESOURCE)) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << res << " is not a PP_Resource."; 703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DCHECK(CanOperateOnResource(res)); 723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ResourceMap::iterator i = live_resources_.find(res); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i == live_resources_.end()) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Prevent underflow of refcount. 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i->second.second == 0) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i->second.second--; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i->second.second == 0) { 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LastPluginRefWasDeleted(i->second.first); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // When we go from 1 to 0 plugin ref count, free the additional "real" ref 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // on its behalf. THIS WILL MOST LIKELY RELEASE THE OBJECT AND REMOVE IT 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // FROM OUR LIST. 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i->second.first->Release(); 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceTracker::ReleaseResourceSoon(PP_Resource res) { 93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::current()->PostNonNestableTask( 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RunWhileLocked(base::Bind(&ResourceTracker::ReleaseResource, 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) weak_ptr_factory_.GetWeakPtr(), 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) res))); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceTracker::DidCreateInstance(PP_Instance instance) { 101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CheckThreadingPreconditions(); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Due to the infrastructure of some tests, the instance is registered 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // twice in a few cases. It would be nice not to do that and assert here 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // instead. 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (instance_map_.find(instance) != instance_map_.end()) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) instance_map_[instance] = linked_ptr<InstanceData>(new InstanceData); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceTracker::DidDeleteInstance(PP_Instance instance) { 111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CheckThreadingPreconditions(); 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InstanceMap::iterator found_instance = instance_map_.find(instance); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Due to the infrastructure of some tests, the instance is unregistered 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // twice in a few cases. It would be nice not to do that and assert here 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // instead. 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (found_instance == instance_map_.end()) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InstanceData& data = *found_instance->second; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Force release all plugin references to resources associated with the 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // deleted instance. Make a copy since as we iterate through them, each one 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // will remove itself from the tracking info individually. 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ResourceSet to_delete = data.resources; 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ResourceSet::iterator cur = to_delete.begin(); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (cur != to_delete.end()) { 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note that it's remotely possible for the object to already be deleted 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // from the live resources. One case is if a resource object is holding 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the last ref to another. When we release the first one, it will release 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the second one. So the second one will be gone when we eventually get 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to it. 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ResourceMap::iterator found_resource = live_resources_.find(*cur); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (found_resource != live_resources_.end()) { 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Resource* resource = found_resource->second.first; 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (found_resource->second.second > 0) { 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LastPluginRefWasDeleted(resource); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) found_resource->second.second = 0; 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This will most likely delete the resource object and remove it 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // from the live_resources_ list. 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) resource->Release(); 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cur++; 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // In general the above pass will delete all the resources and there won't 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // be any left in the map. However, if parts of the implementation are still 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // holding on to internal refs, we need to tell them that the instance is 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // gone. 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) to_delete = data.resources; 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cur = to_delete.begin(); 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (cur != to_delete.end()) { 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ResourceMap::iterator found_resource = live_resources_.find(*cur); 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (found_resource != live_resources_.end()) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) found_resource->second.first->NotifyInstanceWasDeleted(); 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cur++; 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) instance_map_.erase(instance); 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int ResourceTracker::GetLiveObjectsForInstance(PP_Instance instance) const { 166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CheckThreadingPreconditions(); 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InstanceMap::const_iterator found = instance_map_.find(instance); 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (found == instance_map_.end()) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return static_cast<int>(found->second->resources.size()); 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void ResourceTracker::UseOddResourceValueInDebugMode() { 1743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#if !defined(NDEBUG) 1753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DCHECK_EQ(0, last_resource_value_); 1763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) ++last_resource_value_; 1783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#endif 1793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 1803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PP_Resource ResourceTracker::AddResource(Resource* object) { 182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CheckThreadingPreconditions(); 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the plugin manages to create too many resources, don't do crazy stuff. 1843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (last_resource_value_ >= kMaxPPId) 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Allocate an ID. Note there's a rare error condition below that means we 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // could end up not using |new_id|, but that's harmless. 1893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) PP_Resource new_id = MakeTypedId(GetNextResourceValue(), PP_ID_TYPE_RESOURCE); 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Some objects have a 0 instance, meaning they aren't associated with any 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // instance, so they won't be in |instance_map_|. This is (as of this writing) 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // only true of the PPB_MessageLoop resource for the main thread. 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (object->pp_instance()) { 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InstanceMap::iterator found = instance_map_.find(object->pp_instance()); 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (found == instance_map_.end()) { 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If you hit this, it's likely somebody forgot to call DidCreateInstance, 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the resource was created with an invalid PP_Instance, or the renderer 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // side tried to create a resource for a plugin that crashed/exited. This 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // could happen for OOP plugins where due to reentrancies in context of 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // outgoing sync calls the renderer can send events after a plugin has 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // exited. 203a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) VLOG(1) << "Failed to find plugin instance in instance map"; 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) found->second->resources.insert(new_id); 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) live_resources_[new_id] = ResourceAndRefCount(object, 0); 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return new_id; 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceTracker::RemoveResource(Resource* object) { 214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CheckThreadingPreconditions(); 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PP_Resource pp_resource = object->pp_resource(); 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InstanceMap::iterator found = instance_map_.find(object->pp_instance()); 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (found != instance_map_.end()) 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) found->second->resources.erase(pp_resource); 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) live_resources_.erase(pp_resource); 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceTracker::LastPluginRefWasDeleted(Resource* object) { 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Bug http://crbug.com/134611 indicates that sometimes the resource tracker 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is null here. This should never be the case since if we have a resource in 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the tracker, it should always have a valid instance associated with it 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (except for the resource for the main thread's message loop, which has 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // instance set to 0). 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // As a result, we do some CHECKs here to see what types of problems the 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // instance might have before dispatching. 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(brettw) remove these checks when this bug is no longer relevant. 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note, we do an imperfect check here; this might be a loop that's not the 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // main one. 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const bool is_message_loop = (object->AsPPB_MessageLoop_API() != NULL); 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(object->pp_instance() || is_message_loop); 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CallbackTracker* callback_tracker = 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PpapiGlobals::Get()->GetCallbackTrackerForInstance(object->pp_instance()); 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(callback_tracker || is_message_loop); 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (callback_tracker) 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback_tracker->PostAbortForResource(object->pp_resource()); 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) object->NotifyLastPluginRefWasDeleted(); 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)int32 ResourceTracker::GetNextResourceValue() { 2453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#if defined(NDEBUG) 2463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return ++last_resource_value_; 2473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#else 2483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // In debug mode, the least significant bit indicates which side (renderer 2493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // or plugin process) created the resource. Increment by 2 so it's always the 2503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // same. 2513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) last_resource_value_ += 2; 2523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return last_resource_value_; 2533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#endif 2543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 2553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 2563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)bool ResourceTracker::CanOperateOnResource(PP_Resource res) { 2573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#if defined(NDEBUG) 2583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return true; 2593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#else 2603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // The invalid PP_Resource value could appear at both sides. 2613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (res == 0) 2623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return true; 2633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 2643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Skipping the type bits, the least significant bit of |res| should be the 2653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // same as that of |last_resource_value_|. 2663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return ((res >> kPPIdTypeBits) & 1) == (last_resource_value_ & 1); 2673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#endif 2683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 2693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace ppapi 271