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;
}