// 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/proxy/resource_message_params.h"

#include "base/logging.h"
#include "base/memory/read_only_shared_memory_region.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/proxy/ppapi_messages.h"

namespace ppapi {
namespace proxy {

ResourceMessageParams::SerializedHandles::SerializedHandles()
    : should_close_(false) {
}

ResourceMessageParams::SerializedHandles::~SerializedHandles() {
  if (should_close_) {
    for (std::vector<SerializedHandle>::iterator iter = data_.begin();
         iter != data_.end(); ++iter) {
      iter->Close();
    }
  }
}

ResourceMessageParams::ResourceMessageParams()
    : pp_resource_(0),
      sequence_(0),
      handles_(new SerializedHandles()) {
}

ResourceMessageParams::ResourceMessageParams(PP_Resource resource,
                                             int32_t sequence)
    : pp_resource_(resource),
      sequence_(sequence),
      handles_(new SerializedHandles()) {
}

ResourceMessageParams::~ResourceMessageParams() {
}

void ResourceMessageParams::Serialize(base::Pickle* msg) const {
  WriteHeader(msg);
  WriteHandles(msg);
}

bool ResourceMessageParams::Deserialize(const base::Pickle* msg,
                                        base::PickleIterator* iter) {
  return ReadHeader(msg, iter) && ReadHandles(msg, iter);
}

void ResourceMessageParams::WriteHeader(base::Pickle* msg) const {
  IPC::WriteParam(msg, pp_resource_);
  IPC::WriteParam(msg, sequence_);
}

void ResourceMessageParams::WriteHandles(base::Pickle* msg) const {
  IPC::WriteParam(msg, handles_->data());
}

bool ResourceMessageParams::ReadHeader(const base::Pickle* msg,
                                       base::PickleIterator* iter) {
  DCHECK(handles_->data().empty());
  handles_->set_should_close(true);
  return IPC::ReadParam(msg, iter, &pp_resource_) &&
         IPC::ReadParam(msg, iter, &sequence_);
}

bool ResourceMessageParams::ReadHandles(const base::Pickle* msg,
                                        base::PickleIterator* iter) {
  return IPC::ReadParam(msg, iter, &handles_->data());
}

void ResourceMessageParams::ConsumeHandles() const {
  // Note: we must not invalidate the handles. This is used for converting
  // handles from the host OS to NaCl, and that conversion will not work if we
  // invalidate the handles (see HandleConverter).
  handles_->set_should_close(false);
}

SerializedHandle ResourceMessageParams::TakeHandleOfTypeAtIndex(
    size_t index,
    SerializedHandle::Type type) const {
  SerializedHandle handle;
  std::vector<SerializedHandle>& data = handles_->data();
  if (index < data.size() && data[index].type() == type)
    handle = std::move(data[index]);
  return handle;
}

bool ResourceMessageParams::TakeSharedMemoryHandleAtIndex(
    size_t index,
    base::SharedMemoryHandle* handle) const {
  SerializedHandle serialized = TakeHandleOfTypeAtIndex(
      index, SerializedHandle::SHARED_MEMORY);
  if (!serialized.is_shmem())
    return false;
  *handle = serialized.shmem();
  return true;
}

bool ResourceMessageParams::TakeReadOnlySharedMemoryRegionAtIndex(
    size_t index,
    base::ReadOnlySharedMemoryRegion* region) const {
  SerializedHandle serialized =
      TakeHandleOfTypeAtIndex(index, SerializedHandle::SHARED_MEMORY_REGION);
  if (!serialized.is_shmem_region())
    return false;
  *region = base::ReadOnlySharedMemoryRegion::Deserialize(
      serialized.TakeSharedMemoryRegion());
  return true;
}

bool ResourceMessageParams::TakeSocketHandleAtIndex(
    size_t index,
    IPC::PlatformFileForTransit* handle) const {
  SerializedHandle serialized = TakeHandleOfTypeAtIndex(
      index, SerializedHandle::SOCKET);
  if (!serialized.is_socket())
    return false;
  *handle = serialized.descriptor();
  return true;
}

bool ResourceMessageParams::TakeFileHandleAtIndex(
    size_t index,
    IPC::PlatformFileForTransit* handle) const {
  SerializedHandle serialized = TakeHandleOfTypeAtIndex(
      index, SerializedHandle::FILE);
  if (!serialized.is_file())
    return false;
  *handle = serialized.descriptor();
  return true;
}

void ResourceMessageParams::TakeAllSharedMemoryHandles(
    std::vector<base::SharedMemoryHandle>* handles) const {
  for (size_t i = 0; i < handles_->data().size(); ++i) {
    base::SharedMemoryHandle handle;
    if (TakeSharedMemoryHandleAtIndex(i, &handle))
      handles->push_back(handle);
  }
}

void ResourceMessageParams::TakeAllHandles(
    std::vector<SerializedHandle>* handles) const {
  std::vector<SerializedHandle>& data = handles_->data();
  for (size_t i = 0; i < data.size(); ++i)
    handles->push_back(std::move(data[i]));
}

void ResourceMessageParams::AppendHandle(SerializedHandle handle) const {
  handles_->data().push_back(std::move(handle));
}

ResourceMessageCallParams::ResourceMessageCallParams()
    : ResourceMessageParams(),
      has_callback_(0) {
}

ResourceMessageCallParams::ResourceMessageCallParams(PP_Resource resource,
                                                     int32_t sequence)
    : ResourceMessageParams(resource, sequence),
      has_callback_(0) {
}

ResourceMessageCallParams::~ResourceMessageCallParams() {
}

void ResourceMessageCallParams::Serialize(base::Pickle* msg) const {
  ResourceMessageParams::Serialize(msg);
  IPC::WriteParam(msg, has_callback_);
}

bool ResourceMessageCallParams::Deserialize(const base::Pickle* msg,
                                            base::PickleIterator* iter) {
  if (!ResourceMessageParams::Deserialize(msg, iter))
    return false;
  return IPC::ReadParam(msg, iter, &has_callback_);
}

ResourceMessageReplyParams::ResourceMessageReplyParams()
    : ResourceMessageParams(),
      result_(PP_OK) {
}

ResourceMessageReplyParams::ResourceMessageReplyParams(PP_Resource resource,
                                                       int32_t sequence)
    : ResourceMessageParams(resource, sequence),
      result_(PP_OK) {
}

ResourceMessageReplyParams::~ResourceMessageReplyParams() {
}

void ResourceMessageReplyParams::Serialize(base::Pickle* msg) const {
  // Rather than serialize all of ResourceMessageParams first, we serialize all
  // non-handle data first, then the handles. When transferring to NaCl on
  // Windows, we need to be able to translate Windows-style handles to POSIX-
  // style handles, and it's easier to put all the regular stuff at the front.
  WriteReplyHeader(msg);
  WriteHandles(msg);
}

bool ResourceMessageReplyParams::Deserialize(const base::Pickle* msg,
                                             base::PickleIterator* iter) {
  return (ReadHeader(msg, iter) && IPC::ReadParam(msg, iter, &result_) &&
          ReadHandles(msg, iter));
}

void ResourceMessageReplyParams::WriteReplyHeader(base::Pickle* msg) const {
  WriteHeader(msg);
  IPC::WriteParam(msg, result_);
}

}  // namespace proxy
}  // namespace ppapi
