Revert "libmojo: Uprev the library to r456626 from Chromium"

This reverts commit 8ac9103e05b66812c25348943383f9365d1ce3e0.

Reason for revert: Broke the mac_sdk
Exempt-From-Owner-Approval: Fixing mac_sdk

Change-Id: I0b74d1abaa66933a93fd6f82ff018e8948c1204e
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.mojom b/ipc/ipc.mojom
deleted file mode 100644
index 0a4fcfa..0000000
--- a/ipc/ipc.mojom
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2016 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.
-
-module IPC.mojom;
-
-// NOTE: This MUST match the value of MSG_ROUTING_NONE in src/ipc/ipc_message.h.
-const int32 kRoutingIdNone = -2;
-
-struct SerializedHandle {
-  handle the_handle;
-
-  enum Type {
-    MOJO_HANDLE,
-    PLATFORM_FILE,
-    WIN_HANDLE,
-    MACH_PORT,
-  };
-
-  Type type;
-};
-
-// A placeholder interface type since we don't yet support generic associated
-// message pipe handles.
-interface GenericInterface {};
-
-interface Channel {
-  // Informs the remote end of this client's PID. Must be called exactly once,
-  // before any calls to Receive() below.
-  SetPeerPid(int32 pid);
-
-  // Transmits a classical Chrome IPC message.
-  Receive(array<uint8> data, array<SerializedHandle>? handles);
-
-  // Requests a Channel-associated interface.
-  GetAssociatedInterface(string name, associated GenericInterface& request);
-};
-
-// A strictly nominal interface used to identify Channel bootstrap requests.
-interface ChannelBootstrap {};
diff --git a/ipc/ipc_channel_handle.h b/ipc/ipc_channel_handle.h
index ef31b84..2e9dc3e 100644
--- a/ipc/ipc_channel_handle.h
+++ b/ipc/ipc_channel_handle.h
@@ -10,31 +10,60 @@
 #include "build/build_config.h"
 #include "mojo/public/cpp/system/message_pipe.h"
 
-#if defined(OS_NACL_SFI)
+#if defined(OS_POSIX)
 #include "base/file_descriptor_posix.h"
-#endif  // defined (OS_NACL_SFI)
+#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 {
 
-// Note that serialization for this object is defined in the ParamTraits
-// template specialization in ipc_message_utils.h.
-#if defined(OS_NACL_SFI)
 struct ChannelHandle {
+  // Note that serialization for this object is defined in the ParamTraits
+  // template specialization in ipc_message_utils.h.
   ChannelHandle() {}
-  explicit ChannelHandle(const base::FileDescriptor& s) : socket(s) {}
-
-  base::FileDescriptor socket;
-};
-#else
-struct ChannelHandle {
-  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) {}
 
-  bool is_mojo_channel_handle() const { return mojo_handle.is_valid(); }
-
+  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;
 };
-#endif  // defined(OS_NACL_SFI)
 
 }  // namespace IPC
 
diff --git a/ipc/ipc_listener.h b/ipc/ipc_listener.h
index d7ad75c..0277086 100644
--- a/ipc/ipc_listener.h
+++ b/ipc/ipc_listener.h
@@ -7,11 +7,8 @@
 
 #include <stdint.h>
 
-#include <string>
-
 #include "build/build_config.h"
 #include "ipc/ipc_export.h"
-#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h"
 
 namespace IPC {
 
@@ -35,12 +32,6 @@
   // Called when a message's deserialization failed.
   virtual void OnBadMessageReceived(const Message& message) {}
 
-  // Called when an associated interface request is received on a Channel and
-  // the Channel has no registered handler for it.
-  virtual void OnAssociatedInterfaceRequest(
-      const std::string& interface_name,
-      mojo::ScopedInterfaceEndpointHandle handle) {}
-
 #if defined(OS_POSIX)
   // Called on the server side when a channel that listens for connections
   // denies an attempt to connect.
diff --git a/ipc/ipc_message.cc b/ipc/ipc_message.cc
index f5e9ac7..83ee495 100644
--- a/ipc/ipc_message.cc
+++ b/ipc/ipc_message.cc
@@ -11,8 +11,10 @@
 #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"
@@ -50,6 +52,9 @@
 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;
@@ -63,6 +68,9 @@
   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;
@@ -78,10 +86,12 @@
 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;
@@ -92,6 +102,7 @@
 Message& Message::operator=(const Message& other) {
   *static_cast<base::Pickle*>(this) = other;
   attachment_set_ = other.attachment_set_;
+  sender_pid_ = other.sender_pid_;
   return *this;
 }
 
@@ -135,6 +146,26 @@
       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,
@@ -151,6 +182,43 @@
   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)
@@ -159,32 +227,53 @@
   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);
+      &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;
@@ -193,7 +282,9 @@
   if (!attachment_set)
     return false;
 
-  *attachment = attachment_set->GetAttachmentAt(index);
+  *attachment = brokerable
+                    ? attachment_set->GetBrokerableAttachmentAt(index)
+                    : attachment_set->GetNonBrokerableAttachmentAt(index);
 
   return nullptr != attachment->get();
 }
@@ -202,4 +293,13 @@
   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
index 43e9ae3..56c3a46 100644
--- a/ipc/ipc_message.h
+++ b/ipc/ipc_message.h
@@ -15,6 +15,8 @@
 #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)
@@ -30,6 +32,7 @@
 //------------------------------------------------------------------------------
 
 struct LogData;
+class MessageAttachment;
 class MessageAttachmentSet;
 
 class IPC_EXPORT Message : public base::Pickle {
@@ -188,13 +191,34 @@
     // 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(
@@ -206,6 +230,13 @@
       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
@@ -242,6 +273,12 @@
     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
@@ -275,6 +312,10 @@
     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_;
diff --git a/ipc/ipc_message_attachment.h b/ipc/ipc_message_attachment.h
index 9ff1de8..7f7137d 100644
--- a/ipc/ipc_message_attachment.h
+++ b/ipc/ipc_message_attachment.h
@@ -10,7 +10,6 @@
 #include "base/memory/ref_counted.h"
 #include "base/pickle.h"
 #include "build/build_config.h"
-#include "ipc/ipc.mojom.h"
 #include "ipc/ipc_export.h"
 
 namespace IPC {
@@ -19,10 +18,18 @@
 // or a mojo |MessagePipe|. |GetType()| returns the type of the subclass.
 class IPC_EXPORT MessageAttachment : public base::Pickle::Attachment {
  public:
-  using Type = mojom::SerializedHandle::Type;
+  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();
diff --git a/ipc/ipc_message_attachment_set.cc b/ipc/ipc_message_attachment_set.cc
index b9a990d..3b7eefb 100644
--- a/ipc/ipc_message_attachment_set.cc
+++ b/ipc/ipc_message_attachment_set.cc
@@ -11,8 +11,16 @@
 #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 {
@@ -35,7 +43,7 @@
 }
 
 MessageAttachmentSet::~MessageAttachmentSet() {
-  if (consumed_descriptor_highwater_ == size())
+  if (consumed_descriptor_highwater_ == num_non_brokerable_attachments())
     return;
 
   // We close all the owning descriptors. If this message should have
@@ -46,24 +54,39 @@
   // (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 attachments: "
-               << consumed_descriptor_highwater_ << "/" << size();
+  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);
+                                   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());
+  return static_cast<unsigned>(attachments_.size() +
+                               brokerable_attachments_.size());
 }
 
 bool MessageAttachmentSet::AddAttachment(
     scoped_refptr<MessageAttachment> attachment,
-    size_t* index) {
+    size_t* index,
+    bool* brokerable) {
 #if defined(OS_POSIX)
-  if (attachment->GetType() == MessageAttachment::Type::PLATFORM_FILE &&
+  if (attachment->GetType() == MessageAttachment::TYPE_PLATFORM_FILE &&
       num_descriptors() == kMaxDescriptorsPerMessage) {
     DLOG(WARNING) << "Cannot add file descriptor. MessageAttachmentSet full.";
     return false;
@@ -71,12 +94,19 @@
 #endif
 
   switch (attachment->GetType()) {
-    case MessageAttachment::Type::PLATFORM_FILE:
-    case MessageAttachment::Type::MOJO_HANDLE:
-    case MessageAttachment::Type::WIN_HANDLE:
-    case MessageAttachment::Type::MACH_PORT:
+    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;
@@ -84,14 +114,16 @@
 
 bool MessageAttachmentSet::AddAttachment(
     scoped_refptr<MessageAttachment> attachment) {
+  bool brokerable;
   size_t index;
-  return AddAttachment(attachment, &index);
+  return AddAttachment(attachment, &index, &brokerable);
 }
 
-scoped_refptr<MessageAttachment> MessageAttachmentSet::GetAttachmentAt(
-    unsigned index) {
-  if (index >= size()) {
-    DLOG(WARNING) << "Accessing out of bound index:" << index << "/" << size();
+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>();
   }
 
@@ -116,7 +148,8 @@
   // 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_ == size()) {
+  if (index == 0 &&
+      consumed_descriptor_highwater_ == num_non_brokerable_attachments()) {
     consumed_descriptor_highwater_ = 0;
   }
 
@@ -128,9 +161,90 @@
   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
index de37211..764c818 100644
--- a/ipc/ipc_message_attachment_set.h
+++ b/ipc/ipc_message_attachment_set.h
@@ -14,17 +14,31 @@
 #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. All attachments are wrapped in a mojo handle
-// if necessary and sent over the mojo message pipe.
+// 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_|.
 //
-// For ChannelNacl under SFI NaCl, only Type::PLATFORM_FILE is supported. In
-// that case, the FD is sent over socket.
+// 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> {
@@ -33,31 +47,57 @@
 
   // 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 attachments_.empty(); }
+  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);
+                     size_t* index,
+                     bool* brokerable);
 
   // Similar to the above method, but without output variables.
   bool AddAttachment(scoped_refptr<MessageAttachment> attachment);
 
-  // Take the nth from the beginning of the vector, Code using this /must/
-  // access the attachments in order, and must do it at most once.
+  // 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> GetAttachmentAt(unsigned index);
+  scoped_refptr<MessageAttachment> GetNonBrokerableAttachmentAt(unsigned index);
 
-  // Marks all the descriptors as consumed and closes those which are
-  // auto-close.
+  // 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
@@ -68,6 +108,32 @@
   // 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
 
   // ---------------------------------------------------------------------------
@@ -77,16 +143,17 @@
 
   ~MessageAttachmentSet();
 
-  // Return the number of file descriptors
-  unsigned num_descriptors() const;
-
+  // 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.
-  unsigned consumed_descriptor_highwater_;
+  mutable unsigned consumed_descriptor_highwater_;
 
   DISALLOW_COPY_AND_ASSIGN(MessageAttachmentSet);
 };
diff --git a/ipc/ipc_message_start.h b/ipc/ipc_message_start.h
index 3c41f04..c1e1b9f 100644
--- a/ipc/ipc_message_start.h
+++ b/ipc/ipc_message_start.h
@@ -29,7 +29,9 @@
   FileUtilitiesMsgStart,
   DatabaseMsgStart,
   DOMStorageMsgStart,
+  IndexedDBMsgStart,
   SpeechRecognitionMsgStart,
+  AutofillMsgStart,
   SafeBrowsingMsgStart,
   P2PMsgStart,
   ResourceMsgStart,
@@ -84,6 +86,7 @@
   ScreenOrientationMsgStart,
   MediaStreamTrackMetricsHostMsgStart,
   ChromeExtensionMsgStart,
+  TranslateMsgStart,
   PushMessagingMsgStart,
   GinJavaBridgeMsgStart,
   ChromeUtilityPrintingMsgStart,
@@ -107,11 +110,13 @@
   CastCryptoMsgStart,
   CastChannelMsgStart,
   DataReductionProxyStart,
+  ContentSettingsMsgStart,
   ChromeAppBannerMsgStart,
   AttachmentBrokerMsgStart,
   RenderProcessMsgStart,
   PageLoadMetricsMsgStart,
   MemoryMsgStart,
+  MediaSessionMsgStart,
   IPCTestMsgStart,
   ArcInstanceMsgStart,
   ArcInstanceHostMsgStart,
diff --git a/ipc/ipc_message_utils.cc b/ipc/ipc_message_utils.cc
index bf8daa5..60c12ab 100644
--- a/ipc/ipc_message_utils.cc
+++ b/ipc/ipc_message_utils.cc
@@ -13,7 +13,6 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/time/time.h"
-#include "base/unguessable_token.h"
 #include "base/values.h"
 #include "build/build_config.h"
 #include "ipc/ipc_channel_handle.h"
@@ -22,7 +21,6 @@
 #include "ipc/ipc_mojo_param_traits.h"
 
 #if defined(OS_POSIX)
-#include "base/file_descriptor_posix.h"
 #include "ipc/ipc_platform_file_attachment_posix.h"
 #endif
 
@@ -43,7 +41,7 @@
 
 namespace {
 
-const int kMaxRecursionDepth = 200;
+const int kMaxRecursionDepth = 100;
 
 template<typename CharType>
 void LogBytes(const std::vector<CharType>& data, std::string* out) {
@@ -78,25 +76,25 @@
                   const base::Value* value,
                   int recursion) {
   if (recursion > kMaxRecursionDepth) {
-    LOG(ERROR) << "Max recursion depth hit in GetValueSize.";
+    LOG(WARNING) << "Max recursion depth hit in GetValueSize.";
     return;
   }
 
   sizer->AddInt();
   switch (value->GetType()) {
-    case base::Value::Type::NONE:
+    case base::Value::TYPE_NULL:
       break;
-    case base::Value::Type::BOOLEAN:
+    case base::Value::TYPE_BOOLEAN:
       sizer->AddBool();
       break;
-    case base::Value::Type::INTEGER:
+    case base::Value::TYPE_INTEGER:
       sizer->AddInt();
       break;
-    case base::Value::Type::DOUBLE:
+    case base::Value::TYPE_DOUBLE:
       sizer->AddDouble();
       break;
-    case base::Value::Type::STRING: {
-      const base::Value* result;
+    case base::Value::TYPE_STRING: {
+      const base::StringValue* result;
       value->GetAsString(&result);
       if (value->GetAsString(&result)) {
         DCHECK(result);
@@ -109,11 +107,13 @@
       }
       break;
     }
-    case base::Value::Type::BINARY: {
-      sizer->AddData(static_cast<int>(value->GetSize()));
+    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: {
+    case base::Value::TYPE_DICTIONARY: {
       sizer->AddInt();
       const base::DictionaryValue* dict =
           static_cast<const base::DictionaryValue*>(value);
@@ -124,7 +124,7 @@
       }
       break;
     }
-    case base::Value::Type::LIST: {
+    case base::Value::TYPE_LIST: {
       sizer->AddInt();
       const base::ListValue* list = static_cast<const base::ListValue*>(value);
       for (const auto& entry : *list) {
@@ -140,48 +140,50 @@
 void WriteValue(base::Pickle* m, const base::Value* value, int recursion) {
   bool result;
   if (recursion > kMaxRecursionDepth) {
-    LOG(ERROR) << "Max recursion depth hit in WriteValue.";
+    LOG(WARNING) << "Max recursion depth hit in WriteValue.";
     return;
   }
 
-  m->WriteInt(static_cast<int>(value->GetType()));
+  m->WriteInt(value->GetType());
 
   switch (value->GetType()) {
-    case base::Value::Type::NONE:
+    case base::Value::TYPE_NULL:
     break;
-    case base::Value::Type::BOOLEAN: {
+    case base::Value::TYPE_BOOLEAN: {
       bool val;
       result = value->GetAsBoolean(&val);
       DCHECK(result);
       WriteParam(m, val);
       break;
     }
-    case base::Value::Type::INTEGER: {
+    case base::Value::TYPE_INTEGER: {
       int val;
       result = value->GetAsInteger(&val);
       DCHECK(result);
       WriteParam(m, val);
       break;
     }
-    case base::Value::Type::DOUBLE: {
+    case base::Value::TYPE_DOUBLE: {
       double val;
       result = value->GetAsDouble(&val);
       DCHECK(result);
       WriteParam(m, val);
       break;
     }
-    case base::Value::Type::STRING: {
+    case base::Value::TYPE_STRING: {
       std::string val;
       result = value->GetAsString(&val);
       DCHECK(result);
       WriteParam(m, val);
       break;
     }
-    case base::Value::Type::BINARY: {
-      m->WriteData(value->GetBuffer(), static_cast<int>(value->GetSize()));
+    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: {
+    case base::Value::TYPE_DICTIONARY: {
       const base::DictionaryValue* dict =
           static_cast<const base::DictionaryValue*>(value);
 
@@ -194,7 +196,7 @@
       }
       break;
     }
-    case base::Value::Type::LIST: {
+    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) {
@@ -252,7 +254,7 @@
                base::Value** value,
                int recursion) {
   if (recursion > kMaxRecursionDepth) {
-    LOG(ERROR) << "Max recursion depth hit in ReadValue.";
+    LOG(WARNING) << "Max recursion depth hit in ReadValue.";
     return false;
   }
 
@@ -260,39 +262,39 @@
   if (!ReadParam(m, iter, &type))
     return false;
 
-  switch (static_cast<base::Value::Type>(type)) {
-    case base::Value::Type::NONE:
+  switch (type) {
+    case base::Value::TYPE_NULL:
       *value = base::Value::CreateNullValue().release();
     break;
-    case base::Value::Type::BOOLEAN: {
+    case base::Value::TYPE_BOOLEAN: {
       bool val;
       if (!ReadParam(m, iter, &val))
         return false;
-      *value = new base::Value(val);
+      *value = new base::FundamentalValue(val);
       break;
     }
-    case base::Value::Type::INTEGER: {
+    case base::Value::TYPE_INTEGER: {
       int val;
       if (!ReadParam(m, iter, &val))
         return false;
-      *value = new base::Value(val);
+      *value = new base::FundamentalValue(val);
       break;
     }
-    case base::Value::Type::DOUBLE: {
+    case base::Value::TYPE_DOUBLE: {
       double val;
       if (!ReadParam(m, iter, &val))
         return false;
-      *value = new base::Value(val);
+      *value = new base::FundamentalValue(val);
       break;
     }
-    case base::Value::Type::STRING: {
+    case base::Value::TYPE_STRING: {
       std::string val;
       if (!ReadParam(m, iter, &val))
         return false;
-      *value = new base::Value(val);
+      *value = new base::StringValue(val);
       break;
     }
-    case base::Value::Type::BINARY: {
+    case base::Value::TYPE_BINARY: {
       const char* data;
       int length;
       if (!iter->ReadData(&data, &length))
@@ -302,14 +304,14 @@
       *value = val.release();
       break;
     }
-    case base::Value::Type::DICTIONARY: {
+    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: {
+    case base::Value::TYPE_LIST: {
       std::unique_ptr<base::ListValue> val(new base::ListValue());
       if (!ReadListValue(m, iter, val.get(), recursion))
         return false;
@@ -584,6 +586,28 @@
   }
 }
 
+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);
@@ -598,8 +622,7 @@
                                               base::PickleIterator* iter,
                                               param_type* r) {
   int type;
-  if (!ReadParam(m, iter, &type) ||
-      type != static_cast<int>(base::Value::Type::DICTIONARY))
+  if (!ReadParam(m, iter, &type) || type != base::Value::TYPE_DICTIONARY)
     return false;
 
   return ReadDictionaryValue(m, iter, r, 0);
@@ -655,14 +678,8 @@
   if (!m->ReadAttachment(iter, &attachment))
     return false;
 
-  if (static_cast<MessageAttachment*>(attachment.get())->GetType() !=
-      MessageAttachment::Type::PLATFORM_FILE) {
-    return false;
-  }
-
   *r = base::FileDescriptor(
-      static_cast<internal::PlatformFileAttachment*>(attachment.get())
-          ->TakePlatformFile(),
+      static_cast<MessageAttachment*>(attachment.get())->TakePlatformFile(),
       true);
   return true;
 }
@@ -815,8 +832,7 @@
                                         base::PickleIterator* iter,
                                         param_type* r) {
   int type;
-  if (!ReadParam(m, iter, &type) ||
-      type != static_cast<int>(base::Value::Type::LIST))
+  if (!ReadParam(m, iter, &type) || type != base::Value::TYPE_LIST)
     return false;
 
   return ReadListValue(m, iter, r, 0);
@@ -982,81 +998,47 @@
   ParamTraits<int64_t>::Log(p.ToInternalValue(), l);
 }
 
-// If base::UnguessableToken is no longer 128 bits, the IPC serialization logic
-// below should be updated.
-static_assert(sizeof(base::UnguessableToken) == 2 * sizeof(uint64_t),
-              "base::UnguessableToken should be of size 2 * sizeof(uint64_t).");
-
-void ParamTraits<base::UnguessableToken>::GetSize(base::PickleSizer* sizer,
-                                                  const param_type& p) {
-  sizer->AddBytes(2 * sizeof(uint64_t));
-}
-
-void ParamTraits<base::UnguessableToken>::Write(base::Pickle* m,
-                                                const param_type& p) {
-  DCHECK(!p.is_empty());
-
-  ParamTraits<uint64_t>::Write(m, p.GetHighForSerialization());
-  ParamTraits<uint64_t>::Write(m, p.GetLowForSerialization());
-}
-
-bool ParamTraits<base::UnguessableToken>::Read(const base::Pickle* m,
-                                               base::PickleIterator* iter,
-                                               param_type* r) {
-  uint64_t high, low;
-  if (!ParamTraits<uint64_t>::Read(m, iter, &high) ||
-      !ParamTraits<uint64_t>::Read(m, iter, &low))
-    return false;
-
-  // Receiving a zeroed UnguessableToken is a security issue.
-  if (high == 0 && low == 0)
-    return false;
-
-  *r = base::UnguessableToken::Deserialize(high, low);
-  return true;
-}
-
-void ParamTraits<base::UnguessableToken>::Log(const param_type& p,
-                                              std::string* l) {
-  l->append(p.ToString());
-}
-
 void ParamTraits<IPC::ChannelHandle>::GetSize(base::PickleSizer* sizer,
                                               const param_type& p) {
-#if defined(OS_NACL_SFI)
+  GetParamSize(sizer, p.name);
+#if defined(OS_POSIX)
   GetParamSize(sizer, p.socket);
-#else
-  GetParamSize(sizer, p.mojo_handle);
 #endif
+  GetParamSize(sizer, p.mojo_handle);
 }
 
 void ParamTraits<IPC::ChannelHandle>::Write(base::Pickle* m,
                                             const param_type& p) {
-#if defined(OS_NACL_SFI)
+#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);
-#else
-  WriteParam(m, p.mojo_handle);
 #endif
+  WriteParam(m, p.mojo_handle);
 }
 
 bool ParamTraits<IPC::ChannelHandle>::Read(const base::Pickle* m,
                                            base::PickleIterator* iter,
                                            param_type* r) {
-#if defined(OS_NACL_SFI)
-  return ReadParam(m, iter, &r->socket);
-#else
-  return ReadParam(m, iter, &r->mojo_handle);
+  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("ChannelHandle(");
-#if defined(OS_NACL_SFI)
+  l->append(base::StringPrintf("ChannelHandle(%s", p.name.c_str()));
+#if defined(OS_POSIX)
+  l->append(", ");
   ParamTraits<base::FileDescriptor>::Log(p.socket, l);
-#else
-  LogParam(p.mojo_handle, l);
 #endif
+  l->append(", ");
+  LogParam(p.mojo_handle, l);
   l->append(")");
 }
 
diff --git a/ipc/ipc_message_utils.h b/ipc/ipc_message_utils.h
index 40dd670..6712d3c 100644
--- a/ipc/ipc_message_utils.h
+++ b/ipc/ipc_message_utils.h
@@ -27,6 +27,7 @@
 #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"
@@ -39,7 +40,6 @@
 class Time;
 class TimeDelta;
 class TimeTicks;
-class UnguessableToken;
 struct FileDescriptor;
 
 #if (defined(OS_MACOSX) && !defined(OS_IOS)) || defined(OS_WIN)
@@ -307,37 +307,6 @@
   static void Log(const param_type& p, std::string* l);
 };
 
-template <class P, size_t Size>
-struct ParamTraits<P[Size]> {
-  using param_type = P[Size];
-  static void GetSize(base::PickleSizer* sizer, const param_type& p) {
-    for (const P& element : p)
-      GetParamSize(sizer, element);
-  }
-  static void Write(base::Pickle* m, const param_type& p) {
-    for (const P& element : p)
-      WriteParam(m, element);
-  }
-  static bool Read(const base::Pickle* m,
-                   base::PickleIterator* iter,
-                   param_type* r) {
-    for (P& element : *r) {
-      if (!ReadParam(m, iter, &element))
-        return false;
-    }
-    return true;
-  }
-  static void Log(const param_type& p, std::string* l) {
-    l->append("[");
-    for (const P& element : p) {
-      if (&element != &p[0])
-        l->append(" ");
-      LogParam(element, l);
-    }
-    l->append("]");
-  }
-};
-
 // STL ParamTraits -------------------------------------------------------------
 
 template <>
@@ -543,6 +512,17 @@
   }
 };
 
+// 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 <>
@@ -687,17 +667,6 @@
 };
 
 template <>
-struct IPC_EXPORT ParamTraits<base::UnguessableToken> {
-  typedef base::UnguessableToken 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) {}
@@ -1130,9 +1099,10 @@
 // Generic message subclasses
 
 // defined in ipc_logging.cc
-IPC_EXPORT void GenerateLogData(const Message& message,
-                                LogData* data,
-                                bool get_params);
+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) {
@@ -1159,7 +1129,7 @@
     // 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);
+    GenerateLogData("", *msg, data, true);
     msg->set_dont_log();
     reply->set_sync_log_data(data);
   }
diff --git a/ipc/ipc_mojo_handle_attachment.cc b/ipc/ipc_mojo_handle_attachment.cc
index e3421c3..819a12b 100644
--- a/ipc/ipc_mojo_handle_attachment.cc
+++ b/ipc/ipc_mojo_handle_attachment.cc
@@ -18,9 +18,16 @@
 }
 
 MessageAttachment::Type MojoHandleAttachment::GetType() const {
-  return Type::MOJO_HANDLE;
+  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_);
 }
diff --git a/ipc/ipc_mojo_handle_attachment.h b/ipc/ipc_mojo_handle_attachment.h
index d615276..6aa1888 100644
--- a/ipc/ipc_mojo_handle_attachment.h
+++ b/ipc/ipc_mojo_handle_attachment.h
@@ -26,6 +26,11 @@
 
   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();
 
diff --git a/ipc/ipc_mojo_message_helper.cc b/ipc/ipc_mojo_message_helper.cc
index a87a2d6..8f86945 100644
--- a/ipc/ipc_mojo_message_helper.cc
+++ b/ipc/ipc_mojo_message_helper.cc
@@ -32,7 +32,7 @@
 
   MessageAttachment::Type type =
       static_cast<MessageAttachment*>(attachment.get())->GetType();
-  if (type != MessageAttachment::Type::MOJO_HANDLE) {
+  if (type != MessageAttachment::TYPE_MOJO_HANDLE) {
     LOG(ERROR) << "Unxpected attachment type:" << type;
     return false;
   }
diff --git a/ipc/ipc_platform_file_attachment_posix.cc b/ipc/ipc_platform_file_attachment_posix.cc
index 7111cfa..b130ab2 100644
--- a/ipc/ipc_platform_file_attachment_posix.cc
+++ b/ipc/ipc_platform_file_attachment_posix.cc
@@ -20,7 +20,7 @@
 }
 
 MessageAttachment::Type PlatformFileAttachment::GetType() const {
-  return Type::PLATFORM_FILE;
+  return TYPE_PLATFORM_FILE;
 }
 
 base::PlatformFile PlatformFileAttachment::TakePlatformFile() {
@@ -30,7 +30,7 @@
 
 base::PlatformFile GetPlatformFile(
     scoped_refptr<MessageAttachment> attachment) {
-  DCHECK_EQ(attachment->GetType(), MessageAttachment::Type::PLATFORM_FILE);
+  DCHECK_EQ(attachment->GetType(), MessageAttachment::TYPE_PLATFORM_FILE);
   return static_cast<PlatformFileAttachment*>(attachment.get())->file();
 }
 
diff --git a/ipc/ipc_platform_file_attachment_posix.h b/ipc/ipc_platform_file_attachment_posix.h
index 9b07900..d1eff60 100644
--- a/ipc/ipc_platform_file_attachment_posix.h
+++ b/ipc/ipc_platform_file_attachment_posix.h
@@ -23,7 +23,7 @@
   explicit PlatformFileAttachment(base::ScopedFD file);
 
   Type GetType() const override;
-  base::PlatformFile TakePlatformFile();
+  base::PlatformFile TakePlatformFile() override;
 
   base::PlatformFile file() const { return file_; }
   bool Owns() const { return owning_.is_valid(); }
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_