// 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::UnsafeSharedMemoryRegion region) {
  CheckThreadingPreconditions();

  scoped_refptr<ArrayBufferVar> array_buffer(
      CreateShmArrayBuffer(size_in_bytes, std::move(region)));
  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
