EDK: Plumb Handle/HandleVector yet one more layer down: MessageInTransit.

The "remaining" layer is TransportData and things that deal with it
(e.g., serialization code).

R=azani@chromium.org

Review URL: https://codereview.chromium.org/1957553003 .
diff --git a/mojo/edk/system/channel_endpoint.cc b/mojo/edk/system/channel_endpoint.cc
index 6de03d3..204914d 100644
--- a/mojo/edk/system/channel_endpoint.cc
+++ b/mojo/edk/system/channel_endpoint.cc
@@ -165,7 +165,7 @@
   DCHECK(local_id_.is_valid());
   DCHECK(remote_id_.is_valid());
 
-  message->SerializeAndCloseDispatchers(channel_);
+  message->SerializeAndCloseHandles(channel_);
   message->set_source_id(local_id_);
   message->set_destination_id(remote_id_);
   return channel_->WriteMessage(std::move(message));
diff --git a/mojo/edk/system/local_message_pipe_endpoint.cc b/mojo/edk/system/local_message_pipe_endpoint.cc
index b8a75ac..dd0c953 100644
--- a/mojo/edk/system/local_message_pipe_endpoint.cc
+++ b/mojo/edk/system/local_message_pipe_endpoint.cc
@@ -9,7 +9,6 @@
 #include <utility>
 
 #include "base/logging.h"
-#include "mojo/edk/system/dispatcher.h"
 #include "mojo/edk/system/message_in_transit.h"
 
 namespace mojo {
@@ -95,24 +94,15 @@
   else
     enough_space = false;
 
-  if (DispatcherVector* queued_dispatchers = message->dispatchers()) {
+  if (HandleVector* queued_handles = message->handles()) {
     if (num_handles)
-      *num_handles = static_cast<uint32_t>(queued_dispatchers->size());
+      *num_handles = static_cast<uint32_t>(queued_handles->size());
     if (enough_space) {
-      if (queued_dispatchers->empty()) {
+      if (queued_handles->empty()) {
         // Nothing to do.
-      } else if (queued_dispatchers->size() <= max_num_handles) {
+      } else if (queued_handles->size() <= max_num_handles) {
         DCHECK(handles);
-        // TODO(vtl): The rest of this code in this block is temporary, until I
-        // plumb |Handle|s into |MessageInTransit|. This should really just be
-        // something like:
-        //   handles->swap(*queued_handles);
-        handles->reserve(queued_dispatchers->size());
-        for (size_t i = 0; i < queued_dispatchers->size(); i++) {
-          // We're not enforcing handle rights yet, so "none" is OK.
-          handles->push_back(Handle(std::move(queued_dispatchers->at(i)),
-                                    MOJO_HANDLE_RIGHT_NONE));
-        }
+        handles->swap(*queued_handles);
       } else {
         enough_space = false;
       }
diff --git a/mojo/edk/system/message_in_transit.cc b/mojo/edk/system/message_in_transit.cc
index 26e9252..4dbcf7d 100644
--- a/mojo/edk/system/message_in_transit.cc
+++ b/mojo/edk/system/message_in_transit.cc
@@ -109,13 +109,13 @@
 }
 
 MessageInTransit::~MessageInTransit() {
-  if (dispatchers_) {
-    for (size_t i = 0; i < dispatchers_->size(); i++) {
-      if (!(*dispatchers_)[i])
+  if (handles_) {
+    for (size_t i = 0; i < handles_->size(); i++) {
+      if (!handles_->at(i))
         continue;
 
-      (*dispatchers_)[i]->AssertHasOneRef();
-      (*dispatchers_)[i]->Close();
+      handles_->at(i).dispatcher->AssertHasOneRef();
+      handles_->at(i).dispatcher->Close();
     }
   }
 }
@@ -141,39 +141,51 @@
   return true;
 }
 
+void MessageInTransit::SetHandles(std::unique_ptr<HandleVector> handles) {
+  DCHECK(handles);
+  DCHECK(!handles_);
+  DCHECK(!transport_data_);
+
+  handles_ = std::move(handles);
+#ifndef NDEBUG
+  for (size_t i = 0; i < handles_->size(); i++) {
+    if (handles_->at(i))
+      handles_->at(i).dispatcher->AssertHasOneRef();
+  }
+#endif
+}
+
 void MessageInTransit::SetDispatchers(
     std::unique_ptr<DispatcherVector> dispatchers) {
   DCHECK(dispatchers);
-  DCHECK(!dispatchers_);
-  DCHECK(!transport_data_);
 
-  dispatchers_ = std::move(dispatchers);
-#ifndef NDEBUG
-  for (size_t i = 0; i < dispatchers_->size(); i++) {
-    if ((*dispatchers_)[i])
-      (*dispatchers_)[i]->AssertHasOneRef();
+  std::unique_ptr<HandleVector> handles(new HandleVector());
+  handles->reserve(dispatchers->size());
+  for (size_t i = 0; i < dispatchers->size(); i++) {
+    handles->push_back(
+        Handle(std::move(dispatchers->at(i)), MOJO_HANDLE_RIGHT_NONE));
   }
-#endif
+  SetHandles(std::move(handles));
 }
 
 void MessageInTransit::SetTransportData(
     std::unique_ptr<TransportData> transport_data) {
   DCHECK(transport_data);
   DCHECK(!transport_data_);
-  DCHECK(!dispatchers_);
+  DCHECK(!handles_);
 
   transport_data_ = std::move(transport_data);
   UpdateTotalSize();
 }
 
-void MessageInTransit::SerializeAndCloseDispatchers(Channel* channel) {
+void MessageInTransit::SerializeAndCloseHandles(Channel* channel) {
   DCHECK(channel);
   DCHECK(!transport_data_);
 
-  if (!dispatchers_ || !dispatchers_->size())
+  if (!handles_ || !handles_->size())
     return;
 
-  transport_data_.reset(new TransportData(std::move(dispatchers_), channel));
+  transport_data_.reset(new TransportData(std::move(handles_), channel));
 
   // Update the sizes in the message header.
   UpdateTotalSize();
@@ -191,8 +203,8 @@
   header()->destination_id = ChannelEndpointId();
   header()->num_bytes = num_bytes;
   header()->unused = 0;
-  // Note: If dispatchers are subsequently attached, then |total_size| will have
-  // to be adjusted.
+  // Note: If handles are subsequently attached, then |total_size| will have to
+  // be adjusted.
   UpdateTotalSize();
 }
 
diff --git a/mojo/edk/system/message_in_transit.h b/mojo/edk/system/message_in_transit.h
index 2d5c049..f2ec026 100644
--- a/mojo/edk/system/message_in_transit.h
+++ b/mojo/edk/system/message_in_transit.h
@@ -15,6 +15,7 @@
 #include "mojo/edk/platform/aligned_alloc.h"
 #include "mojo/edk/system/channel_endpoint_id.h"
 #include "mojo/edk/system/dispatcher.h"
+#include "mojo/edk/system/handle.h"
 #include "mojo/edk/system/memory.h"
 #include "mojo/public/cpp/system/macros.h"
 
@@ -183,21 +184,23 @@
                                  size_t buffer_size,
                                  size_t* next_message_size);
 
-  // Makes this message "own" the given set of dispatchers. The dispatchers must
-  // not be referenced from anywhere else (in particular, not from the handle
-  // table), i.e., each dispatcher must have a reference count of 1. This
-  // message must not already have dispatchers.
+  // Makes this message "own" the given set of handles. Each handle's dispatcher
+  // must not be referenced from anywhere else (in particular, not from any
+  // handle in the handle table), i.e., the dispatcher must have a reference
+  // count of 1. This message must not already have handles.
+  void SetHandles(std::unique_ptr<HandleVector> handles);
+  // TODO(vtl): Delete this.
   void SetDispatchers(std::unique_ptr<DispatcherVector> dispatchers);
 
   // Sets the |TransportData| for this message. This should only be done when
-  // there are no dispatchers and no existing |TransportData|.
+  // there are no handles and no existing |TransportData|.
   void SetTransportData(std::unique_ptr<TransportData> transport_data);
 
-  // Serializes any dispatchers to the secondary buffer. This message must not
+  // Serializes any handles to the secondary buffer. This message must not
   // already have a secondary buffer (so this must only be called once). The
   // caller must ensure (e.g., by holding on to a reference) that |channel|
   // stays alive through the call.
-  void SerializeAndCloseDispatchers(Channel* channel);
+  void SerializeAndCloseHandles(Channel* channel);
 
   // Gets the main buffer and its size (in number of bytes), respectively.
   const void* main_buffer() const { return main_buffer_.get(); }
@@ -229,15 +232,13 @@
     header()->destination_id = destination_id;
   }
 
-  // Gets the dispatchers attached to this message; this may return null if
-  // there are none. Note that the caller may mutate the set of dispatchers
-  // (e.g., take ownership of all the dispatchers, leaving the vector empty).
-  DispatcherVector* dispatchers() { return dispatchers_.get(); }
+  // Gets the handles attached to this message; this may return null if there
+  // are none. Note that the caller may mutate the set of handles (e.g., take
+  // ownership of all the handles, leaving the vector empty).
+  HandleVector* handles() { return handles_.get(); }
 
-  // Returns true if this message has dispatchers attached.
-  bool has_dispatchers() const {
-    return dispatchers_ && !dispatchers_->empty();
-  }
+  // Returns true if this message has handles attached.
+  bool has_handles() const { return handles_ && !handles_->empty(); }
 
   // Rounds |n| up to a multiple of |kMessageAlignment|.
   static inline size_t RoundUpMessageAlignment(size_t n) {
@@ -254,8 +255,8 @@
     // Total size of the message, including the header, the message data
     // ("bytes") including padding (to make it a multiple of |kMessageAlignment|
     // bytes), and serialized handle information. Note that this may not be the
-    // correct value if dispatchers are attached but
-    // |SerializeAndCloseDispatchers()| has not been called.
+    // correct value if handles are attached but |SerializeAndCloseHandles()|
+    // has not been called.
     uint32_t total_size;
     Type type;                         // 2 bytes.
     Subtype subtype;                   // 2 bytes.
@@ -280,11 +281,11 @@
 
   std::unique_ptr<TransportData> transport_data_;  // May be null.
 
-  // Any dispatchers that may be attached to this message. These dispatchers
-  // should be "owned" by this message, i.e., have a ref count of exactly 1. (We
-  // allow a dispatcher entry to be null, in case it couldn't be duplicated for
-  // some reason.)
-  std::unique_ptr<DispatcherVector> dispatchers_;
+  // Any handles that may be attached to this message. These handles should be
+  // "owned" by this message, i.e., their dispatcher have a ref count of exactly
+  // 1. (We allow a handle entry to be "null"/invalid, in case it couldn't be
+  // duplicated for some reason.)
+  std::unique_ptr<HandleVector> handles_;
 
   MOJO_DISALLOW_COPY_AND_ASSIGN(MessageInTransit);
 };
diff --git a/mojo/edk/system/message_pipe.cc b/mojo/edk/system/message_pipe.cc
index 5c73ac9..a1d2d13 100644
--- a/mojo/edk/system/message_pipe.cc
+++ b/mojo/edk/system/message_pipe.cc
@@ -356,24 +356,22 @@
     unsigned port,
     MessageInTransit* message,
     std::vector<HandleTransport>* transports) {
-  DCHECK(!message->has_dispatchers());
+  DCHECK(!message->has_handles());
 
-  // Clone the dispatchers and attach them to the message. (This must be done as
-  // a separate loop, since we want to leave the dispatchers alone on failure.)
-  std::unique_ptr<DispatcherVector> dispatchers(new DispatcherVector());
-  dispatchers->reserve(transports->size());
+  // Clone the handles and attach them to the message. (This must be done as a
+  // separate loop, since we want to leave the handles alone on failure.)
+  std::unique_ptr<HandleVector> handles(new HandleVector());
+  handles->reserve(transports->size());
   for (size_t i = 0; i < transports->size(); i++) {
     if ((*transports)[i].is_valid()) {
-      // TODO(vtl): Plumb this into |MessageInTransit|. (I.e., |dispatchers| ->
-      // |handles|, etc.)
-      Handle h = (*transports)[i].CreateEquivalentHandleAndClose(this, port);
-      dispatchers->push_back(std::move(h.dispatcher));
+      handles->push_back(
+          transports->at(i).CreateEquivalentHandleAndClose(this, port));
     } else {
       LOG(WARNING) << "Enqueueing null dispatcher";
-      dispatchers->push_back(nullptr);
+      handles->push_back(Handle());
     }
   }
-  message->SetDispatchers(std::move(dispatchers));
+  message->SetHandles(std::move(handles));
   return MOJO_RESULT_OK;
 }
 
diff --git a/mojo/edk/system/transport_data.cc b/mojo/edk/system/transport_data.cc
index fedfce6..058d795 100644
--- a/mojo/edk/system/transport_data.cc
+++ b/mojo/edk/system/transport_data.cc
@@ -19,6 +19,22 @@
 namespace mojo {
 namespace system {
 
+namespace {
+
+// TODO(vtl): Temporary, until |TransportData| really supports handles.
+std::unique_ptr<DispatcherVector> DispatcherVectorFromHandleVector(
+    std::unique_ptr<HandleVector> handles) {
+  DCHECK(handles);
+
+  std::unique_ptr<DispatcherVector> dispatchers(new DispatcherVector());
+  dispatchers->reserve(handles->size());
+  for (size_t i = 0; i < handles->size(); i++)
+    dispatchers->push_back(std::move(handles->at(i).dispatcher));
+  return dispatchers;
+}
+
+}  // namespace
+
 // The maximum amount of space needed per platform handle.
 // (|{Channel,RawChannel}::GetSerializedPlatformHandleSize()| should always
 // return a value which is at most this. This is only used to calculate
@@ -63,6 +79,12 @@
                 "alignment");
 };
 
+// TODO(vtl): Make this the real one.
+TransportData::TransportData(std::unique_ptr<HandleVector> handles,
+                             Channel* channel)
+    : TransportData(DispatcherVectorFromHandleVector(std::move(handles)),
+                    channel) {}
+
 TransportData::TransportData(std::unique_ptr<DispatcherVector> dispatchers,
                              Channel* channel)
     : buffer_size_() {
diff --git a/mojo/edk/system/transport_data.h b/mojo/edk/system/transport_data.h
index 771e071..8698a6d 100644
--- a/mojo/edk/system/transport_data.h
+++ b/mojo/edk/system/transport_data.h
@@ -86,6 +86,8 @@
   // The maximum total number of platform handles that may be attached.
   static size_t GetMaxPlatformHandles();
 
+  TransportData(std::unique_ptr<HandleVector> handles, Channel* channel);
+  // TODO(vtl): Remove this, once |TransportData| really supports handles.
   TransportData(std::unique_ptr<DispatcherVector> dispatchers,
                 Channel* channel);