// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ppapi/shared_impl/var_tracker.h"

#include <string.h>

#include <limits>

#include "base/logging.h"
#include "base/memory/shared_memory.h"
#include "ppapi/shared_impl/host_resource.h"
#include "ppapi/shared_impl/id_assignment.h"
#include "ppapi/shared_impl/proxy_lock.h"
#include "ppapi/shared_impl/resource_var.h"
#include "ppapi/shared_impl/var.h"

namespace ppapi {

VarTracker::VarInfo::VarInfo()
    : var(), ref_count(0), track_with_no_reference_count(0) {}

VarTracker::VarInfo::VarInfo(Var* v, int input_ref_count)
    : var(v), ref_count(input_ref_count), track_with_no_reference_count(0) {}

VarTracker::VarTracker(ThreadMode thread_mode) : last_var_id_(0) {
  if (thread_mode == SINGLE_THREADED)
    thread_checker_.reset(new base::ThreadChecker);
}

VarTracker::~VarTracker() {}

void VarTracker::CheckThreadingPreconditions() const {
  DCHECK(!thread_checker_ || thread_checker_->CalledOnValidThread());
#ifndef NDEBUG
  ProxyLock::AssertAcquired();
#endif
}

int32_t VarTracker::AddVar(Var* var) {
  CheckThreadingPreconditions();

  return AddVarInternal(var, ADD_VAR_TAKE_ONE_REFERENCE);
}

Var* VarTracker::GetVar(int32_t var_id) const {
  CheckThreadingPreconditions();

  VarMap::const_iterator result = live_vars_.find(var_id);
  if (result == live_vars_.end())
    return NULL;
  return result->second.var.get();
}

Var* VarTracker::GetVar(const PP_Var& var) const {
  CheckThreadingPreconditions();

  if (!IsVarTypeRefcounted(var.type))
    return NULL;
  return GetVar(static_cast<int32_t>(var.value.as_id));
}

bool VarTracker::AddRefVar(int32_t var_id) {
  CheckThreadingPreconditions();

  DLOG_IF(ERROR, !CheckIdType(var_id, PP_ID_TYPE_VAR))
      << var_id << " is not a PP_Var ID.";
  VarMap::iterator found = live_vars_.find(var_id);
  if (found == live_vars_.end()) {
    NOTREACHED();  // Invalid var.
    return false;
  }

  VarInfo& info = found->second;
  if (info.ref_count == 0) {
    // All live vars with no refcount should be tracked objects.
    DCHECK(info.track_with_no_reference_count > 0);
    DCHECK(info.var->GetType() == PP_VARTYPE_OBJECT);

    TrackedObjectGettingOneRef(found);
  }

  // Basic refcount increment.
  info.ref_count++;
  return true;
}

bool VarTracker::AddRefVar(const PP_Var& var) {
  CheckThreadingPreconditions();

  if (!IsVarTypeRefcounted(var.type))
    return true;
  return AddRefVar(static_cast<int32_t>(var.value.as_id));
}

bool VarTracker::ReleaseVar(int32_t var_id) {
  CheckThreadingPreconditions();

  DLOG_IF(ERROR, !CheckIdType(var_id, PP_ID_TYPE_VAR))
      << var_id << " is not a PP_Var ID.";
  VarMap::iterator found = live_vars_.find(var_id);
  if (found == live_vars_.end())
    return false;

  VarInfo& info = found->second;
  if (info.ref_count == 0) {
    NOTREACHED() << "Releasing an object with zero ref";
    return false;
  }
  info.ref_count--;

  if (info.ref_count == 0) {
    // Hold a reference to the Var until it is erased so that we don't re-enter
    // live_vars_.erase() during deletion.
    // TODO(raymes): Make deletion of Vars iterative instead of recursive.
    scoped_refptr<Var> var(info.var);
    if (var->GetType() == PP_VARTYPE_OBJECT) {
      // Objects have special requirements and may not necessarily be released
      // when the refcount goes to 0.
      ObjectGettingZeroRef(found);
    } else {
      // All other var types can just be released.
      DCHECK(info.track_with_no_reference_count == 0);
      var->ResetVarID();
      live_vars_.erase(found);
    }
  }
  return true;
}

bool VarTracker::ReleaseVar(const PP_Var& var) {
  CheckThreadingPreconditions();

  if (!IsVarTypeRefcounted(var.type))
    return false;
  return ReleaseVar(static_cast<int32_t>(var.value.as_id));
}

int32_t VarTracker::AddVarInternal(Var* var, AddVarRefMode mode) {
  // If the plugin manages to create millions of strings.
  if (last_var_id_ == std::numeric_limits<int32_t>::max() >> kPPIdTypeBits)
    return 0;

  int32_t new_id = MakeTypedId(++last_var_id_, PP_ID_TYPE_VAR);
  std::pair<VarMap::iterator, bool> was_inserted =
      live_vars_.insert(std::make_pair(
          new_id, VarInfo(var, mode == ADD_VAR_TAKE_ONE_REFERENCE ? 1 : 0)));
  // We should never insert an ID that already exists.
  DCHECK(was_inserted.second);

  return new_id;
}

VarTracker::VarMap::iterator VarTracker::GetLiveVar(int32_t id) {
  return live_vars_.find(id);
}

int VarTracker::GetRefCountForObject(const PP_Var& plugin_object) {
  CheckThreadingPreconditions();

  VarMap::iterator found = GetLiveVar(plugin_object);
  if (found == live_vars_.end())
    return -1;
  return found->second.ref_count;
}

int VarTracker::GetTrackedWithNoReferenceCountForObject(
    const PP_Var& plugin_object) {
  CheckThreadingPreconditions();

  VarMap::iterator found = GetLiveVar(plugin_object);
  if (found == live_vars_.end())
    return -1;
  return found->second.track_with_no_reference_count;
}

// static
bool VarTracker::IsVarTypeRefcounted(PP_VarType type) {
  return type >= PP_VARTYPE_STRING;
}

VarTracker::VarMap::iterator VarTracker::GetLiveVar(const PP_Var& var) {
  return live_vars_.find(static_cast<int32_t>(var.value.as_id));
}

VarTracker::VarMap::const_iterator VarTracker::GetLiveVar(const PP_Var& var)
    const {
  return live_vars_.find(static_cast<int32_t>(var.value.as_id));
}

PP_Var VarTracker::MakeArrayBufferPPVar(uint32_t size_in_bytes) {
  CheckThreadingPreconditions();

  scoped_refptr<ArrayBufferVar> array_buffer(CreateArrayBuffer(size_in_bytes));
  if (!array_buffer.get())
    return PP_MakeNull();
  return array_buffer->GetPPVar();
}

PP_Var VarTracker::MakeArrayBufferPPVar(uint32_t size_in_bytes,
                                        const void* data) {
  CheckThreadingPreconditions();

  ArrayBufferVar* array_buffer = MakeArrayBufferVar(size_in_bytes, data);
  return array_buffer ? array_buffer->GetPPVar() : PP_MakeNull();
}

ArrayBufferVar* VarTracker::MakeArrayBufferVar(uint32_t size_in_bytes,
                                               const void* data) {
  CheckThreadingPreconditions();

  ArrayBufferVar* array_buffer(CreateArrayBuffer(size_in_bytes));
  if (!array_buffer)
    return NULL;
  memcpy(array_buffer->Map(), data, size_in_bytes);
  return array_buffer;
}

PP_Var VarTracker::MakeArrayBufferPPVar(uint32_t size_in_bytes,
                                        base::SharedMemoryHandle handle) {
  CheckThreadingPreconditions();

  scoped_refptr<ArrayBufferVar> array_buffer(
      CreateShmArrayBuffer(size_in_bytes, handle));
  if (!array_buffer.get())
    return PP_MakeNull();
  return array_buffer->GetPPVar();
}

PP_Var VarTracker::MakeResourcePPVar(PP_Resource pp_resource) {
  CheckThreadingPreconditions();

  ResourceVar* resource_var = MakeResourceVar(pp_resource);
  return resource_var ? resource_var->GetPPVar() : PP_MakeNull();
}

std::vector<PP_Var> VarTracker::GetLiveVars() {
  CheckThreadingPreconditions();

  std::vector<PP_Var> var_vector;
  var_vector.reserve(live_vars_.size());
  for (VarMap::const_iterator iter = live_vars_.begin();
       iter != live_vars_.end();
       ++iter) {
    var_vector.push_back(iter->second.var->GetPPVar());
  }
  return var_vector;
}

void VarTracker::TrackedObjectGettingOneRef(VarMap::const_iterator obj) {
  // Anybody using tracked objects should override this.
  NOTREACHED();
}

void VarTracker::ObjectGettingZeroRef(VarMap::iterator iter) {
  DeleteObjectInfoIfNecessary(iter);
}

bool VarTracker::DeleteObjectInfoIfNecessary(VarMap::iterator iter) {
  if (iter->second.ref_count != 0 ||
      iter->second.track_with_no_reference_count != 0)
    return false;  // Object still alive.
  iter->second.var->ResetVarID();
  live_vars_.erase(iter);
  return true;
}

}  // namespace ppapi
