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