Initial import of libmojo r405848

This brings libmojo in sync with libchrome.

Bug: 27569341
Test: mma -j32 libmojo
Change-Id: Ia7cb877e46dd3f86f18888b5d8d80bef5468b266
diff --git a/ipc/attachment_broker.h b/ipc/attachment_broker.h
new file mode 100644
index 0000000..a106e29
--- /dev/null
+++ b/ipc/attachment_broker.h
@@ -0,0 +1,176 @@
+// Copyright 2015 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.
+
+#ifndef IPC_ATTACHMENT_BROKER_H_
+#define IPC_ATTACHMENT_BROKER_H_
+
+#include "base/gtest_prod_util.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/process/process_handle.h"
+#include "base/synchronization/lock.h"
+#include "build/build_config.h"
+#include "ipc/brokerable_attachment.h"
+#include "ipc/ipc_export.h"
+#include "ipc/ipc_listener.h"
+
+// If the platform has no attachments that need brokering, then it shouldn't
+// compile any code that calls member functions of AttachmentBroker. This
+// prevents symbols only used by AttachmentBroker and its subclasses from
+// making it into the binary.
+#if defined(OS_WIN) || (defined(OS_MACOSX) && !defined(OS_IOS))
+#define USE_ATTACHMENT_BROKER 1
+#else
+#define USE_ATTACHMENT_BROKER 0
+#endif  // defined(OS_WIN)
+
+namespace base {
+class SequencedTaskRunner;
+class SingleThreadTaskRunner;
+};
+
+namespace IPC {
+
+class AttachmentBroker;
+class Endpoint;
+
+// Classes that inherit from this abstract base class are capable of
+// communicating with a broker to send and receive attachments to Chrome IPC
+// messages.
+class IPC_EXPORT SupportsAttachmentBrokering {
+ public:
+  // Returns an AttachmentBroker used to broker attachments of IPC messages to
+  // other processes. There must be exactly one AttachmentBroker per process.
+  virtual AttachmentBroker* GetAttachmentBroker() = 0;
+};
+
+// Responsible for brokering attachments to Chrome IPC messages. On platforms
+// that support attachment brokering, every IPC channel should have a reference
+// to a AttachmentBroker.
+// This class is not thread safe. The implementation of this class assumes that
+// it is only ever used on the same thread as its consumers.
+class IPC_EXPORT AttachmentBroker : public Listener {
+ public:
+  // A standard observer interface that allows consumers of the AttachmentBroker
+  // to be notified when a new attachment has been received.
+  class Observer {
+   public:
+    virtual void ReceivedBrokerableAttachmentWithId(
+        const BrokerableAttachment::AttachmentId& id) = 0;
+  };
+
+  // Each process has at most one attachment broker. The process is responsible
+  // for ensuring that |broker| stays alive for as long as the process is
+  // sending/receiving ipc messages.
+  static void SetGlobal(AttachmentBroker* broker);
+  static AttachmentBroker* GetGlobal();
+
+  AttachmentBroker();
+  ~AttachmentBroker() override;
+
+  // Sends |attachment| to |destination_process|. The implementation uses an
+  // IPC::Channel to communicate with the broker process. This may be the same
+  // IPC::Channel that is requesting the brokering of an attachment.
+  // Returns true on success and false otherwise.
+  virtual bool SendAttachmentToProcess(
+      const scoped_refptr<BrokerableAttachment>& attachment,
+      base::ProcessId destination_process) = 0;
+
+  // Returns whether the attachment was available. If the attachment was
+  // available, populates the output parameter |attachment|.
+  bool GetAttachmentWithId(BrokerableAttachment::AttachmentId id,
+                           scoped_refptr<BrokerableAttachment>* attachment);
+
+  // Any given observer should only ever add itself once to the observer list.
+  // Notifications to |observer| will be posted to |runner|.
+  // The |observer| is expected to call RemoveObserver() before being destroyed.
+  void AddObserver(Observer* observer,
+                   const scoped_refptr<base::SequencedTaskRunner>& runner);
+  void RemoveObserver(Observer* observer);
+
+  // These two methods should only be called by the broker process.
+  //
+  // Each unprivileged process should have one IPC channel on which it
+  // communicates attachment information with the broker process. In the broker
+  // process, these channels must be registered and deregistered with the
+  // Attachment Broker as they are created and destroyed.
+  //
+  // Invocations of Send() on |endpoint| will occur on thread bound to |runner|.
+  virtual void RegisterCommunicationChannel(
+      Endpoint* endpoint,
+      scoped_refptr<base::SingleThreadTaskRunner> runner);
+  virtual void DeregisterCommunicationChannel(Endpoint* endpoint);
+
+  // In each unprivileged process, exactly one channel should be used to
+  // communicate brokerable attachments with the broker process.
+  virtual void RegisterBrokerCommunicationChannel(Endpoint* endpoint);
+  virtual void DeregisterBrokerCommunicationChannel(Endpoint* endpoint);
+
+  // Informs the attachment broker that a channel endpoint has received its
+  // peer's PID.
+  virtual void ReceivedPeerPid(base::ProcessId peer_pid);
+
+  // True if and only if this broker is privileged.
+  virtual bool IsPrivilegedBroker();
+
+ protected:
+  using AttachmentVector = std::vector<scoped_refptr<BrokerableAttachment>>;
+
+  // Adds |attachment| to |attachments_|, and notifies the observers.
+  void HandleReceivedAttachment(
+      const scoped_refptr<BrokerableAttachment>& attachment);
+
+  // Informs the observers that a new BrokerableAttachment has been received.
+  void NotifyObservers(const BrokerableAttachment::AttachmentId& id);
+
+  // Informs the observer identified by |unique_id| that a new
+  // BrokerableAttachment has been received.
+  void NotifyObserver(int unique_id,
+                      const BrokerableAttachment::AttachmentId& id);
+
+  // This method is exposed for testing only.
+  AttachmentVector* get_attachments() { return &attachments_; }
+
+  base::Lock* get_lock() { return &lock_; }
+
+ private:
+#if defined(OS_WIN)
+  FRIEND_TEST_ALL_PREFIXES(AttachmentBrokerUnprivilegedWinTest,
+                           ReceiveValidMessage);
+  FRIEND_TEST_ALL_PREFIXES(AttachmentBrokerUnprivilegedWinTest,
+                           ReceiveInvalidMessage);
+#endif  // defined(OS_WIN)
+
+  // A vector of BrokerableAttachments that have been received, but not yet
+  // consumed.
+  // A std::vector is used instead of a std::map because this container is
+  // expected to have few elements, for which a std::vector is expected to have
+  // better performance.
+  AttachmentVector attachments_;
+
+  struct ObserverInfo {
+    ObserverInfo();
+    ObserverInfo(const ObserverInfo& other);
+    ~ObserverInfo();
+
+    Observer* observer;
+    int unique_id;
+
+    // Notifications must be dispatched onto |runner|.
+    scoped_refptr<base::SequencedTaskRunner> runner;
+  };
+  std::vector<ObserverInfo> observers_;
+
+  // This member holds the last id given to an ObserverInfo.
+  int last_unique_id_;
+
+  // The AttachmentBroker can be accessed from any thread, so modifications to
+  // internal state must be guarded by a lock.
+  base::Lock lock_;
+  DISALLOW_COPY_AND_ASSIGN(AttachmentBroker);
+};
+
+}  // namespace IPC
+
+#endif  // IPC_ATTACHMENT_BROKER_H_
diff --git a/ipc/brokerable_attachment.cc b/ipc/brokerable_attachment.cc
new file mode 100644
index 0000000..96ce5bb
--- /dev/null
+++ b/ipc/brokerable_attachment.cc
@@ -0,0 +1,72 @@
+// Copyright 2015 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 "ipc/brokerable_attachment.h"
+
+#include <stddef.h>
+
+#include "build/build_config.h"
+#include "ipc/attachment_broker.h"
+
+namespace IPC {
+
+// BrokerableAttachment::AttachmentId ------------------------------------------
+#if !USE_ATTACHMENT_BROKER
+// static
+BrokerableAttachment::AttachmentId
+BrokerableAttachment::AttachmentId::CreateIdWithRandomNonce() {
+  CHECK(false) << "Platforms that don't support attachment brokering shouldn't "
+                  "be trying to generating a random nonce.";
+  return AttachmentId();
+}
+#endif
+
+BrokerableAttachment::AttachmentId::AttachmentId() {
+  for (size_t i = 0; i < BrokerableAttachment::kNonceSize; ++i)
+    nonce[i] = 0;
+}
+
+BrokerableAttachment::AttachmentId::AttachmentId(const char* start_address,
+                                                 size_t size) {
+  DCHECK(size == BrokerableAttachment::kNonceSize);
+  for (size_t i = 0; i < BrokerableAttachment::kNonceSize; ++i)
+    nonce[i] = start_address[i];
+}
+
+void BrokerableAttachment::AttachmentId::SerializeToBuffer(char* start_address,
+                                                           size_t size) {
+  DCHECK(size == BrokerableAttachment::kNonceSize);
+  for (size_t i = 0; i < BrokerableAttachment::kNonceSize; ++i)
+    start_address[i] = nonce[i];
+}
+
+// BrokerableAttachment::BrokerableAttachment ----------------------------------
+
+BrokerableAttachment::BrokerableAttachment()
+    : id_(AttachmentId::CreateIdWithRandomNonce()) {}
+
+BrokerableAttachment::BrokerableAttachment(const AttachmentId& id) : id_(id) {}
+
+BrokerableAttachment::~BrokerableAttachment() {}
+
+BrokerableAttachment::AttachmentId BrokerableAttachment::GetIdentifier() const {
+  return id_;
+}
+
+bool BrokerableAttachment::NeedsBrokering() const {
+  return GetBrokerableType() == PLACEHOLDER;
+}
+
+BrokerableAttachment::Type BrokerableAttachment::GetType() const {
+  return TYPE_BROKERABLE_ATTACHMENT;
+}
+
+#if defined(OS_POSIX)
+base::PlatformFile BrokerableAttachment::TakePlatformFile() {
+  NOTREACHED();
+  return base::PlatformFile();
+}
+#endif  // OS_POSIX
+
+}  // namespace IPC
diff --git a/ipc/brokerable_attachment.h b/ipc/brokerable_attachment.h
new file mode 100644
index 0000000..50e7fd2
--- /dev/null
+++ b/ipc/brokerable_attachment.h
@@ -0,0 +1,91 @@
+// Copyright 2015 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.
+
+#ifndef IPC_BROKERABLE_ATTACHMENT_H_
+#define IPC_BROKERABLE_ATTACHMENT_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <algorithm>
+
+#include "base/macros.h"
+#include "build/build_config.h"
+#include "ipc/ipc_export.h"
+#include "ipc/ipc_message_attachment.h"
+
+namespace IPC {
+
+// This subclass of MessageAttachment requires an AttachmentBroker to be
+// attached to a Chrome IPC message.
+class IPC_EXPORT BrokerableAttachment : public MessageAttachment {
+ public:
+  static const size_t kNonceSize = 16;
+  // An id uniquely identifies an attachment sent via a broker.
+  struct IPC_EXPORT AttachmentId {
+    uint8_t nonce[kNonceSize];
+
+    // Generates an AttachmentId with an unguessable, random nonce.
+    static AttachmentId CreateIdWithRandomNonce();
+
+    // Creates an AttachmentId with a zeroed nonce. This should only be used by
+    // the IPC translation system, which requires that classes have a default
+    // constructor.
+    AttachmentId();
+
+    // Constructs an AttachmentId from a buffer.
+    AttachmentId(const char* start_address, size_t size);
+
+    // Writes the nonce into a buffer.
+    void SerializeToBuffer(char* start_address, size_t size);
+
+    bool operator==(const AttachmentId& rhs) const {
+      return std::equal(nonce, nonce + kNonceSize, rhs.nonce);
+    }
+
+    bool operator<(const AttachmentId& rhs) const {
+      return std::lexicographical_compare(nonce, nonce + kNonceSize, rhs.nonce,
+                                          rhs.nonce + kNonceSize);
+    }
+  };
+
+  enum BrokerableType {
+    PLACEHOLDER,
+    WIN_HANDLE,
+    MACH_PORT,
+  };
+
+  // The identifier is unique across all Chrome processes.
+  AttachmentId GetIdentifier() const;
+
+  // Whether the attachment still needs information from the broker before it
+  // can be used.
+  bool NeedsBrokering() const;
+
+  // Returns TYPE_BROKERABLE_ATTACHMENT
+  Type GetType() const override;
+
+  virtual BrokerableType GetBrokerableType() const = 0;
+
+// MessageAttachment override.
+#if defined(OS_POSIX)
+  base::PlatformFile TakePlatformFile() override;
+#endif  // OS_POSIX
+
+ protected:
+  BrokerableAttachment();
+  BrokerableAttachment(const AttachmentId& id);
+  ~BrokerableAttachment() override;
+
+ private:
+  // This member uniquely identifies a BrokerableAttachment across all Chrome
+  // processes.
+  const AttachmentId id_;
+
+  DISALLOW_COPY_AND_ASSIGN(BrokerableAttachment);
+};
+
+}  // namespace IPC
+
+#endif  // IPC_BROKERABLE_ATTACHMENT_H_
diff --git a/ipc/ipc_channel_handle.h b/ipc/ipc_channel_handle.h
new file mode 100644
index 0000000..2e9dc3e
--- /dev/null
+++ b/ipc/ipc_channel_handle.h
@@ -0,0 +1,70 @@
+// 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.
+
+#ifndef IPC_IPC_CHANNEL_HANDLE_H_
+#define IPC_IPC_CHANNEL_HANDLE_H_
+
+#include <string>
+
+#include "build/build_config.h"
+#include "mojo/public/cpp/system/message_pipe.h"
+
+#if defined(OS_POSIX)
+#include "base/file_descriptor_posix.h"
+#elif defined(OS_WIN)
+#include <windows.h>
+#endif  // defined (OS_WIN)
+
+// On Windows, any process can create an IPC channel and others can fetch
+// it by name.  We pass around the channel names over IPC.
+// On Windows the initialization of ChannelHandle with an existing pipe
+// handle is provided for convenience.
+// NOTE: A ChannelHandle with a pipe handle Will NOT be marshalled over IPC.
+
+// On POSIX, we instead pass around handles to channel endpoints via IPC.
+// When it's time to IPC a new channel endpoint around, we send both the
+// channel name as well as a base::FileDescriptor, which is itself a special
+// type that knows how to copy a socket endpoint over IPC.
+//
+// In sum, this data structure can be used to pass channel information by name
+// in both Windows and Posix. When passing a handle to a channel over IPC,
+// use this data structure only for POSIX.
+
+namespace IPC {
+
+struct ChannelHandle {
+  // Note that serialization for this object is defined in the ParamTraits
+  // template specialization in ipc_message_utils.h.
+  ChannelHandle() {}
+  // The name that is passed in should be an absolute path for Posix.
+  // Otherwise there may be a problem in IPC communication between
+  // processes with different working directories.
+  ChannelHandle(const std::string& n) : name(n) {}
+  ChannelHandle(const char* n) : name(n) {}
+#if defined(OS_WIN)
+  explicit ChannelHandle(HANDLE h) : pipe(h) {}
+#elif defined(OS_POSIX)
+  ChannelHandle(const std::string& n, const base::FileDescriptor& s)
+      : name(n), socket(s) {}
+#endif  // defined(OS_POSIX)
+  ChannelHandle(mojo::MessagePipeHandle h) : mojo_handle(h) {}
+
+  std::string name;
+#if defined(OS_POSIX)
+  base::FileDescriptor socket;
+#elif defined(OS_WIN)
+  // A simple container to automatically initialize pipe handle
+  struct PipeHandle {
+    PipeHandle() : handle(NULL) {}
+    PipeHandle(HANDLE h) : handle(h) {}
+    HANDLE handle;
+  };
+  PipeHandle pipe;
+#endif  // defined (OS_WIN)
+  mojo::MessagePipeHandle mojo_handle;
+};
+
+}  // namespace IPC
+
+#endif  // IPC_IPC_CHANNEL_HANDLE_H_
diff --git a/ipc/ipc_export.h b/ipc/ipc_export.h
new file mode 100644
index 0000000..e1cbe88
--- /dev/null
+++ b/ipc/ipc_export.h
@@ -0,0 +1,34 @@
+// Copyright (c) 2011 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.
+
+#ifndef IPC_IPC_EXPORT_H_
+#define IPC_IPC_EXPORT_H_
+
+// Defines IPC_EXPORT so that functionality implemented by the IPC module can be
+// exported to consumers.
+
+#if defined(COMPONENT_BUILD)
+#if defined(WIN32)
+
+#if defined(IPC_IMPLEMENTATION)
+#define IPC_EXPORT __declspec(dllexport)
+#else
+#define IPC_EXPORT __declspec(dllimport)
+#endif  // defined(IPC_IMPLEMENTATION)
+
+#else  // defined(WIN32)
+
+#if defined(IPC_IMPLEMENTATION)
+#define IPC_EXPORT __attribute__((visibility("default")))
+#else
+#define IPC_EXPORT
+#endif
+
+#endif
+
+#else  // defined(COMPONENT_BUILD)
+#define IPC_EXPORT
+#endif
+
+#endif  // IPC_IPC_EXPORT_H_
diff --git a/ipc/ipc_listener.h b/ipc/ipc_listener.h
new file mode 100644
index 0000000..0277086
--- /dev/null
+++ b/ipc/ipc_listener.h
@@ -0,0 +1,51 @@
+// 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.
+
+#ifndef IPC_IPC_LISTENER_H_
+#define IPC_IPC_LISTENER_H_
+
+#include <stdint.h>
+
+#include "build/build_config.h"
+#include "ipc/ipc_export.h"
+
+namespace IPC {
+
+class Message;
+
+// Implemented by consumers of a Channel to receive messages.
+class IPC_EXPORT Listener {
+ public:
+  // Called when a message is received.  Returns true iff the message was
+  // handled.
+  virtual bool OnMessageReceived(const Message& message) = 0;
+
+  // Called when the channel is connected and we have received the internal
+  // Hello message from the peer.
+  virtual void OnChannelConnected(int32_t peer_pid) {}
+
+  // Called when an error is detected that causes the channel to close.
+  // This method is not called when a channel is closed normally.
+  virtual void OnChannelError() {}
+
+  // Called when a message's deserialization failed.
+  virtual void OnBadMessageReceived(const Message& message) {}
+
+#if defined(OS_POSIX)
+  // Called on the server side when a channel that listens for connections
+  // denies an attempt to connect.
+  virtual void OnChannelDenied() {}
+
+  // Called on the server side when a channel that listens for connections
+  // has an error that causes the listening channel to close.
+  virtual void OnChannelListenError() {}
+#endif  // OS_POSIX
+
+ protected:
+  virtual ~Listener() {}
+};
+
+}  // namespace IPC
+
+#endif  // IPC_IPC_LISTENER_H_
diff --git a/ipc/ipc_message.cc b/ipc/ipc_message.cc
new file mode 100644
index 0000000..83ee495
--- /dev/null
+++ b/ipc/ipc_message.cc
@@ -0,0 +1,305 @@
+// 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 "ipc/ipc_message.h"
+
+#include <limits.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include "base/atomic_sequence_num.h"
+#include "base/logging.h"
+#include "build/build_config.h"
+#include "ipc/attachment_broker.h"
+#include "ipc/ipc_message_attachment.h"
+#include "ipc/ipc_message_attachment_set.h"
+#include "ipc/placeholder_brokerable_attachment.h"
+
+#if defined(OS_POSIX)
+#include "base/file_descriptor_posix.h"
+#include "ipc/ipc_platform_file_attachment_posix.h"
+#endif
+
+namespace {
+
+base::StaticAtomicSequenceNumber g_ref_num;
+
+// Create a reference number for identifying IPC messages in traces. The return
+// values has the reference number stored in the upper 24 bits, leaving the low
+// 8 bits set to 0 for use as flags.
+inline uint32_t GetRefNumUpper24() {
+  base::trace_event::TraceLog* trace_log =
+      base::trace_event::TraceLog::GetInstance();
+  uint32_t pid = trace_log ? trace_log->process_id() : 0;
+  uint32_t count = g_ref_num.GetNext();
+  // The 24 bit hash is composed of 14 bits of the count and 10 bits of the
+  // Process ID. With the current trace event buffer cap, the 14-bit count did
+  // not appear to wrap during a trace. Note that it is not a big deal if
+  // collisions occur, as this is only used for debugging and trace analysis.
+  return ((pid << 14) | (count & 0x3fff)) << 8;
+}
+
+}  // namespace
+
+namespace IPC {
+
+//------------------------------------------------------------------------------
+
+Message::~Message() {
+}
+
+Message::Message() : base::Pickle(sizeof(Header)) {
+  header()->routing = header()->type = 0;
+  header()->flags = GetRefNumUpper24();
+#if USE_ATTACHMENT_BROKER
+  header()->num_brokered_attachments = 0;
+#endif
+#if defined(OS_POSIX)
+  header()->num_fds = 0;
+  header()->pad = 0;
+#endif
+  Init();
+}
+
+Message::Message(int32_t routing_id, uint32_t type, PriorityValue priority)
+    : base::Pickle(sizeof(Header)) {
+  header()->routing = routing_id;
+  header()->type = type;
+  DCHECK((priority & 0xffffff00) == 0);
+  header()->flags = priority | GetRefNumUpper24();
+#if USE_ATTACHMENT_BROKER
+  header()->num_brokered_attachments = 0;
+#endif
+#if defined(OS_POSIX)
+  header()->num_fds = 0;
+  header()->pad = 0;
+#endif
+  Init();
+}
+
+Message::Message(const char* data, int data_len)
+    : base::Pickle(data, data_len) {
+  Init();
+}
+
+Message::Message(const Message& other) : base::Pickle(other) {
+  Init();
+  attachment_set_ = other.attachment_set_;
+  sender_pid_ = other.sender_pid_;
+}
+
+void Message::Init() {
+  dispatch_error_ = false;
+  sender_pid_ = base::kNullProcessId;
+#ifdef IPC_MESSAGE_LOG_ENABLED
+  received_time_ = 0;
+  dont_log_ = false;
+  log_data_ = NULL;
+#endif
+}
+
+Message& Message::operator=(const Message& other) {
+  *static_cast<base::Pickle*>(this) = other;
+  attachment_set_ = other.attachment_set_;
+  sender_pid_ = other.sender_pid_;
+  return *this;
+}
+
+void Message::SetHeaderValues(int32_t routing, uint32_t type, uint32_t flags) {
+  // This should only be called when the message is already empty.
+  DCHECK(payload_size() == 0);
+
+  header()->routing = routing;
+  header()->type = type;
+  header()->flags = flags;
+}
+
+void Message::EnsureMessageAttachmentSet() {
+  if (attachment_set_.get() == NULL)
+    attachment_set_ = new MessageAttachmentSet;
+}
+
+#ifdef IPC_MESSAGE_LOG_ENABLED
+void Message::set_sent_time(int64_t time) {
+  DCHECK((header()->flags & HAS_SENT_TIME_BIT) == 0);
+  header()->flags |= HAS_SENT_TIME_BIT;
+  WriteInt64(time);
+}
+
+int64_t Message::sent_time() const {
+  if ((header()->flags & HAS_SENT_TIME_BIT) == 0)
+    return 0;
+
+  const char* data = end_of_payload();
+  data -= sizeof(int64_t);
+  return *(reinterpret_cast<const int64_t*>(data));
+}
+
+void Message::set_received_time(int64_t time) const {
+  received_time_ = time;
+}
+#endif
+
+Message::NextMessageInfo::NextMessageInfo()
+    : message_size(0), message_found(false), pickle_end(nullptr),
+      message_end(nullptr) {}
+Message::NextMessageInfo::~NextMessageInfo() {}
+
+Message::SerializedAttachmentIds
+Message::SerializedIdsOfBrokerableAttachments() {
+  DCHECK(HasBrokerableAttachments());
+  std::vector<scoped_refptr<IPC::BrokerableAttachment>> attachments(
+      attachment_set_->GetBrokerableAttachments());
+  CHECK_LE(attachments.size(), std::numeric_limits<size_t>::max() /
+                                   BrokerableAttachment::kNonceSize);
+  size_t size = attachments.size() * BrokerableAttachment::kNonceSize;
+  char* buffer = static_cast<char*>(malloc(size));
+  for (size_t i = 0; i < attachments.size(); ++i) {
+    char* start_range = buffer + i * BrokerableAttachment::kNonceSize;
+    BrokerableAttachment::AttachmentId id = attachments[i]->GetIdentifier();
+    id.SerializeToBuffer(start_range, BrokerableAttachment::kNonceSize);
+  }
+  SerializedAttachmentIds ids;
+  ids.buffer = buffer;
+  ids.size = size;
+  return ids;
+}
+
+// static
+void Message::FindNext(const char* range_start,
+                       const char* range_end,
+                       NextMessageInfo* info) {
+  DCHECK(info);
+  info->message_found = false;
+  info->message_size = 0;
+
+  size_t pickle_size = 0;
+  if (!base::Pickle::PeekNext(sizeof(Header),
+                              range_start, range_end, &pickle_size))
+    return;
+
+  bool have_entire_pickle =
+      static_cast<size_t>(range_end - range_start) >= pickle_size;
+
+#if USE_ATTACHMENT_BROKER
+  // TODO(dskiba): determine message_size when entire pickle is not available
+
+  if (!have_entire_pickle)
+    return;
+
+  const char* pickle_end = range_start + pickle_size;
+
+  // The data is not copied.
+  Message message(range_start, static_cast<int>(pickle_size));
+  size_t num_attachments = message.header()->num_brokered_attachments;
+
+  // Check for possible overflows.
+  size_t max_size_t = std::numeric_limits<size_t>::max();
+  if (num_attachments >= max_size_t / BrokerableAttachment::kNonceSize)
+    return;
+
+  size_t attachment_length = num_attachments * BrokerableAttachment::kNonceSize;
+  if (pickle_size > max_size_t - attachment_length)
+    return;
+
+  // Check whether the range includes the attachments.
+  size_t buffer_length = static_cast<size_t>(range_end - range_start);
+  if (buffer_length < attachment_length + pickle_size)
+    return;
+
+  for (size_t i = 0; i < num_attachments; ++i) {
+    const char* attachment_start =
+        pickle_end + i * BrokerableAttachment::kNonceSize;
+    BrokerableAttachment::AttachmentId id(attachment_start,
+                                          BrokerableAttachment::kNonceSize);
+    info->attachment_ids.push_back(id);
+  }
+  info->message_end =
+      pickle_end + num_attachments * BrokerableAttachment::kNonceSize;
+  info->message_size = info->message_end - range_start;
+#else
+  info->message_size = pickle_size;
+
+  if (!have_entire_pickle)
+    return;
+
+  const char* pickle_end = range_start + pickle_size;
+
+  info->message_end = pickle_end;
+#endif  // USE_ATTACHMENT_BROKER
+
+  info->pickle_end = pickle_end;
+  info->message_found = true;
+}
+
+bool Message::AddPlaceholderBrokerableAttachmentWithId(
+    BrokerableAttachment::AttachmentId id) {
+  scoped_refptr<PlaceholderBrokerableAttachment> attachment(
+      new PlaceholderBrokerableAttachment(id));
+  return attachment_set()->AddAttachment(attachment);
+}
+
+bool Message::WriteAttachment(
+    scoped_refptr<base::Pickle::Attachment> attachment) {
+  bool brokerable;
+  size_t index;
+  bool success = attachment_set()->AddAttachment(
+      make_scoped_refptr(static_cast<MessageAttachment*>(attachment.get())),
+      &index, &brokerable);
+  DCHECK(success);
+
+  // NOTE: If you add more data to the pickle, make sure to update
+  // PickleSizer::AddAttachment.
+
+  // Write the type of descriptor.
+  WriteBool(brokerable);
+
+  // Write the index of the descriptor so that we don't have to
+  // keep the current descriptor as extra decoding state when deserialising.
+  WriteInt(static_cast<int>(index));
+
+#if USE_ATTACHMENT_BROKER
+  if (brokerable)
+    header()->num_brokered_attachments++;
+#endif
+
+  return success;
+}
+
+bool Message::ReadAttachment(
+    base::PickleIterator* iter,
+    scoped_refptr<base::Pickle::Attachment>* attachment) const {
+  bool brokerable;
+  if (!iter->ReadBool(&brokerable))
+    return false;
+
+  int index;
+  if (!iter->ReadInt(&index))
+    return false;
+
+  MessageAttachmentSet* attachment_set = attachment_set_.get();
+  if (!attachment_set)
+    return false;
+
+  *attachment = brokerable
+                    ? attachment_set->GetBrokerableAttachmentAt(index)
+                    : attachment_set->GetNonBrokerableAttachmentAt(index);
+
+  return nullptr != attachment->get();
+}
+
+bool Message::HasAttachments() const {
+  return attachment_set_.get() && !attachment_set_->empty();
+}
+
+bool Message::HasMojoHandles() const {
+  return attachment_set_.get() && attachment_set_->num_mojo_handles() > 0;
+}
+
+bool Message::HasBrokerableAttachments() const {
+  return attachment_set_.get() &&
+         attachment_set_->num_brokerable_attachments() > 0;
+}
+
+}  // namespace IPC
diff --git a/ipc/ipc_message.h b/ipc/ipc_message.h
new file mode 100644
index 0000000..56c3a46
--- /dev/null
+++ b/ipc/ipc_message.h
@@ -0,0 +1,346 @@
+// 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.
+
+#ifndef IPC_IPC_MESSAGE_H_
+#define IPC_IPC_MESSAGE_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <string>
+
+#include "base/gtest_prod_util.h"
+#include "base/memory/ref_counted.h"
+#include "base/pickle.h"
+#include "base/trace_event/trace_event.h"
+#include "build/build_config.h"
+#include "ipc/attachment_broker.h"
+#include "ipc/brokerable_attachment.h"
+#include "ipc/ipc_export.h"
+
+#if !defined(NDEBUG)
+#define IPC_MESSAGE_LOG_ENABLED
+#endif
+
+namespace IPC {
+
+namespace internal {
+class ChannelReader;
+}  // namespace internal
+
+//------------------------------------------------------------------------------
+
+struct LogData;
+class MessageAttachment;
+class MessageAttachmentSet;
+
+class IPC_EXPORT Message : public base::Pickle {
+ public:
+  enum PriorityValue {
+    PRIORITY_LOW = 1,
+    PRIORITY_NORMAL,
+    PRIORITY_HIGH
+  };
+
+  // Bit values used in the flags field.
+  // Upper 24 bits of flags store a reference number, so this enum is limited to
+  // 8 bits.
+  enum {
+    PRIORITY_MASK     = 0x03,  // Low 2 bits of store the priority value.
+    SYNC_BIT          = 0x04,
+    REPLY_BIT         = 0x08,
+    REPLY_ERROR_BIT   = 0x10,
+    UNBLOCK_BIT       = 0x20,
+    PUMPING_MSGS_BIT  = 0x40,
+    HAS_SENT_TIME_BIT = 0x80,
+  };
+
+  ~Message() override;
+
+  Message();
+
+  // Initialize a message with a user-defined type, priority value, and
+  // destination WebView ID.
+  Message(int32_t routing_id, uint32_t type, PriorityValue priority);
+
+  // Initializes a message from a const block of data.  The data is not copied;
+  // instead the data is merely referenced by this message.  Only const methods
+  // should be used on the message when initialized this way.
+  Message(const char* data, int data_len);
+
+  Message(const Message& other);
+  Message& operator=(const Message& other);
+
+  PriorityValue priority() const {
+    return static_cast<PriorityValue>(header()->flags & PRIORITY_MASK);
+  }
+
+  // True if this is a synchronous message.
+  void set_sync() {
+    header()->flags |= SYNC_BIT;
+  }
+  bool is_sync() const {
+    return (header()->flags & SYNC_BIT) != 0;
+  }
+
+  // Set this on a reply to a synchronous message.
+  void set_reply() {
+    header()->flags |= REPLY_BIT;
+  }
+
+  bool is_reply() const {
+    return (header()->flags & REPLY_BIT) != 0;
+  }
+
+  // Set this on a reply to a synchronous message to indicate that no receiver
+  // was found.
+  void set_reply_error() {
+    header()->flags |= REPLY_ERROR_BIT;
+  }
+
+  bool is_reply_error() const {
+    return (header()->flags & REPLY_ERROR_BIT) != 0;
+  }
+
+  // Normally when a receiver gets a message and they're blocked on a
+  // synchronous message Send, they buffer a message.  Setting this flag causes
+  // the receiver to be unblocked and the message to be dispatched immediately.
+  void set_unblock(bool unblock) {
+    if (unblock) {
+      header()->flags |= UNBLOCK_BIT;
+    } else {
+      header()->flags &= ~UNBLOCK_BIT;
+    }
+  }
+
+  bool should_unblock() const {
+    return (header()->flags & UNBLOCK_BIT) != 0;
+  }
+
+  // Tells the receiver that the caller is pumping messages while waiting
+  // for the result.
+  bool is_caller_pumping_messages() const {
+    return (header()->flags & PUMPING_MSGS_BIT) != 0;
+  }
+
+  void set_dispatch_error() const {
+    dispatch_error_ = true;
+  }
+
+  bool dispatch_error() const {
+    return dispatch_error_;
+  }
+
+  uint32_t type() const {
+    return header()->type;
+  }
+
+  int32_t routing_id() const {
+    return header()->routing;
+  }
+
+  void set_routing_id(int32_t new_id) {
+    header()->routing = new_id;
+  }
+
+  uint32_t flags() const {
+    return header()->flags;
+  }
+
+  // Sets all the given header values. The message should be empty at this
+  // call.
+  void SetHeaderValues(int32_t routing, uint32_t type, uint32_t flags);
+
+  template<class T, class S, class P>
+  static bool Dispatch(const Message* msg, T* obj, S* sender, P* parameter,
+                       void (T::*func)()) {
+    (obj->*func)();
+    return true;
+  }
+
+  template<class T, class S, class P>
+  static bool Dispatch(const Message* msg, T* obj, S* sender, P* parameter,
+                       void (T::*func)(P*)) {
+    (obj->*func)(parameter);
+    return true;
+  }
+
+  // Used for async messages with no parameters.
+  static void Log(std::string* name, const Message* msg, std::string* l) {
+  }
+
+  // The static method FindNext() returns several pieces of information, which
+  // are aggregated into an instance of this struct.
+  struct IPC_EXPORT NextMessageInfo {
+    NextMessageInfo();
+    ~NextMessageInfo();
+
+    // Total message size. Always valid if |message_found| is true.
+    // If |message_found| is false but we could determine message size
+    // from the header, this field is non-zero. Otherwise it's zero.
+    size_t message_size;
+    // Whether an entire message was found in the given memory range.
+    bool message_found;
+    // Only filled in if |message_found| is true.
+    // The start address is passed into FindNext() by the caller, so isn't
+    // repeated in this struct. The end address of the pickle should be used to
+    // construct a base::Pickle.
+    const char* pickle_end;
+    // Only filled in if |message_found| is true.
+    // The end address of the message should be used to determine the start
+    // address of the next message.
+    const char* message_end;
+    // If the message has brokerable attachments, this vector will contain the
+    // ids of the brokerable attachments. The caller of FindNext() is
+    // responsible for adding the attachments to the message.
+    std::vector<BrokerableAttachment::AttachmentId> attachment_ids;
+  };
+
+  struct SerializedAttachmentIds {
+    void* buffer;
+    size_t size;
+  };
+  // Creates a buffer that contains a serialization of the ids of the brokerable
+  // attachments of the message. This buffer is intended to be sent over the IPC
+  // channel immediately after the pickled message. The caller takes ownership
+  // of the buffer.
+  // This method should only be called if the message has brokerable
+  // attachments.
+  SerializedAttachmentIds SerializedIdsOfBrokerableAttachments();
+
+  // |info| is an output parameter and must not be nullptr.
+  static void FindNext(const char* range_start,
+                       const char* range_end,
+                       NextMessageInfo* info);
+
+  // Adds a placeholder brokerable attachment that must be replaced before the
+  // message can be dispatched.
+  bool AddPlaceholderBrokerableAttachmentWithId(
+      BrokerableAttachment::AttachmentId id);
+
+  // WriteAttachment appends |attachment| to the end of the set. It returns
+  // false iff the set is full.
+  bool WriteAttachment(
+      scoped_refptr<base::Pickle::Attachment> attachment) override;
+  // ReadAttachment parses an attachment given the parsing state |iter| and
+  // writes it to |*attachment|. It returns true on success.
+  bool ReadAttachment(
+      base::PickleIterator* iter,
+      scoped_refptr<base::Pickle::Attachment>* attachment) const override;
+  // Returns true if there are any attachment in this message.
+  bool HasAttachments() const override;
+  // Returns true if there are any MojoHandleAttachments in this message.
+  bool HasMojoHandles() const;
+  // Whether the message has any brokerable attachments.
+  bool HasBrokerableAttachments() const;
+
+  void set_sender_pid(base::ProcessId id) { sender_pid_ = id; }
+  base::ProcessId get_sender_pid() const { return sender_pid_; }
+
+#ifdef IPC_MESSAGE_LOG_ENABLED
+  // Adds the outgoing time from Time::Now() at the end of the message and sets
+  // a bit to indicate that it's been added.
+  void set_sent_time(int64_t time);
+  int64_t sent_time() const;
+
+  void set_received_time(int64_t time) const;
+  int64_t received_time() const { return received_time_; }
+  void set_output_params(const std::string& op) const { output_params_ = op; }
+  const std::string& output_params() const { return output_params_; }
+  // The following four functions are needed so we can log sync messages with
+  // delayed replies.  We stick the log data from the sent message into the
+  // reply message, so that when it's sent and we have the output parameters
+  // we can log it.  As such, we set a flag on the sent message to not log it.
+  void set_sync_log_data(LogData* data) const { log_data_ = data; }
+  LogData* sync_log_data() const { return log_data_; }
+  void set_dont_log() const { dont_log_ = true; }
+  bool dont_log() const { return dont_log_; }
+#endif
+
+ protected:
+  friend class Channel;
+  friend class ChannelMojo;
+  friend class ChannelNacl;
+  friend class ChannelPosix;
+  friend class ChannelWin;
+  friend class internal::ChannelReader;
+  friend class MessageReplyDeserializer;
+  friend class SyncMessage;
+
+#pragma pack(push, 4)
+  struct Header : base::Pickle::Header {
+    int32_t routing;  // ID of the view that this message is destined for
+    uint32_t type;    // specifies the user-defined message type
+    uint32_t flags;   // specifies control flags for the message
+#if USE_ATTACHMENT_BROKER
+    // The number of brokered attachments included with this message. The
+    // ids of the brokered attachment ids are sent immediately after the pickled
+    // message, before the next pickled message is sent.
+    uint32_t num_brokered_attachments;
+#endif
+#if defined(OS_POSIX)
+    uint16_t num_fds; // the number of descriptors included with this message
+    uint16_t pad;     // explicitly initialize this to appease valgrind
+#endif
+  };
+#pragma pack(pop)
+
+  Header* header() {
+    return headerT<Header>();
+  }
+  const Header* header() const {
+    return headerT<Header>();
+  }
+
+  void Init();
+
+  // Used internally to support IPC::Listener::OnBadMessageReceived.
+  mutable bool dispatch_error_;
+
+  // The set of file descriptors associated with this message.
+  scoped_refptr<MessageAttachmentSet> attachment_set_;
+
+  // Ensure that a MessageAttachmentSet is allocated
+  void EnsureMessageAttachmentSet();
+
+  MessageAttachmentSet* attachment_set() {
+    EnsureMessageAttachmentSet();
+    return attachment_set_.get();
+  }
+  const MessageAttachmentSet* attachment_set() const {
+    return attachment_set_.get();
+  }
+
+  // The process id of the sender of the message. This member is populated with
+  // a valid value for every message dispatched to listeners.
+  base::ProcessId sender_pid_;
+
+#ifdef IPC_MESSAGE_LOG_ENABLED
+  // Used for logging.
+  mutable int64_t received_time_;
+  mutable std::string output_params_;
+  mutable LogData* log_data_;
+  mutable bool dont_log_;
+#endif
+
+  FRIEND_TEST_ALL_PREFIXES(IPCMessageTest, FindNext);
+  FRIEND_TEST_ALL_PREFIXES(IPCMessageTest, FindNextOverflow);
+};
+
+//------------------------------------------------------------------------------
+
+}  // namespace IPC
+
+enum SpecialRoutingIDs {
+  // indicates that we don't have a routing ID yet.
+  MSG_ROUTING_NONE = -2,
+
+  // indicates a general message not sent to a particular tab.
+  MSG_ROUTING_CONTROL = INT32_MAX,
+};
+
+#define IPC_REPLY_ID 0xFFFFFFF0  // Special message id for replies
+#define IPC_LOGGING_ID 0xFFFFFFF1  // Special message id for logging
+
+#endif  // IPC_IPC_MESSAGE_H_
diff --git a/ipc/ipc_message_attachment.cc b/ipc/ipc_message_attachment.cc
new file mode 100644
index 0000000..83440ae
--- /dev/null
+++ b/ipc/ipc_message_attachment.cc
@@ -0,0 +1,15 @@
+// Copyright (c) 2015 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 "ipc/ipc_message_attachment.h"
+
+namespace IPC {
+
+MessageAttachment::MessageAttachment() {
+}
+
+MessageAttachment::~MessageAttachment() {
+}
+
+}  // namespace IPC
diff --git a/ipc/ipc_message_attachment.h b/ipc/ipc_message_attachment.h
new file mode 100644
index 0000000..7f7137d
--- /dev/null
+++ b/ipc/ipc_message_attachment.h
@@ -0,0 +1,43 @@
+// Copyright (c) 2015 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.
+
+#ifndef IPC_IPC_MESSAGE_ATTACHMENT_H_
+#define IPC_IPC_MESSAGE_ATTACHMENT_H_
+
+#include "base/files/file.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/pickle.h"
+#include "build/build_config.h"
+#include "ipc/ipc_export.h"
+
+namespace IPC {
+
+// Auxiliary data sent with |Message|. This can be a platform file descriptor
+// or a mojo |MessagePipe|. |GetType()| returns the type of the subclass.
+class IPC_EXPORT MessageAttachment : public base::Pickle::Attachment {
+ public:
+  enum Type {
+    TYPE_PLATFORM_FILE,          // The instance is |PlatformFileAttachment|.
+    TYPE_MOJO_HANDLE,            // The instance is |MojoHandleAttachment|.
+    TYPE_BROKERABLE_ATTACHMENT,  // The instance is |BrokerableAttachment|.
+  };
+
+  virtual Type GetType() const = 0;
+
+#if defined(OS_POSIX)
+  virtual base::PlatformFile TakePlatformFile() = 0;
+#endif  // OS_POSIX
+
+ protected:
+  friend class base::RefCountedThreadSafe<MessageAttachment>;
+  MessageAttachment();
+  ~MessageAttachment() override;
+
+  DISALLOW_COPY_AND_ASSIGN(MessageAttachment);
+};
+
+}  // namespace IPC
+
+#endif  // IPC_IPC_MESSAGE_ATTACHMENT_H_
diff --git a/ipc/ipc_message_attachment_set.cc b/ipc/ipc_message_attachment_set.cc
new file mode 100644
index 0000000..3b7eefb
--- /dev/null
+++ b/ipc/ipc_message_attachment_set.cc
@@ -0,0 +1,250 @@
+// Copyright (c) 2011 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 "ipc/ipc_message_attachment_set.h"
+
+#include <stddef.h>
+
+#include <algorithm>
+
+#include "base/logging.h"
+#include "base/posix/eintr_wrapper.h"
+#include "build/build_config.h"
+#include "ipc/brokerable_attachment.h"
+#include "ipc/ipc_message_attachment.h"
+
+#if defined(OS_POSIX)
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include "ipc/ipc_platform_file_attachment_posix.h"
+#endif // OS_POSIX
+
+namespace IPC {
+
+namespace {
+
+unsigned count_attachments_of_type(
+    const std::vector<scoped_refptr<MessageAttachment>>& attachments,
+    MessageAttachment::Type type) {
+  unsigned count = 0;
+  for (const scoped_refptr<MessageAttachment>& attachment : attachments) {
+    if (attachment->GetType() == type)
+      ++count;
+  }
+  return count;
+}
+
+}  // namespace
+
+MessageAttachmentSet::MessageAttachmentSet()
+    : consumed_descriptor_highwater_(0) {
+}
+
+MessageAttachmentSet::~MessageAttachmentSet() {
+  if (consumed_descriptor_highwater_ == num_non_brokerable_attachments())
+    return;
+
+  // We close all the owning descriptors. If this message should have
+  // been transmitted, then closing those with close flags set mirrors
+  // the expected behaviour.
+  //
+  // If this message was received with more descriptors than expected
+  // (which could a DOS against the browser by a rogue renderer) then all
+  // the descriptors have their close flag set and we free all the extra
+  // kernel resources.
+  LOG(WARNING) << "MessageAttachmentSet destroyed with unconsumed descriptors: "
+               << consumed_descriptor_highwater_ << "/" << num_descriptors();
+}
+
+unsigned MessageAttachmentSet::num_descriptors() const {
+  return count_attachments_of_type(attachments_,
+                                   MessageAttachment::TYPE_PLATFORM_FILE);
+}
+
+unsigned MessageAttachmentSet::num_mojo_handles() const {
+  return count_attachments_of_type(attachments_,
+                                   MessageAttachment::TYPE_MOJO_HANDLE);
+}
+
+unsigned MessageAttachmentSet::num_brokerable_attachments() const {
+  return static_cast<unsigned>(brokerable_attachments_.size());
+}
+
+unsigned MessageAttachmentSet::num_non_brokerable_attachments() const {
+  return static_cast<unsigned>(attachments_.size());
+}
+
+unsigned MessageAttachmentSet::size() const {
+  return static_cast<unsigned>(attachments_.size() +
+                               brokerable_attachments_.size());
+}
+
+bool MessageAttachmentSet::AddAttachment(
+    scoped_refptr<MessageAttachment> attachment,
+    size_t* index,
+    bool* brokerable) {
+#if defined(OS_POSIX)
+  if (attachment->GetType() == MessageAttachment::TYPE_PLATFORM_FILE &&
+      num_descriptors() == kMaxDescriptorsPerMessage) {
+    DLOG(WARNING) << "Cannot add file descriptor. MessageAttachmentSet full.";
+    return false;
+  }
+#endif
+
+  switch (attachment->GetType()) {
+    case MessageAttachment::TYPE_PLATFORM_FILE:
+    case MessageAttachment::TYPE_MOJO_HANDLE:
+      attachments_.push_back(attachment);
+      *index = attachments_.size() - 1;
+      *brokerable = false;
+      return true;
+    case MessageAttachment::TYPE_BROKERABLE_ATTACHMENT:
+      BrokerableAttachment* brokerable_attachment =
+          static_cast<BrokerableAttachment*>(attachment.get());
+      scoped_refptr<BrokerableAttachment> a(brokerable_attachment);
+      brokerable_attachments_.push_back(a);
+      *index = brokerable_attachments_.size() - 1;
+      *brokerable = true;
+      return true;
+  }
+  return false;
+}
+
+bool MessageAttachmentSet::AddAttachment(
+    scoped_refptr<MessageAttachment> attachment) {
+  bool brokerable;
+  size_t index;
+  return AddAttachment(attachment, &index, &brokerable);
+}
+
+scoped_refptr<MessageAttachment>
+MessageAttachmentSet::GetNonBrokerableAttachmentAt(unsigned index) {
+  if (index >= num_non_brokerable_attachments()) {
+    DLOG(WARNING) << "Accessing out of bound index:" << index << "/"
+                  << num_non_brokerable_attachments();
+    return scoped_refptr<MessageAttachment>();
+  }
+
+  // We should always walk the descriptors in order, so it's reasonable to
+  // enforce this. Consider the case where a compromised renderer sends us
+  // the following message:
+  //
+  //   ExampleMsg:
+  //     num_fds:2 msg:FD(index = 1) control:SCM_RIGHTS {n, m}
+  //
+  // Here the renderer sent us a message which should have a descriptor, but
+  // actually sent two in an attempt to fill our fd table and kill us. By
+  // setting the index of the descriptor in the message to 1 (it should be
+  // 0), we would record a highwater of 1 and then consider all the
+  // descriptors to have been used.
+  //
+  // So we can either track of the use of each descriptor in a bitset, or we
+  // can enforce that we walk the indexes strictly in order.
+  //
+  // There's one more wrinkle: When logging messages, we may reparse them. So
+  // we have an exception: When the consumed_descriptor_highwater_ is at the
+  // end of the array and index 0 is requested, we reset the highwater value.
+  // TODO(morrita): This is absurd. This "wringle" disallow to introduce clearer
+  // ownership model. Only client is NaclIPCAdapter. See crbug.com/415294
+  if (index == 0 &&
+      consumed_descriptor_highwater_ == num_non_brokerable_attachments()) {
+    consumed_descriptor_highwater_ = 0;
+  }
+
+  if (index != consumed_descriptor_highwater_)
+    return scoped_refptr<MessageAttachment>();
+
+  consumed_descriptor_highwater_ = index + 1;
+
+  return attachments_[index];
+}
+
+scoped_refptr<MessageAttachment>
+MessageAttachmentSet::GetBrokerableAttachmentAt(unsigned index) {
+  if (index >= num_brokerable_attachments()) {
+    DLOG(WARNING) << "Accessing out of bound index:" << index << "/"
+                  << num_brokerable_attachments();
+    return scoped_refptr<MessageAttachment>();
+  }
+
+  scoped_refptr<BrokerableAttachment> brokerable_attachment(
+      brokerable_attachments_[index]);
+  return scoped_refptr<MessageAttachment>(brokerable_attachment.get());
+}
+
+void MessageAttachmentSet::CommitAllDescriptors() {
+  attachments_.clear();
+  consumed_descriptor_highwater_ = 0;
+}
+
+std::vector<scoped_refptr<IPC::BrokerableAttachment>>
+MessageAttachmentSet::GetBrokerableAttachments() const {
+  return brokerable_attachments_;
+}
+
+void MessageAttachmentSet::ReplacePlaceholderWithAttachment(
+    const scoped_refptr<BrokerableAttachment>& attachment) {
+  DCHECK_NE(BrokerableAttachment::PLACEHOLDER, attachment->GetBrokerableType());
+  for (auto it = brokerable_attachments_.begin();
+       it != brokerable_attachments_.end(); ++it) {
+    if ((*it)->GetBrokerableType() == BrokerableAttachment::PLACEHOLDER &&
+        (*it)->GetIdentifier() == attachment->GetIdentifier()) {
+      *it = attachment;
+      return;
+    }
+  }
+
+  // This function should only be called if there is a placeholder ready to be
+  // replaced.
+  NOTREACHED();
+}
+
+#if defined(OS_POSIX)
+
+void MessageAttachmentSet::PeekDescriptors(base::PlatformFile* buffer) const {
+  for (size_t i = 0; i != attachments_.size(); ++i)
+    buffer[i] = internal::GetPlatformFile(attachments_[i]);
+}
+
+bool MessageAttachmentSet::ContainsDirectoryDescriptor() const {
+  struct stat st;
+
+  for (auto i = attachments_.begin(); i != attachments_.end(); ++i) {
+    if (fstat(internal::GetPlatformFile(*i), &st) == 0 && S_ISDIR(st.st_mode))
+      return true;
+  }
+
+  return false;
+}
+
+void MessageAttachmentSet::ReleaseFDsToClose(
+    std::vector<base::PlatformFile>* fds) {
+  for (size_t i = 0; i < attachments_.size(); ++i) {
+    internal::PlatformFileAttachment* file =
+        static_cast<internal::PlatformFileAttachment*>(attachments_[i].get());
+    if (file->Owns())
+      fds->push_back(file->TakePlatformFile());
+  }
+
+  CommitAllDescriptors();
+}
+
+void MessageAttachmentSet::AddDescriptorsToOwn(const base::PlatformFile* buffer,
+                                               unsigned count) {
+  DCHECK(count <= kMaxDescriptorsPerMessage);
+  DCHECK_EQ(num_descriptors(), 0u);
+  DCHECK_EQ(consumed_descriptor_highwater_, 0u);
+
+  attachments_.reserve(count);
+  for (unsigned i = 0; i < count; ++i)
+    AddAttachment(
+        new internal::PlatformFileAttachment(base::ScopedFD(buffer[i])));
+}
+
+#endif  // OS_POSIX
+
+}  // namespace IPC
+
+
diff --git a/ipc/ipc_message_attachment_set.h b/ipc/ipc_message_attachment_set.h
new file mode 100644
index 0000000..764c818
--- /dev/null
+++ b/ipc/ipc_message_attachment_set.h
@@ -0,0 +1,163 @@
+// Copyright (c) 2011 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.
+
+#ifndef IPC_IPC_MESSAGE_ATTACHMENT_SET_H_
+#define IPC_IPC_MESSAGE_ATTACHMENT_SET_H_
+
+#include <stddef.h>
+
+#include <vector>
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "build/build_config.h"
+#include "ipc/ipc_export.h"
+
+#if defined(OS_POSIX)
+#include "base/files/file.h"
+#endif
+
+namespace IPC {
+
+class BrokerableAttachment;
+class MessageAttachment;
+
+// -----------------------------------------------------------------------------
+// A MessageAttachmentSet is an ordered set of MessageAttachment objects
+// associated with an IPC message. There are three types of MessageAttachments:
+//   1) TYPE_PLATFORM_FILE is transmitted over the Channel's underlying
+//   UNIX domain socket
+//   2) TYPE_MOJO_HANDLE is transmitted over the Mojo MessagePipe.
+//   3) TYPE_BROKERABLE_ATTACHMENT is transmitted by the Attachment Broker.
+// Any given IPC Message can have attachments of type (1) or (2), but not both.
+// These are stored in |attachments_|. Attachments of type (3) are stored in
+// |brokerable_attachments_|.
+//
+// To produce a deterministic ordering, all attachments in |attachments_| are
+// considered to come before those in |brokerable_attachments_|. These
+// attachments are transmitted across different communication channels, and
+// multiplexed by the receiver, so ordering between them cannot be guaranteed.
+//
+// -----------------------------------------------------------------------------
+class IPC_EXPORT MessageAttachmentSet
+    : public base::RefCountedThreadSafe<MessageAttachmentSet> {
+ public:
+  MessageAttachmentSet();
+
+  // Return the number of attachments
+  unsigned size() const;
+  // Return the number of file descriptors
+  unsigned num_descriptors() const;
+  // Return the number of mojo handles in the attachment set
+  unsigned num_mojo_handles() const;
+  // Return the number of brokerable attachments in the attachment set.
+  unsigned num_brokerable_attachments() const;
+  // Return the number of non-brokerable attachments in the attachment set.
+  unsigned num_non_brokerable_attachments() const;
+
+  // Return true if no unconsumed descriptors remain
+  bool empty() const { return 0 == size(); }
+
+  // Returns whether the attachment was successfully added.
+  // |index| is an output variable. On success, it contains the index of the
+  // newly added attachment.
+  // |brokerable| is an output variable. On success, it describes which vector
+  // the attachment was added to.
+  bool AddAttachment(scoped_refptr<MessageAttachment> attachment,
+                     size_t* index,
+                     bool* brokerable);
+
+  // Similar to the above method, but without output variables.
+  bool AddAttachment(scoped_refptr<MessageAttachment> attachment);
+
+  // Take the nth non-brokerable attachment from the beginning of the vector,
+  // Code using this /must/ access the attachments in order, and must do it at
+  // most once.
+  //
+  // This interface is designed for the deserialising code as it doesn't
+  // support close flags.
+  //   returns: an attachment, or nullptr on error
+  scoped_refptr<MessageAttachment> GetNonBrokerableAttachmentAt(unsigned index);
+
+  // Similar to GetNonBrokerableAttachmentAt, but there are no ordering
+  // requirements.
+  scoped_refptr<MessageAttachment> GetBrokerableAttachmentAt(unsigned index);
+
+  // This must be called after transmitting the descriptors returned by
+  // PeekDescriptors. It marks all the non-brokerable descriptors as consumed
+  // and closes those which are auto-close.
+  void CommitAllDescriptors();
+
+  // Returns a vector of all brokerable attachments.
+  std::vector<scoped_refptr<IPC::BrokerableAttachment>>
+  GetBrokerableAttachments() const;
+
+  // Replaces a placeholder brokerable attachment with |attachment|, matching
+  // them by their id.
+  void ReplacePlaceholderWithAttachment(
+      const scoped_refptr<BrokerableAttachment>& attachment);
+
+#if defined(OS_POSIX)
+  // This is the maximum number of descriptors per message. We need to know this
+  // because the control message kernel interface has to be given a buffer which
+  // is large enough to store all the descriptor numbers. Otherwise the kernel
+  // tells us that it truncated the control data and the extra descriptors are
+  // lost.
+  //
+  // In debugging mode, it's a fatal error to try and add more than this number
+  // of descriptors to a MessageAttachmentSet.
+  static const size_t kMaxDescriptorsPerMessage = 7;
+
+  // ---------------------------------------------------------------------------
+  // Interfaces for transmission...
+
+  // Fill an array with file descriptors without 'consuming' them.
+  // CommitAllDescriptors must be called after these descriptors have been
+  // transmitted.
+  //   buffer: (output) a buffer of, at least, size() integers.
+  void PeekDescriptors(base::PlatformFile* buffer) const;
+  // Returns true if any contained file descriptors appear to be handles to a
+  // directory.
+  bool ContainsDirectoryDescriptor() const;
+  // Fetch all filedescriptors with the "auto close" property. Used instead of
+  // CommitAllDescriptors() when closing must be handled manually.
+  void ReleaseFDsToClose(std::vector<base::PlatformFile>* fds);
+
+  // ---------------------------------------------------------------------------
+
+  // ---------------------------------------------------------------------------
+  // Interfaces for receiving...
+
+  // Set the contents of the set from the given buffer. This set must be empty
+  // before calling. The auto-close flag is set on all the descriptors so that
+  // unconsumed descriptors are closed on destruction.
+  void AddDescriptorsToOwn(const base::PlatformFile* buffer, unsigned count);
+
+#endif  // OS_POSIX
+
+  // ---------------------------------------------------------------------------
+
+ private:
+  friend class base::RefCountedThreadSafe<MessageAttachmentSet>;
+
+  ~MessageAttachmentSet();
+
+  // All elements either have type TYPE_PLATFORM_FILE or TYPE_MOJO_HANDLE.
+  std::vector<scoped_refptr<MessageAttachment>> attachments_;
+
+  // All elements have type TYPE_BROKERABLE_ATTACHMENT.
+  std::vector<scoped_refptr<BrokerableAttachment>> brokerable_attachments_;
+
+  // This contains the index of the next descriptor which should be consumed.
+  // It's used in a couple of ways. Firstly, at destruction we can check that
+  // all the descriptors have been read (with GetNthDescriptor). Secondly, we
+  // can check that they are read in order.
+  mutable unsigned consumed_descriptor_highwater_;
+
+  DISALLOW_COPY_AND_ASSIGN(MessageAttachmentSet);
+};
+
+}  // namespace IPC
+
+#endif  // IPC_IPC_MESSAGE_ATTACHMENT_SET_H_
diff --git a/ipc/ipc_message_start.h b/ipc/ipc_message_start.h
new file mode 100644
index 0000000..c1e1b9f
--- /dev/null
+++ b/ipc/ipc_message_start.h
@@ -0,0 +1,133 @@
+// Copyright 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.
+
+#ifndef IPC_IPC_MESSAGE_START_H_
+#define IPC_IPC_MESSAGE_START_H_
+
+// Used by IPC_BEGIN_MESSAGES so that each message class starts from a unique
+// base.  Messages have unique IDs across channels in order for the IPC logging
+// code to figure out the message class from its ID.
+enum IPCMessageStart {
+  AutomationMsgStart = 0,
+  FrameMsgStart,
+  PageMsgStart,
+  ViewMsgStart,
+  InputMsgStart,
+  ProfileImportMsgStart,
+  TestMsgStart,
+  DevToolsMsgStart,
+  WorkerMsgStart,
+  NaClMsgStart,
+  UtilityMsgStart,
+  GpuChannelMsgStart,
+  GpuMsgStart,
+  MediaMsgStart,
+  ServiceMsgStart,
+  PpapiMsgStart,
+  FirefoxImporterUnittestMsgStart,
+  FileUtilitiesMsgStart,
+  DatabaseMsgStart,
+  DOMStorageMsgStart,
+  IndexedDBMsgStart,
+  SpeechRecognitionMsgStart,
+  AutofillMsgStart,
+  SafeBrowsingMsgStart,
+  P2PMsgStart,
+  ResourceMsgStart,
+  FileSystemMsgStart,
+  ChildProcessMsgStart,
+  ClipboardMsgStart,
+  BlobMsgStart,
+  AppCacheMsgStart,
+  AudioMsgStart,
+  MidiMsgStart,
+  ChromeMsgStart,
+  DragMsgStart,
+  PrintMsgStart,
+  SpellCheckMsgStart,
+  ExtensionMsgStart,
+  VideoCaptureMsgStart,
+  QuotaMsgStart,
+  TextInputClientMsgStart,
+  ChromeUtilityMsgStart,
+  MediaStreamMsgStart,
+  ChromeBenchmarkingMsgStart,
+  JavaBridgeMsgStart,
+  GamepadMsgStart,
+  ShellMsgStart,
+  AccessibilityMsgStart,
+  PrefetchMsgStart,
+  PrerenderMsgStart,
+  ChromotingMsgStart,
+  BrowserPluginMsgStart,
+  AndroidWebViewMsgStart,
+  MetroViewerMsgStart,
+  CCMsgStart,
+  MediaPlayerMsgStart,
+  TracingMsgStart,
+  PeerConnectionTrackerMsgStart,
+  VisitedLinkMsgStart,
+  AppShimMsgStart,
+  WebRtcLoggingMsgStart,
+  TtsMsgStart,
+  WebSocketMsgStart,
+  NaClHostMsgStart,
+  WebRTCIdentityMsgStart,
+  PowerMonitorMsgStart,
+  EncryptedMediaMsgStart,
+  CacheStorageMsgStart,
+  ServiceWorkerMsgStart,
+  MessagePortMsgStart,
+  EmbeddedWorkerMsgStart,
+  EmbeddedWorkerContextMsgStart,
+  CastMsgStart,
+  CdmMsgStart,
+  ScreenOrientationMsgStart,
+  MediaStreamTrackMetricsHostMsgStart,
+  ChromeExtensionMsgStart,
+  TranslateMsgStart,
+  PushMessagingMsgStart,
+  GinJavaBridgeMsgStart,
+  ChromeUtilityPrintingMsgStart,
+  AecDumpMsgStart,
+  OzoneGpuMsgStart,
+  ChromeUtilityExtensionsMsgStart,
+  PlatformNotificationMsgStart,
+  PDFMsgStart,
+  ManifestManagerMsgStart,
+  ExtensionUtilityMsgStart,
+  LayoutTestMsgStart,
+  NetworkHintsMsgStart,
+  BluetoothMsgStart,
+  CastMediaMsgStart,
+  AwMessagePortMsgStart,
+  SyncCompositorMsgStart,
+  ExtensionsGuestViewMsgStart,
+  GuestViewMsgStart,
+  // Note: CastCryptoMsgStart and CastChannelMsgStart reserved for Chromecast
+  // internal code. Contact gunsch@ before changing/removing.
+  CastCryptoMsgStart,
+  CastChannelMsgStart,
+  DataReductionProxyStart,
+  ContentSettingsMsgStart,
+  ChromeAppBannerMsgStart,
+  AttachmentBrokerMsgStart,
+  RenderProcessMsgStart,
+  PageLoadMetricsMsgStart,
+  MemoryMsgStart,
+  MediaSessionMsgStart,
+  IPCTestMsgStart,
+  ArcInstanceMsgStart,
+  ArcInstanceHostMsgStart,
+  DistillerMsgStart,
+  ArcCameraMsgStart,
+  DWriteFontProxyMsgStart,
+  MediaPlayerDelegateMsgStart,
+  SurfaceViewManagerMsgStart,
+  ExtensionWorkerMsgStart,
+  SubresourceFilterMsgStart,
+  LastIPCMsgStart  // Must come last.
+};
+
+#endif  // IPC_IPC_MESSAGE_START_H_
diff --git a/ipc/ipc_message_utils.cc b/ipc/ipc_message_utils.cc
new file mode 100644
index 0000000..60c12ab
--- /dev/null
+++ b/ipc/ipc_message_utils.cc
@@ -0,0 +1,1220 @@
+// 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 "ipc/ipc_message_utils.h"
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "base/files/file_path.h"
+#include "base/json/json_writer.h"
+#include "base/strings/nullable_string16.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/time/time.h"
+#include "base/values.h"
+#include "build/build_config.h"
+#include "ipc/ipc_channel_handle.h"
+#include "ipc/ipc_message_attachment.h"
+#include "ipc/ipc_message_attachment_set.h"
+#include "ipc/ipc_mojo_param_traits.h"
+
+#if defined(OS_POSIX)
+#include "ipc/ipc_platform_file_attachment_posix.h"
+#endif
+
+#if (defined(OS_MACOSX) && !defined(OS_IOS)) || defined(OS_WIN)
+#include "base/memory/shared_memory_handle.h"
+#endif  // (defined(OS_MACOSX) && !defined(OS_IOS)) || defined(OS_WIN)
+
+#if defined(OS_MACOSX) && !defined(OS_IOS)
+#include "ipc/mach_port_mac.h"
+#endif
+
+#if defined(OS_WIN)
+#include <tchar.h>
+#include "ipc/handle_win.h"
+#endif
+
+namespace IPC {
+
+namespace {
+
+const int kMaxRecursionDepth = 100;
+
+template<typename CharType>
+void LogBytes(const std::vector<CharType>& data, std::string* out) {
+#if defined(OS_WIN)
+  // Windows has a GUI for logging, which can handle arbitrary binary data.
+  for (size_t i = 0; i < data.size(); ++i)
+    out->push_back(data[i]);
+#else
+  // On POSIX, we log to stdout, which we assume can display ASCII.
+  static const size_t kMaxBytesToLog = 100;
+  for (size_t i = 0; i < std::min(data.size(), kMaxBytesToLog); ++i) {
+    if (isprint(data[i]))
+      out->push_back(data[i]);
+    else
+      out->append(
+          base::StringPrintf("[%02X]", static_cast<unsigned char>(data[i])));
+  }
+  if (data.size() > kMaxBytesToLog) {
+    out->append(base::StringPrintf(
+        " and %u more bytes",
+        static_cast<unsigned>(data.size() - kMaxBytesToLog)));
+  }
+#endif
+}
+
+bool ReadValue(const base::Pickle* m,
+               base::PickleIterator* iter,
+               base::Value** value,
+               int recursion);
+
+void GetValueSize(base::PickleSizer* sizer,
+                  const base::Value* value,
+                  int recursion) {
+  if (recursion > kMaxRecursionDepth) {
+    LOG(WARNING) << "Max recursion depth hit in GetValueSize.";
+    return;
+  }
+
+  sizer->AddInt();
+  switch (value->GetType()) {
+    case base::Value::TYPE_NULL:
+      break;
+    case base::Value::TYPE_BOOLEAN:
+      sizer->AddBool();
+      break;
+    case base::Value::TYPE_INTEGER:
+      sizer->AddInt();
+      break;
+    case base::Value::TYPE_DOUBLE:
+      sizer->AddDouble();
+      break;
+    case base::Value::TYPE_STRING: {
+      const base::StringValue* result;
+      value->GetAsString(&result);
+      if (value->GetAsString(&result)) {
+        DCHECK(result);
+        GetParamSize(sizer, result->GetString());
+      } else {
+        std::string str;
+        bool as_string_result = value->GetAsString(&str);
+        DCHECK(as_string_result);
+        GetParamSize(sizer, str);
+      }
+      break;
+    }
+    case base::Value::TYPE_BINARY: {
+      const base::BinaryValue* binary =
+          static_cast<const base::BinaryValue*>(value);
+      sizer->AddData(static_cast<int>(binary->GetSize()));
+      break;
+    }
+    case base::Value::TYPE_DICTIONARY: {
+      sizer->AddInt();
+      const base::DictionaryValue* dict =
+          static_cast<const base::DictionaryValue*>(value);
+      for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd();
+           it.Advance()) {
+        GetParamSize(sizer, it.key());
+        GetValueSize(sizer, &it.value(), recursion + 1);
+      }
+      break;
+    }
+    case base::Value::TYPE_LIST: {
+      sizer->AddInt();
+      const base::ListValue* list = static_cast<const base::ListValue*>(value);
+      for (const auto& entry : *list) {
+        GetValueSize(sizer, entry.get(), recursion + 1);
+      }
+      break;
+    }
+    default:
+      NOTREACHED() << "Invalid base::Value type.";
+  }
+}
+
+void WriteValue(base::Pickle* m, const base::Value* value, int recursion) {
+  bool result;
+  if (recursion > kMaxRecursionDepth) {
+    LOG(WARNING) << "Max recursion depth hit in WriteValue.";
+    return;
+  }
+
+  m->WriteInt(value->GetType());
+
+  switch (value->GetType()) {
+    case base::Value::TYPE_NULL:
+    break;
+    case base::Value::TYPE_BOOLEAN: {
+      bool val;
+      result = value->GetAsBoolean(&val);
+      DCHECK(result);
+      WriteParam(m, val);
+      break;
+    }
+    case base::Value::TYPE_INTEGER: {
+      int val;
+      result = value->GetAsInteger(&val);
+      DCHECK(result);
+      WriteParam(m, val);
+      break;
+    }
+    case base::Value::TYPE_DOUBLE: {
+      double val;
+      result = value->GetAsDouble(&val);
+      DCHECK(result);
+      WriteParam(m, val);
+      break;
+    }
+    case base::Value::TYPE_STRING: {
+      std::string val;
+      result = value->GetAsString(&val);
+      DCHECK(result);
+      WriteParam(m, val);
+      break;
+    }
+    case base::Value::TYPE_BINARY: {
+      const base::BinaryValue* binary =
+          static_cast<const base::BinaryValue*>(value);
+      m->WriteData(binary->GetBuffer(), static_cast<int>(binary->GetSize()));
+      break;
+    }
+    case base::Value::TYPE_DICTIONARY: {
+      const base::DictionaryValue* dict =
+          static_cast<const base::DictionaryValue*>(value);
+
+      WriteParam(m, static_cast<int>(dict->size()));
+
+      for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd();
+           it.Advance()) {
+        WriteParam(m, it.key());
+        WriteValue(m, &it.value(), recursion + 1);
+      }
+      break;
+    }
+    case base::Value::TYPE_LIST: {
+      const base::ListValue* list = static_cast<const base::ListValue*>(value);
+      WriteParam(m, static_cast<int>(list->GetSize()));
+      for (const auto& entry : *list) {
+        WriteValue(m, entry.get(), recursion + 1);
+      }
+      break;
+    }
+  }
+}
+
+// Helper for ReadValue that reads a DictionaryValue into a pre-allocated
+// object.
+bool ReadDictionaryValue(const base::Pickle* m,
+                         base::PickleIterator* iter,
+                         base::DictionaryValue* value,
+                         int recursion) {
+  int size;
+  if (!ReadParam(m, iter, &size))
+    return false;
+
+  for (int i = 0; i < size; ++i) {
+    std::string key;
+    base::Value* subval;
+    if (!ReadParam(m, iter, &key) ||
+        !ReadValue(m, iter, &subval, recursion + 1))
+      return false;
+    value->SetWithoutPathExpansion(key, subval);
+  }
+
+  return true;
+}
+
+// Helper for ReadValue that reads a ReadListValue into a pre-allocated
+// object.
+bool ReadListValue(const base::Pickle* m,
+                   base::PickleIterator* iter,
+                   base::ListValue* value,
+                   int recursion) {
+  int size;
+  if (!ReadParam(m, iter, &size))
+    return false;
+
+  for (int i = 0; i < size; ++i) {
+    base::Value* subval;
+    if (!ReadValue(m, iter, &subval, recursion + 1))
+      return false;
+    value->Set(i, subval);
+  }
+
+  return true;
+}
+
+bool ReadValue(const base::Pickle* m,
+               base::PickleIterator* iter,
+               base::Value** value,
+               int recursion) {
+  if (recursion > kMaxRecursionDepth) {
+    LOG(WARNING) << "Max recursion depth hit in ReadValue.";
+    return false;
+  }
+
+  int type;
+  if (!ReadParam(m, iter, &type))
+    return false;
+
+  switch (type) {
+    case base::Value::TYPE_NULL:
+      *value = base::Value::CreateNullValue().release();
+    break;
+    case base::Value::TYPE_BOOLEAN: {
+      bool val;
+      if (!ReadParam(m, iter, &val))
+        return false;
+      *value = new base::FundamentalValue(val);
+      break;
+    }
+    case base::Value::TYPE_INTEGER: {
+      int val;
+      if (!ReadParam(m, iter, &val))
+        return false;
+      *value = new base::FundamentalValue(val);
+      break;
+    }
+    case base::Value::TYPE_DOUBLE: {
+      double val;
+      if (!ReadParam(m, iter, &val))
+        return false;
+      *value = new base::FundamentalValue(val);
+      break;
+    }
+    case base::Value::TYPE_STRING: {
+      std::string val;
+      if (!ReadParam(m, iter, &val))
+        return false;
+      *value = new base::StringValue(val);
+      break;
+    }
+    case base::Value::TYPE_BINARY: {
+      const char* data;
+      int length;
+      if (!iter->ReadData(&data, &length))
+        return false;
+      std::unique_ptr<base::BinaryValue> val =
+          base::BinaryValue::CreateWithCopiedBuffer(data, length);
+      *value = val.release();
+      break;
+    }
+    case base::Value::TYPE_DICTIONARY: {
+      std::unique_ptr<base::DictionaryValue> val(new base::DictionaryValue());
+      if (!ReadDictionaryValue(m, iter, val.get(), recursion))
+        return false;
+      *value = val.release();
+      break;
+    }
+    case base::Value::TYPE_LIST: {
+      std::unique_ptr<base::ListValue> val(new base::ListValue());
+      if (!ReadListValue(m, iter, val.get(), recursion))
+        return false;
+      *value = val.release();
+      break;
+    }
+    default:
+    return false;
+  }
+
+  return true;
+}
+
+}  // namespace
+
+// -----------------------------------------------------------------------------
+
+LogData::LogData()
+    : routing_id(0),
+      type(0),
+      sent(0),
+      receive(0),
+      dispatch(0) {
+}
+
+LogData::LogData(const LogData& other) = default;
+
+LogData::~LogData() {
+}
+
+void ParamTraits<bool>::Log(const param_type& p, std::string* l) {
+  l->append(p ? "true" : "false");
+}
+
+void ParamTraits<signed char>::GetSize(base::PickleSizer* sizer,
+                                       const param_type& p) {
+  sizer->AddBytes(sizeof(param_type));
+}
+
+void ParamTraits<signed char>::Write(base::Pickle* m, const param_type& p) {
+  m->WriteBytes(&p, sizeof(param_type));
+}
+
+bool ParamTraits<signed char>::Read(const base::Pickle* m,
+                                    base::PickleIterator* iter,
+                                    param_type* r) {
+  const char* data;
+  if (!iter->ReadBytes(&data, sizeof(param_type)))
+    return false;
+  memcpy(r, data, sizeof(param_type));
+  return true;
+}
+
+void ParamTraits<signed char>::Log(const param_type& p, std::string* l) {
+  l->append(base::IntToString(p));
+}
+
+void ParamTraits<unsigned char>::GetSize(base::PickleSizer* sizer,
+                                       const param_type& p) {
+  sizer->AddBytes(sizeof(param_type));
+}
+
+void ParamTraits<unsigned char>::Write(base::Pickle* m, const param_type& p) {
+  m->WriteBytes(&p, sizeof(param_type));
+}
+
+bool ParamTraits<unsigned char>::Read(const base::Pickle* m,
+                                      base::PickleIterator* iter,
+                                      param_type* r) {
+  const char* data;
+  if (!iter->ReadBytes(&data, sizeof(param_type)))
+    return false;
+  memcpy(r, data, sizeof(param_type));
+  return true;
+}
+
+void ParamTraits<unsigned char>::Log(const param_type& p, std::string* l) {
+  l->append(base::UintToString(p));
+}
+
+void ParamTraits<unsigned short>::GetSize(base::PickleSizer* sizer,
+                                          const param_type& p) {
+  sizer->AddBytes(sizeof(param_type));
+}
+
+void ParamTraits<unsigned short>::Write(base::Pickle* m, const param_type& p) {
+  m->WriteBytes(&p, sizeof(param_type));
+}
+
+bool ParamTraits<unsigned short>::Read(const base::Pickle* m,
+                                       base::PickleIterator* iter,
+                                       param_type* r) {
+  const char* data;
+  if (!iter->ReadBytes(&data, sizeof(param_type)))
+    return false;
+  memcpy(r, data, sizeof(param_type));
+  return true;
+}
+
+void ParamTraits<unsigned short>::Log(const param_type& p, std::string* l) {
+  l->append(base::UintToString(p));
+}
+
+void ParamTraits<int>::Log(const param_type& p, std::string* l) {
+  l->append(base::IntToString(p));
+}
+
+void ParamTraits<unsigned int>::Log(const param_type& p, std::string* l) {
+  l->append(base::UintToString(p));
+}
+
+#if defined(OS_WIN) || defined(OS_LINUX) || \
+    (defined(OS_ANDROID) && defined(ARCH_CPU_64_BITS))
+void ParamTraits<long>::Log(const param_type& p, std::string* l) {
+  l->append(base::Int64ToString(static_cast<int64_t>(p)));
+}
+
+void ParamTraits<unsigned long>::Log(const param_type& p, std::string* l) {
+  l->append(base::Uint64ToString(static_cast<uint64_t>(p)));
+}
+#endif
+
+void ParamTraits<long long>::Log(const param_type& p, std::string* l) {
+  l->append(base::Int64ToString(static_cast<int64_t>(p)));
+}
+
+void ParamTraits<unsigned long long>::Log(const param_type& p, std::string* l) {
+  l->append(base::Uint64ToString(p));
+}
+
+void ParamTraits<float>::Log(const param_type& p, std::string* l) {
+  l->append(base::StringPrintf("%e", p));
+}
+
+void ParamTraits<double>::GetSize(base::PickleSizer* sizer,
+                                  const param_type& p) {
+  sizer->AddBytes(sizeof(param_type));
+}
+
+void ParamTraits<double>::Write(base::Pickle* m, const param_type& p) {
+  m->WriteBytes(reinterpret_cast<const char*>(&p), sizeof(param_type));
+}
+
+bool ParamTraits<double>::Read(const base::Pickle* m,
+                               base::PickleIterator* iter,
+                               param_type* r) {
+  const char *data;
+  if (!iter->ReadBytes(&data, sizeof(*r))) {
+    NOTREACHED();
+    return false;
+  }
+  memcpy(r, data, sizeof(param_type));
+  return true;
+}
+
+void ParamTraits<double>::Log(const param_type& p, std::string* l) {
+  l->append(base::StringPrintf("%e", p));
+}
+
+
+void ParamTraits<std::string>::Log(const param_type& p, std::string* l) {
+  l->append(p);
+}
+
+void ParamTraits<base::string16>::Log(const param_type& p, std::string* l) {
+  l->append(base::UTF16ToUTF8(p));
+}
+
+void ParamTraits<std::vector<char>>::GetSize(base::PickleSizer* sizer,
+                                             const param_type& p) {
+  sizer->AddData(static_cast<int>(p.size()));
+}
+
+void ParamTraits<std::vector<char>>::Write(base::Pickle* m,
+                                           const param_type& p) {
+  if (p.empty()) {
+    m->WriteData(NULL, 0);
+  } else {
+    m->WriteData(&p.front(), static_cast<int>(p.size()));
+  }
+}
+
+bool ParamTraits<std::vector<char>>::Read(const base::Pickle* m,
+                                          base::PickleIterator* iter,
+                                          param_type* r) {
+  const char *data;
+  int data_size = 0;
+  if (!iter->ReadData(&data, &data_size) || data_size < 0)
+    return false;
+  r->resize(data_size);
+  if (data_size)
+    memcpy(&r->front(), data, data_size);
+  return true;
+}
+
+void ParamTraits<std::vector<char> >::Log(const param_type& p, std::string* l) {
+  LogBytes(p, l);
+}
+
+void ParamTraits<std::vector<unsigned char>>::GetSize(base::PickleSizer* sizer,
+                                                      const param_type& p) {
+  sizer->AddData(static_cast<int>(p.size()));
+}
+
+void ParamTraits<std::vector<unsigned char>>::Write(base::Pickle* m,
+                                                    const param_type& p) {
+  if (p.empty()) {
+    m->WriteData(NULL, 0);
+  } else {
+    m->WriteData(reinterpret_cast<const char*>(&p.front()),
+                 static_cast<int>(p.size()));
+  }
+}
+
+bool ParamTraits<std::vector<unsigned char>>::Read(const base::Pickle* m,
+                                                   base::PickleIterator* iter,
+                                                   param_type* r) {
+  const char *data;
+  int data_size = 0;
+  if (!iter->ReadData(&data, &data_size) || data_size < 0)
+    return false;
+  r->resize(data_size);
+  if (data_size)
+    memcpy(&r->front(), data, data_size);
+  return true;
+}
+
+void ParamTraits<std::vector<unsigned char> >::Log(const param_type& p,
+                                                   std::string* l) {
+  LogBytes(p, l);
+}
+
+void ParamTraits<std::vector<bool>>::GetSize(base::PickleSizer* sizer,
+                                             const param_type& p) {
+  GetParamSize(sizer, static_cast<int>(p.size()));
+  for (size_t i = 0; i < p.size(); ++i)
+    GetParamSize(sizer, static_cast<bool>(p[i]));
+}
+
+void ParamTraits<std::vector<bool>>::Write(base::Pickle* m,
+                                           const param_type& p) {
+  WriteParam(m, static_cast<int>(p.size()));
+  // Cast to bool below is required because libc++'s
+  // vector<bool>::const_reference is different from bool, and we want to avoid
+  // writing an extra specialization of ParamTraits for it.
+  for (size_t i = 0; i < p.size(); i++)
+    WriteParam(m, static_cast<bool>(p[i]));
+}
+
+bool ParamTraits<std::vector<bool>>::Read(const base::Pickle* m,
+                                          base::PickleIterator* iter,
+                                          param_type* r) {
+  int size;
+  // ReadLength() checks for < 0 itself.
+  if (!iter->ReadLength(&size))
+    return false;
+  r->resize(size);
+  for (int i = 0; i < size; i++) {
+    bool value;
+    if (!ReadParam(m, iter, &value))
+      return false;
+    (*r)[i] = value;
+  }
+  return true;
+}
+
+void ParamTraits<std::vector<bool> >::Log(const param_type& p, std::string* l) {
+  for (size_t i = 0; i < p.size(); ++i) {
+    if (i != 0)
+      l->push_back(' ');
+    LogParam(static_cast<bool>(p[i]), l);
+  }
+}
+
+void ParamTraits<BrokerableAttachment::AttachmentId>::Write(
+    base::Pickle* m,
+    const param_type& p) {
+  m->WriteBytes(p.nonce, BrokerableAttachment::kNonceSize);
+}
+
+bool ParamTraits<BrokerableAttachment::AttachmentId>::Read(
+    const base::Pickle* m,
+    base::PickleIterator* iter,
+    param_type* r) {
+  const char* data;
+  if (!iter->ReadBytes(&data, BrokerableAttachment::kNonceSize))
+    return false;
+  memcpy(r->nonce, data, BrokerableAttachment::kNonceSize);
+  return true;
+}
+
+void ParamTraits<BrokerableAttachment::AttachmentId>::Log(const param_type& p,
+                                                          std::string* l) {
+  l->append(base::HexEncode(p.nonce, BrokerableAttachment::kNonceSize));
+}
+
+void ParamTraits<base::DictionaryValue>::GetSize(base::PickleSizer* sizer,
+                                                 const param_type& p) {
+  GetValueSize(sizer, &p, 0);
+}
+
+void ParamTraits<base::DictionaryValue>::Write(base::Pickle* m,
+                                               const param_type& p) {
+  WriteValue(m, &p, 0);
+}
+
+bool ParamTraits<base::DictionaryValue>::Read(const base::Pickle* m,
+                                              base::PickleIterator* iter,
+                                              param_type* r) {
+  int type;
+  if (!ReadParam(m, iter, &type) || type != base::Value::TYPE_DICTIONARY)
+    return false;
+
+  return ReadDictionaryValue(m, iter, r, 0);
+}
+
+void ParamTraits<base::DictionaryValue>::Log(const param_type& p,
+                                             std::string* l) {
+  std::string json;
+  base::JSONWriter::Write(p, &json);
+  l->append(json);
+}
+
+#if defined(OS_POSIX)
+void ParamTraits<base::FileDescriptor>::GetSize(base::PickleSizer* sizer,
+                                                const param_type& p) {
+  GetParamSize(sizer, p.fd >= 0);
+  if (p.fd >= 0)
+    sizer->AddAttachment();
+}
+
+void ParamTraits<base::FileDescriptor>::Write(base::Pickle* m,
+                                              const param_type& p) {
+  const bool valid = p.fd >= 0;
+  WriteParam(m, valid);
+
+  if (!valid)
+    return;
+
+  if (p.auto_close) {
+    if (!m->WriteAttachment(
+            new internal::PlatformFileAttachment(base::ScopedFD(p.fd))))
+      NOTREACHED();
+  } else {
+    if (!m->WriteAttachment(new internal::PlatformFileAttachment(p.fd)))
+      NOTREACHED();
+  }
+}
+
+bool ParamTraits<base::FileDescriptor>::Read(const base::Pickle* m,
+                                             base::PickleIterator* iter,
+                                             param_type* r) {
+  *r = base::FileDescriptor();
+
+  bool valid;
+  if (!ReadParam(m, iter, &valid))
+    return false;
+
+  // TODO(morrita): Seems like this should return false.
+  if (!valid)
+    return true;
+
+  scoped_refptr<base::Pickle::Attachment> attachment;
+  if (!m->ReadAttachment(iter, &attachment))
+    return false;
+
+  *r = base::FileDescriptor(
+      static_cast<MessageAttachment*>(attachment.get())->TakePlatformFile(),
+      true);
+  return true;
+}
+
+void ParamTraits<base::FileDescriptor>::Log(const param_type& p,
+                                            std::string* l) {
+  if (p.auto_close) {
+    l->append(base::StringPrintf("FD(%d auto-close)", p.fd));
+  } else {
+    l->append(base::StringPrintf("FD(%d)", p.fd));
+  }
+}
+#endif  // defined(OS_POSIX)
+
+#if defined(OS_MACOSX) && !defined(OS_IOS)
+void ParamTraits<base::SharedMemoryHandle>::GetSize(base::PickleSizer* sizer,
+                                                    const param_type& p) {
+  GetParamSize(sizer, p.GetMemoryObject());
+  uint32_t dummy = 0;
+  GetParamSize(sizer, dummy);
+}
+
+void ParamTraits<base::SharedMemoryHandle>::Write(base::Pickle* m,
+                                                  const param_type& p) {
+  MachPortMac mach_port_mac(p.GetMemoryObject());
+  ParamTraits<MachPortMac>::Write(m, mach_port_mac);
+  size_t size = 0;
+  bool result = p.GetSize(&size);
+  DCHECK(result);
+  ParamTraits<uint32_t>::Write(m, static_cast<uint32_t>(size));
+
+  // If the caller intended to pass ownership to the IPC stack, release a
+  // reference.
+  if (p.OwnershipPassesToIPC())
+    p.Close();
+}
+
+bool ParamTraits<base::SharedMemoryHandle>::Read(const base::Pickle* m,
+                                                 base::PickleIterator* iter,
+                                                 param_type* r) {
+  MachPortMac mach_port_mac;
+  if (!ParamTraits<MachPortMac>::Read(m, iter, &mach_port_mac))
+    return false;
+
+  uint32_t size;
+  if (!ParamTraits<uint32_t>::Read(m, iter, &size))
+    return false;
+
+  *r = base::SharedMemoryHandle(mach_port_mac.get_mach_port(),
+                                static_cast<size_t>(size),
+                                base::GetCurrentProcId());
+  return true;
+}
+
+void ParamTraits<base::SharedMemoryHandle>::Log(const param_type& p,
+                                                std::string* l) {
+  l->append("Mach port: ");
+  LogParam(p.GetMemoryObject(), l);
+}
+
+#elif defined(OS_WIN)
+void ParamTraits<base::SharedMemoryHandle>::GetSize(base::PickleSizer* s,
+                                                    const param_type& p) {
+  GetParamSize(s, p.NeedsBrokering());
+  if (p.NeedsBrokering()) {
+    GetParamSize(s, p.GetHandle());
+  } else {
+    GetParamSize(s, HandleToLong(p.GetHandle()));
+  }
+}
+
+void ParamTraits<base::SharedMemoryHandle>::Write(base::Pickle* m,
+                                                  const param_type& p) {
+  m->WriteBool(p.NeedsBrokering());
+
+  if (p.NeedsBrokering()) {
+    HandleWin handle_win(p.GetHandle(), HandleWin::DUPLICATE);
+    ParamTraits<HandleWin>::Write(m, handle_win);
+
+    // If the caller intended to pass ownership to the IPC stack, release a
+    // reference.
+    if (p.OwnershipPassesToIPC() && p.BelongsToCurrentProcess())
+      p.Close();
+  } else {
+    m->WriteInt(HandleToLong(p.GetHandle()));
+  }
+}
+
+bool ParamTraits<base::SharedMemoryHandle>::Read(const base::Pickle* m,
+                                                 base::PickleIterator* iter,
+                                                 param_type* r) {
+  bool needs_brokering;
+  if (!iter->ReadBool(&needs_brokering))
+    return false;
+
+  if (needs_brokering) {
+    HandleWin handle_win;
+    if (!ParamTraits<HandleWin>::Read(m, iter, &handle_win))
+      return false;
+    *r = base::SharedMemoryHandle(handle_win.get_handle(),
+                                  base::GetCurrentProcId());
+    return true;
+  }
+
+  int handle_int;
+  if (!iter->ReadInt(&handle_int))
+    return false;
+  HANDLE handle = LongToHandle(handle_int);
+  *r = base::SharedMemoryHandle(handle, base::GetCurrentProcId());
+  return true;
+}
+
+void ParamTraits<base::SharedMemoryHandle>::Log(const param_type& p,
+                                                std::string* l) {
+  LogParam(p.GetHandle(), l);
+  l->append(" needs brokering: ");
+  LogParam(p.NeedsBrokering(), l);
+}
+#endif  // defined(OS_MACOSX) && !defined(OS_IOS)
+
+void ParamTraits<base::FilePath>::GetSize(base::PickleSizer* sizer,
+                                          const param_type& p) {
+  p.GetSizeForPickle(sizer);
+}
+
+void ParamTraits<base::FilePath>::Write(base::Pickle* m, const param_type& p) {
+  p.WriteToPickle(m);
+}
+
+bool ParamTraits<base::FilePath>::Read(const base::Pickle* m,
+                                       base::PickleIterator* iter,
+                                       param_type* r) {
+  return r->ReadFromPickle(iter);
+}
+
+void ParamTraits<base::FilePath>::Log(const param_type& p, std::string* l) {
+  ParamTraits<base::FilePath::StringType>::Log(p.value(), l);
+}
+
+void ParamTraits<base::ListValue>::GetSize(base::PickleSizer* sizer,
+                                           const param_type& p) {
+  GetValueSize(sizer, &p, 0);
+}
+
+void ParamTraits<base::ListValue>::Write(base::Pickle* m, const param_type& p) {
+  WriteValue(m, &p, 0);
+}
+
+bool ParamTraits<base::ListValue>::Read(const base::Pickle* m,
+                                        base::PickleIterator* iter,
+                                        param_type* r) {
+  int type;
+  if (!ReadParam(m, iter, &type) || type != base::Value::TYPE_LIST)
+    return false;
+
+  return ReadListValue(m, iter, r, 0);
+}
+
+void ParamTraits<base::ListValue>::Log(const param_type& p, std::string* l) {
+  std::string json;
+  base::JSONWriter::Write(p, &json);
+  l->append(json);
+}
+
+void ParamTraits<base::NullableString16>::GetSize(base::PickleSizer* sizer,
+                                                  const param_type& p) {
+  GetParamSize(sizer, p.string());
+  GetParamSize(sizer, p.is_null());
+}
+
+void ParamTraits<base::NullableString16>::Write(base::Pickle* m,
+                                                const param_type& p) {
+  WriteParam(m, p.string());
+  WriteParam(m, p.is_null());
+}
+
+bool ParamTraits<base::NullableString16>::Read(const base::Pickle* m,
+                                               base::PickleIterator* iter,
+                                               param_type* r) {
+  base::string16 string;
+  if (!ReadParam(m, iter, &string))
+    return false;
+  bool is_null;
+  if (!ReadParam(m, iter, &is_null))
+    return false;
+  *r = base::NullableString16(string, is_null);
+  return true;
+}
+
+void ParamTraits<base::NullableString16>::Log(const param_type& p,
+                                              std::string* l) {
+  l->append("(");
+  LogParam(p.string(), l);
+  l->append(", ");
+  LogParam(p.is_null(), l);
+  l->append(")");
+}
+
+void ParamTraits<base::File::Info>::GetSize(base::PickleSizer* sizer,
+                                            const param_type& p) {
+  GetParamSize(sizer, p.size);
+  GetParamSize(sizer, p.is_directory);
+  GetParamSize(sizer, p.last_modified.ToDoubleT());
+  GetParamSize(sizer, p.last_accessed.ToDoubleT());
+  GetParamSize(sizer, p.creation_time.ToDoubleT());
+}
+
+void ParamTraits<base::File::Info>::Write(base::Pickle* m,
+                                          const param_type& p) {
+  WriteParam(m, p.size);
+  WriteParam(m, p.is_directory);
+  WriteParam(m, p.last_modified.ToDoubleT());
+  WriteParam(m, p.last_accessed.ToDoubleT());
+  WriteParam(m, p.creation_time.ToDoubleT());
+}
+
+bool ParamTraits<base::File::Info>::Read(const base::Pickle* m,
+                                         base::PickleIterator* iter,
+                                         param_type* p) {
+  double last_modified, last_accessed, creation_time;
+  if (!ReadParam(m, iter, &p->size) ||
+      !ReadParam(m, iter, &p->is_directory) ||
+      !ReadParam(m, iter, &last_modified) ||
+      !ReadParam(m, iter, &last_accessed) ||
+      !ReadParam(m, iter, &creation_time))
+    return false;
+  p->last_modified = base::Time::FromDoubleT(last_modified);
+  p->last_accessed = base::Time::FromDoubleT(last_accessed);
+  p->creation_time = base::Time::FromDoubleT(creation_time);
+  return true;
+}
+
+void ParamTraits<base::File::Info>::Log(const param_type& p,
+                                        std::string* l) {
+  l->append("(");
+  LogParam(p.size, l);
+  l->append(",");
+  LogParam(p.is_directory, l);
+  l->append(",");
+  LogParam(p.last_modified.ToDoubleT(), l);
+  l->append(",");
+  LogParam(p.last_accessed.ToDoubleT(), l);
+  l->append(",");
+  LogParam(p.creation_time.ToDoubleT(), l);
+  l->append(")");
+}
+
+void ParamTraits<base::Time>::GetSize(base::PickleSizer* sizer,
+                                      const param_type& p) {
+  sizer->AddInt64();
+}
+
+void ParamTraits<base::Time>::Write(base::Pickle* m, const param_type& p) {
+  ParamTraits<int64_t>::Write(m, p.ToInternalValue());
+}
+
+bool ParamTraits<base::Time>::Read(const base::Pickle* m,
+                                   base::PickleIterator* iter,
+                                   param_type* r) {
+  int64_t value;
+  if (!ParamTraits<int64_t>::Read(m, iter, &value))
+    return false;
+  *r = base::Time::FromInternalValue(value);
+  return true;
+}
+
+void ParamTraits<base::Time>::Log(const param_type& p, std::string* l) {
+  ParamTraits<int64_t>::Log(p.ToInternalValue(), l);
+}
+
+void ParamTraits<base::TimeDelta>::GetSize(base::PickleSizer* sizer,
+                                           const param_type& p) {
+  sizer->AddInt64();
+}
+
+void ParamTraits<base::TimeDelta>::Write(base::Pickle* m, const param_type& p) {
+  ParamTraits<int64_t>::Write(m, p.ToInternalValue());
+}
+
+bool ParamTraits<base::TimeDelta>::Read(const base::Pickle* m,
+                                        base::PickleIterator* iter,
+                                        param_type* r) {
+  int64_t value;
+  bool ret = ParamTraits<int64_t>::Read(m, iter, &value);
+  if (ret)
+    *r = base::TimeDelta::FromInternalValue(value);
+
+  return ret;
+}
+
+void ParamTraits<base::TimeDelta>::Log(const param_type& p, std::string* l) {
+  ParamTraits<int64_t>::Log(p.ToInternalValue(), l);
+}
+
+void ParamTraits<base::TimeTicks>::GetSize(base::PickleSizer* sizer,
+                                           const param_type& p) {
+  sizer->AddInt64();
+}
+
+void ParamTraits<base::TimeTicks>::Write(base::Pickle* m, const param_type& p) {
+  ParamTraits<int64_t>::Write(m, p.ToInternalValue());
+}
+
+bool ParamTraits<base::TimeTicks>::Read(const base::Pickle* m,
+                                        base::PickleIterator* iter,
+                                        param_type* r) {
+  int64_t value;
+  bool ret = ParamTraits<int64_t>::Read(m, iter, &value);
+  if (ret)
+    *r = base::TimeTicks::FromInternalValue(value);
+
+  return ret;
+}
+
+void ParamTraits<base::TimeTicks>::Log(const param_type& p, std::string* l) {
+  ParamTraits<int64_t>::Log(p.ToInternalValue(), l);
+}
+
+void ParamTraits<IPC::ChannelHandle>::GetSize(base::PickleSizer* sizer,
+                                              const param_type& p) {
+  GetParamSize(sizer, p.name);
+#if defined(OS_POSIX)
+  GetParamSize(sizer, p.socket);
+#endif
+  GetParamSize(sizer, p.mojo_handle);
+}
+
+void ParamTraits<IPC::ChannelHandle>::Write(base::Pickle* m,
+                                            const param_type& p) {
+#if defined(OS_WIN)
+  // On Windows marshalling pipe handle is not supported.
+  DCHECK(p.pipe.handle == NULL);
+#endif  // defined (OS_WIN)
+  WriteParam(m, p.name);
+#if defined(OS_POSIX)
+  WriteParam(m, p.socket);
+#endif
+  WriteParam(m, p.mojo_handle);
+}
+
+bool ParamTraits<IPC::ChannelHandle>::Read(const base::Pickle* m,
+                                           base::PickleIterator* iter,
+                                           param_type* r) {
+  return ReadParam(m, iter, &r->name)
+#if defined(OS_POSIX)
+      && ReadParam(m, iter, &r->socket)
+#endif
+      && ReadParam(m, iter, &r->mojo_handle);
+}
+
+void ParamTraits<IPC::ChannelHandle>::Log(const param_type& p,
+                                          std::string* l) {
+  l->append(base::StringPrintf("ChannelHandle(%s", p.name.c_str()));
+#if defined(OS_POSIX)
+  l->append(", ");
+  ParamTraits<base::FileDescriptor>::Log(p.socket, l);
+#endif
+  l->append(", ");
+  LogParam(p.mojo_handle, l);
+  l->append(")");
+}
+
+void ParamTraits<LogData>::GetSize(base::PickleSizer* sizer,
+                                   const param_type& p) {
+  GetParamSize(sizer, p.channel);
+  GetParamSize(sizer, p.routing_id);
+  GetParamSize(sizer, p.type);
+  GetParamSize(sizer, p.flags);
+  GetParamSize(sizer, p.sent);
+  GetParamSize(sizer, p.receive);
+  GetParamSize(sizer, p.dispatch);
+  GetParamSize(sizer, p.message_name);
+  GetParamSize(sizer, p.params);
+}
+
+void ParamTraits<LogData>::Write(base::Pickle* m, const param_type& p) {
+  WriteParam(m, p.channel);
+  WriteParam(m, p.routing_id);
+  WriteParam(m, p.type);
+  WriteParam(m, p.flags);
+  WriteParam(m, p.sent);
+  WriteParam(m, p.receive);
+  WriteParam(m, p.dispatch);
+  WriteParam(m, p.message_name);
+  WriteParam(m, p.params);
+}
+
+bool ParamTraits<LogData>::Read(const base::Pickle* m,
+                                base::PickleIterator* iter,
+                                param_type* r) {
+  return
+      ReadParam(m, iter, &r->channel) &&
+      ReadParam(m, iter, &r->routing_id) &&
+      ReadParam(m, iter, &r->type) &&
+      ReadParam(m, iter, &r->flags) &&
+      ReadParam(m, iter, &r->sent) &&
+      ReadParam(m, iter, &r->receive) &&
+      ReadParam(m, iter, &r->dispatch) &&
+      ReadParam(m, iter, &r->message_name) &&
+      ReadParam(m, iter, &r->params);
+}
+
+void ParamTraits<LogData>::Log(const param_type& p, std::string* l) {
+  // Doesn't make sense to implement this!
+}
+
+void ParamTraits<Message>::Write(base::Pickle* m, const Message& p) {
+#if defined(OS_POSIX)
+  // We don't serialize the file descriptors in the nested message, so there
+  // better not be any.
+  DCHECK(!p.HasAttachments());
+#endif
+
+  // Don't just write out the message. This is used to send messages between
+  // NaCl (Posix environment) and the browser (could be on Windows). The message
+  // header formats differ between these systems (so does handle sharing, but
+  // we already asserted we don't have any handles). So just write out the
+  // parts of the header we use.
+  //
+  // Be careful also to use only explicitly-sized types. The NaCl environment
+  // could be 64-bit and the host browser could be 32-bits. The nested message
+  // may or may not be safe to send between 32-bit and 64-bit systems, but we
+  // leave that up to the code sending the message to ensure.
+  m->WriteUInt32(static_cast<uint32_t>(p.routing_id()));
+  m->WriteUInt32(p.type());
+  m->WriteUInt32(p.flags());
+  m->WriteData(p.payload(), static_cast<uint32_t>(p.payload_size()));
+}
+
+bool ParamTraits<Message>::Read(const base::Pickle* m,
+                                base::PickleIterator* iter,
+                                Message* r) {
+  uint32_t routing_id, type, flags;
+  if (!iter->ReadUInt32(&routing_id) ||
+      !iter->ReadUInt32(&type) ||
+      !iter->ReadUInt32(&flags))
+    return false;
+
+  int payload_size;
+  const char* payload;
+  if (!iter->ReadData(&payload, &payload_size))
+    return false;
+
+  r->SetHeaderValues(static_cast<int32_t>(routing_id), type, flags);
+  return r->WriteBytes(payload, payload_size);
+}
+
+void ParamTraits<Message>::Log(const Message& p, std::string* l) {
+  l->append("<IPC::Message>");
+}
+
+#if defined(OS_WIN)
+void ParamTraits<HANDLE>::GetSize(base::PickleSizer* sizer,
+                                  const param_type& p) {
+  sizer->AddInt();
+}
+
+// Note that HWNDs/HANDLE/HCURSOR/HACCEL etc are always 32 bits, even on 64
+// bit systems. That's why we use the Windows macros to convert to 32 bits.
+void ParamTraits<HANDLE>::Write(base::Pickle* m, const param_type& p) {
+  m->WriteInt(HandleToLong(p));
+}
+
+bool ParamTraits<HANDLE>::Read(const base::Pickle* m,
+                               base::PickleIterator* iter,
+                               param_type* r) {
+  int32_t temp;
+  if (!iter->ReadInt(&temp))
+    return false;
+  *r = LongToHandle(temp);
+  return true;
+}
+
+void ParamTraits<HANDLE>::Log(const param_type& p, std::string* l) {
+  l->append(base::StringPrintf("0x%p", p));
+}
+
+void ParamTraits<LOGFONT>::GetSize(base::PickleSizer* sizer,
+                                   const param_type& p) {
+  sizer->AddData(sizeof(LOGFONT));
+}
+
+void ParamTraits<LOGFONT>::Write(base::Pickle* m, const param_type& p) {
+  m->WriteData(reinterpret_cast<const char*>(&p), sizeof(LOGFONT));
+}
+
+bool ParamTraits<LOGFONT>::Read(const base::Pickle* m,
+                                base::PickleIterator* iter,
+                                param_type* r) {
+  const char *data;
+  int data_size = 0;
+  if (iter->ReadData(&data, &data_size) && data_size == sizeof(LOGFONT)) {
+    const LOGFONT *font = reinterpret_cast<LOGFONT*>(const_cast<char*>(data));
+    if (_tcsnlen(font->lfFaceName, LF_FACESIZE) < LF_FACESIZE) {
+      memcpy(r, data, sizeof(LOGFONT));
+      return true;
+    }
+  }
+
+  NOTREACHED();
+  return false;
+}
+
+void ParamTraits<LOGFONT>::Log(const param_type& p, std::string* l) {
+  l->append(base::StringPrintf("<LOGFONT>"));
+}
+
+void ParamTraits<MSG>::GetSize(base::PickleSizer* sizer, const param_type& p) {
+  sizer->AddData(sizeof(MSG));
+}
+
+void ParamTraits<MSG>::Write(base::Pickle* m, const param_type& p) {
+  m->WriteData(reinterpret_cast<const char*>(&p), sizeof(MSG));
+}
+
+bool ParamTraits<MSG>::Read(const base::Pickle* m,
+                            base::PickleIterator* iter,
+                            param_type* r) {
+  const char *data;
+  int data_size = 0;
+  bool result = iter->ReadData(&data, &data_size);
+  if (result && data_size == sizeof(MSG)) {
+    memcpy(r, data, sizeof(MSG));
+  } else {
+    result = false;
+    NOTREACHED();
+  }
+
+  return result;
+}
+
+void ParamTraits<MSG>::Log(const param_type& p, std::string* l) {
+  l->append("<MSG>");
+}
+
+#endif  // OS_WIN
+
+}  // namespace IPC
diff --git a/ipc/ipc_message_utils.h b/ipc/ipc_message_utils.h
new file mode 100644
index 0000000..6712d3c
--- /dev/null
+++ b/ipc/ipc_message_utils.h
@@ -0,0 +1,1149 @@
+// 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.
+
+#ifndef IPC_IPC_MESSAGE_UTILS_H_
+#define IPC_IPC_MESSAGE_UTILS_H_
+
+#include <limits.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include <algorithm>
+#include <map>
+#include <memory>
+#include <set>
+#include <string>
+#include <tuple>
+#include <vector>
+
+#include "base/containers/small_map.h"
+#include "base/containers/stack_container.h"
+#include "base/files/file.h"
+#include "base/format_macros.h"
+#include "base/memory/scoped_vector.h"
+#include "base/optional.h"
+#include "base/strings/string16.h"
+#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
+#include "build/build_config.h"
+#include "ipc/brokerable_attachment.h"
+#include "ipc/ipc_message_start.h"
+#include "ipc/ipc_param_traits.h"
+#include "ipc/ipc_sync_message.h"
+
+namespace base {
+class DictionaryValue;
+class FilePath;
+class ListValue;
+class NullableString16;
+class Time;
+class TimeDelta;
+class TimeTicks;
+struct FileDescriptor;
+
+#if (defined(OS_MACOSX) && !defined(OS_IOS)) || defined(OS_WIN)
+class SharedMemoryHandle;
+#endif  // (defined(OS_MACOSX) && !defined(OS_IOS)) || defined(OS_WIN)
+}
+
+namespace IPC {
+
+struct ChannelHandle;
+
+// -----------------------------------------------------------------------------
+// How we send IPC message logs across channels.
+struct IPC_EXPORT LogData {
+  LogData();
+  LogData(const LogData& other);
+  ~LogData();
+
+  std::string channel;
+  int32_t routing_id;
+  uint32_t type;  // "User-defined" message type, from ipc_message.h.
+  std::string flags;
+  int64_t sent;  // Time that the message was sent (i.e. at Send()).
+  int64_t receive;  // Time before it was dispatched (i.e. before calling
+                    // OnMessageReceived).
+  int64_t dispatch;  // Time after it was dispatched (i.e. after calling
+                     // OnMessageReceived).
+  std::string message_name;
+  std::string params;
+};
+
+//-----------------------------------------------------------------------------
+
+// A dummy struct to place first just to allow leading commas for all
+// members in the macro-generated constructor initializer lists.
+struct NoParams {
+};
+
+// Specializations are checked by 'IPC checker' part of find-bad-constructs
+// Clang plugin (see WriteParam() below for the details).
+template <typename... Ts>
+struct CheckedTuple {
+  typedef std::tuple<Ts...> Tuple;
+};
+
+template <class P>
+static inline void GetParamSize(base::PickleSizer* sizer, const P& p) {
+  typedef typename SimilarTypeTraits<P>::Type Type;
+  ParamTraits<Type>::GetSize(sizer, static_cast<const Type&>(p));
+}
+
+// This function is checked by 'IPC checker' part of find-bad-constructs
+// Clang plugin to make it's not called on the following types:
+// 1. long / unsigned long (but not typedefs to)
+// 2. intmax_t, uintmax_t, intptr_t, uintptr_t, wint_t,
+//    size_t, rsize_t, ssize_t, ptrdiff_t, dev_t, off_t, clock_t,
+//    time_t, suseconds_t (including typedefs to)
+// 3. Any template referencing types above (e.g. std::vector<size_t>)
+template <class P>
+static inline void WriteParam(base::Pickle* m, const P& p) {
+  typedef typename SimilarTypeTraits<P>::Type Type;
+  ParamTraits<Type>::Write(m, static_cast<const Type& >(p));
+}
+
+template <class P>
+static inline bool WARN_UNUSED_RESULT ReadParam(const base::Pickle* m,
+                                                base::PickleIterator* iter,
+                                                P* p) {
+  typedef typename SimilarTypeTraits<P>::Type Type;
+  return ParamTraits<Type>::Read(m, iter, reinterpret_cast<Type* >(p));
+}
+
+template <class P>
+static inline void LogParam(const P& p, std::string* l) {
+  typedef typename SimilarTypeTraits<P>::Type Type;
+  ParamTraits<Type>::Log(static_cast<const Type& >(p), l);
+}
+
+// Primitive ParamTraits -------------------------------------------------------
+
+template <>
+struct ParamTraits<bool> {
+  typedef bool param_type;
+  static void GetSize(base::PickleSizer* sizer, const param_type& p) {
+    sizer->AddBool();
+  }
+  static void Write(base::Pickle* m, const param_type& p) { m->WriteBool(p); }
+  static bool Read(const base::Pickle* m,
+                   base::PickleIterator* iter,
+                   param_type* r) {
+    return iter->ReadBool(r);
+  }
+  IPC_EXPORT static void Log(const param_type& p, std::string* l);
+};
+
+template <>
+struct IPC_EXPORT ParamTraits<signed char> {
+  typedef signed char param_type;
+  static void GetSize(base::PickleSizer* sizer, const param_type& p);
+  static void Write(base::Pickle* m, const param_type& p);
+  static bool Read(const base::Pickle* m,
+                   base::PickleIterator* iter,
+                   param_type* r);
+  static void Log(const param_type& p, std::string* l);
+};
+
+template <>
+struct IPC_EXPORT ParamTraits<unsigned char> {
+  typedef unsigned char param_type;
+  static void GetSize(base::PickleSizer* sizer, const param_type& p);
+  static void Write(base::Pickle* m, const param_type& p);
+  static bool Read(const base::Pickle* m,
+                   base::PickleIterator* iter,
+                   param_type* r);
+  static void Log(const param_type& p, std::string* l);
+};
+
+template <>
+struct IPC_EXPORT ParamTraits<unsigned short> {
+  typedef unsigned short param_type;
+  static void GetSize(base::PickleSizer* sizer, const param_type& p);
+  static void Write(base::Pickle* m, const param_type& p);
+  static bool Read(const base::Pickle* m,
+                   base::PickleIterator* iter,
+                   param_type* r);
+  static void Log(const param_type& p, std::string* l);
+};
+
+template <>
+struct ParamTraits<int> {
+  typedef int param_type;
+  static void GetSize(base::PickleSizer* sizer, const param_type& p) {
+    sizer->AddInt();
+  }
+  static void Write(base::Pickle* m, const param_type& p) { m->WriteInt(p); }
+  static bool Read(const base::Pickle* m,
+                   base::PickleIterator* iter,
+                   param_type* r) {
+    return iter->ReadInt(r);
+  }
+  IPC_EXPORT static void Log(const param_type& p, std::string* l);
+};
+
+template <>
+struct ParamTraits<unsigned int> {
+  typedef unsigned int param_type;
+  static void GetSize(base::PickleSizer* sizer, const param_type& p) {
+    sizer->AddInt();
+  }
+  static void Write(base::Pickle* m, const param_type& p) { m->WriteInt(p); }
+  static bool Read(const base::Pickle* m,
+                   base::PickleIterator* iter,
+                   param_type* r) {
+    return iter->ReadInt(reinterpret_cast<int*>(r));
+  }
+  IPC_EXPORT static void Log(const param_type& p, std::string* l);
+};
+
+// long isn't safe to send over IPC because it's 4 bytes on 32 bit builds but
+// 8 bytes on 64 bit builds. So if a 32 bit and 64 bit process have a channel
+// that would cause problem.
+// We need to keep this on for a few configs:
+//   1) Windows because DWORD is typedef'd to it, which is fine because we have
+//      very few IPCs that cross this boundary.
+//   2) We also need to keep it for Linux for two reasons: int64_t is typedef'd
+//      to long, and gfx::PluginWindow is long and is used in one GPU IPC.
+//   3) Android 64 bit also has int64_t typedef'd to long.
+// Since we want to support Android 32<>64 bit IPC, as long as we don't have
+// these traits for 32 bit ARM then that'll catch any errors.
+#if defined(OS_WIN) || defined(OS_LINUX) || \
+    (defined(OS_ANDROID) && defined(ARCH_CPU_64_BITS))
+template <>
+struct ParamTraits<long> {
+  typedef long param_type;
+  static void GetSize(base::PickleSizer* sizer, const param_type& p) {
+    sizer->AddLong();
+  }
+  static void Write(base::Pickle* m, const param_type& p) {
+    m->WriteLong(p);
+  }
+  static bool Read(const base::Pickle* m,
+                   base::PickleIterator* iter,
+                   param_type* r) {
+    return iter->ReadLong(r);
+  }
+  IPC_EXPORT static void Log(const param_type& p, std::string* l);
+};
+
+template <>
+struct ParamTraits<unsigned long> {
+  typedef unsigned long param_type;
+  static void GetSize(base::PickleSizer* sizer, const param_type& p) {
+    sizer->AddLong();
+  }
+  static void Write(base::Pickle* m, const param_type& p) {
+    m->WriteLong(p);
+  }
+  static bool Read(const base::Pickle* m,
+                   base::PickleIterator* iter,
+                   param_type* r) {
+    return iter->ReadLong(reinterpret_cast<long*>(r));
+  }
+  IPC_EXPORT static void Log(const param_type& p, std::string* l);
+};
+#endif
+
+template <>
+struct ParamTraits<long long> {
+  typedef long long param_type;
+  static void GetSize(base::PickleSizer* sizer, const param_type& p) {
+    sizer->AddInt64();
+  }
+  static void Write(base::Pickle* m, const param_type& p) {
+    m->WriteInt64(static_cast<int64_t>(p));
+  }
+  static bool Read(const base::Pickle* m,
+                   base::PickleIterator* iter,
+                   param_type* r) {
+    return iter->ReadInt64(reinterpret_cast<int64_t*>(r));
+  }
+  IPC_EXPORT static void Log(const param_type& p, std::string* l);
+};
+
+template <>
+struct ParamTraits<unsigned long long> {
+  typedef unsigned long long param_type;
+  static void GetSize(base::PickleSizer* sizer, const param_type& p) {
+    sizer->AddInt64();
+  }
+  static void Write(base::Pickle* m, const param_type& p) { m->WriteInt64(p); }
+  static bool Read(const base::Pickle* m,
+                   base::PickleIterator* iter,
+                   param_type* r) {
+    return iter->ReadInt64(reinterpret_cast<int64_t*>(r));
+  }
+  IPC_EXPORT static void Log(const param_type& p, std::string* l);
+};
+
+// Note that the IPC layer doesn't sanitize NaNs and +/- INF values.  Clients
+// should be sure to check the sanity of these values after receiving them over
+// IPC.
+template <>
+struct IPC_EXPORT ParamTraits<float> {
+  typedef float param_type;
+  static void GetSize(base::PickleSizer* sizer, const param_type& p) {
+    sizer->AddFloat();
+  }
+  static void Write(base::Pickle* m, const param_type& p) { m->WriteFloat(p); }
+  static bool Read(const base::Pickle* m,
+                   base::PickleIterator* iter,
+                   param_type* r) {
+    return iter->ReadFloat(r);
+  }
+  static void Log(const param_type& p, std::string* l);
+};
+
+template <>
+struct IPC_EXPORT ParamTraits<double> {
+  typedef double param_type;
+  static void GetSize(base::PickleSizer* sizer, const param_type& p);
+  static void Write(base::Pickle* m, const param_type& p);
+  static bool Read(const base::Pickle* m,
+                   base::PickleIterator* iter,
+                   param_type* r);
+  static void Log(const param_type& p, std::string* l);
+};
+
+// STL ParamTraits -------------------------------------------------------------
+
+template <>
+struct ParamTraits<std::string> {
+  typedef std::string param_type;
+  static void GetSize(base::PickleSizer* sizer, const param_type& p) {
+    sizer->AddString(p);
+  }
+  static void Write(base::Pickle* m, const param_type& p) { m->WriteString(p); }
+  static bool Read(const base::Pickle* m,
+                   base::PickleIterator* iter,
+                   param_type* r) {
+    return iter->ReadString(r);
+  }
+  IPC_EXPORT static void Log(const param_type& p, std::string* l);
+};
+
+template <>
+struct ParamTraits<base::string16> {
+  typedef base::string16 param_type;
+  static void GetSize(base::PickleSizer* sizer, const param_type& p) {
+    sizer->AddString16(p);
+  }
+  static void Write(base::Pickle* m, const param_type& p) {
+    m->WriteString16(p);
+  }
+  static bool Read(const base::Pickle* m,
+                   base::PickleIterator* iter,
+                   param_type* r) {
+    return iter->ReadString16(r);
+  }
+  IPC_EXPORT static void Log(const param_type& p, std::string* l);
+};
+
+template <>
+struct IPC_EXPORT ParamTraits<std::vector<char> > {
+  typedef std::vector<char> param_type;
+  static void GetSize(base::PickleSizer* sizer, const param_type& p);
+  static void Write(base::Pickle* m, const param_type& p);
+  static bool Read(const base::Pickle*,
+                   base::PickleIterator* iter,
+                   param_type* r);
+  static void Log(const param_type& p, std::string* l);
+};
+
+template <>
+struct IPC_EXPORT ParamTraits<std::vector<unsigned char> > {
+  typedef std::vector<unsigned char> param_type;
+  static void GetSize(base::PickleSizer* sizer, const param_type& p);
+  static void Write(base::Pickle* m, const param_type& p);
+  static bool Read(const base::Pickle* m,
+                   base::PickleIterator* iter,
+                   param_type* r);
+  static void Log(const param_type& p, std::string* l);
+};
+
+template <>
+struct IPC_EXPORT ParamTraits<std::vector<bool> > {
+  typedef std::vector<bool> param_type;
+  static void GetSize(base::PickleSizer* sizer, const param_type& p);
+  static void Write(base::Pickle* m, const param_type& p);
+  static bool Read(const base::Pickle* m,
+                   base::PickleIterator* iter,
+                   param_type* r);
+  static void Log(const param_type& p, std::string* l);
+};
+
+template <class P>
+struct ParamTraits<std::vector<P>> {
+  typedef std::vector<P> param_type;
+  static void GetSize(base::PickleSizer* sizer, const param_type& p) {
+    GetParamSize(sizer, static_cast<int>(p.size()));
+    for (size_t i = 0; i < p.size(); i++)
+      GetParamSize(sizer, p[i]);
+  }
+  static void Write(base::Pickle* m, const param_type& p) {
+    WriteParam(m, static_cast<int>(p.size()));
+    for (size_t i = 0; i < p.size(); i++)
+      WriteParam(m, p[i]);
+  }
+  static bool Read(const base::Pickle* m,
+                   base::PickleIterator* iter,
+                   param_type* r) {
+    int size;
+    // ReadLength() checks for < 0 itself.
+    if (!iter->ReadLength(&size))
+      return false;
+    // Resizing beforehand is not safe, see BUG 1006367 for details.
+    if (INT_MAX / sizeof(P) <= static_cast<size_t>(size))
+      return false;
+    r->resize(size);
+    for (int i = 0; i < size; i++) {
+      if (!ReadParam(m, iter, &(*r)[i]))
+        return false;
+    }
+    return true;
+  }
+  static void Log(const param_type& p, std::string* l) {
+    for (size_t i = 0; i < p.size(); ++i) {
+      if (i != 0)
+        l->append(" ");
+      LogParam((p[i]), l);
+    }
+  }
+};
+
+template <class P>
+struct ParamTraits<std::set<P> > {
+  typedef std::set<P> param_type;
+  static void GetSize(base::PickleSizer* sizer, const param_type& p) {
+    GetParamSize(sizer, static_cast<int>(p.size()));
+    typename param_type::const_iterator iter;
+    for (iter = p.begin(); iter != p.end(); ++iter)
+      GetParamSize(sizer, *iter);
+  }
+  static void Write(base::Pickle* m, const param_type& p) {
+    WriteParam(m, static_cast<int>(p.size()));
+    typename param_type::const_iterator iter;
+    for (iter = p.begin(); iter != p.end(); ++iter)
+      WriteParam(m, *iter);
+  }
+  static bool Read(const base::Pickle* m,
+                   base::PickleIterator* iter,
+                   param_type* r) {
+    int size;
+    if (!iter->ReadLength(&size))
+      return false;
+    for (int i = 0; i < size; ++i) {
+      P item;
+      if (!ReadParam(m, iter, &item))
+        return false;
+      r->insert(item);
+    }
+    return true;
+  }
+  static void Log(const param_type& p, std::string* l) {
+    l->append("<std::set>");
+  }
+};
+
+template <class K, class V, class C, class A>
+struct ParamTraits<std::map<K, V, C, A> > {
+  typedef std::map<K, V, C, A> param_type;
+  static void GetSize(base::PickleSizer* sizer, const param_type& p) {
+    GetParamSize(sizer, static_cast<int>(p.size()));
+    typename param_type::const_iterator iter;
+    for (iter = p.begin(); iter != p.end(); ++iter) {
+      GetParamSize(sizer, iter->first);
+      GetParamSize(sizer, iter->second);
+    }
+  }
+  static void Write(base::Pickle* m, const param_type& p) {
+    WriteParam(m, static_cast<int>(p.size()));
+    typename param_type::const_iterator iter;
+    for (iter = p.begin(); iter != p.end(); ++iter) {
+      WriteParam(m, iter->first);
+      WriteParam(m, iter->second);
+    }
+  }
+  static bool Read(const base::Pickle* m,
+                   base::PickleIterator* iter,
+                   param_type* r) {
+    int size;
+    if (!ReadParam(m, iter, &size) || size < 0)
+      return false;
+    for (int i = 0; i < size; ++i) {
+      K k;
+      if (!ReadParam(m, iter, &k))
+        return false;
+      V& value = (*r)[k];
+      if (!ReadParam(m, iter, &value))
+        return false;
+    }
+    return true;
+  }
+  static void Log(const param_type& p, std::string* l) {
+    l->append("<std::map>");
+  }
+};
+
+template <class A, class B>
+struct ParamTraits<std::pair<A, B> > {
+  typedef std::pair<A, B> param_type;
+  static void GetSize(base::PickleSizer* sizer, const param_type& p) {
+    GetParamSize(sizer, p.first);
+    GetParamSize(sizer, p.second);
+  }
+  static void Write(base::Pickle* m, const param_type& p) {
+    WriteParam(m, p.first);
+    WriteParam(m, p.second);
+  }
+  static bool Read(const base::Pickle* m,
+                   base::PickleIterator* iter,
+                   param_type* r) {
+    return ReadParam(m, iter, &r->first) && ReadParam(m, iter, &r->second);
+  }
+  static void Log(const param_type& p, std::string* l) {
+    l->append("(");
+    LogParam(p.first, l);
+    l->append(", ");
+    LogParam(p.second, l);
+    l->append(")");
+  }
+};
+
+// IPC ParamTraits -------------------------------------------------------------
+template <>
+struct IPC_EXPORT ParamTraits<BrokerableAttachment::AttachmentId> {
+  typedef BrokerableAttachment::AttachmentId param_type;
+  static void Write(base::Pickle* m, const param_type& p);
+  static bool Read(const base::Pickle* m,
+                   base::PickleIterator* iter,
+                   param_type* r);
+  static void Log(const param_type& p, std::string* l);
+};
+
+// Base ParamTraits ------------------------------------------------------------
+
+template <>
+struct IPC_EXPORT ParamTraits<base::DictionaryValue> {
+  typedef base::DictionaryValue param_type;
+  static void GetSize(base::PickleSizer* sizer, const param_type& p);
+  static void Write(base::Pickle* m, const param_type& p);
+  static bool Read(const base::Pickle* m,
+                   base::PickleIterator* iter,
+                   param_type* r);
+  static void Log(const param_type& p, std::string* l);
+};
+
+#if defined(OS_POSIX)
+// FileDescriptors may be serialised over IPC channels on POSIX. On the
+// receiving side, the FileDescriptor is a valid duplicate of the file
+// descriptor which was transmitted: *it is not just a copy of the integer like
+// HANDLEs on Windows*. The only exception is if the file descriptor is < 0. In
+// this case, the receiving end will see a value of -1. *Zero is a valid file
+// descriptor*.
+//
+// The received file descriptor will have the |auto_close| flag set to true. The
+// code which handles the message is responsible for taking ownership of it.
+// File descriptors are OS resources and must be closed when no longer needed.
+//
+// When sending a file descriptor, the file descriptor must be valid at the time
+// of transmission. Since transmission is not synchronous, one should consider
+// dup()ing any file descriptors to be transmitted and setting the |auto_close|
+// flag, which causes the file descriptor to be closed after writing.
+template<>
+struct IPC_EXPORT ParamTraits<base::FileDescriptor> {
+  typedef base::FileDescriptor param_type;
+  static void GetSize(base::PickleSizer* sizer, const param_type& p);
+  static void Write(base::Pickle* m, const param_type& p);
+  static bool Read(const base::Pickle* m,
+                   base::PickleIterator* iter,
+                   param_type* r);
+  static void Log(const param_type& p, std::string* l);
+};
+#endif  // defined(OS_POSIX)
+
+#if (defined(OS_MACOSX) && !defined(OS_IOS)) || defined(OS_WIN)
+template <>
+struct IPC_EXPORT ParamTraits<base::SharedMemoryHandle> {
+  typedef base::SharedMemoryHandle param_type;
+  static void GetSize(base::PickleSizer* sizer, const param_type& p);
+  static void Write(base::Pickle* m, const param_type& p);
+  static bool Read(const base::Pickle* m,
+                   base::PickleIterator* iter,
+                   param_type* r);
+  static void Log(const param_type& p, std::string* l);
+};
+#endif  // (defined(OS_MACOSX) && !defined(OS_IOS)) || defined(OS_WIN)
+
+template <>
+struct IPC_EXPORT ParamTraits<base::FilePath> {
+  typedef base::FilePath param_type;
+  static void GetSize(base::PickleSizer* sizer, const param_type& p);
+  static void Write(base::Pickle* m, const param_type& p);
+  static bool Read(const base::Pickle* m,
+                   base::PickleIterator* iter,
+                   param_type* r);
+  static void Log(const param_type& p, std::string* l);
+};
+
+template <>
+struct IPC_EXPORT ParamTraits<base::ListValue> {
+  typedef base::ListValue param_type;
+  static void GetSize(base::PickleSizer* sizer, const param_type& p);
+  static void Write(base::Pickle* m, const param_type& p);
+  static bool Read(const base::Pickle* m,
+                   base::PickleIterator* iter,
+                   param_type* r);
+  static void Log(const param_type& p, std::string* l);
+};
+
+template <>
+struct IPC_EXPORT ParamTraits<base::NullableString16> {
+  typedef base::NullableString16 param_type;
+  static void GetSize(base::PickleSizer* sizer, const param_type& p);
+  static void Write(base::Pickle* m, const param_type& p);
+  static bool Read(const base::Pickle* m,
+                   base::PickleIterator* iter,
+                   param_type* r);
+  static void Log(const param_type& p, std::string* l);
+};
+
+template <>
+struct IPC_EXPORT ParamTraits<base::File::Info> {
+  typedef base::File::Info param_type;
+  static void GetSize(base::PickleSizer* sizer, const param_type& p);
+  static void Write(base::Pickle* m, const param_type& p);
+  static bool Read(const base::Pickle* m,
+                   base::PickleIterator* iter,
+                   param_type* r);
+  static void Log(const param_type& p, std::string* l);
+};
+
+template <>
+struct SimilarTypeTraits<base::File::Error> {
+  typedef int Type;
+};
+
+#if defined(OS_WIN)
+template <>
+struct SimilarTypeTraits<HWND> {
+  typedef HANDLE Type;
+};
+#endif  // defined(OS_WIN)
+
+template <>
+struct IPC_EXPORT ParamTraits<base::Time> {
+  typedef base::Time param_type;
+  static void GetSize(base::PickleSizer* sizer, const param_type& p);
+  static void Write(base::Pickle* m, const param_type& p);
+  static bool Read(const base::Pickle* m,
+                   base::PickleIterator* iter,
+                   param_type* r);
+  static void Log(const param_type& p, std::string* l);
+};
+
+template <>
+struct IPC_EXPORT ParamTraits<base::TimeDelta> {
+  typedef base::TimeDelta param_type;
+  static void GetSize(base::PickleSizer* sizer, const param_type& p);
+  static void Write(base::Pickle* m, const param_type& p);
+  static bool Read(const base::Pickle* m,
+                   base::PickleIterator* iter,
+                   param_type* r);
+  static void Log(const param_type& p, std::string* l);
+};
+
+template <>
+struct IPC_EXPORT ParamTraits<base::TimeTicks> {
+  typedef base::TimeTicks param_type;
+  static void GetSize(base::PickleSizer* sizer, const param_type& p);
+  static void Write(base::Pickle* m, const param_type& p);
+  static bool Read(const base::Pickle* m,
+                   base::PickleIterator* iter,
+                   param_type* r);
+  static void Log(const param_type& p, std::string* l);
+};
+
+template <>
+struct ParamTraits<std::tuple<>> {
+  typedef std::tuple<> param_type;
+  static void GetSize(base::PickleSizer* sizer, const param_type& p) {}
+  static void Write(base::Pickle* m, const param_type& p) {}
+  static bool Read(const base::Pickle* m,
+                   base::PickleIterator* iter,
+                   param_type* r) {
+    return true;
+  }
+  static void Log(const param_type& p, std::string* l) {
+  }
+};
+
+template <class A>
+struct ParamTraits<std::tuple<A>> {
+  typedef std::tuple<A> param_type;
+  static void GetSize(base::PickleSizer* sizer, const param_type& p) {
+    GetParamSize(sizer, std::get<0>(p));
+  }
+  static void Write(base::Pickle* m, const param_type& p) {
+    WriteParam(m, std::get<0>(p));
+  }
+  static bool Read(const base::Pickle* m,
+                   base::PickleIterator* iter,
+                   param_type* r) {
+    return ReadParam(m, iter, &std::get<0>(*r));
+  }
+  static void Log(const param_type& p, std::string* l) {
+    LogParam(std::get<0>(p), l);
+  }
+};
+
+template <class A, class B>
+struct ParamTraits<std::tuple<A, B>> {
+  typedef std::tuple<A, B> param_type;
+  static void GetSize(base::PickleSizer* sizer, const param_type& p) {
+    GetParamSize(sizer, std::get<0>(p));
+    GetParamSize(sizer, std::get<1>(p));
+  }
+  static void Write(base::Pickle* m, const param_type& p) {
+    WriteParam(m, std::get<0>(p));
+    WriteParam(m, std::get<1>(p));
+  }
+  static bool Read(const base::Pickle* m,
+                   base::PickleIterator* iter,
+                   param_type* r) {
+    return (ReadParam(m, iter, &std::get<0>(*r)) &&
+            ReadParam(m, iter, &std::get<1>(*r)));
+  }
+  static void Log(const param_type& p, std::string* l) {
+    LogParam(std::get<0>(p), l);
+    l->append(", ");
+    LogParam(std::get<1>(p), l);
+  }
+};
+
+template <class A, class B, class C>
+struct ParamTraits<std::tuple<A, B, C>> {
+  typedef std::tuple<A, B, C> param_type;
+  static void GetSize(base::PickleSizer* sizer, const param_type& p) {
+    GetParamSize(sizer, std::get<0>(p));
+    GetParamSize(sizer, std::get<1>(p));
+    GetParamSize(sizer, std::get<2>(p));
+  }
+  static void Write(base::Pickle* m, const param_type& p) {
+    WriteParam(m, std::get<0>(p));
+    WriteParam(m, std::get<1>(p));
+    WriteParam(m, std::get<2>(p));
+  }
+  static bool Read(const base::Pickle* m,
+                   base::PickleIterator* iter,
+                   param_type* r) {
+    return (ReadParam(m, iter, &std::get<0>(*r)) &&
+            ReadParam(m, iter, &std::get<1>(*r)) &&
+            ReadParam(m, iter, &std::get<2>(*r)));
+  }
+  static void Log(const param_type& p, std::string* l) {
+    LogParam(std::get<0>(p), l);
+    l->append(", ");
+    LogParam(std::get<1>(p), l);
+    l->append(", ");
+    LogParam(std::get<2>(p), l);
+  }
+};
+
+template <class A, class B, class C, class D>
+struct ParamTraits<std::tuple<A, B, C, D>> {
+  typedef std::tuple<A, B, C, D> param_type;
+  static void GetSize(base::PickleSizer* sizer, const param_type& p) {
+    GetParamSize(sizer, std::get<0>(p));
+    GetParamSize(sizer, std::get<1>(p));
+    GetParamSize(sizer, std::get<2>(p));
+    GetParamSize(sizer, std::get<3>(p));
+  }
+  static void Write(base::Pickle* m, const param_type& p) {
+    WriteParam(m, std::get<0>(p));
+    WriteParam(m, std::get<1>(p));
+    WriteParam(m, std::get<2>(p));
+    WriteParam(m, std::get<3>(p));
+  }
+  static bool Read(const base::Pickle* m,
+                   base::PickleIterator* iter,
+                   param_type* r) {
+    return (ReadParam(m, iter, &std::get<0>(*r)) &&
+            ReadParam(m, iter, &std::get<1>(*r)) &&
+            ReadParam(m, iter, &std::get<2>(*r)) &&
+            ReadParam(m, iter, &std::get<3>(*r)));
+  }
+  static void Log(const param_type& p, std::string* l) {
+    LogParam(std::get<0>(p), l);
+    l->append(", ");
+    LogParam(std::get<1>(p), l);
+    l->append(", ");
+    LogParam(std::get<2>(p), l);
+    l->append(", ");
+    LogParam(std::get<3>(p), l);
+  }
+};
+
+template <class A, class B, class C, class D, class E>
+struct ParamTraits<std::tuple<A, B, C, D, E>> {
+  typedef std::tuple<A, B, C, D, E> param_type;
+  static void GetSize(base::PickleSizer* sizer, const param_type& p) {
+    GetParamSize(sizer, std::get<0>(p));
+    GetParamSize(sizer, std::get<1>(p));
+    GetParamSize(sizer, std::get<2>(p));
+    GetParamSize(sizer, std::get<3>(p));
+    GetParamSize(sizer, std::get<4>(p));
+  }
+  static void Write(base::Pickle* m, const param_type& p) {
+    WriteParam(m, std::get<0>(p));
+    WriteParam(m, std::get<1>(p));
+    WriteParam(m, std::get<2>(p));
+    WriteParam(m, std::get<3>(p));
+    WriteParam(m, std::get<4>(p));
+  }
+  static bool Read(const base::Pickle* m,
+                   base::PickleIterator* iter,
+                   param_type* r) {
+    return (ReadParam(m, iter, &std::get<0>(*r)) &&
+            ReadParam(m, iter, &std::get<1>(*r)) &&
+            ReadParam(m, iter, &std::get<2>(*r)) &&
+            ReadParam(m, iter, &std::get<3>(*r)) &&
+            ReadParam(m, iter, &std::get<4>(*r)));
+  }
+  static void Log(const param_type& p, std::string* l) {
+    LogParam(std::get<0>(p), l);
+    l->append(", ");
+    LogParam(std::get<1>(p), l);
+    l->append(", ");
+    LogParam(std::get<2>(p), l);
+    l->append(", ");
+    LogParam(std::get<3>(p), l);
+    l->append(", ");
+    LogParam(std::get<4>(p), l);
+  }
+};
+
+template<class P>
+struct ParamTraits<ScopedVector<P> > {
+  typedef ScopedVector<P> param_type;
+  static void Write(base::Pickle* m, const param_type& p) {
+    WriteParam(m, static_cast<int>(p.size()));
+    for (size_t i = 0; i < p.size(); i++)
+      WriteParam(m, *p[i]);
+  }
+  static bool Read(const base::Pickle* m,
+                   base::PickleIterator* iter,
+                   param_type* r) {
+    int size = 0;
+    if (!iter->ReadLength(&size))
+      return false;
+    if (INT_MAX/sizeof(P) <= static_cast<size_t>(size))
+      return false;
+    r->resize(size);
+    for (int i = 0; i < size; i++) {
+      (*r)[i] = new P();
+      if (!ReadParam(m, iter, (*r)[i]))
+        return false;
+    }
+    return true;
+  }
+  static void Log(const param_type& p, std::string* l) {
+    for (size_t i = 0; i < p.size(); ++i) {
+      if (i != 0)
+        l->append(" ");
+      LogParam(*p[i], l);
+    }
+  }
+};
+
+template <class P, size_t stack_capacity>
+struct ParamTraits<base::StackVector<P, stack_capacity> > {
+  typedef base::StackVector<P, stack_capacity> param_type;
+  static void GetSize(base::PickleSizer* sizer, const param_type& p) {
+    GetParamSize(sizer, static_cast<int>(p->size()));
+    for (size_t i = 0; i < p->size(); i++)
+      GetParamSize(sizer, p[i]);
+  }
+  static void Write(base::Pickle* m, const param_type& p) {
+    WriteParam(m, static_cast<int>(p->size()));
+    for (size_t i = 0; i < p->size(); i++)
+      WriteParam(m, p[i]);
+  }
+  static bool Read(const base::Pickle* m,
+                   base::PickleIterator* iter,
+                   param_type* r) {
+    int size;
+    // ReadLength() checks for < 0 itself.
+    if (!iter->ReadLength(&size))
+      return false;
+    // Sanity check for the vector size.
+    if (INT_MAX / sizeof(P) <= static_cast<size_t>(size))
+      return false;
+    P value;
+    for (int i = 0; i < size; i++) {
+      if (!ReadParam(m, iter, &value))
+        return false;
+      (*r)->push_back(value);
+    }
+    return true;
+  }
+  static void Log(const param_type& p, std::string* l) {
+    for (size_t i = 0; i < p->size(); ++i) {
+      if (i != 0)
+        l->append(" ");
+      LogParam((p[i]), l);
+    }
+  }
+};
+
+template <typename NormalMap,
+          int kArraySize,
+          typename EqualKey,
+          typename MapInit>
+struct ParamTraits<base::SmallMap<NormalMap, kArraySize, EqualKey, MapInit> > {
+  typedef base::SmallMap<NormalMap, kArraySize, EqualKey, MapInit> param_type;
+  typedef typename param_type::key_type K;
+  typedef typename param_type::data_type V;
+  static void GetSize(base::PickleSizer* sizer, const param_type& p) {
+    GetParamSize(sizer, static_cast<int>(p.size()));
+    typename param_type::const_iterator iter;
+    for (iter = p.begin(); iter != p.end(); ++iter) {
+      GetParamSize(sizer, iter->first);
+      GetParamSize(sizer, iter->second);
+    }
+  }
+  static void Write(base::Pickle* m, const param_type& p) {
+    WriteParam(m, static_cast<int>(p.size()));
+    typename param_type::const_iterator iter;
+    for (iter = p.begin(); iter != p.end(); ++iter) {
+      WriteParam(m, iter->first);
+      WriteParam(m, iter->second);
+    }
+  }
+  static bool Read(const base::Pickle* m,
+                   base::PickleIterator* iter,
+                   param_type* r) {
+    int size;
+    if (!iter->ReadLength(&size))
+      return false;
+    for (int i = 0; i < size; ++i) {
+      K key;
+      if (!ReadParam(m, iter, &key))
+        return false;
+      V& value = (*r)[key];
+      if (!ReadParam(m, iter, &value))
+        return false;
+    }
+    return true;
+  }
+  static void Log(const param_type& p, std::string* l) {
+    l->append("<base::SmallMap>");
+  }
+};
+
+template <class P>
+struct ParamTraits<std::unique_ptr<P>> {
+  typedef std::unique_ptr<P> param_type;
+  static void GetSize(base::PickleSizer* sizer, const param_type& p) {
+    bool valid = !!p;
+    GetParamSize(sizer, valid);
+    if (valid)
+      GetParamSize(sizer, *p);
+  }
+  static void Write(base::Pickle* m, const param_type& p) {
+    bool valid = !!p;
+    WriteParam(m, valid);
+    if (valid)
+      WriteParam(m, *p);
+  }
+  static bool Read(const base::Pickle* m,
+                   base::PickleIterator* iter,
+                   param_type* r) {
+    bool valid = false;
+    if (!ReadParam(m, iter, &valid))
+      return false;
+
+    if (!valid) {
+      r->reset();
+      return true;
+    }
+
+    param_type temp(new P());
+    if (!ReadParam(m, iter, temp.get()))
+      return false;
+
+    r->swap(temp);
+    return true;
+  }
+  static void Log(const param_type& p, std::string* l) {
+    if (p)
+      LogParam(*p, l);
+    else
+      l->append("NULL");
+  }
+};
+
+template <class P>
+struct ParamTraits<base::Optional<P>> {
+  typedef base::Optional<P> param_type;
+  static void GetSize(base::PickleSizer* sizer, const param_type& p) {
+    const bool is_set = static_cast<bool>(p);
+    GetParamSize(sizer, is_set);
+    if (is_set)
+      GetParamSize(sizer, p.value());
+  }
+  static void Write(base::Pickle* m, const param_type& p) {
+    const bool is_set = static_cast<bool>(p);
+    WriteParam(m, is_set);
+    if (is_set)
+      WriteParam(m, p.value());
+  }
+  static bool Read(const base::Pickle* m,
+                   base::PickleIterator* iter,
+                   param_type* r) {
+    bool is_set = false;
+    if (!iter->ReadBool(&is_set))
+      return false;
+    if (is_set) {
+      P value;
+      if (!ReadParam(m, iter, &value))
+        return false;
+      *r = std::move(value);
+    }
+    return true;
+  }
+  static void Log(const param_type& p, std::string* l) {
+    if (p)
+      LogParam(p.value(), l);
+    else
+      l->append("(unset)");
+  }
+};
+
+// IPC types ParamTraits -------------------------------------------------------
+
+// A ChannelHandle is basically a platform-inspecific wrapper around the
+// fact that IPC endpoints are handled specially on POSIX.  See above comments
+// on FileDescriptor for more background.
+template<>
+struct IPC_EXPORT ParamTraits<IPC::ChannelHandle> {
+  typedef ChannelHandle param_type;
+  static void GetSize(base::PickleSizer* sizer, const param_type& p);
+  static void Write(base::Pickle* m, const param_type& p);
+  static bool Read(const base::Pickle* m,
+                   base::PickleIterator* iter,
+                   param_type* r);
+  static void Log(const param_type& p, std::string* l);
+};
+
+template <>
+struct IPC_EXPORT ParamTraits<LogData> {
+  typedef LogData param_type;
+  static void GetSize(base::PickleSizer* sizer, const param_type& p);
+  static void Write(base::Pickle* m, const param_type& p);
+  static bool Read(const base::Pickle* m,
+                   base::PickleIterator* iter,
+                   param_type* r);
+  static void Log(const param_type& p, std::string* l);
+};
+
+template <>
+struct IPC_EXPORT ParamTraits<Message> {
+  static void Write(base::Pickle* m, const Message& p);
+  static bool Read(const base::Pickle* m,
+                   base::PickleIterator* iter,
+                   Message* r);
+  static void Log(const Message& p, std::string* l);
+};
+
+// Windows ParamTraits ---------------------------------------------------------
+
+#if defined(OS_WIN)
+template <>
+struct IPC_EXPORT ParamTraits<HANDLE> {
+  typedef HANDLE param_type;
+  static void GetSize(base::PickleSizer* sizer, const param_type& p);
+  static void Write(base::Pickle* m, const param_type& p);
+  static bool Read(const base::Pickle* m,
+                   base::PickleIterator* iter,
+                   param_type* r);
+  static void Log(const param_type& p, std::string* l);
+};
+
+template <>
+struct IPC_EXPORT ParamTraits<LOGFONT> {
+  typedef LOGFONT param_type;
+  static void GetSize(base::PickleSizer* sizer, const param_type& p);
+  static void Write(base::Pickle* m, const param_type& p);
+  static bool Read(const base::Pickle* m,
+                   base::PickleIterator* iter,
+                   param_type* r);
+  static void Log(const param_type& p, std::string* l);
+};
+
+template <>
+struct IPC_EXPORT ParamTraits<MSG> {
+  typedef MSG param_type;
+  static void GetSize(base::PickleSizer* sizer, const param_type& p);
+  static void Write(base::Pickle* m, const param_type& p);
+  static bool Read(const base::Pickle* m,
+                   base::PickleIterator* iter,
+                   param_type* r);
+  static void Log(const param_type& p, std::string* l);
+};
+#endif  // defined(OS_WIN)
+
+//-----------------------------------------------------------------------------
+// Generic message subclasses
+
+// defined in ipc_logging.cc
+IPC_EXPORT void GenerateLogData(const std::string& channel,
+                                const Message& message,
+                                LogData* data, bool get_params);
+
+
+#if defined(IPC_MESSAGE_LOG_ENABLED)
+inline void AddOutputParamsToLog(const Message* msg, std::string* l) {
+  const std::string& output_params = msg->output_params();
+  if (!l->empty() && !output_params.empty())
+    l->append(", ");
+
+  l->append(output_params);
+}
+
+template <class ReplyParamType>
+inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
+                                    const Message* msg) {
+  if (msg->received_time() != 0) {
+    std::string output_params;
+    LogParam(reply_params, &output_params);
+    msg->set_output_params(output_params);
+  }
+}
+
+inline void ConnectMessageAndReply(const Message* msg, Message* reply) {
+  if (msg->sent_time()) {
+    // Don't log the sync message after dispatch, as we don't have the
+    // output parameters at that point.  Instead, save its data and log it
+    // with the outgoing reply message when it's sent.
+    LogData* data = new LogData;
+    GenerateLogData("", *msg, data, true);
+    msg->set_dont_log();
+    reply->set_sync_log_data(data);
+  }
+}
+#else
+inline void AddOutputParamsToLog(const Message* msg, std::string* l) {}
+
+template <class ReplyParamType>
+inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
+                                    const Message* msg) {}
+
+inline void ConnectMessageAndReply(const Message* msg, Message* reply) {}
+#endif
+
+}  // namespace IPC
+
+#endif  // IPC_IPC_MESSAGE_UTILS_H_
diff --git a/ipc/ipc_mojo_handle_attachment.cc b/ipc/ipc_mojo_handle_attachment.cc
new file mode 100644
index 0000000..819a12b
--- /dev/null
+++ b/ipc/ipc_mojo_handle_attachment.cc
@@ -0,0 +1,36 @@
+// Copyright (c) 2015 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 "ipc/ipc_mojo_handle_attachment.h"
+
+#include <utility>
+
+#include "build/build_config.h"
+
+namespace IPC {
+namespace internal {
+
+MojoHandleAttachment::MojoHandleAttachment(mojo::ScopedHandle handle)
+    : handle_(std::move(handle)) {}
+
+MojoHandleAttachment::~MojoHandleAttachment() {
+}
+
+MessageAttachment::Type MojoHandleAttachment::GetType() const {
+  return TYPE_MOJO_HANDLE;
+}
+
+#if defined(OS_POSIX)
+base::PlatformFile MojoHandleAttachment::TakePlatformFile() {
+  NOTREACHED();
+  return base::kInvalidPlatformFile;
+}
+#endif  // OS_POSIX
+
+mojo::ScopedHandle MojoHandleAttachment::TakeHandle() {
+  return std::move(handle_);
+}
+
+}  // namespace internal
+}  // namespace IPC
diff --git a/ipc/ipc_mojo_handle_attachment.h b/ipc/ipc_mojo_handle_attachment.h
new file mode 100644
index 0000000..6aa1888
--- /dev/null
+++ b/ipc/ipc_mojo_handle_attachment.h
@@ -0,0 +1,47 @@
+// Copyright (c) 2015 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.
+
+#ifndef IPC_IPC_MOJO_HANDLE_ATTACHMENT_H_
+#define IPC_IPC_MOJO_HANDLE_ATTACHMENT_H_
+
+#include "base/files/file.h"
+#include "base/macros.h"
+#include "build/build_config.h"
+#include "ipc/ipc_export.h"
+#include "ipc/ipc_message_attachment.h"
+#include "mojo/public/cpp/system/handle.h"
+
+namespace IPC {
+
+namespace internal {
+
+// A MessageAttachment that holds a MojoHandle.
+// This can hold any type of transferrable Mojo handle (i.e. message pipe, data
+// pipe, etc), but the receiver is expected to know what type of handle to
+// expect.
+class IPC_EXPORT MojoHandleAttachment : public MessageAttachment {
+ public:
+  explicit MojoHandleAttachment(mojo::ScopedHandle handle);
+
+  Type GetType() const override;
+
+#if defined(OS_POSIX)
+  // Should not be called.
+  base::PlatformFile TakePlatformFile() override;
+#endif  // OS_POSIX
+
+  // Returns the owning handle transferring the ownership.
+  mojo::ScopedHandle TakeHandle();
+
+ private:
+  ~MojoHandleAttachment() override;
+  mojo::ScopedHandle handle_;
+
+  DISALLOW_COPY_AND_ASSIGN(MojoHandleAttachment);
+};
+
+}  // namespace internal
+}  // namespace IPC
+
+#endif  // IPC_IPC_MOJO_HANDLE_ATTACHMENT_H_
diff --git a/ipc/ipc_mojo_message_helper.cc b/ipc/ipc_mojo_message_helper.cc
new file mode 100644
index 0000000..8f86945
--- /dev/null
+++ b/ipc/ipc_mojo_message_helper.cc
@@ -0,0 +1,51 @@
+// Copyright (c) 2015 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 "ipc/ipc_mojo_message_helper.h"
+
+#include <utility>
+
+#include "ipc/ipc_mojo_handle_attachment.h"
+
+namespace IPC {
+
+// static
+bool MojoMessageHelper::WriteMessagePipeTo(
+    base::Pickle* message,
+    mojo::ScopedMessagePipeHandle handle) {
+  message->WriteAttachment(new internal::MojoHandleAttachment(
+      mojo::ScopedHandle::From(std::move(handle))));
+  return true;
+}
+
+// static
+bool MojoMessageHelper::ReadMessagePipeFrom(
+    const base::Pickle* message,
+    base::PickleIterator* iter,
+    mojo::ScopedMessagePipeHandle* handle) {
+  scoped_refptr<base::Pickle::Attachment> attachment;
+  if (!message->ReadAttachment(iter, &attachment)) {
+    LOG(ERROR) << "Failed to read attachment for message pipe.";
+    return false;
+  }
+
+  MessageAttachment::Type type =
+      static_cast<MessageAttachment*>(attachment.get())->GetType();
+  if (type != MessageAttachment::TYPE_MOJO_HANDLE) {
+    LOG(ERROR) << "Unxpected attachment type:" << type;
+    return false;
+  }
+
+  handle->reset(mojo::MessagePipeHandle(
+      static_cast<internal::MojoHandleAttachment*>(attachment.get())
+          ->TakeHandle()
+          .release()
+          .value()));
+  return true;
+}
+
+MojoMessageHelper::MojoMessageHelper() {
+}
+
+}  // namespace IPC
diff --git a/ipc/ipc_mojo_message_helper.h b/ipc/ipc_mojo_message_helper.h
new file mode 100644
index 0000000..4a71b5c
--- /dev/null
+++ b/ipc/ipc_mojo_message_helper.h
@@ -0,0 +1,29 @@
+// Copyright (c) 2015 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.
+
+#ifndef IPC_IPC_MOJO_MESSAGE_HELPER_H_
+#define IPC_IPC_MOJO_MESSAGE_HELPER_H_
+
+#include "ipc/ipc_export.h"
+#include "ipc/ipc_message.h"
+#include "mojo/public/cpp/system/message_pipe.h"
+
+namespace IPC {
+
+// Reads and writes |mojo::MessagePipe| from/to |Message|.
+class IPC_EXPORT MojoMessageHelper {
+ public:
+  static bool WriteMessagePipeTo(base::Pickle* message,
+                                 mojo::ScopedMessagePipeHandle handle);
+  static bool ReadMessagePipeFrom(const base::Pickle* message,
+                                  base::PickleIterator* iter,
+                                  mojo::ScopedMessagePipeHandle* handle);
+
+ private:
+  MojoMessageHelper();
+};
+
+}  // namespace IPC
+
+#endif  // IPC_IPC_MOJO_MESSAGE_HELPER_H_
diff --git a/ipc/ipc_mojo_param_traits.cc b/ipc/ipc_mojo_param_traits.cc
new file mode 100644
index 0000000..189af35
--- /dev/null
+++ b/ipc/ipc_mojo_param_traits.cc
@@ -0,0 +1,50 @@
+// Copyright 2015 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 "ipc/ipc_mojo_param_traits.h"
+
+#include "ipc/ipc_message_utils.h"
+#include "ipc/ipc_mojo_message_helper.h"
+
+namespace IPC {
+
+void ParamTraits<mojo::MessagePipeHandle>::GetSize(base::PickleSizer* sizer,
+                                                   const param_type& p) {
+  GetParamSize(sizer, p.is_valid());
+  if (p.is_valid())
+    sizer->AddAttachment();
+}
+
+void ParamTraits<mojo::MessagePipeHandle>::Write(base::Pickle* m,
+                                                 const param_type& p) {
+  WriteParam(m, p.is_valid());
+  if (p.is_valid())
+    MojoMessageHelper::WriteMessagePipeTo(m, mojo::ScopedMessagePipeHandle(p));
+}
+
+bool ParamTraits<mojo::MessagePipeHandle>::Read(const base::Pickle* m,
+                                                base::PickleIterator* iter,
+                                                param_type* r) {
+  bool is_valid;
+  if (!ReadParam(m, iter, &is_valid))
+    return false;
+  if (!is_valid)
+    return true;
+
+  mojo::ScopedMessagePipeHandle handle;
+  if (!MojoMessageHelper::ReadMessagePipeFrom(m, iter, &handle))
+    return false;
+  DCHECK(handle.is_valid());
+  *r = handle.release();
+  return true;
+}
+
+void ParamTraits<mojo::MessagePipeHandle>::Log(const param_type& p,
+                                               std::string* l) {
+  l->append("mojo::MessagePipeHandle(");
+  LogParam(p.value(), l);
+  l->append(")");
+}
+
+}  // namespace IPC
diff --git a/ipc/ipc_mojo_param_traits.h b/ipc/ipc_mojo_param_traits.h
new file mode 100644
index 0000000..39be43e
--- /dev/null
+++ b/ipc/ipc_mojo_param_traits.h
@@ -0,0 +1,34 @@
+// Copyright 2015 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.
+
+#ifndef IPC_IPC_MOJO_PARAM_TRAITS_H_
+#define IPC_IPC_MOJO_PARAM_TRAITS_H_
+
+#include <string>
+
+#include "ipc/ipc_export.h"
+#include "ipc/ipc_param_traits.h"
+#include "mojo/public/cpp/system/message_pipe.h"
+
+namespace base {
+class Pickle;
+class PickleIterator;
+class PickleSizer;
+}
+
+namespace IPC {
+
+template <>
+struct IPC_EXPORT ParamTraits<mojo::MessagePipeHandle> {
+  typedef mojo::MessagePipeHandle param_type;
+  static void GetSize(base::PickleSizer* sizer, const param_type& p);
+  static void Write(base::Pickle* m, const param_type& p);
+  static bool Read(const base::Pickle* m, base::PickleIterator* iter,
+                   param_type* r);
+  static void Log(const param_type& p, std::string* l);
+};
+
+}  // namespace IPC
+
+#endif  // IPC_IPC_MOJO_PARAM_TRAITS_H_
diff --git a/ipc/ipc_param_traits.h b/ipc/ipc_param_traits.h
new file mode 100644
index 0000000..45e975c
--- /dev/null
+++ b/ipc/ipc_param_traits.h
@@ -0,0 +1,23 @@
+// Copyright (c) 2010 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.
+
+#ifndef IPC_IPC_PARAM_TRAITS_H_
+#define IPC_IPC_PARAM_TRAITS_H_
+
+// Our IPC system uses the following partially specialized header to define how
+// a data type is read, written and logged in the IPC system.
+
+namespace IPC {
+
+template <class P> struct ParamTraits {
+};
+
+template <class P>
+struct SimilarTypeTraits {
+  typedef P Type;
+};
+
+}  // namespace IPC
+
+#endif  // IPC_IPC_PARAM_TRAITS_H_
diff --git a/ipc/ipc_platform_file_attachment_posix.cc b/ipc/ipc_platform_file_attachment_posix.cc
new file mode 100644
index 0000000..b130ab2
--- /dev/null
+++ b/ipc/ipc_platform_file_attachment_posix.cc
@@ -0,0 +1,38 @@
+// Copyright (c) 2015 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 "ipc/ipc_platform_file_attachment_posix.h"
+
+#include <utility>
+
+namespace IPC {
+namespace internal {
+
+PlatformFileAttachment::PlatformFileAttachment(base::PlatformFile file)
+    : file_(file) {
+}
+
+PlatformFileAttachment::PlatformFileAttachment(base::ScopedFD file)
+    : file_(file.get()), owning_(std::move(file)) {}
+
+PlatformFileAttachment::~PlatformFileAttachment() {
+}
+
+MessageAttachment::Type PlatformFileAttachment::GetType() const {
+  return TYPE_PLATFORM_FILE;
+}
+
+base::PlatformFile PlatformFileAttachment::TakePlatformFile() {
+  ignore_result(owning_.release());
+  return file_;
+}
+
+base::PlatformFile GetPlatformFile(
+    scoped_refptr<MessageAttachment> attachment) {
+  DCHECK_EQ(attachment->GetType(), MessageAttachment::TYPE_PLATFORM_FILE);
+  return static_cast<PlatformFileAttachment*>(attachment.get())->file();
+}
+
+}  // namespace internal
+}  // namespace IPC
diff --git a/ipc/ipc_platform_file_attachment_posix.h b/ipc/ipc_platform_file_attachment_posix.h
new file mode 100644
index 0000000..d1eff60
--- /dev/null
+++ b/ipc/ipc_platform_file_attachment_posix.h
@@ -0,0 +1,43 @@
+// Copyright (c) 2015 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.
+
+#ifndef IPC_IPC_PLATFORM_FILE_ATTACHMENT_H_
+#define IPC_IPC_PLATFORM_FILE_ATTACHMENT_H_
+
+#include "ipc/ipc_export.h"
+#include "ipc/ipc_message_attachment.h"
+
+namespace IPC {
+namespace internal {
+
+// A platform file that is sent over |Channel| as a part of |Message|.
+// PlatformFileAttachment optionally owns the file and |owning_| is set in that
+// case. Also, |file_| is not cleared even after the ownership is taken.
+// Some old clients require this strange behavior.
+class IPC_EXPORT PlatformFileAttachment : public MessageAttachment {
+ public:
+  // Non-owning constructor
+  explicit PlatformFileAttachment(base::PlatformFile file);
+  // Owning constructor
+  explicit PlatformFileAttachment(base::ScopedFD file);
+
+  Type GetType() const override;
+  base::PlatformFile TakePlatformFile() override;
+
+  base::PlatformFile file() const { return file_; }
+  bool Owns() const { return owning_.is_valid(); }
+
+ private:
+  ~PlatformFileAttachment() override;
+
+  base::PlatformFile file_;
+  base::ScopedFD owning_;
+};
+
+base::PlatformFile GetPlatformFile(scoped_refptr<MessageAttachment> attachment);
+
+}  // namespace internal
+}  // namespace IPC
+
+#endif  // IPC_IPC_PLATFORM_FILE_ATTACHMENT_H_
diff --git a/ipc/ipc_sync_message.h b/ipc/ipc_sync_message.h
new file mode 100644
index 0000000..ed5204f
--- /dev/null
+++ b/ipc/ipc_sync_message.h
@@ -0,0 +1,104 @@
+// 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.
+
+#ifndef IPC_IPC_SYNC_MESSAGE_H_
+#define IPC_IPC_SYNC_MESSAGE_H_
+
+#include <stdint.h>
+
+#if defined(OS_WIN)
+#include <windows.h>
+#endif
+
+#include <memory>
+#include <string>
+
+#include "build/build_config.h"
+#include "ipc/ipc_message.h"
+
+namespace IPC {
+
+class MessageReplyDeserializer;
+class MojoEvent;
+
+class IPC_EXPORT SyncMessage : public Message {
+ public:
+  SyncMessage(int32_t routing_id,
+              uint32_t type,
+              PriorityValue priority,
+              MessageReplyDeserializer* deserializer);
+  ~SyncMessage() override;
+
+  // Call this to get a deserializer for the output parameters.
+  // Note that this can only be called once, and the caller is responsible
+  // for deleting the deserializer when they're done.
+  MessageReplyDeserializer* GetReplyDeserializer();
+
+  // If this message can cause the receiver to block while waiting for user
+  // input (i.e. by calling MessageBox), then the caller needs to pump window
+  // messages and dispatch asynchronous messages while waiting for the reply.
+  // This call enables message pumping behavior while waiting for a reply to
+  // this message.
+  void EnableMessagePumping() {
+    header()->flags |= PUMPING_MSGS_BIT;
+  }
+
+  // Indicates whether window messages should be pumped while waiting for a
+  // reply to this message.
+  bool ShouldPumpMessages() const {
+    return (header()->flags & PUMPING_MSGS_BIT) != 0;
+  }
+
+  // Returns true if the message is a reply to the given request id.
+  static bool IsMessageReplyTo(const Message& msg, int request_id);
+
+  // Given a reply message, returns an iterator to the beginning of the data
+  // (i.e. skips over the synchronous specific data).
+  static base::PickleIterator GetDataIterator(const Message* msg);
+
+  // Given a synchronous message (or its reply), returns its id.
+  static int GetMessageId(const Message& msg);
+
+  // Generates a reply message to the given message.
+  static Message* GenerateReply(const Message* msg);
+
+ private:
+  struct SyncHeader {
+    // unique ID (unique per sender)
+    int message_id;
+  };
+
+  static bool ReadSyncHeader(const Message& msg, SyncHeader* header);
+  static bool WriteSyncHeader(Message* msg, const SyncHeader& header);
+
+  std::unique_ptr<MessageReplyDeserializer> deserializer_;
+};
+
+// Used to deserialize parameters from a reply to a synchronous message
+class IPC_EXPORT MessageReplyDeserializer {
+ public:
+  virtual ~MessageReplyDeserializer() {}
+  bool SerializeOutputParameters(const Message& msg);
+ private:
+  // Derived classes need to implement this, using the given iterator (which
+  // is skipped past the header for synchronous messages).
+  virtual bool SerializeOutputParameters(const Message& msg,
+                                         base::PickleIterator iter) = 0;
+};
+
+// When sending a synchronous message, this structure contains an object
+// that knows how to deserialize the response.
+struct PendingSyncMsg {
+  PendingSyncMsg(int id, MessageReplyDeserializer* d, MojoEvent* e)
+      : id(id), deserializer(d), done_event(e), send_result(false) { }
+
+  int id;
+  MessageReplyDeserializer* deserializer;
+  MojoEvent* done_event;
+  bool send_result;
+};
+
+}  // namespace IPC
+
+#endif  // IPC_IPC_SYNC_MESSAGE_H_
diff --git a/ipc/placeholder_brokerable_attachment.cc b/ipc/placeholder_brokerable_attachment.cc
new file mode 100644
index 0000000..e64e398
--- /dev/null
+++ b/ipc/placeholder_brokerable_attachment.cc
@@ -0,0 +1,14 @@
+// Copyright 2015 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 "ipc/placeholder_brokerable_attachment.h"
+
+namespace IPC {
+
+BrokerableAttachment::BrokerableType
+PlaceholderBrokerableAttachment::GetBrokerableType() const {
+  return PLACEHOLDER;
+}
+
+}  // namespace IPC
diff --git a/ipc/placeholder_brokerable_attachment.h b/ipc/placeholder_brokerable_attachment.h
new file mode 100644
index 0000000..a8b08ef
--- /dev/null
+++ b/ipc/placeholder_brokerable_attachment.h
@@ -0,0 +1,29 @@
+// Copyright 2015 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.
+
+#ifndef IPC_PLACEHOLDER_BROKERABLE_ATTACHMENT_H_
+#define IPC_PLACEHOLDER_BROKERABLE_ATTACHMENT_H_
+
+#include "base/macros.h"
+#include "ipc/brokerable_attachment.h"
+#include "ipc/ipc_export.h"
+
+namespace IPC {
+
+// This subclass of BrokerableAttachment has an AttachmentId, and nothing else.
+// It is intended to be replaced by the attachment broker.
+class IPC_EXPORT PlaceholderBrokerableAttachment : public BrokerableAttachment {
+ public:
+  PlaceholderBrokerableAttachment(const AttachmentId& id)
+      : BrokerableAttachment(id){};
+  BrokerableType GetBrokerableType() const override;
+
+ protected:
+  ~PlaceholderBrokerableAttachment() override{};
+  DISALLOW_COPY_AND_ASSIGN(PlaceholderBrokerableAttachment);
+};
+
+}  // namespace IPC
+
+#endif  // IPC_PLACEHOLDER_BROKERABLE_ATTACHMENT_H_