EDK: Make TransportData preserve handle rights.

Now, at least theoretically, handle rights should be preserved when sent
over a message pipe (including across processes). (I'll add/update tests
separately.)

R=azani@chromium.org, vardhan@google.com

Review URL: https://codereview.chromium.org/1956843002 .
diff --git a/mojo/edk/system/channel.cc b/mojo/edk/system/channel.cc
index b52cba6..7ce9e76 100644
--- a/mojo/edk/system/channel.cc
+++ b/mojo/edk/system/channel.cc
@@ -408,7 +408,7 @@
   std::unique_ptr<MessageInTransit> message(new MessageInTransit(message_view));
   if (message_view.transport_data_buffer_size() > 0) {
     DCHECK(message_view.transport_data_buffer());
-    message->SetDispatchers(TransportData::DeserializeDispatchers(
+    message->SetHandles(TransportData::DeserializeHandles(
         message_view.transport_data_buffer(),
         message_view.transport_data_buffer_size(), std::move(platform_handles),
         this));
diff --git a/mojo/edk/system/message_in_transit.cc b/mojo/edk/system/message_in_transit.cc
index 4dbcf7d..c40b9f5 100644
--- a/mojo/edk/system/message_in_transit.cc
+++ b/mojo/edk/system/message_in_transit.cc
@@ -10,6 +10,7 @@
 
 #include "base/logging.h"
 #include "mojo/edk/system/configuration.h"
+#include "mojo/edk/system/dispatcher.h"
 #include "mojo/edk/system/transport_data.h"
 
 using mojo::platform::AlignedAlloc;
@@ -155,19 +156,6 @@
 #endif
 }
 
-void MessageInTransit::SetDispatchers(
-    std::unique_ptr<DispatcherVector> dispatchers) {
-  DCHECK(dispatchers);
-
-  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));
-  }
-  SetHandles(std::move(handles));
-}
-
 void MessageInTransit::SetTransportData(
     std::unique_ptr<TransportData> transport_data) {
   DCHECK(transport_data);
diff --git a/mojo/edk/system/message_in_transit.h b/mojo/edk/system/message_in_transit.h
index f2ec026..654311e 100644
--- a/mojo/edk/system/message_in_transit.h
+++ b/mojo/edk/system/message_in_transit.h
@@ -14,7 +14,6 @@
 
 #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"
@@ -189,8 +188,6 @@
   // 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 handles and no existing |TransportData|.
diff --git a/mojo/edk/system/message_pipe_endpoint.h b/mojo/edk/system/message_pipe_endpoint.h
index 65462ea..837e660 100644
--- a/mojo/edk/system/message_pipe_endpoint.h
+++ b/mojo/edk/system/message_pipe_endpoint.h
@@ -11,6 +11,7 @@
 #include <vector>
 
 #include "mojo/edk/system/handle.h"
+#include "mojo/edk/system/handle_signals_state.h"
 #include "mojo/edk/system/memory.h"
 #include "mojo/edk/system/message_in_transit.h"
 #include "mojo/public/c/system/handle.h"
diff --git a/mojo/edk/system/message_pipe_test_utils.h b/mojo/edk/system/message_pipe_test_utils.h
index 23a96f6..6f2ebdf 100644
--- a/mojo/edk/system/message_pipe_test_utils.h
+++ b/mojo/edk/system/message_pipe_test_utils.h
@@ -9,6 +9,7 @@
 
 #include "mojo/edk/platform/scoped_platform_handle.h"
 #include "mojo/edk/system/channel.h"
+#include "mojo/edk/system/handle_signals_state.h"
 #include "mojo/edk/system/test/test_io_thread.h"
 #include "mojo/edk/test/multiprocess_test_helper.h"
 #include "mojo/edk/util/ref_ptr.h"
diff --git a/mojo/edk/system/transport_data.cc b/mojo/edk/system/transport_data.cc
index 058d795..05a03ba 100644
--- a/mojo/edk/system/transport_data.cc
+++ b/mojo/edk/system/transport_data.cc
@@ -19,22 +19,6 @@
 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
@@ -79,19 +63,13 @@
                 "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_() {
-  DCHECK(dispatchers);
+  DCHECK(handles);
   DCHECK(channel);
 
-  const size_t num_handles = dispatchers->size();
+  const size_t num_handles = handles->size();
   DCHECK_GT(num_handles, 0u);
 
   // The offset to the start of the (Mojo) handle table.
@@ -108,11 +86,12 @@
   std::vector<size_t> all_max_platform_handles(num_handles);
 #endif
   for (size_t i = 0; i < num_handles; i++) {
-    if (Dispatcher* dispatcher = (*dispatchers)[i].get()) {
+    if (handles->at(i)) {
       size_t max_size = 0;
       size_t max_platform_handles = 0;
       Dispatcher::TransportDataAccess::StartSerialize(
-          dispatcher, channel, &max_size, &max_platform_handles);
+          handles->at(i).dispatcher.get(), channel, &max_size,
+          &max_platform_handles);
 
       DCHECK_LE(max_size, kMaxSerializedDispatcherSize);
       estimated_size += MessageInTransit::RoundUpMessageAlignment(max_size);
@@ -159,8 +138,8 @@
       buffer_.get() + handle_table_start_offset);
   size_t current_offset = serialized_dispatcher_start_offset;
   for (size_t i = 0; i < num_handles; i++) {
-    Dispatcher* dispatcher = (*dispatchers)[i].get();
-    if (!dispatcher) {
+    Handle& handle = handles->at(i);
+    if (!handle) {
       static_assert(static_cast<int32_t>(Dispatcher::Type::UNKNOWN) == 0,
                     "Value of Dispatcher::Type::UNKNOWN must be 0");
       continue;
@@ -174,12 +153,12 @@
     void* destination = buffer_.get() + current_offset;
     size_t actual_size = 0;
     if (Dispatcher::TransportDataAccess::EndSerializeAndClose(
-            dispatcher, channel, destination, &actual_size,
+            handle.dispatcher.get(), channel, destination, &actual_size,
             platform_handles_.get())) {
-      handle_table[i].type = static_cast<int32_t>(dispatcher->GetType());
+      handle_table[i].type = static_cast<int32_t>(handle.dispatcher->GetType());
       handle_table[i].offset = static_cast<uint32_t>(current_offset);
       handle_table[i].size = static_cast<uint32_t>(actual_size);
-// (Okay to not set |unused| since we cleared the entire buffer.)
+      handle_table[i].rights = handle.rights;
 
 #if DCHECK_IS_ON()
       DCHECK_LE(actual_size, all_max_sizes[i]);
@@ -212,8 +191,6 @@
   // There's no aligned realloc, so it's no good way to release unused space (if
   // we overshot our estimated space requirements).
   buffer_size_ = current_offset;
-
-  // |dispatchers_| will be destroyed as it goes out of scope.
 }
 
 TransportData::TransportData(
@@ -331,7 +308,7 @@
 }
 
 // static
-std::unique_ptr<DispatcherVector> TransportData::DeserializeDispatchers(
+std::unique_ptr<HandleVector> TransportData::DeserializeHandles(
     const void* buffer,
     size_t buffer_size,
     std::unique_ptr<std::vector<ScopedPlatformHandle>> platform_handles,
@@ -342,8 +319,7 @@
 
   const Header* header = static_cast<const Header*>(buffer);
   const size_t num_handles = header->num_handles;
-  std::unique_ptr<DispatcherVector> dispatchers(
-      new DispatcherVector(num_handles));
+  std::unique_ptr<HandleVector> handles(new HandleVector(num_handles));
 
   const HandleTableEntry* handle_table =
       reinterpret_cast<const HandleTableEntry*>(
@@ -357,11 +333,13 @@
     DCHECK_LE(offset + size, buffer_size);
 
     const void* source = static_cast<const char*>(buffer) + offset;
-    (*dispatchers)[i] = Dispatcher::TransportDataAccess::Deserialize(
-        channel, handle_table[i].type, source, size, platform_handles.get());
+    (*handles)[i] = Handle(Dispatcher::TransportDataAccess::Deserialize(
+                               channel, handle_table[i].type, source, size,
+                               platform_handles.get()),
+                           handle_table[i].rights);
   }
 
-  return dispatchers;
+  return handles;
 }
 
 }  // namespace system
diff --git a/mojo/edk/system/transport_data.h b/mojo/edk/system/transport_data.h
index 8698a6d..310e33d 100644
--- a/mojo/edk/system/transport_data.h
+++ b/mojo/edk/system/transport_data.h
@@ -13,6 +13,8 @@
 #include "mojo/edk/platform/aligned_alloc.h"
 #include "mojo/edk/platform/scoped_platform_handle.h"
 #include "mojo/edk/system/dispatcher.h"
+#include "mojo/edk/system/handle.h"
+#include "mojo/public/c/system/handle.h"
 #include "mojo/public/cpp/system/macros.h"
 
 namespace mojo {
@@ -87,9 +89,6 @@
   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);
 
   // This is used for users of |MessageInTransit|/|TransportData|/|RawChannel|
   // that want to simply transport data and platform handles, and not
@@ -138,10 +137,10 @@
                                      size_t* num_platform_handles,
                                      const void** platform_handle_table);
 
-  // Deserializes dispatchers from the given (serialized) transport data buffer
+  // Deserializes handles from the given (serialized) transport data buffer
   // (typically from a |MessageInTransit::View|) and vector of platform handles.
   // |buffer| should be non-null and |buffer_size| should be nonzero.
-  static std::unique_ptr<DispatcherVector> DeserializeDispatchers(
+  static std::unique_ptr<HandleVector> DeserializeHandles(
       const void* buffer,
       size_t buffer_size,
       std::unique_ptr<std::vector<platform::ScopedPlatformHandle>>
@@ -168,7 +167,7 @@
     int32_t type;     // From |Dispatcher::Type| (|UNKNOWN| for "invalid").
     uint32_t offset;  // Relative to the start of the "secondary buffer".
     uint32_t size;    // (Not including any padding.)
-    uint32_t unused;
+    MojoHandleRights rights;
   };
 
   const Header* header() const {