Fix failing tests with ChannelMojo enabled.
This ChannelMojo to:
- take a ScopedMessagePipeHandle instead of a string token so an
in-process renderer can be passed the message pipe directly;
- send brokered attachments as mojo handles; and
- offer messages to AttachmentBroker.
This also fixes and re-enables ipc_channel_mojo_unittest.cc.
BUG=579813
Committed: https://crrev.com/013cfed7ecf91b0700bec7147631d4fbedb6b64e
Cr-Commit-Position: refs/heads/master@{#380294}
Review URL: https://codereview.chromium.org/1768903002
Cr-Commit-Position: refs/heads/master@{#380360}
diff --git a/ipc/mojo/ipc_channel_mojo.cc b/ipc/mojo/ipc_channel_mojo.cc
index 69936481..8832d8d 100644
--- a/ipc/mojo/ipc_channel_mojo.cc
+++ b/ipc/mojo/ipc_channel_mojo.cc
@@ -29,30 +29,59 @@
#include "ipc/ipc_platform_file_attachment_posix.h"
#endif
+#if defined(OS_MACOSX)
+#include "ipc/mach_port_attachment_mac.h"
+#endif
+
+#if defined(OS_WIN)
+#include "ipc/handle_attachment_win.h"
+#endif
+
namespace IPC {
namespace {
class MojoChannelFactory : public ChannelFactory {
public:
- MojoChannelFactory(const std::string& token, Channel::Mode mode)
- : token_(token), mode_(mode) {}
+ MojoChannelFactory(mojo::ScopedMessagePipeHandle handle, Channel::Mode mode)
+ : handle_(std::move(handle)), mode_(mode) {}
- std::string GetName() const override {
- return token_;
- }
+ std::string GetName() const override { return ""; }
scoped_ptr<Channel> BuildChannel(Listener* listener) override {
- return ChannelMojo::Create(token_, mode_, listener);
+ return ChannelMojo::Create(std::move(handle_), mode_, listener);
}
private:
- const std::string token_;
+ mojo::ScopedMessagePipeHandle handle_;
const Channel::Mode mode_;
DISALLOW_COPY_AND_ASSIGN(MojoChannelFactory);
};
+mojom::SerializedHandlePtr CreateSerializedHandle(
+ mojo::ScopedHandle handle,
+ mojom::SerializedHandle::Type type) {
+ mojom::SerializedHandlePtr serialized_handle = mojom::SerializedHandle::New();
+ serialized_handle->the_handle = std::move(handle);
+ serialized_handle->type = type;
+ return serialized_handle;
+}
+
+MojoResult WrapPlatformHandle(mojo::edk::ScopedPlatformHandle handle,
+ mojom::SerializedHandle::Type type,
+ mojom::SerializedHandlePtr* serialized) {
+ MojoHandle wrapped_handle;
+ MojoResult wrap_result = mojo::edk::CreatePlatformHandleWrapper(
+ std::move(handle), &wrapped_handle);
+ if (wrap_result != MOJO_RESULT_OK)
+ return wrap_result;
+
+ *serialized = CreateSerializedHandle(
+ mojo::MakeScopedHandle(mojo::Handle(wrapped_handle)), type);
+ return MOJO_RESULT_OK;
+}
+
#if defined(OS_POSIX) && !defined(OS_NACL)
base::ScopedFD TakeOrDupFile(internal::PlatformFileAttachment* attachment) {
@@ -62,6 +91,109 @@
#endif
+MojoResult WrapAttachmentImpl(MessageAttachment* attachment,
+ mojom::SerializedHandlePtr* serialized) {
+ if (attachment->GetType() == MessageAttachment::TYPE_MOJO_HANDLE) {
+ *serialized = CreateSerializedHandle(
+ static_cast<internal::MojoHandleAttachment&>(*attachment).TakeHandle(),
+ mojom::SerializedHandle::Type::MOJO_HANDLE);
+ return MOJO_RESULT_OK;
+ }
+#if defined(OS_POSIX) && !defined(OS_NACL)
+ if (attachment->GetType() == MessageAttachment::TYPE_PLATFORM_FILE) {
+ // We dup() the handles in IPC::Message to transmit.
+ // IPC::MessageAttachmentSet has intricate lifecycle semantics
+ // of FDs, so just to dup()-and-own them is the safest option.
+ base::ScopedFD file = TakeOrDupFile(
+ static_cast<IPC::internal::PlatformFileAttachment*>(attachment));
+ if (!file.is_valid()) {
+ DPLOG(WARNING) << "Failed to dup FD to transmit.";
+ return MOJO_RESULT_UNKNOWN;
+ }
+
+ return WrapPlatformHandle(mojo::edk::ScopedPlatformHandle(
+ mojo::edk::PlatformHandle(file.release())),
+ mojom::SerializedHandle::Type::MOJO_HANDLE,
+ serialized);
+ }
+#endif
+#if defined(OS_MACOSX)
+ DCHECK_EQ(attachment->GetType(),
+ MessageAttachment::TYPE_BROKERABLE_ATTACHMENT);
+ DCHECK_EQ(static_cast<BrokerableAttachment&>(*attachment).GetBrokerableType(),
+ BrokerableAttachment::MACH_PORT);
+ internal::MachPortAttachmentMac& mach_port_attachment =
+ static_cast<internal::MachPortAttachmentMac&>(*attachment);
+ MojoResult result = WrapPlatformHandle(
+ mojo::edk::ScopedPlatformHandle(
+ mojo::edk::PlatformHandle(mach_port_attachment.get_mach_port())),
+ mojom::SerializedHandle::Type::MACH_PORT, serialized);
+ mach_port_attachment.reset_mach_port_ownership();
+ return result;
+#elif defined(OS_WIN)
+ DCHECK_EQ(attachment->GetType(),
+ MessageAttachment::TYPE_BROKERABLE_ATTACHMENT);
+ DCHECK_EQ(static_cast<BrokerableAttachment&>(*attachment).GetBrokerableType(),
+ BrokerableAttachment::WIN_HANDLE);
+ internal::HandleAttachmentWin& handle_attachment =
+ static_cast<internal::HandleAttachmentWin&>(*attachment);
+ MojoResult result = WrapPlatformHandle(
+ mojo::edk::ScopedPlatformHandle(
+ mojo::edk::PlatformHandle(handle_attachment.get_handle())),
+ mojom::SerializedHandle::Type::WIN_HANDLE, serialized);
+ handle_attachment.reset_handle_ownership();
+ return result;
+#else
+ NOTREACHED();
+ return MOJO_RESULT_UNKNOWN;
+#endif // defined(OS_MACOSX)
+}
+
+MojoResult WrapAttachment(MessageAttachment* attachment,
+ mojo::Array<mojom::SerializedHandlePtr>* handles) {
+ mojom::SerializedHandlePtr serialized_handle;
+ MojoResult wrap_result = WrapAttachmentImpl(attachment, &serialized_handle);
+ if (wrap_result != MOJO_RESULT_OK) {
+ LOG(WARNING) << "Pipe failed to wrap handles. Closing: " << wrap_result;
+ return wrap_result;
+ }
+ handles->push_back(std::move(serialized_handle));
+ return MOJO_RESULT_OK;
+}
+
+MojoResult UnwrapAttachment(mojom::SerializedHandlePtr handle,
+ scoped_refptr<MessageAttachment>* attachment) {
+ if (handle->type == mojom::SerializedHandle::Type::MOJO_HANDLE) {
+ *attachment =
+ new IPC::internal::MojoHandleAttachment(std::move(handle->the_handle));
+ return MOJO_RESULT_OK;
+ }
+ mojo::edk::ScopedPlatformHandle platform_handle;
+ MojoResult unwrap_result = mojo::edk::PassWrappedPlatformHandle(
+ handle->the_handle.release().value(), &platform_handle);
+ if (unwrap_result != MOJO_RESULT_OK)
+ return unwrap_result;
+#if defined(OS_MACOSX)
+ if (handle->type == mojom::SerializedHandle::Type::MACH_PORT &&
+ platform_handle.get().type == mojo::edk::PlatformHandle::Type::MACH) {
+ *attachment = new internal::MachPortAttachmentMac(
+ platform_handle.release().port,
+ internal::MachPortAttachmentMac::FROM_WIRE);
+ return MOJO_RESULT_OK;
+ }
+#endif // defined(OS_MACOSX)
+#if defined(OS_WIN)
+ if (handle->type == mojom::SerializedHandle::Type::WIN_HANDLE) {
+ *attachment = new internal::HandleAttachmentWin(
+ platform_handle.release().handle,
+ internal::HandleAttachmentWin::FROM_WIRE);
+ return MOJO_RESULT_OK;
+ }
+#endif // defined(OS_WIN)
+ NOTREACHED();
+ return MOJO_RESULT_UNKNOWN;
+}
+
} // namespace
//------------------------------------------------------------------------------
@@ -74,53 +206,40 @@
}
// static
-scoped_ptr<ChannelMojo> ChannelMojo::Create(const std::string& token,
- Mode mode,
- Listener* listener) {
- return make_scoped_ptr(
- new ChannelMojo(token, mode, listener));
+scoped_ptr<ChannelMojo> ChannelMojo::Create(
+ mojo::ScopedMessagePipeHandle handle,
+ Mode mode,
+ Listener* listener) {
+ return make_scoped_ptr(new ChannelMojo(std::move(handle), mode, listener));
}
// static
scoped_ptr<ChannelFactory> ChannelMojo::CreateServerFactory(
- const std::string& token) {
+ mojo::ScopedMessagePipeHandle handle) {
return make_scoped_ptr(
- new MojoChannelFactory(token, Channel::MODE_SERVER));
+ new MojoChannelFactory(std::move(handle), Channel::MODE_SERVER));
}
// static
scoped_ptr<ChannelFactory> ChannelMojo::CreateClientFactory(
- const std::string& token) {
+ mojo::ScopedMessagePipeHandle handle) {
return make_scoped_ptr(
- new MojoChannelFactory(token, Channel::MODE_CLIENT));
+ new MojoChannelFactory(std::move(handle), Channel::MODE_CLIENT));
}
-ChannelMojo::ChannelMojo(const std::string& token,
+ChannelMojo::ChannelMojo(mojo::ScopedMessagePipeHandle handle,
Mode mode,
Listener* listener)
- : listener_(listener),
- peer_pid_(base::kNullProcessId),
- waiting_connect_(true),
- weak_factory_(this) {
+ : listener_(listener), waiting_connect_(true), weak_factory_(this) {
// Create MojoBootstrap after all members are set as it touches
// ChannelMojo from a different thread.
- bootstrap_ = MojoBootstrap::Create(token, mode, this);
+ bootstrap_ = MojoBootstrap::Create(std::move(handle), mode, this);
}
ChannelMojo::~ChannelMojo() {
Close();
}
-scoped_ptr<internal::MessagePipeReader, ChannelMojo::ReaderDeleter>
-ChannelMojo::CreateMessageReader(mojom::ChannelAssociatedPtrInfo sender,
- mojom::ChannelAssociatedRequest receiver) {
- mojom::ChannelAssociatedPtr sender_ptr;
- sender_ptr.Bind(std::move(sender));
- return scoped_ptr<internal::MessagePipeReader, ChannelMojo::ReaderDeleter>(
- new internal::MessagePipeReader(std::move(sender_ptr),
- std::move(receiver), this));
-}
-
bool ChannelMojo::Connect() {
DCHECK(!message_reader_);
bootstrap_->Connect();
@@ -138,8 +257,8 @@
mojom::ChannelAssociatedPtrInfo send_channel,
mojom::ChannelAssociatedRequest receive_channel,
int32_t peer_pid) {
- set_peer_pid(peer_pid);
- InitMessageReader(std::move(send_channel), std::move(receive_channel));
+ InitMessageReader(std::move(send_channel), std::move(receive_channel),
+ peer_pid);
}
void ChannelMojo::OnBootstrapError() {
@@ -147,9 +266,13 @@
}
void ChannelMojo::InitMessageReader(mojom::ChannelAssociatedPtrInfo sender,
- mojom::ChannelAssociatedRequest receiver) {
- scoped_ptr<internal::MessagePipeReader, ChannelMojo::ReaderDeleter> reader =
- CreateMessageReader(std::move(sender), std::move(receiver));
+ mojom::ChannelAssociatedRequest receiver,
+ base::ProcessId peer_pid) {
+ mojom::ChannelAssociatedPtr sender_ptr;
+ sender_ptr.Bind(std::move(sender));
+ scoped_ptr<internal::MessagePipeReader, ChannelMojo::ReaderDeleter> reader(
+ new internal::MessagePipeReader(std::move(sender_ptr),
+ std::move(receiver), peer_pid, this));
for (size_t i = 0; i < pending_messages_.size(); ++i) {
bool sent = reader->Send(std::move(pending_messages_[i]));
@@ -192,7 +315,10 @@
}
base::ProcessId ChannelMojo::GetPeerPID() const {
- return peer_pid_;
+ if (!message_reader_)
+ return base::kNullProcessId;
+
+ return message_reader_->GetPeerPid();
}
base::ProcessId ChannelMojo::GetSelfPID() const {
@@ -203,6 +329,10 @@
TRACE_EVENT2("ipc,toplevel", "ChannelMojo::OnMessageReceived",
"class", IPC_MESSAGE_ID_CLASS(message.type()),
"line", IPC_MESSAGE_ID_LINE(message.type()));
+ if (AttachmentBroker* broker = AttachmentBroker::GetGlobal()) {
+ if (broker->OnMessageReceived(message))
+ return;
+ }
listener_->OnMessageReceived(message);
if (message.dispatch_error())
listener_->OnBadMessageReceived(message);
@@ -221,81 +351,53 @@
// static
MojoResult ChannelMojo::ReadFromMessageAttachmentSet(
Message* message,
- mojo::Array<mojo::ScopedHandle>* handles) {
- // We dup() the handles in IPC::Message to transmit.
- // IPC::MessageAttachmentSet has intricate lifecycle semantics
- // of FDs, so just to dup()-and-own them is the safest option.
+ mojo::Array<mojom::SerializedHandlePtr>* handles) {
if (message->HasAttachments()) {
MessageAttachmentSet* set = message->attachment_set();
for (unsigned i = 0; i < set->num_non_brokerable_attachments(); ++i) {
- scoped_refptr<MessageAttachment> attachment =
- set->GetNonBrokerableAttachmentAt(i);
- switch (attachment->GetType()) {
- case MessageAttachment::TYPE_PLATFORM_FILE:
-#if defined(OS_POSIX) && !defined(OS_NACL)
- {
- base::ScopedFD file =
- TakeOrDupFile(static_cast<IPC::internal::PlatformFileAttachment*>(
- attachment.get()));
- if (!file.is_valid()) {
- DPLOG(WARNING) << "Failed to dup FD to transmit.";
- set->CommitAllDescriptors();
- return MOJO_RESULT_UNKNOWN;
- }
-
- MojoHandle wrapped_handle;
- MojoResult wrap_result = mojo::edk::CreatePlatformHandleWrapper(
- mojo::edk::ScopedPlatformHandle(
- mojo::edk::PlatformHandle(file.release())),
- &wrapped_handle);
- if (MOJO_RESULT_OK != wrap_result) {
- LOG(WARNING) << "Pipe failed to wrap handles. Closing: "
- << wrap_result;
- set->CommitAllDescriptors();
- return wrap_result;
- }
-
- handles->push_back(
- mojo::MakeScopedHandle(mojo::Handle(wrapped_handle)));
- }
-#else
- NOTREACHED();
-#endif // defined(OS_POSIX) && !defined(OS_NACL)
- break;
- case MessageAttachment::TYPE_MOJO_HANDLE: {
- mojo::ScopedHandle handle =
- static_cast<IPC::internal::MojoHandleAttachment*>(
- attachment.get())->TakeHandle();
- handles->push_back(std::move(handle));
- } break;
- case MessageAttachment::TYPE_BROKERABLE_ATTACHMENT:
- // Brokerable attachments are handled by the AttachmentBroker so
- // there's no need to do anything here.
- NOTREACHED();
- break;
+ MojoResult result = WrapAttachment(
+ set->GetNonBrokerableAttachmentAt(i).get(), handles);
+ if (result != MOJO_RESULT_OK) {
+ set->CommitAllDescriptors();
+ return result;
}
}
-
+ for (unsigned i = 0; i < set->num_brokerable_attachments(); ++i) {
+ MojoResult result =
+ WrapAttachment(set->GetBrokerableAttachmentAt(i).get(), handles);
+ if (result != MOJO_RESULT_OK) {
+ set->CommitAllDescriptors();
+ return result;
+ }
+ }
set->CommitAllDescriptors();
}
-
return MOJO_RESULT_OK;
}
// static
MojoResult ChannelMojo::WriteToMessageAttachmentSet(
- mojo::Array<mojo::ScopedHandle> handle_buffer,
+ mojo::Array<mojom::SerializedHandlePtr> handle_buffer,
Message* message) {
for (size_t i = 0; i < handle_buffer.size(); ++i) {
+ scoped_refptr<MessageAttachment> unwrapped_attachment;
+ MojoResult unwrap_result = UnwrapAttachment(std::move(handle_buffer[i]),
+ &unwrapped_attachment);
+ if (unwrap_result != MOJO_RESULT_OK) {
+ LOG(WARNING) << "Pipe failed to unwrap handles. Closing: "
+ << unwrap_result;
+ return unwrap_result;
+ }
+ DCHECK(unwrapped_attachment);
+
bool ok = message->attachment_set()->AddAttachment(
- new IPC::internal::MojoHandleAttachment(std::move(handle_buffer[i])));
+ std::move(unwrapped_attachment));
DCHECK(ok);
if (!ok) {
LOG(ERROR) << "Failed to add new Mojo handle.";
return MOJO_RESULT_UNKNOWN;
}
}
-
return MOJO_RESULT_OK;
}