// Copyright (c) 2013 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/proxy/raw_var_data.h"

#include <stack>

#include "base/containers/hash_tables.h"
#include "base/stl_util.h"
#include "ipc/ipc_message.h"
#include "ppapi/proxy/ppapi_param_traits.h"
#include "ppapi/shared_impl/array_var.h"
#include "ppapi/shared_impl/dictionary_var.h"
#include "ppapi/shared_impl/ppapi_globals.h"
#include "ppapi/shared_impl/resource_var.h"
#include "ppapi/shared_impl/scoped_pp_var.h"
#include "ppapi/shared_impl/var.h"
#include "ppapi/shared_impl/var_tracker.h"

using std::make_pair;

namespace ppapi {
namespace proxy {

namespace {

// When sending array buffers, if the size is over 256K, we use shared
// memory instead of sending the data over IPC. Light testing suggests
// shared memory is much faster for 256K and larger messages.
static const uint32 kMinimumArrayBufferSizeForShmem = 256 * 1024;
static uint32 g_minimum_array_buffer_size_for_shmem =
    kMinimumArrayBufferSizeForShmem;

struct StackEntry {
  StackEntry(PP_Var v, size_t i) : var(v), data_index(i) {}
  PP_Var var;
  size_t data_index;
};

// For a given PP_Var, returns the RawVarData associated with it, or creates a
// new one if there is no existing one. The data is appended to |data| if it
// is newly created. The index into |data| pointing to the result is returned.
// |visited_map| keeps track of RawVarDatas that have already been created.
size_t GetOrCreateRawVarData(const PP_Var& var,
                             base::hash_map<int64_t, size_t>* visited_map,
                             ScopedVector<RawVarData>* data) {
  if (VarTracker::IsVarTypeRefcounted(var.type)) {
    base::hash_map<int64_t, size_t>::iterator it = visited_map->find(
        var.value.as_id);
    if (it != visited_map->end()) {
      return it->second;
    } else {
      data->push_back(RawVarData::Create(var.type));
      (*visited_map)[var.value.as_id] = data->size() - 1;
    }
  } else {
    data->push_back(RawVarData::Create(var.type));
  }
  return data->size() - 1;
}

bool CanHaveChildren(PP_Var var) {
  return var.type == PP_VARTYPE_ARRAY || var.type == PP_VARTYPE_DICTIONARY;
}

}  // namespace

// RawVarDataGraph ------------------------------------------------------------
RawVarDataGraph::RawVarDataGraph() {
}

RawVarDataGraph::~RawVarDataGraph() {
}

// This function uses a stack-based DFS search to traverse the var graph. Each
// iteration, the top node on the stack examined. If the node has not been
// visited yet (i.e. !initialized()) then it is added to the list of
// |parent_ids| which contains all of the nodes on the path from the start node
// to the current node. Each of that nodes children are examined. If they appear
// in the list of |parent_ids| it means we have a cycle and we return NULL.
// Otherwise, if they haven't been visited yet we add them to the stack, If the
// node at the top of the stack has already been visited, then we pop it off the
// stack and erase it from |parent_ids|.
// static
scoped_ptr<RawVarDataGraph> RawVarDataGraph::Create(const PP_Var& var,
                                                    PP_Instance instance) {
  scoped_ptr<RawVarDataGraph> graph(new RawVarDataGraph);
  // Map of |var.value.as_id| to a RawVarData index in RawVarDataGraph.
  base::hash_map<int64_t, size_t> visited_map;
  base::hash_set<int64_t> parent_ids;

  std::stack<StackEntry> stack;
  stack.push(StackEntry(var, GetOrCreateRawVarData(var, &visited_map,
                                                   &graph->data_)));

  while (!stack.empty()) {
    PP_Var current_var = stack.top().var;
    RawVarData* current_var_data = graph->data_[stack.top().data_index];

    if (current_var_data->initialized()) {
      stack.pop();
      if (CanHaveChildren(current_var))
        parent_ids.erase(current_var.value.as_id);
      continue;
    }

    if (CanHaveChildren(current_var))
      parent_ids.insert(current_var.value.as_id);
    if (!current_var_data->Init(current_var, instance)) {
      NOTREACHED();
      return scoped_ptr<RawVarDataGraph>();
    }

    // Add child nodes to the stack.
    if (current_var.type == PP_VARTYPE_ARRAY) {
      ArrayVar* array_var = ArrayVar::FromPPVar(current_var);
      if (!array_var) {
        NOTREACHED();
        return scoped_ptr<RawVarDataGraph>();
      }
      for (ArrayVar::ElementVector::const_iterator iter =
               array_var->elements().begin();
           iter != array_var->elements().end();
           ++iter) {
        const PP_Var& child = iter->get();
        // If a child of this node is already in parent_ids, we have a cycle so
        // we just return null.
        if (CanHaveChildren(child) && parent_ids.count(child.value.as_id) != 0)
          return scoped_ptr<RawVarDataGraph>();
        size_t child_id = GetOrCreateRawVarData(child, &visited_map,
                                                &graph->data_);
        static_cast<ArrayRawVarData*>(current_var_data)->AddChild(child_id);
        if (!graph->data_[child_id]->initialized())
          stack.push(StackEntry(child, child_id));
      }
    } else if (current_var.type == PP_VARTYPE_DICTIONARY) {
      DictionaryVar* dict_var = DictionaryVar::FromPPVar(current_var);
      if (!dict_var) {
        NOTREACHED();
        return scoped_ptr<RawVarDataGraph>();
      }
      for (DictionaryVar::KeyValueMap::const_iterator iter =
               dict_var->key_value_map().begin();
           iter != dict_var->key_value_map().end();
           ++iter) {
        const PP_Var& child = iter->second.get();
        if (CanHaveChildren(child) && parent_ids.count(child.value.as_id) != 0)
          return scoped_ptr<RawVarDataGraph>();
        size_t child_id = GetOrCreateRawVarData(child, &visited_map,
                                                &graph->data_);
        static_cast<DictionaryRawVarData*>(
            current_var_data)->AddChild(iter->first, child_id);
        if (!graph->data_[child_id]->initialized())
          stack.push(StackEntry(child, child_id));
      }
    }
  }
  return graph.Pass();
}

PP_Var RawVarDataGraph::CreatePPVar(PP_Instance instance) {
  // Create and initialize each node in the graph.
  std::vector<PP_Var> graph;
  for (size_t i = 0; i < data_.size(); ++i)
    graph.push_back(data_[i]->CreatePPVar(instance));
  for (size_t i = 0; i < data_.size(); ++i)
    data_[i]->PopulatePPVar(graph[i], graph);
  // Everything except the root will have one extra ref. Remove that ref.
  for (size_t i = 1; i < data_.size(); ++i)
    ScopedPPVar(ScopedPPVar::PassRef(), graph[i]);
  // The first element is the root.
  return graph[0];
}

void RawVarDataGraph::Write(IPC::Message* m,
                            const HandleWriter& handle_writer) {
  // Write the size, followed by each node in the graph.
  m->WriteUInt32(static_cast<uint32_t>(data_.size()));
  for (size_t i = 0; i < data_.size(); ++i) {
    m->WriteInt(data_[i]->Type());
    data_[i]->Write(m, handle_writer);
  }
}

// static
scoped_ptr<RawVarDataGraph> RawVarDataGraph::Read(const IPC::Message* m,
                                                  PickleIterator* iter) {
  scoped_ptr<RawVarDataGraph> result(new RawVarDataGraph);
  uint32_t size = 0;
  if (!iter->ReadUInt32(&size))
    return scoped_ptr<RawVarDataGraph>();
  for (uint32_t i = 0; i < size; ++i) {
    int32_t type;
    if (!iter->ReadInt(&type))
      return scoped_ptr<RawVarDataGraph>();
    PP_VarType var_type = static_cast<PP_VarType>(type);
    result->data_.push_back(RawVarData::Create(var_type));
    if (!result->data_.back()->Read(var_type, m, iter))
      return scoped_ptr<RawVarDataGraph>();
  }
  return result.Pass();
}

std::vector<SerializedHandle*> RawVarDataGraph::GetHandles() {
  std::vector<SerializedHandle*> result;
  for (size_t i = 0; i < data_.size(); ++i) {
    SerializedHandle* handle = data_[i]->GetHandle();
    if (handle)
      result.push_back(handle);
  }
  return result;
}

// static
void RawVarDataGraph::SetMinimumArrayBufferSizeForShmemForTest(
    uint32 threshold) {
  if (threshold == 0)
    g_minimum_array_buffer_size_for_shmem = kMinimumArrayBufferSizeForShmem;
  else
    g_minimum_array_buffer_size_for_shmem = threshold;
}

// RawVarData ------------------------------------------------------------------

// static
RawVarData* RawVarData::Create(PP_VarType type) {
  switch (type) {
    case PP_VARTYPE_UNDEFINED:
    case PP_VARTYPE_NULL:
    case PP_VARTYPE_BOOL:
    case PP_VARTYPE_INT32:
    case PP_VARTYPE_DOUBLE:
    case PP_VARTYPE_OBJECT:
      return new BasicRawVarData();
    case PP_VARTYPE_STRING:
      return new StringRawVarData();
    case PP_VARTYPE_ARRAY_BUFFER:
      return new ArrayBufferRawVarData();
    case PP_VARTYPE_ARRAY:
      return new ArrayRawVarData();
    case PP_VARTYPE_DICTIONARY:
      return new DictionaryRawVarData();
    case PP_VARTYPE_RESOURCE:
      return new ResourceRawVarData();
  }
  NOTREACHED();
  return NULL;
}

RawVarData::RawVarData() : initialized_(false) {
}

RawVarData::~RawVarData() {
}

SerializedHandle* RawVarData::GetHandle() {
  return NULL;
}

// BasicRawVarData -------------------------------------------------------------
BasicRawVarData::BasicRawVarData() {
}

BasicRawVarData::~BasicRawVarData() {
}

PP_VarType BasicRawVarData::Type() {
  return var_.type;
}

bool BasicRawVarData::Init(const PP_Var& var, PP_Instance /*instance*/) {
  var_ = var;
  initialized_ = true;
  return true;
}

PP_Var BasicRawVarData::CreatePPVar(PP_Instance instance) {
  return var_;
}

void BasicRawVarData::PopulatePPVar(const PP_Var& var,
                                    const std::vector<PP_Var>& graph) {
}

void BasicRawVarData::Write(
    IPC::Message* m,
    const HandleWriter& handle_writer) {
  switch (var_.type) {
    case PP_VARTYPE_UNDEFINED:
    case PP_VARTYPE_NULL:
      // These don't need any data associated with them other than the type we
      // just serialized.
      break;
    case PP_VARTYPE_BOOL:
      m->WriteBool(PP_ToBool(var_.value.as_bool));
      break;
    case PP_VARTYPE_INT32:
      m->WriteInt(var_.value.as_int);
      break;
    case PP_VARTYPE_DOUBLE:
      IPC::ParamTraits<double>::Write(m, var_.value.as_double);
      break;
    case PP_VARTYPE_OBJECT:
      m->WriteInt64(var_.value.as_id);
      break;
    default:
      NOTREACHED();
      break;
  }
}

bool BasicRawVarData::Read(PP_VarType type,
                           const IPC::Message* m,
                           PickleIterator* iter) {
  PP_Var result;
  result.type = type;
  switch (type) {
    case PP_VARTYPE_UNDEFINED:
    case PP_VARTYPE_NULL:
      // These don't have any data associated with them other than the type we
      // just deserialized.
      break;
    case PP_VARTYPE_BOOL: {
      bool bool_value;
      if (!iter->ReadBool(&bool_value))
        return false;
      result.value.as_bool = PP_FromBool(bool_value);
      break;
    }
    case PP_VARTYPE_INT32:
      if (!iter->ReadInt(&result.value.as_int))
        return false;
      break;
    case PP_VARTYPE_DOUBLE:
      if (!IPC::ParamTraits<double>::Read(m, iter, &result.value.as_double))
        return false;
      break;
    case PP_VARTYPE_OBJECT:
      if (!iter->ReadInt64(&result.value.as_id))
        return false;
      break;
    default:
      NOTREACHED();
      return false;
  }
  var_ = result;
  return true;
}

// StringRawVarData ------------------------------------------------------------
StringRawVarData::StringRawVarData() {
}

StringRawVarData::~StringRawVarData() {
}

PP_VarType StringRawVarData::Type() {
  return PP_VARTYPE_STRING;
}

bool StringRawVarData::Init(const PP_Var& var, PP_Instance /*instance*/) {
  DCHECK(var.type == PP_VARTYPE_STRING);
  StringVar* string_var = StringVar::FromPPVar(var);
  if (!string_var)
    return false;
  data_ = string_var->value();
  initialized_ = true;
  return true;
}

PP_Var StringRawVarData::CreatePPVar(PP_Instance instance) {
  return StringVar::SwapValidatedUTF8StringIntoPPVar(&data_);
}

void StringRawVarData::PopulatePPVar(const PP_Var& var,
                                     const std::vector<PP_Var>& graph) {
}

void StringRawVarData::Write(IPC::Message* m,
                             const HandleWriter& handle_writer) {
  m->WriteString(data_);
}

bool StringRawVarData::Read(PP_VarType type,
                            const IPC::Message* m,
                            PickleIterator* iter) {
  if (!iter->ReadString(&data_))
    return false;
  return true;
}

// ArrayBufferRawVarData -------------------------------------------------------
ArrayBufferRawVarData::ArrayBufferRawVarData() {
}

ArrayBufferRawVarData::~ArrayBufferRawVarData() {
}

PP_VarType ArrayBufferRawVarData::Type() {
  return PP_VARTYPE_ARRAY_BUFFER;
}

bool ArrayBufferRawVarData::Init(const PP_Var& var,
                                 PP_Instance instance) {
  DCHECK(var.type == PP_VARTYPE_ARRAY_BUFFER);
  ArrayBufferVar* buffer_var = ArrayBufferVar::FromPPVar(var);
  if (!buffer_var)
    return false;
  bool using_shmem = false;
  if (buffer_var->ByteLength() >= g_minimum_array_buffer_size_for_shmem &&
      instance != 0) {
    int host_handle_id;
    base::SharedMemoryHandle plugin_handle;
    using_shmem = buffer_var->CopyToNewShmem(instance,
                                             &host_handle_id,
                                             &plugin_handle);
    if (using_shmem) {
      if (host_handle_id != -1) {
        DCHECK(!base::SharedMemory::IsHandleValid(plugin_handle));
        DCHECK(PpapiGlobals::Get()->IsPluginGlobals());
        type_ = ARRAY_BUFFER_SHMEM_HOST;
        host_shm_handle_id_ = host_handle_id;
      } else {
        DCHECK(base::SharedMemory::IsHandleValid(plugin_handle));
        DCHECK(PpapiGlobals::Get()->IsHostGlobals());
        type_ = ARRAY_BUFFER_SHMEM_PLUGIN;
        plugin_shm_handle_ = SerializedHandle(plugin_handle,
                                              buffer_var->ByteLength());
      }
    }
  }
  if (!using_shmem) {
    type_ = ARRAY_BUFFER_NO_SHMEM;
    data_ = std::string(static_cast<const char*>(buffer_var->Map()),
                        buffer_var->ByteLength());
  }
  initialized_ = true;
  return true;
}

PP_Var ArrayBufferRawVarData::CreatePPVar(PP_Instance instance) {
  PP_Var result = PP_MakeUndefined();
  switch (type_) {
    case ARRAY_BUFFER_SHMEM_HOST: {
      base::SharedMemoryHandle host_handle;
      uint32 size_in_bytes;
      bool ok = PpapiGlobals::Get()->GetVarTracker()->
          StopTrackingSharedMemoryHandle(host_shm_handle_id_,
                                         instance,
                                         &host_handle,
                                         &size_in_bytes);
      if (ok) {
        result = PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar(
            size_in_bytes, host_handle);
      } else {
        LOG(ERROR) << "Couldn't find array buffer id: " << host_shm_handle_id_;
        return PP_MakeUndefined();
      }
      break;
    }
    case ARRAY_BUFFER_SHMEM_PLUGIN: {
      result = PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar(
          plugin_shm_handle_.size(),
          plugin_shm_handle_.shmem());
      break;
    }
    case ARRAY_BUFFER_NO_SHMEM: {
      result = PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar(
          static_cast<uint32>(data_.size()), data_.data());
      break;
    }
    default:
      NOTREACHED();
      return PP_MakeUndefined();
  }
  DCHECK(result.type == PP_VARTYPE_ARRAY_BUFFER);
  return result;
}

void ArrayBufferRawVarData::PopulatePPVar(const PP_Var& var,
                                          const std::vector<PP_Var>& graph) {
}

void ArrayBufferRawVarData::Write(
    IPC::Message* m,
    const HandleWriter& handle_writer) {
  m->WriteInt(type_);
  switch (type_) {
    case ARRAY_BUFFER_SHMEM_HOST:
      m->WriteInt(host_shm_handle_id_);
      break;
    case ARRAY_BUFFER_SHMEM_PLUGIN:
      handle_writer.Run(m, plugin_shm_handle_);
      break;
    case ARRAY_BUFFER_NO_SHMEM:
      m->WriteString(data_);
      break;
  }
}

bool ArrayBufferRawVarData::Read(PP_VarType type,
                                 const IPC::Message* m,
                                 PickleIterator* iter) {
  int shmem_type;
  if (!iter->ReadInt(&shmem_type))
    return false;
  type_ = static_cast<ShmemType>(shmem_type);
  switch (type_) {
    case ARRAY_BUFFER_SHMEM_HOST:
      if (!iter->ReadInt(&host_shm_handle_id_))
        return false;
      break;
    case ARRAY_BUFFER_SHMEM_PLUGIN:
      if (!IPC::ParamTraits<SerializedHandle>::Read(
              m, iter, &plugin_shm_handle_)) {
        return false;
      }
      break;
    case ARRAY_BUFFER_NO_SHMEM:
      if (!iter->ReadString(&data_))
        return false;
      break;
    default:
      // We read an invalid ID.
      NOTREACHED();
      return false;
  }
  return true;
}

SerializedHandle* ArrayBufferRawVarData::GetHandle() {
  if (type_ == ARRAY_BUFFER_SHMEM_PLUGIN && plugin_shm_handle_.size() != 0)
    return &plugin_shm_handle_;
  return NULL;
}

// ArrayRawVarData -------------------------------------------------------------
ArrayRawVarData::ArrayRawVarData() {
}

ArrayRawVarData::~ArrayRawVarData() {
}

void ArrayRawVarData::AddChild(size_t element) {
  children_.push_back(element);
}

PP_VarType ArrayRawVarData::Type() {
  return PP_VARTYPE_ARRAY;
}

bool ArrayRawVarData::Init(const PP_Var& var, PP_Instance /*instance*/) {
  initialized_ = true;
  DCHECK(var.type == PP_VARTYPE_ARRAY);
  initialized_ = true;
  return true;
}

PP_Var ArrayRawVarData::CreatePPVar(PP_Instance instance) {
  return (new ArrayVar())->GetPPVar();
}

void ArrayRawVarData::PopulatePPVar(const PP_Var& var,
                                    const std::vector<PP_Var>& graph) {
  if (var.type != PP_VARTYPE_ARRAY) {
    NOTREACHED();
    return;
  }
  ArrayVar* array_var = ArrayVar::FromPPVar(var);
  DCHECK(array_var->elements().empty());
  for (size_t i = 0; i < children_.size(); ++i)
    array_var->elements().push_back(ScopedPPVar(graph[children_[i]]));
}

void ArrayRawVarData::Write(IPC::Message* m,
                            const HandleWriter& handle_writer) {
  m->WriteUInt32(static_cast<uint32_t>(children_.size()));
  for (size_t i = 0; i < children_.size(); ++i)
    m->WriteUInt32(static_cast<uint32_t>(children_[i]));
}

bool ArrayRawVarData::Read(PP_VarType type,
                           const IPC::Message* m,
                           PickleIterator* iter) {
  uint32_t size;
  if (!iter->ReadUInt32(&size))
    return false;
  for (uint32_t i = 0; i < size; ++i) {
    uint32_t index;
    if (!iter->ReadUInt32(&index))
      return false;
    children_.push_back(index);
  }
  return true;
}

// DictionaryRawVarData --------------------------------------------------------
DictionaryRawVarData::DictionaryRawVarData() {
}

DictionaryRawVarData::~DictionaryRawVarData() {
}

void DictionaryRawVarData::AddChild(const std::string& key,
                                    size_t value) {
  children_.push_back(make_pair(key, value));
}

PP_VarType DictionaryRawVarData::Type() {
  return PP_VARTYPE_DICTIONARY;
}

bool DictionaryRawVarData::Init(const PP_Var& var, PP_Instance /*instance*/) {
  DCHECK(var.type == PP_VARTYPE_DICTIONARY);
  initialized_ = true;
  return true;
}

PP_Var DictionaryRawVarData::CreatePPVar(PP_Instance instance) {
  return (new DictionaryVar())->GetPPVar();
}

void DictionaryRawVarData::PopulatePPVar(const PP_Var& var,
                                         const std::vector<PP_Var>& graph) {
  if (var.type != PP_VARTYPE_DICTIONARY) {
    NOTREACHED();
    return;
  }
  DictionaryVar* dictionary_var = DictionaryVar::FromPPVar(var);
  DCHECK(dictionary_var->key_value_map().empty());
  for (size_t i = 0; i < children_.size(); ++i) {
    bool success = dictionary_var->SetWithStringKey(children_[i].first,
                                                    graph[children_[i].second]);
    DCHECK(success);
  }
}

void DictionaryRawVarData::Write(
    IPC::Message* m,
    const HandleWriter& handle_writer) {
  m->WriteUInt32(static_cast<uint32_t>(children_.size()));
  for (size_t i = 0; i < children_.size(); ++i) {
    m->WriteString(children_[i].first);
    m->WriteUInt32(static_cast<uint32_t>(children_[i].second));
  }
}

bool DictionaryRawVarData::Read(PP_VarType type,
                                const IPC::Message* m,
                                PickleIterator* iter) {
  uint32_t size;
  if (!iter->ReadUInt32(&size))
    return false;
  for (uint32_t i = 0; i < size; ++i) {
    std::string key;
    uint32_t value;
    if (!iter->ReadString(&key))
      return false;
    if (!iter->ReadUInt32(&value))
      return false;
    children_.push_back(make_pair(key, value));
  }
  return true;
}

// ResourceRawVarData ----------------------------------------------------------
ResourceRawVarData::ResourceRawVarData()
    : pp_resource_(0),
      pending_renderer_host_id_(0),
      pending_browser_host_id_(0) {}

ResourceRawVarData::~ResourceRawVarData() {
}

PP_VarType ResourceRawVarData::Type() {
  return PP_VARTYPE_RESOURCE;
}

bool ResourceRawVarData::Init(const PP_Var& var, PP_Instance /*instance*/) {
  DCHECK(var.type == PP_VARTYPE_RESOURCE);
  ResourceVar* resource_var = ResourceVar::FromPPVar(var);
  if (!resource_var)
    return false;
  pp_resource_ = resource_var->GetPPResource();
  const IPC::Message* message = resource_var->GetCreationMessage();
  if (message)
    creation_message_.reset(new IPC::Message(*message));
  else
    creation_message_.reset();
  pending_renderer_host_id_ = resource_var->GetPendingRendererHostId();
  pending_browser_host_id_ = resource_var->GetPendingBrowserHostId();
  initialized_ = true;
  return true;
}

PP_Var ResourceRawVarData::CreatePPVar(PP_Instance instance) {
  // If this is not a pending resource host, just create the var.
  if (pp_resource_ || !creation_message_) {
    return PpapiGlobals::Get()->GetVarTracker()->MakeResourcePPVar(
        pp_resource_);
  }

  // This is a pending resource host, so create the resource and var.
  return PpapiGlobals::Get()->GetVarTracker()->MakeResourcePPVarFromMessage(
      instance,
      *creation_message_,
      pending_renderer_host_id_,
      pending_browser_host_id_);
}

void ResourceRawVarData::PopulatePPVar(const PP_Var& var,
                                       const std::vector<PP_Var>& graph) {
}

void ResourceRawVarData::Write(IPC::Message* m,
                               const HandleWriter& handle_writer) {
  m->WriteInt(static_cast<int>(pp_resource_));
  m->WriteInt(pending_renderer_host_id_);
  m->WriteInt(pending_browser_host_id_);
  m->WriteBool(creation_message_);
  if (creation_message_)
    IPC::ParamTraits<IPC::Message>::Write(m, *creation_message_);
}

bool ResourceRawVarData::Read(PP_VarType type,
                              const IPC::Message* m,
                              PickleIterator* iter) {
  int value;
  if (!iter->ReadInt(&value))
    return false;
  pp_resource_ = static_cast<PP_Resource>(value);
  if (!iter->ReadInt(&pending_renderer_host_id_))
    return false;
  if (!iter->ReadInt(&pending_browser_host_id_))
    return false;
  bool has_creation_message;
  if (!iter->ReadBool(&has_creation_message))
    return false;
  if (has_creation_message) {
    creation_message_.reset(new IPC::Message());
    if (!IPC::ParamTraits<IPC::Message>::Read(m, iter, creation_message_.get()))
      return false;
  } else {
    creation_message_.reset();
  }
  return true;
}

}  // namespace proxy
}  // namespace ppapi
