root/ppapi/proxy/raw_var_data.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. GetOrCreateRawVarData
  2. CanHaveChildren
  3. Create
  4. CreatePPVar
  5. Write
  6. Read
  7. GetHandles
  8. SetMinimumArrayBufferSizeForShmemForTest
  9. Create
  10. GetHandle
  11. Init
  12. CreatePPVar
  13. PopulatePPVar
  14. Write
  15. Read
  16. Init
  17. CreatePPVar
  18. PopulatePPVar
  19. Write
  20. Read
  21. Init
  22. CreatePPVar
  23. PopulatePPVar
  24. Write
  25. Read
  26. GetHandle
  27. AddChild
  28. Init
  29. CreatePPVar
  30. PopulatePPVar
  31. Write
  32. Read
  33. AddChild
  34. Init
  35. CreatePPVar
  36. PopulatePPVar
  37. Write
  38. Read
  39. pending_browser_host_id_
  40. Init
  41. CreatePPVar
  42. PopulatePPVar
  43. Write
  44. Read

// 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 (!m->ReadUInt32(iter, &size))
    return scoped_ptr<RawVarDataGraph>();
  for (uint32_t i = 0; i < size; ++i) {
    int32_t type;
    if (!m->ReadInt(iter, &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 (!m->ReadBool(iter, &bool_value))
        return false;
      result.value.as_bool = PP_FromBool(bool_value);
      break;
    }
    case PP_VARTYPE_INT32:
      if (!m->ReadInt(iter, &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 (!m->ReadInt64(iter, &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 (!m->ReadString(iter, &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 (!m->ReadInt(iter, &shmem_type))
    return false;
  type_ = static_cast<ShmemType>(shmem_type);
  switch (type_) {
    case ARRAY_BUFFER_SHMEM_HOST:
      if (!m->ReadInt(iter, &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 (!m->ReadString(iter, &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 (!m->ReadUInt32(iter, &size))
    return false;
  for (uint32_t i = 0; i < size; ++i) {
    uint32_t index;
    if (!m->ReadUInt32(iter, &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 (!m->ReadUInt32(iter, &size))
    return false;
  for (uint32_t i = 0; i < size; ++i) {
    std::string key;
    uint32_t value;
    if (!m->ReadString(iter, &key))
      return false;
    if (!m->ReadUInt32(iter, &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 (!m->ReadInt(iter, &value))
    return false;
  pp_resource_ = static_cast<PP_Resource>(value);
  if (!m->ReadInt(iter, &pending_renderer_host_id_))
    return false;
  if (!m->ReadInt(iter, &pending_browser_host_id_))
    return false;
  bool has_creation_message;
  if (!m->ReadBool(iter, &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

/* [<][>][^][v][top][bottom][index][help] */