[go: nahoru, domu]

Revert "Introduce PlatformChannelServer"

This reverts commit 687d45999515655e5b0df59638f7bf0199dd1b3c.

Reason for revert:
LUCI Bisection identified this CL as the culprit of a build failure. See the analysis: https://luci-bisection.appspot.com/analysis/b/8785419785842466113

Sample failed build: https://ci.chromium.org/b/8785419785842466113

If this is a false positive, please report it at https://bugs.chromium.org/p/chromium/issues/entry?comment=Analysis%3A+https%3A%2F%2Fluci-bisection.appspot.com%2Fanalysis%2Fb%2F8785419785842466113&components=Tools%3ETest%3EFindit&labels=LUCI-Bisection-Wrong%2CPri-3%2CType-Bug&status=Available&summary=Wrongly+blamed+https%3A%2F%2Fchromium-review.googlesource.com%2Fc%2Fchromium%2Fsrc%2F%2B%2F4370636

Original change's description:
> Introduce PlatformChannelServer
>
> This is a lightweight abstraction around a platform-specific IPC
> endpoint which can accept a single new connection from a
> PlatformChannelServerEndpoint, and return it as a connected
> PlatformChannelEndpoint.
>
> All named pipe connection logic is migrated out of Mojo internals
> and the MOJO_INVITAION_TRANSPORT_TYPE_CHANNEL_SERVER enumeration is
> removed from the Mojo API.
>
> Instead the C++ invitation helpers (and one edge case for Mojo Core
> on Windows) now use PlatformChannelServer to establish a proper
> PlatformChannelEndpoint for use.
>
> All PlatformChannelServerEndpoint support is removed from the
> internal Channel and ConnectionParams objects.
>
> This also effectively fixes long-standing data races in
> ChannelPosix around listening server state which this CL
> removes.
>
> Bug: 1411162
> Fixed: 1426421
> Change-Id: I787c922b7b2eda618f5589c29c7e2af9c8221ab1
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4370636
> Reviewed-by: Alex Gough <ajgo@chromium.org>
> Commit-Queue: Ken Rockot <rockot@google.com>
> Cr-Commit-Position: refs/heads/main@{#1122785}
>

Bug: 1411162
Change-Id: I9e454bd355cb5575123564a4744ab4a4c4242517
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4376220
Bot-Commit: luci-bisection@appspot.gserviceaccount.com <luci-bisection@appspot.gserviceaccount.com>
Commit-Queue: luci-bisection@appspot.gserviceaccount.com <luci-bisection@appspot.gserviceaccount.com>
Owners-Override: luci-bisection@appspot.gserviceaccount.com <luci-bisection@appspot.gserviceaccount.com>
Cr-Commit-Position: refs/heads/main@{#1122796}
diff --git a/mojo/core/broker_host.cc b/mojo/core/broker_host.cc
index 7a5d4f94..a037149 100644
--- a/mojo/core/broker_host.cc
+++ b/mojo/core/broker_host.cc
@@ -32,8 +32,11 @@
       client_process_(std::move(client_process))
 #endif
 {
+  CHECK(connection_params.endpoint().is_valid() ||
+        connection_params.server_endpoint().is_valid());
+
   base::CurrentThread::Get()->AddDestructionObserver(this);
-  CHECK(connection_params.endpoint().is_valid());
+
   channel_ = Channel::Create(this, std::move(connection_params),
 #if BUILDFLAG(IS_WIN)
                              client_process_
diff --git a/mojo/core/channel.cc b/mojo/core/channel.cc
index 4b7bbc1..71d2ab3 100644
--- a/mojo/core/channel.cc
+++ b/mojo/core/channel.cc
@@ -893,13 +893,23 @@
 // static
 scoped_refptr<Channel> Channel::CreateForIpczDriver(
     Delegate* delegate,
-    PlatformChannelEndpoint endpoint,
+    Endpoint endpoint,
     scoped_refptr<base::SingleThreadTaskRunner> io_task_runner) {
 #if BUILDFLAG(IS_NACL)
   return nullptr;
 #else
-  return Create(delegate, ConnectionParams{std::move(endpoint)},
-                HandlePolicy::kAcceptHandles, std::move(io_task_runner));
+  ConnectionParams params =
+      absl::visit(base::Overloaded{
+                      [](PlatformChannelEndpoint& endpoint) {
+                        return ConnectionParams(std::move(endpoint));
+                      },
+                      [](PlatformChannelServerEndpoint& endpoint) {
+                        return ConnectionParams(std::move(endpoint));
+                      },
+                  },
+                  endpoint);
+  return Create(delegate, std::move(params), HandlePolicy::kAcceptHandles,
+                std::move(io_task_runner));
 #endif
 }
 
diff --git a/mojo/core/channel.h b/mojo/core/channel.h
index 40e03ebe..4cc0e92 100644
--- a/mojo/core/channel.h
+++ b/mojo/core/channel.h
@@ -22,7 +22,9 @@
 #include "mojo/core/connection_params.h"
 #include "mojo/core/platform_handle_in_transit.h"
 #include "mojo/public/cpp/platform/platform_channel_endpoint.h"
+#include "mojo/public/cpp/platform/platform_channel_server_endpoint.h"
 #include "mojo/public/cpp/platform/platform_handle.h"
+#include "third_party/abseil-cpp/absl/types/variant.h"
 
 namespace mojo::core {
 
@@ -316,9 +318,11 @@
   // header, and the Channel is no longer responsible for encoding or decoding
   // any metadata about transmitted PlatformHandles, since the ipcz driver takes
   // care of that.
+  using Endpoint =
+      absl::variant<PlatformChannelEndpoint, PlatformChannelServerEndpoint>;
   static scoped_refptr<Channel> CreateForIpczDriver(
       Delegate* delegate,
-      PlatformChannelEndpoint endpoint,
+      Endpoint endpoint,
       scoped_refptr<base::SingleThreadTaskRunner> io_task_runner);
 
   Channel(const Channel&) = delete;
diff --git a/mojo/core/channel_mac.cc b/mojo/core/channel_mac.cc
index 229ff07..24405df2 100644
--- a/mojo/core/channel_mac.cc
+++ b/mojo/core/channel_mac.cc
@@ -55,8 +55,14 @@
         self_(this),
         io_task_runner_(io_task_runner),
         watch_controller_(FROM_HERE) {
-    PlatformHandle channel_handle =
-        connection_params.TakeEndpoint().TakePlatformHandle();
+    PlatformHandle channel_handle;
+    if (connection_params.server_endpoint().is_valid()) {
+      channel_handle =
+          connection_params.TakeServerEndpoint().TakePlatformHandle();
+    } else {
+      channel_handle = connection_params.TakeEndpoint().TakePlatformHandle();
+    }
+
     if (channel_handle.is_mach_send()) {
       send_port_ = channel_handle.TakeMachSendRight();
     } else if (channel_handle.is_mach_receive()) {
diff --git a/mojo/core/channel_posix.cc b/mojo/core/channel_posix.cc
index 42b55c2..f57c9b3 100644
--- a/mojo/core/channel_posix.cc
+++ b/mojo/core/channel_posix.cc
@@ -122,8 +122,12 @@
     : Channel(delegate, handle_policy),
       self_(this),
       io_task_runner_(io_task_runner) {
-  socket_ = connection_params.TakeEndpoint().TakePlatformHandle().TakeFD();
-  CHECK(socket_.is_valid());
+  if (connection_params.server_endpoint().is_valid())
+    server_ = connection_params.TakeServerEndpoint();
+  else
+    socket_ = connection_params.TakeEndpoint().TakePlatformHandle().TakeFD();
+
+  CHECK(server_.is_valid() || socket_.is_valid());
 }
 
 ChannelPosix::~ChannelPosix() {
@@ -221,13 +225,19 @@
   read_watcher_ =
       std::make_unique<base::MessagePumpForIO::FdWatchController>(FROM_HERE);
   base::CurrentThread::Get()->AddDestructionObserver(this);
-  write_watcher_ =
-      std::make_unique<base::MessagePumpForIO::FdWatchController>(FROM_HERE);
-  base::CurrentIOThread::Get()->WatchFileDescriptor(
-      socket_.get(), true /* persistent */, base::MessagePumpForIO::WATCH_READ,
-      read_watcher_.get(), this);
-  base::AutoLock lock(write_lock_);
-  FlushOutgoingMessagesNoLock();
+  if (server_.is_valid()) {
+    base::CurrentIOThread::Get()->WatchFileDescriptor(
+        server_.platform_handle().GetFD().get(), false /* persistent */,
+        base::MessagePumpForIO::WATCH_READ, read_watcher_.get(), this);
+  } else {
+    write_watcher_ =
+        std::make_unique<base::MessagePumpForIO::FdWatchController>(FROM_HERE);
+    base::CurrentIOThread::Get()->WatchFileDescriptor(
+        socket_.get(), true /* persistent */,
+        base::MessagePumpForIO::WATCH_READ, read_watcher_.get(), this);
+    base::AutoLock lock(write_lock_);
+    FlushOutgoingMessagesNoLock();
+  }
 }
 
 void ChannelPosix::WaitForWriteOnIOThread() {
@@ -258,8 +268,10 @@
   write_watcher_.reset();
   if (leak_handle_) {
     std::ignore = socket_.release();
+    server_.TakePlatformHandle().release();
   } else {
     socket_.reset();
+    std::ignore = server_.TakePlatformHandle();
   }
 #if BUILDFLAG(IS_IOS)
   fds_to_close_.clear();
@@ -276,6 +288,24 @@
 }
 
 void ChannelPosix::OnFileCanReadWithoutBlocking(int fd) {
+  if (server_.is_valid()) {
+    CHECK_EQ(fd, server_.platform_handle().GetFD().get());
+#if !BUILDFLAG(IS_NACL)
+    read_watcher_.reset();
+    base::CurrentThread::Get()->RemoveDestructionObserver(this);
+
+    AcceptSocketConnection(server_.platform_handle().GetFD().get(), &socket_);
+    std::ignore = server_.TakePlatformHandle();
+    if (!socket_.is_valid()) {
+      OnError(Error::kConnectionFailed);
+      return;
+    }
+    StartOnIOThread();
+#else
+    NOTREACHED();
+#endif
+    return;
+  }
   CHECK_EQ(fd, socket_.get());
 
   bool validation_error = false;
@@ -340,6 +370,10 @@
 // cannot be written, it's queued and a wait is initiated to write the message
 // ASAP on the I/O thread.
 bool ChannelPosix::WriteNoLock(MessageView message_view) {
+  if (server_.is_valid()) {
+    outgoing_messages_.emplace_front(std::move(message_view));
+    return true;
+  }
   size_t bytes_written = 0;
   std::vector<PlatformHandleInTransit> handles = message_view.TakeHandles();
   size_t num_handles = handles.size();
diff --git a/mojo/core/channel_posix.h b/mojo/core/channel_posix.h
index 94b55c9..695be6d 100644
--- a/mojo/core/channel_posix.h
+++ b/mojo/core/channel_posix.h
@@ -98,7 +98,12 @@
   bool CloseHandles(const int* fds, size_t num_fds);
 #endif  // BUILDFLAG(IS_IOS)
 
-  // The socket over which to communicate.
+  // We may be initialized with a server socket, in which case this will be
+  // valid until it accepts an incoming connection.
+  PlatformChannelServerEndpoint server_;
+
+  // The socket over which to communicate. May be passed in at construction time
+  // or accepted over |server_|.
   base::ScopedFD socket_;
 
   // These watchers must only be accessed on the IO thread.
diff --git a/mojo/core/channel_win.cc b/mojo/core/channel_win.cc
index 9f751fa..f75273f 100644
--- a/mojo/core/channel_win.cc
+++ b/mojo/core/channel_win.cc
@@ -67,8 +67,16 @@
         is_untrusted_process_(connection_params.is_untrusted_process()),
         self_(this),
         io_task_runner_(io_task_runner) {
-    handle_ =
-        connection_params.TakeEndpoint().TakePlatformHandle().TakeHandle();
+    if (connection_params.server_endpoint().is_valid()) {
+      handle_ = connection_params.TakeServerEndpoint()
+                    .TakePlatformHandle()
+                    .TakeHandle();
+      needs_connection_ = true;
+    } else {
+      handle_ =
+          connection_params.TakeEndpoint().TakePlatformHandle().TakeHandle();
+    }
+
     CHECK(handle_.IsValid());
   }
 
@@ -178,6 +186,29 @@
     base::CurrentThread::Get()->AddDestructionObserver(this);
     base::CurrentIOThread::Get()->RegisterIOHandler(handle_.Get(), this);
 
+    if (needs_connection_) {
+      BOOL ok = ::ConnectNamedPipe(handle_.Get(), &connect_context_.overlapped);
+      if (ok) {
+        PLOG(ERROR) << "Unexpected success while waiting for pipe connection";
+        OnError(Error::kConnectionFailed);
+        return;
+      }
+
+      const DWORD err = GetLastError();
+      switch (err) {
+        case ERROR_PIPE_CONNECTED:
+          break;
+        case ERROR_IO_PENDING:
+          is_connect_pending_ = true;
+          AddRef();
+          return;
+        case ERROR_NO_DATA:
+        default:
+          OnError(Error::kConnectionFailed);
+          return;
+      }
+    }
+
     // Now that we have registered our IOHandler, we can start writing.
     {
       base::AutoLock lock(write_lock_);
@@ -230,6 +261,16 @@
       } else {
         OnError(Error::kDisconnected);
       }
+    } else if (context == &connect_context_) {
+      DCHECK(is_connect_pending_);
+      is_connect_pending_ = false;
+      ReadMore(0);
+
+      base::AutoLock lock(write_lock_);
+      if (delay_writes_) {
+        delay_writes_ = false;
+        WriteNextNoLock();
+      }
     } else if (context == &read_context_) {
       OnReadDone(static_cast<size_t>(bytes_transfered));
     } else {
@@ -340,9 +381,8 @@
       // If we can't write because the pipe is disconnected then continue
       // reading to fetch any in-flight messages, relying on end-of-stream to
       // signal the actual disconnection.
-      if (is_read_pending_) {
+      if (is_read_pending_ || is_connect_pending_)
         return;
-      }
     }
 
     OnError(error);
@@ -356,9 +396,14 @@
   // The pipe handle this Channel uses for communication.
   base::win::ScopedHandle handle_;
 
+  // Indicates whether |handle_| must wait for a connection.
+  bool needs_connection_ = false;
+
   const scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
 
+  base::MessagePumpForIO::IOContext connect_context_;
   base::MessagePumpForIO::IOContext read_context_;
+  bool is_connect_pending_ = false;
   bool is_read_pending_ = false;
 
   // Protects all fields potentially accessed on multiple threads via Write().
diff --git a/mojo/core/connection_params.cc b/mojo/core/connection_params.cc
index b05b211..dac76f1d 100644
--- a/mojo/core/connection_params.cc
+++ b/mojo/core/connection_params.cc
@@ -15,6 +15,10 @@
 ConnectionParams::ConnectionParams(PlatformChannelEndpoint endpoint)
     : endpoint_(std::move(endpoint)) {}
 
+ConnectionParams::ConnectionParams(
+    PlatformChannelServerEndpoint server_endpoint)
+    : server_endpoint_(std::move(server_endpoint)) {}
+
 ConnectionParams::ConnectionParams(ConnectionParams&&) = default;
 
 ConnectionParams::~ConnectionParams() = default;
diff --git a/mojo/core/connection_params.h b/mojo/core/connection_params.h
index bf8dce5..052f38b 100644
--- a/mojo/core/connection_params.h
+++ b/mojo/core/connection_params.h
@@ -8,6 +8,7 @@
 #include "build/build_config.h"
 #include "mojo/core/system_impl_export.h"
 #include "mojo/public/cpp/platform/platform_channel_endpoint.h"
+#include "mojo/public/cpp/platform/platform_channel_server_endpoint.h"
 
 namespace mojo {
 namespace core {
@@ -17,6 +18,7 @@
  public:
   ConnectionParams();
   explicit ConnectionParams(PlatformChannelEndpoint endpoint);
+  explicit ConnectionParams(PlatformChannelServerEndpoint server_endpoint);
   ConnectionParams(ConnectionParams&&);
 
   ConnectionParams(const ConnectionParams&) = delete;
@@ -27,9 +29,16 @@
   ConnectionParams& operator=(ConnectionParams&&);
 
   const PlatformChannelEndpoint& endpoint() const { return endpoint_; }
+  const PlatformChannelServerEndpoint& server_endpoint() const {
+    return server_endpoint_;
+  }
 
   PlatformChannelEndpoint TakeEndpoint() { return std::move(endpoint_); }
 
+  PlatformChannelServerEndpoint TakeServerEndpoint() {
+    return std::move(server_endpoint_);
+  }
+
   void set_is_async(bool is_async) { is_async_ = is_async; }
   bool is_async() const { return is_async_; }
 
@@ -46,6 +55,7 @@
   bool is_untrusted_process_ = false;
   bool leak_endpoint_ = false;
   PlatformChannelEndpoint endpoint_;
+  PlatformChannelServerEndpoint server_endpoint_;
 };
 
 }  // namespace core
diff --git a/mojo/core/core.cc b/mojo/core/core.cc
index 40027e0..415c175 100644
--- a/mojo/core/core.cc
+++ b/mojo/core/core.cc
@@ -1301,6 +1301,8 @@
     return MOJO_RESULT_INVALID_ARGUMENT;
   if (transport_endpoint->type != MOJO_INVITATION_TRANSPORT_TYPE_CHANNEL &&
       transport_endpoint->type !=
+          MOJO_INVITATION_TRANSPORT_TYPE_CHANNEL_SERVER &&
+      transport_endpoint->type !=
           MOJO_INVITATION_TRANSPORT_TYPE_CHANNEL_ASYNC) {
     return MOJO_RESULT_UNIMPLEMENTED;
   }
@@ -1316,8 +1318,18 @@
   if (!endpoint.is_valid())
     return MOJO_RESULT_INVALID_ARGUMENT;
 
-  ConnectionParams connection_params(
-      PlatformChannelEndpoint(std::move(endpoint)));
+  ConnectionParams connection_params;
+#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_POSIX)
+  if (transport_endpoint->type ==
+      MOJO_INVITATION_TRANSPORT_TYPE_CHANNEL_SERVER) {
+    connection_params =
+        ConnectionParams(PlatformChannelServerEndpoint(std::move(endpoint)));
+  }
+#endif
+  if (!connection_params.server_endpoint().is_valid()) {
+    connection_params =
+        ConnectionParams(PlatformChannelEndpoint(std::move(endpoint)));
+  }
 
   // At this point everything else has been validated, so we can take ownership
   // of the dispatcher.
@@ -1330,6 +1342,7 @@
       // Release ownership of the endpoint platform handle, per the API
       // contract. The caller retains ownership on failure.
       connection_params.TakeEndpoint().TakePlatformHandle().release();
+      connection_params.TakeServerEndpoint().TakePlatformHandle().release();
       return result;
     }
     DCHECK_EQ(removed_dispatcher.get(), invitation_dispatcher);
@@ -1387,6 +1400,8 @@
     return MOJO_RESULT_INVALID_ARGUMENT;
   if (transport_endpoint->type != MOJO_INVITATION_TRANSPORT_TYPE_CHANNEL &&
       transport_endpoint->type !=
+          MOJO_INVITATION_TRANSPORT_TYPE_CHANNEL_SERVER &&
+      transport_endpoint->type !=
           MOJO_INVITATION_TRANSPORT_TYPE_CHANNEL_ASYNC) {
     return MOJO_RESULT_UNIMPLEMENTED;
   }
@@ -1406,8 +1421,18 @@
     return MOJO_RESULT_INVALID_ARGUMENT;
   }
 
-  ConnectionParams connection_params(
-      PlatformChannelEndpoint(std::move(endpoint)));
+  ConnectionParams connection_params;
+#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_POSIX)
+  if (transport_endpoint->type ==
+      MOJO_INVITATION_TRANSPORT_TYPE_CHANNEL_SERVER) {
+    connection_params =
+        ConnectionParams(PlatformChannelServerEndpoint(std::move(endpoint)));
+  }
+#endif
+  if (!connection_params.server_endpoint().is_valid()) {
+    connection_params =
+        ConnectionParams(PlatformChannelEndpoint(std::move(endpoint)));
+  }
   if (options &&
       options->flags & MOJO_ACCEPT_INVITATION_FLAG_LEAK_TRANSPORT_ENDPOINT) {
     connection_params.set_leak_endpoint(true);
diff --git a/mojo/core/embedder/BUILD.gn b/mojo/core/embedder/BUILD.gn
index df6f3e93..fce6597 100644
--- a/mojo/core/embedder/BUILD.gn
+++ b/mojo/core/embedder/BUILD.gn
@@ -21,13 +21,13 @@
   public_deps = [
     "//base",
     "//mojo:buildflags",
-    "//mojo/core:embedder_internal",
     "//mojo/public/cpp/platform",
     "//third_party/ipcz/src:ipcz_chromium",
   ]
 
   deps = [
     ":features",
+    "//mojo/core:embedder_internal",
     "//mojo/public/c/system",
   ]
 }
diff --git a/mojo/core/invitation_unittest.cc b/mojo/core/invitation_unittest.cc
index f8c11dd..346e290 100644
--- a/mojo/core/invitation_unittest.cc
+++ b/mojo/core/invitation_unittest.cc
@@ -45,6 +45,11 @@
 namespace core {
 namespace {
 
+enum class TransportType {
+  kChannel,
+  kChannelServer,
+};
+
 const char kSecondaryChannelHandleSwitch[] = "test-secondary-channel-handle";
 
 class InvitationTest : public test::MojoTestBase {
@@ -61,6 +66,7 @@
       const std::string& test_client_name,
       MojoHandle* primordial_pipes,
       size_t num_primordial_pipes,
+      TransportType transport_type,
       MojoSendInvitationFlags send_flags,
       MojoProcessErrorHandler error_handler = nullptr,
       uintptr_t error_handler_context = 0,
@@ -72,6 +78,7 @@
       base::ProcessHandle process,
       MojoHandle* primordial_pipes,
       size_t num_primordial_pipes,
+      TransportType transport_type,
       MojoSendInvitationFlags flags,
       MojoProcessErrorHandler error_handler,
       uintptr_t error_handler_context,
@@ -99,9 +106,8 @@
 #error "Platform not yet supported."
 #endif
 
-  if (switch_name.empty()) {
+  if (switch_name.empty())
     switch_name = PlatformChannel::kHandleSwitch;
-  }
   command_line->AppendSwitchASCII(std::string(switch_name), value);
 }
 
@@ -299,6 +305,7 @@
     const std::string& test_client_name,
     MojoHandle* primordial_pipes,
     size_t num_primordial_pipes,
+    TransportType transport_type,
     MojoSendInvitationFlags send_flags,
     MojoProcessErrorHandler error_handler,
     uintptr_t error_handler_context,
@@ -316,10 +323,31 @@
   launch_options.start_hidden = true;
 #endif
 
-  PlatformChannel channel;
+#if !BUILDFLAG(IS_FUCHSIA)
+  absl::optional<NamedPlatformChannel> named_channel;
+#endif
+  absl::optional<PlatformChannel> channel;
   PlatformHandle local_endpoint_handle;
-  PrepareToPassRemoteEndpoint(&channel, &launch_options, &command_line);
-  local_endpoint_handle = channel.TakeLocalEndpoint().TakePlatformHandle();
+  if (transport_type == TransportType::kChannel) {
+    channel.emplace();
+    PrepareToPassRemoteEndpoint(&channel.value(), &launch_options,
+                                &command_line);
+    local_endpoint_handle = channel->TakeLocalEndpoint().TakePlatformHandle();
+  } else {
+#if !BUILDFLAG(IS_FUCHSIA)
+    NamedPlatformChannel::Options named_channel_options;
+#if !BUILDFLAG(IS_WIN)
+    CHECK(base::PathService::Get(base::DIR_TEMP,
+                                 &named_channel_options.socket_dir));
+#endif
+    named_channel.emplace(named_channel_options);
+    named_channel->PassServerNameOnCommandLine(&command_line);
+    local_endpoint_handle =
+        named_channel->TakeServerEndpoint().TakePlatformHandle();
+#else   //  !BUILDFLAG(IS_FUCHSIA)
+    NOTREACHED() << "Named pipe support does not exist for Mojo on Fuchsia.";
+#endif  //  !BUILDFLAG(IS_FUCHSIA)
+  }
 
   std::string enable_features;
   std::string disable_features;
@@ -334,12 +362,13 @@
 
   base::Process child_process = base::SpawnMultiProcessTestChild(
       test_client_name, command_line, launch_options);
-  channel.RemoteProcessLaunchAttempted();
+  if (channel)
+    channel->RemoteProcessLaunchAttempted();
 
   SendInvitationToClient(std::move(local_endpoint_handle),
                          child_process.Handle(), primordial_pipes,
-                         num_primordial_pipes, send_flags, error_handler,
-                         error_handler_context, "");
+                         num_primordial_pipes, transport_type, send_flags,
+                         error_handler, error_handler_context, "");
 
   return child_process;
 }
@@ -350,6 +379,7 @@
     base::ProcessHandle process,
     MojoHandle* primordial_pipes,
     size_t num_primordial_pipes,
+    TransportType transport_type,
     MojoSendInvitationFlags flags,
     MojoProcessErrorHandler error_handler,
     uintptr_t error_handler_context,
@@ -377,7 +407,10 @@
 
   MojoInvitationTransportEndpoint transport_endpoint;
   transport_endpoint.struct_size = sizeof(transport_endpoint);
-  transport_endpoint.type = MOJO_INVITATION_TRANSPORT_TYPE_CHANNEL;
+  if (transport_type == TransportType::kChannel)
+    transport_endpoint.type = MOJO_INVITATION_TRANSPORT_TYPE_CHANNEL;
+  else
+    transport_endpoint.type = MOJO_INVITATION_TRANSPORT_TYPE_CHANNEL_SERVER;
   transport_endpoint.num_platform_handles = 1;
   transport_endpoint.platform_handles = &handle;
 
@@ -403,12 +436,17 @@
                                      base::StringPiece switch_name = {}) {
     const auto& command_line = *base::CommandLine::ForCurrentProcess();
     PlatformChannelEndpoint channel_endpoint;
-    if (switch_name.empty()) {
-      channel_endpoint =
-          PlatformChannel::RecoverPassedEndpointFromCommandLine(command_line);
-    } else {
-      channel_endpoint = PlatformChannel::RecoverPassedEndpointFromString(
-          command_line.GetSwitchValueASCII(switch_name));
+#if !BUILDFLAG(IS_FUCHSIA)
+    channel_endpoint = NamedPlatformChannel::ConnectToServer(command_line);
+#endif
+    if (!channel_endpoint.is_valid()) {
+      if (switch_name.empty()) {
+        channel_endpoint =
+            PlatformChannel::RecoverPassedEndpointFromCommandLine(command_line);
+      } else {
+        channel_endpoint = PlatformChannel::RecoverPassedEndpointFromString(
+            command_line.GetSwitchValueASCII(switch_name));
+      }
     }
     MojoPlatformHandle endpoint_handle;
     PlatformHandle::ToMojoPlatformHandle(channel_endpoint.TakePlatformHandle(),
@@ -449,9 +487,9 @@
 
 TEST_F(InvitationTest, SendInvitation) {
   MojoHandle primordial_pipe;
-  base::Process child_process =
-      LaunchChildTestClient("SendInvitationClient", &primordial_pipe, 1,
-                            MOJO_SEND_INVITATION_FLAG_NONE);
+  base::Process child_process = LaunchChildTestClient(
+      "SendInvitationClient", &primordial_pipe, 1, TransportType::kChannel,
+      MOJO_SEND_INVITATION_FLAG_NONE);
 
   WriteMessage(primordial_pipe, kTestMessage1);
   EXPECT_EQ(MOJO_RESULT_OK,
@@ -485,9 +523,9 @@
 
 TEST_F(InvitationTest, SendInvitationMultiplePipes) {
   MojoHandle pipes[2];
-  base::Process child_process =
-      LaunchChildTestClient("SendInvitationMultiplePipesClient", pipes, 2,
-                            MOJO_SEND_INVITATION_FLAG_NONE);
+  base::Process child_process = LaunchChildTestClient(
+      "SendInvitationMultiplePipesClient", pipes, 2, TransportType::kChannel,
+      MOJO_SEND_INVITATION_FLAG_NONE);
 
   WriteMessage(pipes[0], kTestMessage1);
   WriteMessage(pipes[1], kTestMessage2);
@@ -532,6 +570,51 @@
   EXPECT_EQ(MOJO_RESULT_OK, MojoClose(pipes[1]));
 }
 
+// Fuchsia has no named pipe support.
+#if !BUILDFLAG(IS_FUCHSIA)
+// TODO(crbug.com/1426421): Flaky on Linux TSAN.
+#if BUILDFLAG(IS_LINUX) && defined(THREAD_SANITIZER)
+#define MAYBE_SendInvitationWithServer DISABLED_SendInvitationWithServer
+#else
+#define MAYBE_SendInvitationWithServer SendInvitationWithServer
+#endif
+TEST_F(InvitationTest, MAYBE_SendInvitationWithServer) {
+  MojoHandle primordial_pipe;
+  base::Process child_process = LaunchChildTestClient(
+      "SendInvitationWithServerClient", &primordial_pipe, 1,
+      TransportType::kChannelServer, MOJO_SEND_INVITATION_FLAG_NONE);
+
+  WriteMessage(primordial_pipe, kTestMessage1);
+  EXPECT_EQ(MOJO_RESULT_OK,
+            WaitForSignals(primordial_pipe, MOJO_HANDLE_SIGNAL_READABLE));
+  EXPECT_EQ(kTestMessage3, ReadMessage(primordial_pipe));
+  EXPECT_EQ(MOJO_RESULT_OK, MojoClose(primordial_pipe));
+
+  int wait_result = -1;
+  base::WaitForMultiprocessTestChildExit(
+      child_process, TestTimeouts::action_timeout(), &wait_result);
+  child_process.Close();
+  EXPECT_EQ(0, wait_result);
+}
+
+DEFINE_TEST_CLIENT(SendInvitationWithServerClient) {
+  MojoHandle primordial_pipe;
+  MojoHandle invitation = AcceptInvitation(MOJO_ACCEPT_INVITATION_FLAG_NONE);
+  const uint32_t pipe_name = 0;
+  ASSERT_EQ(MOJO_RESULT_OK,
+            MojoExtractMessagePipeFromInvitation(invitation, &pipe_name, 4,
+                                                 nullptr, &primordial_pipe));
+  ASSERT_EQ(MOJO_RESULT_OK, MojoClose(invitation));
+
+  WaitForSignals(primordial_pipe, MOJO_HANDLE_SIGNAL_READABLE);
+  ASSERT_EQ(kTestMessage1, ReadMessage(primordial_pipe));
+  WriteMessage(primordial_pipe, kTestMessage3);
+  WaitForSignals(primordial_pipe, MOJO_HANDLE_SIGNAL_PEER_CLOSED);
+
+  ASSERT_EQ(MOJO_RESULT_OK, MojoClose(primordial_pipe));
+}
+#endif  // !BUILDFLAG(IS_FUCHSIA)
+
 const char kErrorMessage[] = "ur bad :(";
 const char kDisconnectMessage[] = "go away plz";
 
@@ -594,8 +677,9 @@
   RemoteProcessState process_state;
   MojoHandle pipe;
   base::Process child_process = LaunchChildTestClient(
-      "ProcessErrorsClient", &pipe, 1, MOJO_SEND_INVITATION_FLAG_NONE,
-      &TestProcessErrorHandler, reinterpret_cast<uintptr_t>(&process_state));
+      "ProcessErrorsClient", &pipe, 1, TransportType::kChannel,
+      MOJO_SEND_INVITATION_FLAG_NONE, &TestProcessErrorHandler,
+      reinterpret_cast<uintptr_t>(&process_state));
 
   MojoMessageHandle message;
   WaitForSignals(pipe, MOJO_HANDLE_SIGNAL_READABLE);
@@ -666,8 +750,9 @@
 
   MojoHandle pipe;
   base::Process child_process = LaunchChildTestClient(
-      "ReinvitationClient", &pipe, 1, MOJO_SEND_INVITATION_FLAG_NONE, nullptr,
-      0, &command_line, &launch_options);
+      "ReinvitationClient", &pipe, 1, TransportType::kChannel,
+      MOJO_SEND_INVITATION_FLAG_NONE, nullptr, 0, &command_line,
+      &launch_options);
   secondary_channel.RemoteProcessLaunchAttempted();
 
   // Synchronize end-to-end communication first to ensure the process connection
@@ -734,9 +819,9 @@
 
 TEST_F(InvitationTest, SendIsolatedInvitation) {
   MojoHandle primordial_pipe;
-  base::Process child_process =
-      LaunchChildTestClient("SendIsolatedInvitationClient", &primordial_pipe, 1,
-                            MOJO_SEND_INVITATION_FLAG_ISOLATED);
+  base::Process child_process = LaunchChildTestClient(
+      "SendIsolatedInvitationClient", &primordial_pipe, 1,
+      TransportType::kChannel, MOJO_SEND_INVITATION_FLAG_ISOLATED);
 
   WriteMessage(primordial_pipe, kTestMessage1);
   EXPECT_EQ(MOJO_RESULT_OK,
@@ -789,7 +874,8 @@
   MojoHandle primordial_pipe;
   base::Process child_process = LaunchChildTestClient(
       "SendMultipleIsolatedInvitationsClient", &primordial_pipe, 1,
-      MOJO_SEND_INVITATION_FLAG_ISOLATED, nullptr, 0, &command_line, &options);
+      TransportType::kChannel, MOJO_SEND_INVITATION_FLAG_ISOLATED, nullptr, 0,
+      &command_line, &options);
   secondary_transport.RemoteProcessLaunchAttempted();
 
   WriteMessage(primordial_pipe, kTestMessage1);
@@ -802,8 +888,8 @@
   MojoHandle new_pipe;
   SendInvitationToClient(
       secondary_transport.TakeLocalEndpoint().TakePlatformHandle(),
-      child_process.Handle(), &new_pipe, 1, MOJO_SEND_INVITATION_FLAG_ISOLATED,
-      nullptr, 0, "");
+      child_process.Handle(), &new_pipe, 1, TransportType::kChannel,
+      MOJO_SEND_INVITATION_FLAG_ISOLATED, nullptr, 0, "");
   WaitForSignals(primordial_pipe, MOJO_HANDLE_SIGNAL_PEER_CLOSED);
   EXPECT_EQ(MOJO_RESULT_OK, MojoClose(primordial_pipe));
 
@@ -866,17 +952,17 @@
   PlatformChannel channel2;
   MojoHandle pipe0, pipe1;
   const char kConnectionName[] = "there can be only one!";
-  SendInvitationToClient(channel1.TakeLocalEndpoint().TakePlatformHandle(),
-                         base::kNullProcessHandle, &pipe0, 1,
-                         MOJO_SEND_INVITATION_FLAG_ISOLATED, nullptr, 0,
-                         kConnectionName);
+  SendInvitationToClient(
+      channel1.TakeLocalEndpoint().TakePlatformHandle(),
+      base::kNullProcessHandle, &pipe0, 1, TransportType::kChannel,
+      MOJO_SEND_INVITATION_FLAG_ISOLATED, nullptr, 0, kConnectionName);
 
   // Send another invitation with the same connection name. |pipe0| should be
   // disconnected as the first invitation's connection is torn down.
-  SendInvitationToClient(channel2.TakeLocalEndpoint().TakePlatformHandle(),
-                         base::kNullProcessHandle, &pipe1, 1,
-                         MOJO_SEND_INVITATION_FLAG_ISOLATED, nullptr, 0,
-                         kConnectionName);
+  SendInvitationToClient(
+      channel2.TakeLocalEndpoint().TakePlatformHandle(),
+      base::kNullProcessHandle, &pipe1, 1, TransportType::kChannel,
+      MOJO_SEND_INVITATION_FLAG_ISOLATED, nullptr, 0, kConnectionName);
 
   WaitForSignals(pipe0, MOJO_HANDLE_SIGNAL_PEER_CLOSED);
   EXPECT_EQ(MOJO_RESULT_OK, MojoClose(pipe0));
@@ -893,9 +979,11 @@
   MojoHandle pipe0, pipe1;
   SendInvitationToClient(channel.TakeLocalEndpoint().TakePlatformHandle(),
                          base::kNullProcessHandle, &pipe0, 1,
+                         TransportType::kChannel,
                          MOJO_SEND_INVITATION_FLAG_ISOLATED, nullptr, 0, "");
   SendInvitationToClient(channel.TakeRemoteEndpoint().TakePlatformHandle(),
                          base::kNullProcessHandle, &pipe1, 1,
+                         TransportType::kChannel,
                          MOJO_SEND_INVITATION_FLAG_ISOLATED, nullptr, 0, "");
 
   WriteMessage(pipe0, kTestMessage1);
@@ -906,9 +994,9 @@
 
 TEST_F(InvitationTest, BrokenInvitationTransportBreaksAttachedPipe) {
   MojoHandle primordial_pipe;
-  base::Process child_process =
-      LaunchChildTestClient("BrokenTransportClient", &primordial_pipe, 1,
-                            MOJO_SEND_INVITATION_FLAG_NONE);
+  base::Process child_process = LaunchChildTestClient(
+      "BrokenTransportClient", &primordial_pipe, 1, TransportType::kChannel,
+      MOJO_SEND_INVITATION_FLAG_NONE);
 
   EXPECT_EQ(MOJO_RESULT_OK,
             WaitForSignals(primordial_pipe, MOJO_HANDLE_SIGNAL_PEER_CLOSED));
@@ -923,9 +1011,9 @@
 
 TEST_F(InvitationTest, BrokenIsolatedInvitationTransportBreaksAttachedPipe) {
   MojoHandle primordial_pipe;
-  base::Process child_process =
-      LaunchChildTestClient("BrokenTransportClient", &primordial_pipe, 1,
-                            MOJO_SEND_INVITATION_FLAG_ISOLATED);
+  base::Process child_process = LaunchChildTestClient(
+      "BrokenTransportClient", &primordial_pipe, 1, TransportType::kChannel,
+      MOJO_SEND_INVITATION_FLAG_ISOLATED);
 
   EXPECT_EQ(MOJO_RESULT_OK,
             WaitForSignals(primordial_pipe, MOJO_HANDLE_SIGNAL_PEER_CLOSED));
diff --git a/mojo/core/ipcz_driver/invitation.cc b/mojo/core/ipcz_driver/invitation.cc
index 80c4cf0..ef55e9a 100644
--- a/mojo/core/ipcz_driver/invitation.cc
+++ b/mojo/core/ipcz_driver/invitation.cc
@@ -89,9 +89,15 @@
     return IPCZ_INVALID_DRIVER_HANDLE;
   }
 
+  Channel::Endpoint channel_endpoint;
+  if (endpoint.type == MOJO_INVITATION_TRANSPORT_TYPE_CHANNEL_SERVER) {
+    channel_endpoint = PlatformChannelServerEndpoint(std::move(handle));
+  } else {
+    channel_endpoint = PlatformChannelEndpoint(std::move(handle));
+  }
   auto transport = base::MakeRefCounted<Transport>(
-      endpoint_types, PlatformChannelEndpoint(std::move(handle)),
-      std::move(remote_process), is_remote_process_untrusted);
+      endpoint_types, std::move(channel_endpoint), std::move(remote_process),
+      is_remote_process_untrusted);
   transport->SetErrorHandler(error_handler, error_handler_context);
   transport->set_leak_channel_on_shutdown(options.leak_channel_on_shutdown);
   transport->set_is_peer_trusted(options.is_peer_trusted);
diff --git a/mojo/core/ipcz_driver/transport.cc b/mojo/core/ipcz_driver/transport.cc
index e797e92..fa572f7 100644
--- a/mojo/core/ipcz_driver/transport.cc
+++ b/mojo/core/ipcz_driver/transport.cc
@@ -25,6 +25,7 @@
 #include "mojo/public/cpp/platform/platform_channel.h"
 #include "mojo/public/cpp/platform/platform_channel_endpoint.h"
 #include "mojo/public/cpp/platform/platform_handle.h"
+#include "third_party/abseil-cpp/absl/types/variant.h"
 #include "third_party/ipcz/include/ipcz/ipcz.h"
 
 #if BUILDFLAG(IS_WIN)
@@ -200,7 +201,7 @@
 }  // namespace
 
 Transport::Transport(EndpointTypes endpoint_types,
-                     PlatformChannelEndpoint endpoint,
+                     Channel::Endpoint endpoint,
                      base::Process remote_process,
                      bool is_remote_process_untrusted)
     : endpoint_types_(endpoint_types),
@@ -213,7 +214,7 @@
 
 // static
 scoped_refptr<Transport> Transport::Create(EndpointTypes endpoint_types,
-                                           PlatformChannelEndpoint endpoint,
+                                           Channel::Endpoint endpoint,
                                            base::Process remote_process,
                                            bool is_remote_process_untrusted) {
   return base::MakeRefCounted<Transport>(endpoint_types, std::move(endpoint),
@@ -278,7 +279,7 @@
   std::vector<PendingTransmission> pending_transmissions;
   {
     base::AutoLock lock(lock_);
-    if (channel_ || !inactive_endpoint_.is_valid()) {
+    if (channel_ || !IsEndpointValid()) {
       return false;
     }
 
@@ -350,7 +351,7 @@
   scoped_refptr<Channel> channel;
   {
     base::AutoLock lock(lock_);
-    if (inactive_endpoint_.is_valid()) {
+    if (IsEndpointValid()) {
       PendingTransmission transmission;
       transmission.bytes = std::vector<uint8_t>(data.begin(), data.end());
       transmission.handles = std::move(platform_handles);
@@ -588,8 +589,10 @@
   DCHECK_EQ(handles.size(), 1u);
 #endif
 
-  CHECK(inactive_endpoint_.is_valid());
-  handles[0] = inactive_endpoint_.TakePlatformHandle();
+  DCHECK(IsEndpointValid());
+  DCHECK(absl::holds_alternative<PlatformChannelEndpoint>(inactive_endpoint_));
+  handles[0] = absl::get<PlatformChannelEndpoint>(inactive_endpoint_)
+                   .TakePlatformHandle();
   return true;
 }
 
@@ -667,6 +670,18 @@
   self = std::move(self_reference_for_channel_);
 }
 
+bool Transport::IsEndpointValid() const {
+  return absl::visit(base::Overloaded{
+                         [](const PlatformChannelEndpoint& endpoint) {
+                           return endpoint.is_valid();
+                         },
+                         [](const PlatformChannelServerEndpoint& endpoint) {
+                           return endpoint.is_valid();
+                         },
+                     },
+                     inactive_endpoint_);
+}
+
 bool Transport::CanTransmitHandles() const {
 #if BUILDFLAG(IS_WIN)
   // On Windows, we can transmit handles only if at least one endpoint is a
diff --git a/mojo/core/ipcz_driver/transport.h b/mojo/core/ipcz_driver/transport.h
index 9642910..1472037 100644
--- a/mojo/core/ipcz_driver/transport.h
+++ b/mojo/core/ipcz_driver/transport.h
@@ -41,7 +41,7 @@
     EndpointType destination;
   };
   Transport(EndpointTypes endpoint_types,
-            PlatformChannelEndpoint endpoint,
+            Channel::Endpoint endpoint,
             base::Process remote_process,
             bool is_remote_process_untrusted = false);
 
@@ -49,7 +49,7 @@
   // than MakeRefCounted<T>.
   static scoped_refptr<Transport> Create(
       EndpointTypes endpoint_types,
-      PlatformChannelEndpoint endpoint,
+      Channel::Endpoint endpoint,
       base::Process remote_process = base::Process(),
       bool is_remote_process_untrusted = false);
 
@@ -93,7 +93,7 @@
   // invalidating the transport. May only be called on a Transport which has not
   // yet been activated, and only when the channel endpoint is not a server.
   PlatformChannelEndpoint TakeEndpoint() {
-    return std::move(inactive_endpoint_);
+    return std::move(absl::get<PlatformChannelEndpoint>(inactive_endpoint_));
   }
 
   // Handles reports of bad activity from ipcz, resulting from parcel rejection
@@ -168,6 +168,7 @@
 
   ~Transport() override;
 
+  bool IsEndpointValid() const;
   bool CanTransmitHandles() const;
 
   // Indicates whether this transport should serialize its remote process handle
@@ -208,7 +209,7 @@
   // start its underlying Channel instance once activated. Not guarded by a lock
   // since it must not accessed beyond activation, where thread safety becomes a
   // factor.
-  PlatformChannelEndpoint inactive_endpoint_;
+  Channel::Endpoint inactive_endpoint_;
 
   base::Lock lock_;
   scoped_refptr<Channel> channel_ GUARDED_BY(lock_);
diff --git a/mojo/core/node_controller.cc b/mojo/core/node_controller.cc
index 5bb1939..b4998b0 100644
--- a/mojo/core/node_controller.cc
+++ b/mojo/core/node_controller.cc
@@ -162,6 +162,21 @@
       target_process.IsValid() ? target_process.Duplicate() : base::Process(),
       std::move(connection_params), process_error_callback);
 
+#if BUILDFLAG(IS_WIN)
+  // On Windows, if target_process is invalid it means it's elevated or running
+  // in another session so a named pipe should be used instead.
+  if (!target_process.IsValid()) {
+    handle_policy = Channel::HandlePolicy::kRejectHandles;
+    NamedPlatformChannel::Options options;
+    NamedPlatformChannel named_channel(options);
+    node_connection_params =
+        ConnectionParams(named_channel.TakeServerEndpoint());
+    node_connection_params.set_is_untrusted_process(is_untrusted_process);
+    broker_host->SendNamedChannel(named_channel.GetServerName());
+    return node_connection_params;
+  }
+#endif
+
   // Sync connections usurp the passed endpoint and use it for the sync broker
   // channel. A new channel is created here for the NodeChannel and sent over
   // a sync broker message to the client.
@@ -416,48 +431,6 @@
     // |BIND_SYNC_BROKER| message from the invited client.
     node_connection_params = std::move(connection_params);
   } else {
-#if defined(IS_WIN)
-    // On Windows, if `target_process` is invalid we can't duplicate a pipe
-    // handle to the remote client. In that case we instead open a new named
-    // pipe and send the client its name via the broker. Once connected, the new
-    // named pipe will be used for the client Channel.
-    if (!target_process.IsValid()) {
-      NamedPlatformChannel::Options options;
-      NamedPlatformChannel named_channel(options);
-
-      const bool is_untrusted_process =
-          connection_params.is_untrusted_process();
-      BrokerHost* broker_host =
-          new BrokerHost(base::Process(), std::move(connection_params),
-                         process_error_callback);
-      broker_host->SendNamedChannel(named_channel.GetServerName());
-
-      PlatformChannelServer::WaitForConnection(
-          named_channel.TakeServerEndpoint(),
-          base::BindOnce(
-              [](base::Process target_process,
-                 const ports::NodeName& temporary_node_name,
-                 const ProcessErrorCallback& process_error_callback,
-                 bool is_untrusted_process,
-                 scoped_refptr<NodeController> node_controller,
-                 PlatformChannelEndpoint endpoint) {
-                if (!endpoint.is_valid()) {
-                  return;
-                }
-
-                ConnectionParams params(std::move(endpoint));
-                params.set_is_untrusted_process(is_untrusted_process);
-                node_controller->FinishSendBrokerClientInvitationOnIOThread(
-                    std::move(target_process), std::move(params),
-                    temporary_node_name, Channel::HandlePolicy::kRejectHandles,
-                    process_error_callback);
-              },
-              std::move(target_process), temporary_node_name,
-              process_error_callback, is_untrusted_process, this));
-      return;
-    }
-#endif
-
     absl::optional<ConnectionParams> params = CreateSyncNodeConnectionParams(
         target_process, std::move(connection_params), process_error_callback,
         handle_policy);
@@ -471,26 +444,14 @@
     node_connection_params = std::move(*params);
   }
 
-  FinishSendBrokerClientInvitationOnIOThread(
-      std::move(target_process), std::move(node_connection_params),
-      temporary_node_name, handle_policy, process_error_callback);
-#else   // !BUILDFLAG(IS_APPLE) && !BUILDFLAG(IS_NACL) && !BUILDFLAG(IS_FUCHSIA)
-  FinishSendBrokerClientInvitationOnIOThread(
-      std::move(target_process), std::move(connection_params),
-      temporary_node_name, Channel::HandlePolicy::kAcceptHandles,
+  scoped_refptr<NodeChannel> channel = NodeChannel::Create(
+      this, std::move(node_connection_params), handle_policy, io_task_runner_,
       process_error_callback);
+#else   // !BUILDFLAG(IS_APPLE) && !BUILDFLAG(IS_NACL) && !BUILDFLAG(IS_FUCHSIA)
+  scoped_refptr<NodeChannel> channel = NodeChannel::Create(
+      this, std::move(connection_params), Channel::HandlePolicy::kAcceptHandles,
+      io_task_runner_, process_error_callback);
 #endif  // !BUILDFLAG(IS_APPLE) && !BUILDFLAG(IS_NACL) && !BUILDFLAG(IS_FUCHSIA)
-}
-
-void NodeController::FinishSendBrokerClientInvitationOnIOThread(
-    base::Process target_process,
-    ConnectionParams connection_params,
-    ports::NodeName temporary_node_name,
-    Channel::HandlePolicy handle_policy,
-    const ProcessErrorCallback& process_error_callback) {
-  scoped_refptr<NodeChannel> channel =
-      NodeChannel::Create(this, std::move(connection_params), handle_policy,
-                          io_task_runner_, process_error_callback);
 
   // We set up the invitee channel with a temporary name so it can be identified
   // as a pending invitee if it writes any messages to the channel. We may start
diff --git a/mojo/core/node_controller.h b/mojo/core/node_controller.h
index 70a914c..80651533 100644
--- a/mojo/core/node_controller.h
+++ b/mojo/core/node_controller.h
@@ -188,15 +188,8 @@
   void SendBrokerClientInvitationOnIOThread(
       base::Process target_process,
       ConnectionParams connection_params,
-      ports::NodeName temporary_node_name,
+      ports::NodeName token,
       const ProcessErrorCallback& process_error_callback);
-  void FinishSendBrokerClientInvitationOnIOThread(
-      base::Process target_process,
-      ConnectionParams connection_params,
-      ports::NodeName temporary_node_name,
-      Channel::HandlePolicy handle_policy,
-      const ProcessErrorCallback& process_error_callback);
-
   void AcceptBrokerClientInvitationOnIOThread(
       ConnectionParams connection_params,
       absl::optional<PlatformHandle> broker_host_handle);
diff --git a/mojo/public/cpp/platform/BUILD.gn b/mojo/public/cpp/platform/BUILD.gn
index 95326ae7..5c07c91 100644
--- a/mojo/public/cpp/platform/BUILD.gn
+++ b/mojo/public/cpp/platform/BUILD.gn
@@ -28,21 +28,9 @@
     sources += [ "socket_utils_posix.cc" ]
   }
 
-  if (is_win || is_mac || (is_posix && !is_nacl)) {
-    public += [ "platform_channel_server.h" ]
-    sources += [ "platform_channel_server.cc" ]
-  }
-
   if (is_win) {
     public += [ "platform_handle_security_util_win.h" ]
-    sources += [
-      "platform_channel_server_win.cc",
-      "platform_handle_security_util_win.cc",
-    ]
-  } else if (is_mac) {
-    sources += [ "platform_channel_server_mac.cc" ]
-  } else if (is_posix && !is_nacl) {
-    sources += [ "platform_channel_server_posix.cc" ]
+    sources += [ "platform_handle_security_util_win.cc" ]
   }
 
   public_deps = [
diff --git a/mojo/public/cpp/platform/named_platform_channel.h b/mojo/public/cpp/platform/named_platform_channel.h
index 455a9fa..c8e19615 100644
--- a/mojo/public/cpp/platform/named_platform_channel.h
+++ b/mojo/public/cpp/platform/named_platform_channel.h
@@ -87,8 +87,8 @@
   // named pipe server; on POSIX it's a bound, listening domain socket. In each
   // case it should accept a single new connection.
   //
-  // Use with PlatformChannelServer to wait for a new connection, yielding a
-  // PlatformChannelEndpoint that is usable with the Mojo invitations API.
+  // Use the handle to send or receive an invitation, with the endpoint type as
+  // |MOJO_INVITATION_TRANSPORT_TYPE_CHANNEL_SERVER|.
   [[nodiscard]] PlatformChannelServerEndpoint TakeServerEndpoint() {
     return std::move(server_endpoint_);
   }
diff --git a/mojo/public/cpp/platform/platform_channel_server.cc b/mojo/public/cpp/platform/platform_channel_server.cc
deleted file mode 100644
index f9cb895..0000000
--- a/mojo/public/cpp/platform/platform_channel_server.cc
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2023 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "mojo/public/cpp/platform/platform_channel_server.h"
-
-#include <memory>
-#include <utility>
-
-namespace mojo {
-
-PlatformChannelServer::PlatformChannelServer() = default;
-
-PlatformChannelServer::~PlatformChannelServer() = default;
-
-// static
-void PlatformChannelServer::WaitForConnection(
-    PlatformChannelServerEndpoint server_endpoint,
-    ConnectionCallback callback) {
-  auto server = std::make_unique<PlatformChannelServer>();
-  auto* server_ptr = server.get();
-  auto wrapped_callback = base::BindOnce(
-      [](std::unique_ptr<PlatformChannelServer> server,
-         PlatformChannelServer::ConnectionCallback callback,
-         PlatformChannelEndpoint endpoint) {
-        std::move(callback).Run(std::move(endpoint));
-      },
-      std::move(server), std::move(callback));
-  if (!server_ptr->TryListen(server_endpoint, wrapped_callback)) {
-    base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
-        FROM_HERE,
-        base::BindOnce(std::move(wrapped_callback), PlatformChannelEndpoint()));
-  }
-}
-
-bool PlatformChannelServer::TryListen(
-    PlatformChannelServerEndpoint& server_endpoint,
-    ConnectionCallback& callback) {
-  auto listener = Listener::Create();
-  if (!listener->Start(server_endpoint, callback)) {
-    return false;
-  }
-
-  listener_ = std::move(listener);
-  return true;
-}
-
-void PlatformChannelServer::Stop() {
-  listener_.reset();
-}
-
-}  // namespace mojo
diff --git a/mojo/public/cpp/platform/platform_channel_server.h b/mojo/public/cpp/platform/platform_channel_server.h
deleted file mode 100644
index 3d9db8a4..0000000
--- a/mojo/public/cpp/platform/platform_channel_server.h
+++ /dev/null
@@ -1,89 +0,0 @@
-// Copyright 2023 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef MOJO_PUBLIC_CPP_PLATFORM_PLATFORM_CHANNEL_SERVER_H_
-#define MOJO_PUBLIC_CPP_PLATFORM_PLATFORM_CHANNEL_SERVER_H_
-
-#include <memory>
-
-#include "base/component_export.h"
-#include "base/functional/callback.h"
-#include "base/task/single_thread_task_runner.h"
-#include "mojo/public/cpp/platform/platform_channel_endpoint.h"
-#include "mojo/public/cpp/platform/platform_channel_server_endpoint.h"
-
-namespace mojo {
-
-// PlatformChannelServer takes ownership of a PlatformChannelServerEndpoint
-// and listens for a single incoming client connection.
-//
-// This class is not thread-safe and must be used on a thread which runs an I/O
-// MessagePump.
-class COMPONENT_EXPORT(MOJO_CPP_PLATFORM) PlatformChannelServer {
- public:
-  using ConnectionCallback = base::OnceCallback<void(PlatformChannelEndpoint)>;
-
-  // Implemented for each supported platform.
-  class COMPONENT_EXPORT(MOJO_CPP_PLATFORM) Listener {
-   public:
-    virtual ~Listener() = default;
-
-    // Implemented for each supported platform.
-    static std::unique_ptr<Listener> Create();
-
-    // Attempts to start listening on `server_endpoint`. Returns true on success
-    // or false on failure. Same semantics as Listen() below, which calls this.
-    virtual bool Start(PlatformChannelServerEndpoint& server_endpoint,
-                       ConnectionCallback& callback) = 0;
-  };
-
-  PlatformChannelServer();
-
-  // Destruction implicitly stops the listener if started, ensuring the
-  // ConnectionCallback will not be called beyoned the lifetime of this object.
-  ~PlatformChannelServer();
-
-  // Spins up a PlatformChannelServer on the current (I/O) task runner to listen
-  // on `server_endpoint` for an incoming connection. `callback` is always
-  // called eventually, as long as the calling task runner is still running when
-  // either the server accepts a connection or is disconnected. If disconnected,
-  // `callback` receives an invalid endpoint.
-  static void WaitForConnection(PlatformChannelServerEndpoint server_endpoint,
-                                ConnectionCallback callback);
-
-  // Listens on `server_endpoint` for a single connection, invoking `callback`
-  // once it arrives. Must not be called on a server that is already listening.
-  //
-  // If the server endpoint is disconnected before a connection is received,
-  // the callback will be invoked with an invalid endpoint.
-  //
-  // If the server is stopped before a connection is received, `callback` will
-  // not be called.
-  //
-  // If the server could not listen on the given endpoint, this returns false
-  // and `callback` is never called. Otherwise it returns true.
-  //
-  // This takes ownership of (i.e. moves) `server_endpoint` and `callback` if
-  // and only if it returns true.
-  bool TryListen(PlatformChannelServerEndpoint& server_endpoint,
-                 ConnectionCallback& callback);
-
-  // Same as above, but takes a callback by value for convenience when the
-  // doesn't care about retaining the arguments in the failure case.
-  bool Listen(PlatformChannelServerEndpoint server_endpoint,
-              ConnectionCallback callback) {
-    return TryListen(server_endpoint, callback);
-  }
-
-  // Stops listening for new connections immediately. The callback given to
-  // Listen() can no longer be invoked once this is called.
-  void Stop();
-
- private:
-  std::unique_ptr<Listener> listener_;
-};
-
-}  // namespace mojo
-
-#endif  // MOJO_PUBLIC_CPP_PLATFORM_PLATFORM_CHANNEL_SERVER_H_
diff --git a/mojo/public/cpp/platform/platform_channel_server_endpoint.h b/mojo/public/cpp/platform/platform_channel_server_endpoint.h
index 6229a076..c741b87c 100644
--- a/mojo/public/cpp/platform/platform_channel_server_endpoint.h
+++ b/mojo/public/cpp/platform/platform_channel_server_endpoint.h
@@ -11,10 +11,9 @@
 namespace mojo {
 
 // A PlatformHandle with a little extra type information to convey that it's
-// a channel server endpoint, i.e. a handle that should be used with
-// PlatformChannelServer to wait for a new connection and ultimately provide
-// a connected PlatformChannelEndpoint suitable for use with the Mojo
-// invitations API.
+// a channel server endpoint, i.e. a handle that can be used to send invitations
+// as |MOJO_INVITATION_TRANSPORT_TYPE_CHANNEL_SERVER| to a remote
+// PlatformChannelEndpoint.
 class COMPONENT_EXPORT(MOJO_CPP_PLATFORM) PlatformChannelServerEndpoint {
  public:
   PlatformChannelServerEndpoint();
diff --git a/mojo/public/cpp/platform/platform_channel_server_mac.cc b/mojo/public/cpp/platform/platform_channel_server_mac.cc
deleted file mode 100644
index 3eb32fa..0000000
--- a/mojo/public/cpp/platform/platform_channel_server_mac.cc
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright 2023 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "mojo/public/cpp/platform/platform_channel_server.h"
-
-#include <memory>
-#include <utility>
-
-#include "base/check.h"
-#include "base/memory/weak_ptr.h"
-#include "base/task/sequenced_task_runner.h"
-#include "mojo/public/cpp/platform/platform_channel_endpoint.h"
-#include "mojo/public/cpp/platform/platform_handle.h"
-
-namespace mojo {
-
-namespace {
-
-// NOTE: On macOS, PlatformChannelServerEndpoint is not special, as they need to
-// perform the same connection handshake as any other PlatformChannelEndpoint.
-// PlatformChannelServer acts as a simple passthrough implementation for
-// compatibility with application logic on other platforms.
-class ListenerImpl : public PlatformChannelServer::Listener {
- public:
-  ListenerImpl() = default;
-  ~ListenerImpl() override = default;
-
-  // PlatformChannelServer::Listener:
-  bool Start(PlatformChannelServerEndpoint& server_endpoint,
-             PlatformChannelServer::ConnectionCallback& callback) override {
-    if (!server_endpoint.is_valid() ||
-        !server_endpoint.platform_handle().is_mach_receive()) {
-      return false;
-    }
-
-    // Invoke the callback asynchronously to guard against re-entrancy issues.
-    // This simply repackages the server endpoint as a PlatformChannelEndpoint,
-    // since they're functionally equivalent on macOS. Note that we post the
-    // task as a WeakPtr-bound method to ensure that it doesn't run if the
-    // Listener is destroyed first.
-    PlatformChannelEndpoint endpoint{server_endpoint.TakePlatformHandle()};
-    base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
-        FROM_HERE, base::BindOnce(&ListenerImpl::RunCallback,
-                                  weak_ptr_factory_.GetWeakPtr(),
-                                  std::move(callback), std::move(endpoint)));
-    return true;
-  }
-
- private:
-  void RunCallback(PlatformChannelServer::ConnectionCallback callback,
-                   PlatformChannelEndpoint endpoint) {
-    std::move(callback).Run(std::move(endpoint));
-  }
-
-  base::WeakPtrFactory<ListenerImpl> weak_ptr_factory_{this};
-};
-
-}  // namespace
-
-std::unique_ptr<PlatformChannelServer::Listener>
-PlatformChannelServer::Listener::Create() {
-  return std::make_unique<ListenerImpl>();
-}
-
-}  // namespace mojo
diff --git a/mojo/public/cpp/platform/platform_channel_server_posix.cc b/mojo/public/cpp/platform/platform_channel_server_posix.cc
deleted file mode 100644
index 914c93e..0000000
--- a/mojo/public/cpp/platform/platform_channel_server_posix.cc
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright 2023 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "mojo/public/cpp/platform/platform_channel_server.h"
-
-#include <memory>
-#include <utility>
-
-#include "base/check.h"
-#include "base/files/scoped_file.h"
-#include "base/message_loop/message_pump_for_io.h"
-#include "base/notreached.h"
-#include "base/task/current_thread.h"
-#include "mojo/public/cpp/platform/platform_channel_endpoint.h"
-#include "mojo/public/cpp/platform/platform_handle.h"
-#include "mojo/public/cpp/platform/socket_utils_posix.h"
-
-namespace mojo {
-
-namespace {
-
-class ListenerImpl : public PlatformChannelServer::Listener,
-                     public base::MessagePumpForIO::FdWatcher {
- public:
-  ListenerImpl() : watch_controller_(FROM_HERE) {}
-  ~ListenerImpl() override = default;
-
-  // PlatformChannelServer::Listener:
-  bool Start(PlatformChannelServerEndpoint& server_endpoint,
-             PlatformChannelServer::ConnectionCallback& callback) override {
-    if (!server_endpoint.is_valid()) {
-      return false;
-    }
-
-    base::ScopedFD server = server_endpoint.TakePlatformHandle().TakeFD();
-    if (!base::CurrentIOThread::Get()->WatchFileDescriptor(
-            server.get(), /*persistent=*/true,
-            base::MessagePumpForIO::WATCH_READ, &watch_controller_, this)) {
-      return false;
-    }
-
-    server_ = std::move(server);
-    callback_ = std::move(callback);
-    return true;
-  }
-
-  // base::MessagePumpForIO::FdWatcher:
-  void OnFileCanReadWithoutBlocking(int fd) override {
-    base::ScopedFD socket;
-    CHECK_EQ(fd, server_.get());
-    if (!AcceptSocketConnection(fd, &socket)) {
-      // Unrecoverable error, e.g. socket disconnection. Fail.
-      Stop();
-      std::move(callback_).Run({});
-      return;
-    }
-
-    if (!socket.is_valid()) {
-      // Transient failure; a second connection attempt might succeed.
-      return;
-    }
-
-    Stop();
-    std::move(callback_).Run(
-        PlatformChannelEndpoint{PlatformHandle{std::move(socket)}});
-  }
-
-  void OnFileCanWriteWithoutBlocking(int fd) override { NOTREACHED(); }
-
- private:
-  void Stop() {
-    CHECK(server_.is_valid());
-    watch_controller_.StopWatchingFileDescriptor();
-    server_.reset();
-  }
-
-  base::ScopedFD server_;
-  PlatformChannelServer::ConnectionCallback callback_;
-  base::MessagePumpForIO::FdWatchController watch_controller_;
-};
-
-}  // namespace
-
-std::unique_ptr<PlatformChannelServer::Listener>
-PlatformChannelServer::Listener::Create() {
-  return std::make_unique<ListenerImpl>();
-}
-
-}  // namespace mojo
diff --git a/mojo/public/cpp/platform/platform_channel_server_win.cc b/mojo/public/cpp/platform/platform_channel_server_win.cc
deleted file mode 100644
index 08b31902f..0000000
--- a/mojo/public/cpp/platform/platform_channel_server_win.cc
+++ /dev/null
@@ -1,134 +0,0 @@
-// Copyright 2023 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "mojo/public/cpp/platform/platform_channel_server.h"
-
-#include <windows.h>
-
-#include <cstring>
-#include <memory>
-#include <utility>
-
-#include "base/check.h"
-#include "base/memory/weak_ptr.h"
-#include "base/task/current_thread.h"
-#include "base/task/sequenced_task_runner.h"
-#include "base/win/object_watcher.h"
-#include "base/win/scoped_handle.h"
-#include "mojo/public/cpp/platform/platform_channel_endpoint.h"
-#include "mojo/public/cpp/platform/platform_handle.h"
-
-namespace mojo {
-
-namespace {
-
-class ListenerImpl : public PlatformChannelServer::Listener,
-                     public base::win::ObjectWatcher::Delegate {
- public:
-  ListenerImpl() {
-    memset(&connect_overlapped_, 0, sizeof(connect_overlapped_));
-  }
-
-  ~ListenerImpl() override {
-    if (server_.is_valid()) {
-      ::CancelIo(server_.get());
-    }
-  }
-
-  // PlatformChannelServer::Listener:
-  bool Start(PlatformChannelServerEndpoint& server_endpoint,
-             PlatformChannelServer::ConnectionCallback& callback) override {
-    connect_event_.Set(::CreateEvent(NULL, TRUE, FALSE, NULL));
-    if (!connect_event_.is_valid()) {
-      return false;
-    }
-
-    connect_overlapped_.hEvent = connect_event_.get();
-    if (!event_watcher_.StartWatchingOnce(connect_event_.get(), this)) {
-      return false;
-    }
-
-    base::win::ScopedHandle server =
-        server_endpoint.TakePlatformHandle().TakeHandle();
-    BOOL ok = ::ConnectNamedPipe(server.get(), &connect_overlapped_);
-    if (ok) {
-      // This call should always fail with ERROR_IO_PENDING or
-      // ERROR_PIPE_CONNECTED.
-      return false;
-    }
-
-    const DWORD error = ::GetLastError();
-    switch (error) {
-      case ERROR_PIPE_CONNECTED:
-        // Already connected. Invoke the callback asynchronously to avoid any
-        // potential re-entrancy issues in the caller. The task is posted with
-        // a WeakPtr-bound method to ensure that it doesn't run if the server
-        // is stopped first.
-        event_watcher_.StopWatching();
-        connect_event_.Close();
-        base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
-            FROM_HERE, base::BindOnce(&ListenerImpl::RunCallback,
-                                      weak_ptr_factory_.GetWeakPtr(),
-                                      std::move(callback), std::move(server)));
-        break;
-
-      case ERROR_IO_PENDING:
-        // Will continue in OnIOCompleted whenever the event is signaled.
-        break;
-
-      default:
-        // Fail.
-        connect_event_.Close();
-        return false;
-    }
-
-    server_ = std::move(server);
-    callback_ = std::move(callback);
-    return true;
-  }
-
-  // base::win::ObjectWatcher:
-  void OnObjectSignaled(HANDLE object) override {
-    // Event signaled. Check the status of the pipe. The only success case is
-    // when ConnectNamedPipe() returns ERROR_PIPE_CONNECTED here.
-    CHECK_EQ(object, connect_event_.get());
-    BOOL ok = ::ConnectNamedPipe(server_.get(), &connect_overlapped_);
-    if (ok || ::GetLastError() != ERROR_PIPE_CONNECTED) {
-      std::move(callback_).Run({});
-      return;
-    }
-
-    // Success. Pass ownership of the connected pipe to the user-provided
-    // callback.
-    connect_event_.Close();
-    std::move(callback_).Run(
-        PlatformChannelEndpoint{PlatformHandle{std::move(server_)}});
-  }
-
- private:
-  void RunCallback(PlatformChannelServer::ConnectionCallback callback,
-                   base::win::ScopedHandle server) {
-    std::move(callback).Run(
-        PlatformChannelEndpoint{PlatformHandle{std::move(server)}});
-  }
-
-  base::win::ScopedHandle server_;
-
-  OVERLAPPED connect_overlapped_;
-  base::win::ScopedHandle connect_event_;
-  base::win::ObjectWatcher event_watcher_;
-
-  PlatformChannelServer::ConnectionCallback callback_;
-
-  base::WeakPtrFactory<ListenerImpl> weak_ptr_factory_{this};
-};
-
-}  // namespace
-
-std::unique_ptr<PlatformChannelServer::Listener>
-PlatformChannelServer::Listener::Create() {
-  return std::make_unique<ListenerImpl>();
-}
-
-}  // namespace mojo
diff --git a/mojo/public/cpp/platform/tests/BUILD.gn b/mojo/public/cpp/platform/tests/BUILD.gn
index 66de64e..8a7e7c9 100644
--- a/mojo/public/cpp/platform/tests/BUILD.gn
+++ b/mojo/public/cpp/platform/tests/BUILD.gn
@@ -14,12 +14,4 @@
     "//mojo/public/cpp/system",
     "//testing/gtest",
   ]
-
-  if (is_win || is_mac || (is_posix && !is_nacl)) {
-    sources += [ "platform_channel_server_unittest.cc" ]
-    deps += [
-      "//base/test:test_support",
-      "//mojo/core/embedder",
-    ]
-  }
 }
diff --git a/mojo/public/cpp/platform/tests/DEPS b/mojo/public/cpp/platform/tests/DEPS
index d11274b53..ef8ad28 100644
--- a/mojo/public/cpp/platform/tests/DEPS
+++ b/mojo/public/cpp/platform/tests/DEPS
@@ -1,4 +1,3 @@
 include_rules = [
-  "+mojo/core",
   "+mojo/public",
 ]
diff --git a/mojo/public/cpp/platform/tests/platform_channel_server_unittest.cc b/mojo/public/cpp/platform/tests/platform_channel_server_unittest.cc
deleted file mode 100644
index 48c1bc3..0000000
--- a/mojo/public/cpp/platform/tests/platform_channel_server_unittest.cc
+++ /dev/null
@@ -1,252 +0,0 @@
-// Copyright 2023 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "mojo/public/cpp/platform/platform_channel_server.h"
-
-#include <tuple>
-#include <utility>
-
-#include "base/containers/span.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/functional/callback.h"
-#include "base/run_loop.h"
-#include "base/task/single_thread_task_runner.h"
-#include "base/test/bind.h"
-#include "base/test/task_environment.h"
-#include "build/build_config.h"
-#include "mojo/core/channel.h"
-#include "mojo/public/cpp/platform/named_platform_channel.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
-
-namespace mojo {
-namespace {
-
-class RunOnDestruction {
- public:
-  template <typename Fn>
-  explicit RunOnDestruction(Fn fn)
-      : callback_(base::BindLambdaForTesting(fn)) {}
-  RunOnDestruction(RunOnDestruction&&) = default;
-  ~RunOnDestruction() {
-    if (callback_) {
-      std::move(callback_).Run();
-    }
-  }
-
- private:
-  base::OnceClosure callback_;
-};
-
-class TestChannel : public core::Channel::Delegate {
- public:
-  explicit TestChannel(PlatformChannelEndpoint endpoint)
-      : io_task_runner_(base::SingleThreadTaskRunner::GetCurrentDefault()),
-        channel_(
-            core::Channel::Create(this,
-                                  core::ConnectionParams{std::move(endpoint)},
-                                  core::Channel::HandlePolicy::kRejectHandles,
-                                  io_task_runner_)) {
-    channel_->Start();
-  }
-
-  ~TestChannel() override {
-    // We pump the IO task queue after ShutDown() to ensure completion, as
-    // Channel implementions post a cleanup task there.
-    base::RunLoop shutdown_flush;
-    channel_->ShutDown();
-    io_task_runner_->PostTask(FROM_HERE, shutdown_flush.QuitClosure());
-    shutdown_flush.Run();
-  }
-
-  void SendMessage(const std::string& message) {
-    auto data = base::make_span(
-        reinterpret_cast<const uint8_t*>(message.data()), message.size());
-    channel_->Write(core::Channel::Message::CreateIpczMessage(data, {}));
-  }
-
-  std::string WaitForSingleMessage() {
-    wait_for_message_.Run();
-    CHECK(received_message_);
-    return *received_message_;
-  }
-
-  // core::Channel::Delegate:
-  bool IsIpczTransport() const override {
-    // We use Channel in ipcz mode because it's simpler. Doesn't matter if
-    // MojoIpcz is actually enabled.
-    return true;
-  }
-
-  void OnChannelMessage(const void* payload,
-                        size_t payload_size,
-                        std::vector<PlatformHandle> handles) override {
-    received_message_ =
-        std::string(static_cast<const char*>(payload), payload_size);
-    std::move(quit_).Run();
-  }
-
-  void OnChannelError(core::Channel::Error error) override {}
-
- private:
-  const scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
-  const scoped_refptr<core::Channel> channel_;
-  base::RunLoop wait_for_message_;
-  base::OnceClosure quit_{wait_for_message_.QuitClosure()};
-  absl::optional<std::string> received_message_;
-};
-
-class PlatformChannelServerTest : public testing::Test {
- public:
-  PlatformChannelServerTest() { CHECK(temp_dir_.CreateUniqueTempDir()); }
-
-  ~PlatformChannelServerTest() override = default;
-
-  using NamedChannelDetails = std::tuple<PlatformChannelServerEndpoint,
-                                         NamedPlatformChannel::ServerName>;
-  NamedChannelDetails CreateRandomChannel() {
-    NamedPlatformChannel::Options options;
-#if BUILDFLAG(IS_POSIX)
-    options.socket_dir = temp_dir_.GetPath();
-#endif
-    NamedPlatformChannel channel(options);
-    return {channel.TakeServerEndpoint(), channel.GetServerName()};
-  }
-
-  PlatformChannelServer& server() { return server_; }
-
-  void VerifyEndToEndConnection(PlatformChannelEndpoint a,
-                                PlatformChannelEndpoint b) {
-    TestChannel channel_a(std::move(a));
-    TestChannel channel_b(std::move(b));
-
-    const std::string kMessage1 = "Hello, world?";
-    const std::string kMessage2 = "Oh, hi world.";
-    channel_a.SendMessage(kMessage1);
-    channel_b.SendMessage(kMessage2);
-    EXPECT_EQ(kMessage2, channel_a.WaitForSingleMessage());
-    EXPECT_EQ(kMessage1, channel_b.WaitForSingleMessage());
-  }
-
- private:
-  base::ScopedTempDir temp_dir_;
-  base::test::TaskEnvironment task_environment_{
-      base::test::TaskEnvironment::MainThreadType::IO};
-  PlatformChannelServer server_;
-};
-
-TEST_F(PlatformChannelServerTest, ConnectAfterListen) {
-  // Basic test that a client can connect after Listen() and the server will
-  // invoke its user-provided callback with a new functioning endpoint.
-  auto [server_endpoint, name] = CreateRandomChannel();
-
-  base::RunLoop loop;
-  PlatformChannelEndpoint endpoint_a;
-  EXPECT_TRUE(server().Listen(
-      std::move(server_endpoint),
-      base::BindLambdaForTesting([&](PlatformChannelEndpoint endpoint) {
-        endpoint_a = std::move(endpoint);
-        loop.Quit();
-      })));
-  auto endpoint_b = NamedPlatformChannel::ConnectToServer(name);
-  EXPECT_TRUE(endpoint_b.is_valid());
-  loop.Run();
-  VerifyEndToEndConnection(std::move(endpoint_a), std::move(endpoint_b));
-}
-
-TEST_F(PlatformChannelServerTest, ConnectBeforeListen) {
-  // Basic test that a client can connect *before* Listen() and the server will
-  // still invoke its user-provided callback with a new functioning endpoint.
-  auto [server_endpoint, name] = CreateRandomChannel();
-
-  base::RunLoop loop;
-  auto endpoint_a = NamedPlatformChannel::ConnectToServer(name);
-  EXPECT_TRUE(endpoint_a.is_valid());
-  PlatformChannelEndpoint endpoint_b;
-  EXPECT_TRUE(server().Listen(
-      std::move(server_endpoint),
-      base::BindLambdaForTesting([&](PlatformChannelEndpoint endpoint) {
-        endpoint_b = std::move(endpoint);
-        loop.Quit();
-      })));
-  loop.Run();
-  VerifyEndToEndConnection(std::move(endpoint_a), std::move(endpoint_b));
-}
-
-TEST_F(PlatformChannelServerTest, WaitForConnection) {
-  // Tests the static WaitForConnection() helper.
-  auto [server_endpoint, name] = CreateRandomChannel();
-
-  base::RunLoop loop;
-  auto endpoint_a = NamedPlatformChannel::ConnectToServer(name);
-  PlatformChannelEndpoint endpoint_b;
-  PlatformChannelServer::WaitForConnection(
-      std::move(server_endpoint),
-      base::BindLambdaForTesting([&](PlatformChannelEndpoint endpoint) {
-        endpoint_b = std::move(endpoint);
-        loop.Quit();
-      }));
-  loop.Run();
-  VerifyEndToEndConnection(std::move(endpoint_a), std::move(endpoint_b));
-}
-
-TEST_F(PlatformChannelServerTest, NoCallbackAfterListenConnectStop) {
-  // Tests that the ConnectionCallback is never invoked after Stop(), even if
-  // we Listen() and the client connects immediately before the Stop() call.
-  auto [server_endpoint, name] = CreateRandomChannel();
-  bool callback_invoked = false;
-  bool callback_destroyed = false;
-  base::RunLoop loop;
-  EXPECT_TRUE(server().Listen(
-      std::move(server_endpoint),
-      base::BindOnce(
-          // This callback should never run and should be destroyed when we
-          // Stop() below.
-          [](RunOnDestruction, bool* callback_invoked,
-             PlatformChannelEndpoint endpoint) { *callback_invoked = true; },
-          // When the above callback is destroyed, this one will run.
-          RunOnDestruction([&] {
-            callback_destroyed = true;
-            loop.Quit();
-          }),
-          &callback_invoked)));
-  auto endpoint = NamedPlatformChannel::ConnectToServer(name);
-  server().Stop();
-  loop.Run();
-  EXPECT_TRUE(callback_destroyed);
-  EXPECT_FALSE(callback_invoked);
-  EXPECT_TRUE(endpoint.is_valid());
-}
-
-TEST_F(PlatformChannelServerTest, NoCallbackAfterConnectListenStop) {
-  // Tests that the ConnectionCallback is never invoked after Stop(), even if
-  // the client connects before a Listen() which immediately precedes the Stop()
-  // call.
-  auto [server_endpoint, name] = CreateRandomChannel();
-  bool callback_invoked = false;
-  bool callback_destroyed = false;
-  base::RunLoop loop;
-  auto endpoint = NamedPlatformChannel::ConnectToServer(name);
-  EXPECT_TRUE(endpoint.is_valid());
-  EXPECT_TRUE(server().Listen(
-      std::move(server_endpoint),
-      base::BindOnce(
-          // This callback should never run and should be destroyed when we
-          // Stop() below.
-          [](RunOnDestruction, bool* callback_invoked,
-             PlatformChannelEndpoint endpoint) { *callback_invoked = true; },
-          // When the above callback is destroyed, this one will run.
-          RunOnDestruction([&] {
-            callback_destroyed = true;
-            loop.Quit();
-          }),
-          &callback_invoked)));
-  server().Stop();
-  loop.Run();
-  EXPECT_TRUE(callback_destroyed);
-  EXPECT_FALSE(callback_invoked);
-}
-
-}  // namespace
-}  // namespace mojo
diff --git a/mojo/public/cpp/system/invitation.cc b/mojo/public/cpp/system/invitation.cc
index 42e0b46..7245722 100644
--- a/mojo/public/cpp/system/invitation.cc
+++ b/mojo/public/cpp/system/invitation.cc
@@ -4,22 +4,14 @@
 
 #include "mojo/public/cpp/system/invitation.h"
 
-#include <memory>
 #include <tuple>
-#include <utility>
 
 #include "base/numerics/safe_conversions.h"
 #include "build/build_config.h"
-#include "mojo/core/embedder/embedder.h"
 #include "mojo/public/c/system/invitation.h"
 #include "mojo/public/c/system/platform_handle.h"
-#include "mojo/public/cpp/platform/platform_channel_server.h"
 #include "mojo/public/cpp/system/platform_handle.h"
 
-#if BUILDFLAG(IS_WIN)
-#include <windows.h>
-#endif
-
 namespace mojo {
 
 namespace {
@@ -110,38 +102,6 @@
     std::ignore = invitation.release();
 }
 
-void WaitForServerConnection(
-    PlatformChannelServerEndpoint server_endpoint,
-    PlatformChannelServer::ConnectionCallback callback) {
-  core::GetIOTaskRunner()->PostTask(
-      FROM_HERE,
-      base::BindOnce(&PlatformChannelServer::WaitForConnection,
-                     std::move(server_endpoint), std::move(callback)));
-}
-
-base::Process CloneProcessFromHandle(base::ProcessHandle handle) {
-  if (handle == base::kNullProcessHandle) {
-    return base::Process{};
-  }
-
-#if BUILDFLAG(IS_WIN)
-  // We can't use the hack below on Windows, because handle verification will
-  // explode when a new Process instance tries to own the already-owned
-  // `handle`.
-  HANDLE new_handle;
-  BOOL ok =
-      ::DuplicateHandle(::GetCurrentProcess(), handle, ::GetCurrentProcess(),
-                        &new_handle, 0, FALSE, DUPLICATE_SAME_ACCESS);
-  CHECK(ok);
-  return base::Process(new_handle);
-#else
-  base::Process temporary_owner(handle);
-  base::Process clone = temporary_owner.Duplicate();
-  std::ignore = temporary_owner.Release();
-  return clone;
-#endif
-}
-
 }  // namespace
 
 OutgoingInvitation::OutgoingInvitation() {
@@ -209,20 +169,10 @@
                               base::ProcessHandle target_process,
                               PlatformChannelServerEndpoint server_endpoint,
                               const ProcessErrorCallback& error_callback) {
-  WaitForServerConnection(
-      std::move(server_endpoint),
-      base::BindOnce(
-          [](OutgoingInvitation invitation, base::Process target_process,
-             const ProcessErrorCallback& error_callback,
-             PlatformChannelEndpoint endpoint) {
-            SendInvitation(std::move(invitation.handle_),
-                           target_process.Handle(),
-                           endpoint.TakePlatformHandle(),
-                           MOJO_INVITATION_TRANSPORT_TYPE_CHANNEL,
-                           invitation.extra_flags_, error_callback, "");
-          },
-          std::move(invitation), CloneProcessFromHandle(target_process),
-          error_callback));
+  SendInvitation(std::move(invitation.handle_), target_process,
+                 server_endpoint.TakePlatformHandle(),
+                 MOJO_INVITATION_TRANSPORT_TYPE_CHANNEL_SERVER,
+                 invitation.extra_flags_, error_callback, "");
 }
 
 // static
@@ -241,7 +191,7 @@
     PlatformChannelEndpoint channel_endpoint,
     base::StringPiece connection_name,
     base::ProcessHandle target_process) {
-  OutgoingInvitation invitation;
+  mojo::OutgoingInvitation invitation;
   ScopedMessagePipeHandle pipe =
       invitation.AttachMessagePipe(kIsolatedPipeName);
   SendInvitation(std::move(invitation.handle_), target_process,
@@ -257,24 +207,14 @@
     PlatformChannelServerEndpoint server_endpoint,
     base::StringPiece connection_name,
     base::ProcessHandle target_process) {
-  OutgoingInvitation invitation;
+  mojo::OutgoingInvitation invitation;
   ScopedMessagePipeHandle pipe =
       invitation.AttachMessagePipe(kIsolatedPipeName);
-  WaitForServerConnection(
-      std::move(server_endpoint),
-      base::BindOnce(
-          [](OutgoingInvitation invitation, base::Process target_process,
-             const std::string& connection_name,
-             PlatformChannelEndpoint endpoint) {
-            SendInvitation(
-                std::move(invitation.handle_), target_process.Handle(),
-                endpoint.TakePlatformHandle(),
-                MOJO_INVITATION_TRANSPORT_TYPE_CHANNEL,
-                MOJO_SEND_INVITATION_FLAG_ISOLATED | invitation.extra_flags_,
-                ProcessErrorCallback(), connection_name);
-          },
-          std::move(invitation), CloneProcessFromHandle(target_process),
-          std::string(connection_name)));
+  SendInvitation(std::move(invitation.handle_), target_process,
+                 server_endpoint.TakePlatformHandle(),
+                 MOJO_INVITATION_TRANSPORT_TYPE_CHANNEL_SERVER,
+                 MOJO_SEND_INVITATION_FLAG_ISOLATED | invitation.extra_flags_,
+                 ProcessErrorCallback(), connection_name);
   return pipe;
 }