// 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 "base/containers/hash_tables.h"
#include "base/containers/stack.h"
#include "base/memory/ptr_util.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_t kMinimumArrayBufferSizeForShmem = 256 * 1024;
static uint32_t 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,
                             std::vector<std::unique_ptr<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(base::WrapUnique(RawVarData::Create(var.type)));
      (*visited_map)[var.value.as_id] = data->size() - 1;
    }
  } else {
    data->push_back(base::WrapUnique(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
std::unique_ptr<RawVarDataGraph> RawVarDataGraph::Create(const PP_Var& var,
                                                         PP_Instance instance) {
  std::unique_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;

  base::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].get();

    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 nullptr;
    }

    // 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 nullptr;
      }
      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 nullptr;
        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 nullptr;
      }
      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 nullptr;
        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;
}

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(base::Pickle* 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
std::unique_ptr<RawVarDataGraph> RawVarDataGraph::Read(
    const base::Pickle* m,
    base::PickleIterator* iter) {
  std::unique_ptr<RawVarDataGraph> result(new RawVarDataGraph);
  uint32_t size = 0;
  if (!iter->ReadUInt32(&size))
    return nullptr;
  for (uint32_t i = 0; i < size; ++i) {
    int32_t type;
    if (!iter->ReadInt(&type))
      return nullptr;
    PP_VarType var_type = static_cast<PP_VarType>(type);
    result->data_.push_back(base::WrapUnique(RawVarData::Create(var_type)));
    if (!result->data_.back())
      return nullptr;
    if (!result->data_.back()->Read(var_type, m, iter))
      return nullptr;
  }
  return result;
}

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_t 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(base::Pickle* 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::WriteParam(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 base::Pickle* m,
                           base::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::ReadParam(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(base::Pickle* m,
                             const HandleWriter& handle_writer) {
  m->WriteString(data_);
}

bool StringRawVarData::Read(PP_VarType type,
                            const base::Pickle* m,
                            base::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_t 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_t>(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(base::Pickle* 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 base::Pickle* m,
                                 base::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::ReadParam(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(base::Pickle* 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 base::Pickle* m,
                           base::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(base::Pickle* 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 base::Pickle* m,
                                base::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(base::Pickle* 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::WriteParam(m, *creation_message_);
}

bool ResourceRawVarData::Read(PP_VarType type,
                              const base::Pickle* m,
                              base::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::ReadParam(m, iter, creation_message_.get()))
      return false;
  } else {
    creation_message_.reset();
  }
  return true;
}

}  // namespace proxy
}  // namespace ppapi
