diff options
author | tsergeant <tsergeant@chromium.org> | 2016-03-09 19:51:33 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-03-10 03:53:03 +0000 |
commit | 896012863947ba511c55ce7c65aa1002cd3894eb (patch) | |
tree | 81614102d853a7d1fc16e207083905ece2ae14e3 /ipc | |
parent | 4819f8b1cfab20b5598d5426ff48dbeae1b1955a (diff) | |
download | chromium_src-896012863947ba511c55ce7c65aa1002cd3894eb.zip chromium_src-896012863947ba511c55ce7c65aa1002cd3894eb.tar.gz chromium_src-896012863947ba511c55ce7c65aa1002cd3894eb.tar.bz2 |
Revert of Fix failing tests with ChannelMojo enabled. (patchset #3 id:300001 of https://codereview.chromium.org/1768903002/ )
Reason for revert:
This CL is causing failures in ipc_mojo_unittests.
See:
https://build.chromium.org/p/chromium.linux/builders/Linux%20Tests%20%28dbg%29%281%29/builds/52715
https://build.chromium.org/p/chromium.linux/builders/Linux%20Tests%20%28dbg%29%281%29%2832%29/builds/26588
Original issue's description:
> 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}
TBR=rockot@chromium.org,tsepez@chromium.org,ben@chromium.org,sammc@chromium.org
# Skipping CQ checks because original CL landed less than 1 days ago.
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=579813
Review URL: https://codereview.chromium.org/1784773002
Cr-Commit-Position: refs/heads/master@{#380325}
Diffstat (limited to 'ipc')
-rw-r--r-- | ipc/handle_attachment_win.cc | 4 | ||||
-rw-r--r-- | ipc/handle_attachment_win.h | 7 | ||||
-rw-r--r-- | ipc/mach_port_attachment_mac.cc | 3 | ||||
-rw-r--r-- | ipc/mach_port_attachment_mac.h | 7 | ||||
-rw-r--r-- | ipc/mojo/BUILD.gn | 5 | ||||
-rw-r--r-- | ipc/mojo/ipc.mojom | 14 | ||||
-rw-r--r-- | ipc/mojo/ipc_channel_mojo.cc | 286 | ||||
-rw-r--r-- | ipc/mojo/ipc_channel_mojo.h | 29 | ||||
-rw-r--r-- | ipc/mojo/ipc_channel_mojo_unittest.cc | 404 | ||||
-rw-r--r-- | ipc/mojo/ipc_message_pipe_reader.cc | 3 | ||||
-rw-r--r-- | ipc/mojo/ipc_message_pipe_reader.h | 4 | ||||
-rw-r--r-- | ipc/mojo/ipc_mojo.gyp | 5 | ||||
-rw-r--r-- | ipc/mojo/ipc_mojo_bootstrap.cc | 23 | ||||
-rw-r--r-- | ipc/mojo/ipc_mojo_bootstrap.h | 12 | ||||
-rw-r--r-- | ipc/mojo/ipc_mojo_bootstrap_unittest.cc | 14 | ||||
-rw-r--r-- | ipc/mojo/ipc_mojo_handle_attachment.cc | 3 | ||||
-rw-r--r-- | ipc/mojo/ipc_mojo_perftest.cc | 45 |
17 files changed, 428 insertions, 440 deletions
diff --git a/ipc/handle_attachment_win.cc b/ipc/handle_attachment_win.cc index cb6a7ba..39c4ef7 100644 --- a/ipc/handle_attachment_win.cc +++ b/ipc/handle_attachment_win.cc @@ -24,10 +24,6 @@ HandleAttachmentWin::HandleAttachmentWin(const HANDLE& handle, } } -HandleAttachmentWin::HandleAttachmentWin(const HANDLE& handle, - FromWire from_wire) - : handle_(handle), permissions_(HandleWin::INVALID), owns_handle_(true) {} - HandleAttachmentWin::HandleAttachmentWin(const WireFormat& wire_format) : BrokerableAttachment(wire_format.attachment_id), handle_(LongToHandle(wire_format.handle)), diff --git a/ipc/handle_attachment_win.h b/ipc/handle_attachment_win.h index ff0ce91..5e04bdb 100644 --- a/ipc/handle_attachment_win.h +++ b/ipc/handle_attachment_win.h @@ -58,13 +58,6 @@ class IPC_EXPORT HandleAttachmentWin : public BrokerableAttachment { // result. Should only be called by the sender of a Chrome IPC message. HandleAttachmentWin(const HANDLE& handle, HandleWin::Permissions permissions); - enum FromWire { - FROM_WIRE, - }; - // This constructor takes ownership of |handle|. Should only be called by the - // receiver of a Chrome IPC message. - HandleAttachmentWin(const HANDLE& handle, FromWire from_wire); - // This constructor takes ownership of |wire_format.handle| without making a // copy. Should only be called by the receiver of a Chrome IPC message. explicit HandleAttachmentWin(const WireFormat& wire_format); diff --git a/ipc/mach_port_attachment_mac.cc b/ipc/mach_port_attachment_mac.cc index 47fd4e9..65baa34 100644 --- a/ipc/mach_port_attachment_mac.cc +++ b/ipc/mach_port_attachment_mac.cc @@ -20,9 +20,6 @@ MachPortAttachmentMac::MachPortAttachmentMac(mach_port_t mach_port) << "MachPortAttachmentMac mach_port_mod_refs"; } } -MachPortAttachmentMac::MachPortAttachmentMac(mach_port_t mach_port, - FromWire from_wire) - : mach_port_(mach_port), owns_mach_port_(true) {} MachPortAttachmentMac::MachPortAttachmentMac(const WireFormat& wire_format) : BrokerableAttachment(wire_format.attachment_id), diff --git a/ipc/mach_port_attachment_mac.h b/ipc/mach_port_attachment_mac.h index 658cff4..244014e 100644 --- a/ipc/mach_port_attachment_mac.h +++ b/ipc/mach_port_attachment_mac.h @@ -51,13 +51,6 @@ class IPC_EXPORT MachPortAttachmentMac : public BrokerableAttachment { // IPC message. explicit MachPortAttachmentMac(mach_port_t mach_port); - enum FromWire { - FROM_WIRE, - }; - // This constructor takes ownership of |mach_port|, but does not modify its - // ref count. Should only be called by the receiver of a Chrome IPC message. - MachPortAttachmentMac(mach_port_t mach_port, FromWire from_wire); - // This constructor takes ownership of |wire_format.mach_port|, but does not // modify its ref count. Should only be called by the receiver of a Chrome IPC // message. diff --git a/ipc/mojo/BUILD.gn b/ipc/mojo/BUILD.gn index 22f063a..9804845 100644 --- a/ipc/mojo/BUILD.gn +++ b/ipc/mojo/BUILD.gn @@ -43,7 +43,10 @@ component("mojo") { test("ipc_mojo_unittests") { sources = [ - "ipc_channel_mojo_unittest.cc", + # TODO(rockot): Re-enable these when we're ready to start using ChannelMojo + # again. They need to be updated to support multiprocess testing with the + # current Mojo EDK implementation. + #"ipc_channel_mojo_unittest.cc", "ipc_mojo_bootstrap_unittest.cc", "run_all_unittests.cc", ] diff --git a/ipc/mojo/ipc.mojom b/ipc/mojo/ipc.mojom index 6b69ced..dfc5770 100644 --- a/ipc/mojo/ipc.mojom +++ b/ipc/mojo/ipc.mojom @@ -4,21 +4,9 @@ module IPC.mojom; -struct SerializedHandle { - handle the_handle; - - enum Type { - MOJO_HANDLE, - WIN_HANDLE, - MACH_PORT, - }; - - Type type; -}; - struct Message { array<uint8> data; - array<SerializedHandle>? handles; + array<handle>? handles; }; interface Channel { diff --git a/ipc/mojo/ipc_channel_mojo.cc b/ipc/mojo/ipc_channel_mojo.cc index 8832d8d..6993648 100644 --- a/ipc/mojo/ipc_channel_mojo.cc +++ b/ipc/mojo/ipc_channel_mojo.cc @@ -29,59 +29,30 @@ #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(mojo::ScopedMessagePipeHandle handle, Channel::Mode mode) - : handle_(std::move(handle)), mode_(mode) {} + MojoChannelFactory(const std::string& token, Channel::Mode mode) + : token_(token), mode_(mode) {} - std::string GetName() const override { return ""; } + std::string GetName() const override { + return token_; + } scoped_ptr<Channel> BuildChannel(Listener* listener) override { - return ChannelMojo::Create(std::move(handle_), mode_, listener); + return ChannelMojo::Create(token_, mode_, listener); } private: - mojo::ScopedMessagePipeHandle handle_; + const std::string token_; 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) { @@ -91,109 +62,6 @@ base::ScopedFD TakeOrDupFile(internal::PlatformFileAttachment* attachment) { #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 //------------------------------------------------------------------------------ @@ -206,40 +74,53 @@ bool ChannelMojo::ShouldBeUsed() { } // static -scoped_ptr<ChannelMojo> ChannelMojo::Create( - mojo::ScopedMessagePipeHandle handle, - Mode mode, - Listener* listener) { - return make_scoped_ptr(new ChannelMojo(std::move(handle), mode, listener)); +scoped_ptr<ChannelMojo> ChannelMojo::Create(const std::string& token, + Mode mode, + Listener* listener) { + return make_scoped_ptr( + new ChannelMojo(token, mode, listener)); } // static scoped_ptr<ChannelFactory> ChannelMojo::CreateServerFactory( - mojo::ScopedMessagePipeHandle handle) { + const std::string& token) { return make_scoped_ptr( - new MojoChannelFactory(std::move(handle), Channel::MODE_SERVER)); + new MojoChannelFactory(token, Channel::MODE_SERVER)); } // static scoped_ptr<ChannelFactory> ChannelMojo::CreateClientFactory( - mojo::ScopedMessagePipeHandle handle) { + const std::string& token) { return make_scoped_ptr( - new MojoChannelFactory(std::move(handle), Channel::MODE_CLIENT)); + new MojoChannelFactory(token, Channel::MODE_CLIENT)); } -ChannelMojo::ChannelMojo(mojo::ScopedMessagePipeHandle handle, +ChannelMojo::ChannelMojo(const std::string& token, Mode mode, Listener* listener) - : listener_(listener), waiting_connect_(true), weak_factory_(this) { + : listener_(listener), + peer_pid_(base::kNullProcessId), + waiting_connect_(true), + weak_factory_(this) { // Create MojoBootstrap after all members are set as it touches // ChannelMojo from a different thread. - bootstrap_ = MojoBootstrap::Create(std::move(handle), mode, this); + bootstrap_ = MojoBootstrap::Create(token, 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(); @@ -257,8 +138,8 @@ void ChannelMojo::OnPipesAvailable( mojom::ChannelAssociatedPtrInfo send_channel, mojom::ChannelAssociatedRequest receive_channel, int32_t peer_pid) { - InitMessageReader(std::move(send_channel), std::move(receive_channel), - peer_pid); + set_peer_pid(peer_pid); + InitMessageReader(std::move(send_channel), std::move(receive_channel)); } void ChannelMojo::OnBootstrapError() { @@ -266,13 +147,9 @@ void ChannelMojo::OnBootstrapError() { } void ChannelMojo::InitMessageReader(mojom::ChannelAssociatedPtrInfo sender, - 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)); + mojom::ChannelAssociatedRequest receiver) { + scoped_ptr<internal::MessagePipeReader, ChannelMojo::ReaderDeleter> reader = + CreateMessageReader(std::move(sender), std::move(receiver)); for (size_t i = 0; i < pending_messages_.size(); ++i) { bool sent = reader->Send(std::move(pending_messages_[i])); @@ -315,10 +192,7 @@ bool ChannelMojo::Send(Message* message) { } base::ProcessId ChannelMojo::GetPeerPID() const { - if (!message_reader_) - return base::kNullProcessId; - - return message_reader_->GetPeerPid(); + return peer_pid_; } base::ProcessId ChannelMojo::GetSelfPID() const { @@ -329,10 +203,6 @@ void ChannelMojo::OnMessageReceived(const Message& message) { 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); @@ -351,53 +221,81 @@ base::ScopedFD ChannelMojo::TakeClientFileDescriptor() { // static MojoResult ChannelMojo::ReadFromMessageAttachmentSet( Message* message, - mojo::Array<mojom::SerializedHandlePtr>* handles) { + 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. if (message->HasAttachments()) { MessageAttachmentSet* set = message->attachment_set(); for (unsigned i = 0; i < set->num_non_brokerable_attachments(); ++i) { - 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; + 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; } } + set->CommitAllDescriptors(); } + return MOJO_RESULT_OK; } // static MojoResult ChannelMojo::WriteToMessageAttachmentSet( - mojo::Array<mojom::SerializedHandlePtr> handle_buffer, + mojo::Array<mojo::ScopedHandle> 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( - std::move(unwrapped_attachment)); + new IPC::internal::MojoHandleAttachment(std::move(handle_buffer[i]))); DCHECK(ok); if (!ok) { LOG(ERROR) << "Failed to add new Mojo handle."; return MOJO_RESULT_UNKNOWN; } } + return MOJO_RESULT_OK; } diff --git a/ipc/mojo/ipc_channel_mojo.h b/ipc/mojo/ipc_channel_mojo.h index c1b659a..a996790 100644 --- a/ipc/mojo/ipc_channel_mojo.h +++ b/ipc/mojo/ipc_channel_mojo.h @@ -26,9 +26,8 @@ namespace IPC { // Mojo-based IPC::Channel implementation over a Mojo message pipe. // -// ChannelMojo builds a Mojo MessagePipe using the provided message pipe -// |handle| and builds an associated interface for each direction on the -// channel. +// ChannelMojo builds a Mojo MessagePipe using the provided token and builds an +// associated interface for each direction on the channel. // // TODO(morrita): Add APIs to create extra MessagePipes to let // Mojo-based objects talk over this Channel. @@ -41,8 +40,8 @@ class IPC_MOJO_EXPORT ChannelMojo // True if ChannelMojo should be used regardless of the flag. static bool ShouldBeUsed(); - // Creates a ChannelMojo. - static scoped_ptr<ChannelMojo> Create(mojo::ScopedMessagePipeHandle handle, + // Create ChannelMojo. A bootstrap channel is created as well. + static scoped_ptr<ChannelMojo> Create(const std::string& token, Mode mode, Listener* listener); @@ -50,10 +49,10 @@ class IPC_MOJO_EXPORT ChannelMojo // The factory is used to create Mojo-based ChannelProxy family. // |host| must not be null. static scoped_ptr<ChannelFactory> CreateServerFactory( - mojo::ScopedMessagePipeHandle handle); + const std::string& token); static scoped_ptr<ChannelFactory> CreateClientFactory( - mojo::ScopedMessagePipeHandle handle); + const std::string& token); ~ChannelMojo() override; @@ -72,11 +71,11 @@ class IPC_MOJO_EXPORT ChannelMojo // These access protected API of IPC::Message, which has ChannelMojo // as a friend class. static MojoResult WriteToMessageAttachmentSet( - mojo::Array<mojom::SerializedHandlePtr> handle_buffer, + mojo::Array<mojo::ScopedHandle> handle_buffer, Message* message); static MojoResult ReadFromMessageAttachmentSet( Message* message, - mojo::Array<mojom::SerializedHandlePtr>* handles); + mojo::Array<mojo::ScopedHandle>* handles); // MojoBootstrapDelegate implementation void OnPipesAvailable(mojom::ChannelAssociatedPtrInfo send_channel, @@ -90,21 +89,27 @@ class IPC_MOJO_EXPORT ChannelMojo void OnPipeError(internal::MessagePipeReader* reader) override; private: - ChannelMojo(mojo::ScopedMessagePipeHandle handle, + ChannelMojo(const std::string& token, Mode mode, Listener* listener); void InitMessageReader(mojom::ChannelAssociatedPtrInfo sender, - mojom::ChannelAssociatedRequest receiver, - base::ProcessId peer_pid); + mojom::ChannelAssociatedRequest receiver); + + void set_peer_pid(base::ProcessId pid) { peer_pid_ = pid; } // ChannelMojo needs to kill its MessagePipeReader in delayed manner // because the channel wants to kill these readers during the // notifications invoked by them. typedef internal::MessagePipeReader::DelayedDeleter ReaderDeleter; + scoped_ptr<internal::MessagePipeReader, ReaderDeleter> CreateMessageReader( + mojom::ChannelAssociatedPtrInfo sender, + mojom::ChannelAssociatedRequest receiver); + scoped_ptr<MojoBootstrap> bootstrap_; Listener* listener_; + base::ProcessId peer_pid_; scoped_ptr<internal::MessagePipeReader, ReaderDeleter> message_reader_; std::vector<scoped_ptr<Message>> pending_messages_; diff --git a/ipc/mojo/ipc_channel_mojo_unittest.cc b/ipc/mojo/ipc_channel_mojo_unittest.cc index ac09ac3..ec5efa6 100644 --- a/ipc/mojo/ipc_channel_mojo_unittest.cc +++ b/ipc/mojo/ipc_channel_mojo_unittest.cc @@ -15,7 +15,6 @@ #include "base/pickle.h" #include "base/run_loop.h" #include "base/single_thread_task_runner.h" -#include "base/test/test_io_thread.h" #include "base/test/test_timeouts.h" #include "base/thread_task_runner_handle.h" #include "base/threading/thread.h" @@ -23,45 +22,21 @@ #include "ipc/ipc_message.h" #include "ipc/ipc_test_base.h" #include "ipc/ipc_test_channel_listener.h" -#include "ipc/mojo/ipc_channel_mojo.h" #include "ipc/mojo/ipc_mojo_handle_attachment.h" #include "ipc/mojo/ipc_mojo_message_helper.h" #include "ipc/mojo/ipc_mojo_param_traits.h" -#include "mojo/edk/test/mojo_test_base.h" -#include "mojo/edk/test/multiprocess_test_helper.h" -#include "testing/gtest/include/gtest/gtest.h" #if defined(OS_POSIX) #include "base/file_descriptor_posix.h" #include "ipc/ipc_platform_file_attachment_posix.h" #endif -#define DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(client_name, test_base) \ - class client_name##_MainFixture : public test_base { \ - public: \ - void Main(); \ - }; \ - MULTIPROCESS_TEST_MAIN_WITH_SETUP( \ - client_name##TestChildMain, \ - ::mojo::edk::test::MultiprocessTestHelper::ChildSetup) { \ - CHECK(!mojo::edk::test::MultiprocessTestHelper::primordial_pipe_token \ - .empty()); \ - client_name##_MainFixture test; \ - test.Init(mojo::edk::CreateChildMessagePipe( \ - mojo::edk::test::MultiprocessTestHelper::primordial_pipe_token)); \ - test.Main(); \ - return (::testing::Test::HasFatalFailure() || \ - ::testing::Test::HasNonfatalFailure()) \ - ? 1 \ - : 0; \ - } \ - void client_name##_MainFixture::Main() - namespace { class ListenerThatExpectsOK : public IPC::Listener { public: - ListenerThatExpectsOK() : received_ok_(false) {} + ListenerThatExpectsOK() + : received_ok_(false) {} ~ListenerThatExpectsOK() override {} @@ -83,8 +58,8 @@ class ListenerThatExpectsOK : public IPC::Listener { } static void SendOK(IPC::Sender* sender) { - IPC::Message* message = - new IPC::Message(0, 2, IPC::Message::PRIORITY_NORMAL); + IPC::Message* message = new IPC::Message( + 0, 2, IPC::Message::PRIORITY_NORMAL); message->WriteString(std::string("OK")); ASSERT_TRUE(sender->Send(message)); } @@ -95,12 +70,13 @@ class ListenerThatExpectsOK : public IPC::Listener { class ChannelClient { public: - void Init(mojo::ScopedMessagePipeHandle handle) { - handle_ = std::move(handle); - } - void Connect(IPC::Listener* listener) { - channel_ = IPC::ChannelMojo::Create(std::move(handle_), + explicit ChannelClient(IPC::Listener* listener, const char* name) { + channel_ = IPC::ChannelMojo::Create(main_message_loop_.task_runner(), + IPCTestBase::GetChannelName(name), IPC::Channel::MODE_CLIENT, listener); + } + + void Connect() { CHECK(channel_->Connect()); } @@ -117,46 +93,48 @@ class ChannelClient { private: base::MessageLoopForIO main_message_loop_; - mojo::ScopedMessagePipeHandle handle_; scoped_ptr<IPC::ChannelMojo> channel_; }; -class IPCChannelMojoTest : public testing::Test { +class IPCChannelMojoTestBase : public IPCTestBase { public: - IPCChannelMojoTest() : io_thread_(base::TestIOThread::Mode::kAutoStart) {} - - void TearDown() override { base::RunLoop().RunUntilIdle(); } - void InitWithMojo(const std::string& test_client_name) { - handle_ = helper_.StartChild(test_client_name); - } - - void CreateChannel(IPC::Listener* listener) { - channel_ = IPC::ChannelMojo::Create(std::move(handle_), - IPC::Channel::MODE_SERVER, listener); + Init(test_client_name); } - bool ConnectChannel() { return channel_->Connect(); } - - void DestroyChannel() { channel_.reset(); } + void TearDown() override { + // Make sure Mojo IPC support is properly shutdown on the I/O loop before + // TearDown continues. + base::RunLoop run_loop; + task_runner()->PostTask(FROM_HERE, run_loop.QuitClosure()); + run_loop.Run(); - bool WaitForClientShutdown() { return helper_.WaitForChildTestShutdown(); } + IPCTestBase::TearDown(); + } +}; - IPC::Sender* sender() { return channel(); } - IPC::Channel* channel() { return channel_.get(); } +class IPCChannelMojoTest : public IPCChannelMojoTestBase { + protected: + scoped_ptr<IPC::ChannelFactory> CreateChannelFactory( + const IPC::ChannelHandle& handle, + base::SequencedTaskRunner* runner) override { + return IPC::ChannelMojo::CreateServerFactory(task_runner(), handle); + } - private: - base::MessageLoop message_loop_; - base::TestIOThread io_thread_; - mojo::edk::test::MultiprocessTestHelper helper_; - mojo::ScopedMessagePipeHandle handle_; - scoped_ptr<IPC::Channel> channel_; + bool DidStartClient() override { + bool ok = IPCTestBase::DidStartClient(); + DCHECK(ok); + return ok; + } }; + class TestChannelListenerWithExtraExpectations : public IPC::TestChannelListener { public: - TestChannelListenerWithExtraExpectations() : is_connected_called_(false) {} + TestChannelListenerWithExtraExpectations() + : is_connected_called_(false) { + } void OnChannelConnected(int32_t peer_pid) override { IPC::TestChannelListener::OnChannelConnected(peer_pid); @@ -171,7 +149,8 @@ class TestChannelListenerWithExtraExpectations }; // Times out on Android; see http://crbug.com/502290 -#if defined(OS_ANDROID) +// Times out on Linux. crbug.com/585784 +#if defined(OS_ANDROID) || defined(OS_LINUX) #define MAYBE_ConnectedFromClient DISABLED_ConnectedFromClient #else #define MAYBE_ConnectedFromClient ConnectedFromClient @@ -184,12 +163,15 @@ TEST_F(IPCChannelMojoTest, MAYBE_ConnectedFromClient) { CreateChannel(&listener); listener.Init(sender()); ASSERT_TRUE(ConnectChannel()); + ASSERT_TRUE(StartClient()); - IPC::TestChannelListener::SendOneMessage(sender(), "hello from parent"); + IPC::TestChannelListener::SendOneMessage( + sender(), "hello from parent"); base::MessageLoop::current()->Run(); + EXPECT_TRUE(base::kNullProcessId != this->channel()->GetPeerPID()); - channel()->Close(); + this->channel()->Close(); EXPECT_TRUE(WaitForClientShutdown()); EXPECT_TRUE(listener.is_connected_called()); @@ -199,22 +181,28 @@ TEST_F(IPCChannelMojoTest, MAYBE_ConnectedFromClient) { } // A long running process that connects to us -DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(IPCChannelMojoTestClient, ChannelClient) { +MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoTestClient) { TestChannelListenerWithExtraExpectations listener; - Connect(&listener); - listener.Init(channel()); + ChannelClient client(&listener, "IPCChannelMojoTestClient"); + client.Connect(); + listener.Init(client.channel()); - IPC::TestChannelListener::SendOneMessage(channel(), "hello from child"); + IPC::TestChannelListener::SendOneMessage( + client.channel(), "hello from child"); base::MessageLoop::current()->Run(); EXPECT_TRUE(listener.is_connected_called()); EXPECT_TRUE(listener.HasSentAll()); - Close(); + client.Close(); + + return 0; } class ListenerExpectingErrors : public IPC::Listener { public: - ListenerExpectingErrors() : has_error_(false) {} + ListenerExpectingErrors() + : has_error_(false) { + } void OnChannelConnected(int32_t peer_pid) override { base::MessageLoop::current()->QuitWhenIdle(); @@ -233,11 +221,30 @@ class ListenerExpectingErrors : public IPC::Listener { bool has_error_; }; + +class IPCChannelMojoErrorTest : public IPCChannelMojoTestBase { + protected: + scoped_ptr<IPC::ChannelFactory> CreateChannelFactory( + const IPC::ChannelHandle& handle, + base::SequencedTaskRunner* runner) override { + return IPC::ChannelMojo::CreateServerFactory(task_runner(), handle); + } + + bool DidStartClient() override { + bool ok = IPCTestBase::DidStartClient(); + DCHECK(ok); + return ok; + } +}; + class ListenerThatQuits : public IPC::Listener { public: - ListenerThatQuits() {} + ListenerThatQuits() { + } - bool OnMessageReceived(const IPC::Message& message) override { return true; } + bool OnMessageReceived(const IPC::Message& message) override { + return true; + } void OnChannelConnected(int32_t peer_pid) override { base::MessageLoop::current()->QuitWhenIdle(); @@ -245,23 +252,26 @@ class ListenerThatQuits : public IPC::Listener { }; // A long running process that connects to us. -DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(IPCChannelMojoErraticTestClient, - ChannelClient) { +MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoErraticTestClient) { ListenerThatQuits listener; - Connect(&listener); + ChannelClient client(&listener, "IPCChannelMojoErraticTestClient"); + client.Connect(); base::MessageLoop::current()->Run(); - Close(); + client.Close(); + + return 0; } // Times out on Android; see http://crbug.com/502290 -#if defined(OS_ANDROID) +// Times out on Linux. crbug.com/585784 +#if defined(OS_ANDROID) || defined(OS_LINUX) #define MAYBE_SendFailWithPendingMessages DISABLED_SendFailWithPendingMessages #else #define MAYBE_SendFailWithPendingMessages SendFailWithPendingMessages #endif -TEST_F(IPCChannelMojoTest, MAYBE_SendFailWithPendingMessages) { +TEST_F(IPCChannelMojoErrorTest, MAYBE_SendFailWithPendingMessages) { InitWithMojo("IPCChannelMojoErraticTestClient"); // Set up IPC channel and start client. @@ -274,13 +284,14 @@ TEST_F(IPCChannelMojoTest, MAYBE_SendFailWithPendingMessages) { std::string overly_large_data(kMaxMessageNumBytes, '*'); // This messages are queued as pending. for (size_t i = 0; i < 10; ++i) { - IPC::TestChannelListener::SendOneMessage(sender(), - overly_large_data.c_str()); + IPC::TestChannelListener::SendOneMessage( + sender(), overly_large_data.c_str()); } + ASSERT_TRUE(StartClient()); base::MessageLoop::current()->Run(); - channel()->Close(); + this->channel()->Close(); EXPECT_TRUE(WaitForClientShutdown()); EXPECT_TRUE(listener.has_error()); @@ -326,9 +337,6 @@ class HandleSendingHelper { std::string content(GetSendingFileContent().size(), ' '); uint32_t num_bytes = static_cast<uint32_t>(content.size()); - ASSERT_EQ(MOJO_RESULT_OK, - mojo::Wait(pipe.get(), MOJO_HANDLE_SIGNAL_READABLE, - MOJO_DEADLINE_INDEFINITE, nullptr)); EXPECT_EQ(MOJO_RESULT_OK, mojo::ReadMessageRaw(pipe.get(), &content[0], &num_bytes, nullptr, nullptr, 0)); @@ -405,7 +413,8 @@ class ListenerThatExpectsMessagePipe : public IPC::Listener { }; // Times out on Android; see http://crbug.com/502290 -#if defined(OS_ANDROID) +// Times out on Linux. crbug.com/585784 +#if defined(OS_ANDROID) || defined(OS_LINUX) #define MAYBE_SendMessagePipe DISABLED_SendMessagePipe #else #define MAYBE_SendMessagePipe SendMessagePipe @@ -416,33 +425,34 @@ TEST_F(IPCChannelMojoTest, MAYBE_SendMessagePipe) { ListenerThatExpectsOK listener; CreateChannel(&listener); ASSERT_TRUE(ConnectChannel()); + ASSERT_TRUE(StartClient()); TestingMessagePipe pipe; HandleSendingHelper::WritePipeThenSend(channel(), &pipe); base::MessageLoop::current()->Run(); - channel()->Close(); + this->channel()->Close(); EXPECT_TRUE(WaitForClientShutdown()); DestroyChannel(); } -DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(IPCChannelMojoTestSendMessagePipeClient, - ChannelClient) { +MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoTestSendMessagePipeClient) { ListenerThatExpectsMessagePipe listener; - Connect(&listener); - listener.set_sender(channel()); + ChannelClient client(&listener, "IPCChannelMojoTestSendMessagePipeClient"); + client.Connect(); + listener.set_sender(client.channel()); base::MessageLoop::current()->Run(); - Close(); + client.Close(); + + return 0; } void ReadOK(mojo::MessagePipeHandle pipe) { std::string should_be_ok("xx"); uint32_t num_bytes = static_cast<uint32_t>(should_be_ok.size()); - CHECK_EQ(MOJO_RESULT_OK, mojo::Wait(pipe, MOJO_HANDLE_SIGNAL_READABLE, - MOJO_DEADLINE_INDEFINITE, nullptr)); CHECK_EQ(MOJO_RESULT_OK, mojo::ReadMessageRaw(pipe, &should_be_ok[0], &num_bytes, nullptr, nullptr, 0)); @@ -487,22 +497,22 @@ class ListenerThatExpectsMessagePipeUsingParamTrait : public IPC::Listener { bool receiving_valid_; }; -class ParamTraitMessagePipeClient : public ChannelClient { - public: - void RunTest(bool receiving_valid_handle) { - ListenerThatExpectsMessagePipeUsingParamTrait listener( - receiving_valid_handle); - Connect(&listener); - listener.set_sender(channel()); +void ParamTraitMessagePipeClient(bool receiving_valid_handle, + const char* channel_name) { + ListenerThatExpectsMessagePipeUsingParamTrait listener( + receiving_valid_handle); + ChannelClient client(&listener, channel_name); + client.Connect(); + listener.set_sender(client.channel()); - base::MessageLoop::current()->Run(); + base::MessageLoop::current()->Run(); - Close(); - } -}; + client.Close(); +} // Times out on Android; see http://crbug.com/502290 -#if defined(OS_ANDROID) +// Times out on Linux. crbug.com/585784 +#if defined(OS_ANDROID) || defined(OS_LINUX) #define MAYBE_ParamTraitValidMessagePipe DISABLED_ParamTraitValidMessagePipe #else #define MAYBE_ParamTraitValidMessagePipe ParamTraitValidMessagePipe @@ -513,6 +523,7 @@ TEST_F(IPCChannelMojoTest, MAYBE_ParamTraitValidMessagePipe) { ListenerThatExpectsOK listener; CreateChannel(&listener); ASSERT_TRUE(ConnectChannel()); + ASSERT_TRUE(StartClient()); TestingMessagePipe pipe; @@ -521,21 +532,22 @@ TEST_F(IPCChannelMojoTest, MAYBE_ParamTraitValidMessagePipe) { pipe.peer.release()); WriteOK(pipe.self.get()); - channel()->Send(message.release()); + this->channel()->Send(message.release()); base::MessageLoop::current()->Run(); - channel()->Close(); + this->channel()->Close(); EXPECT_TRUE(WaitForClientShutdown()); DestroyChannel(); } -DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(ParamTraitValidMessagePipeClient, - ParamTraitMessagePipeClient) { - RunTest(true); +MULTIPROCESS_IPC_TEST_CLIENT_MAIN(ParamTraitValidMessagePipeClient) { + ParamTraitMessagePipeClient(true, "ParamTraitValidMessagePipeClient"); + return 0; } // Times out on Android; see http://crbug.com/502290 -#if defined(OS_ANDROID) +// Times out on Linux. crbug.com/585784 +#if defined(OS_ANDROID) || defined(OS_LINUX) #define MAYBE_ParamTraitInvalidMessagePipe DISABLED_ParamTraitInvalidMessagePipe #else #define MAYBE_ParamTraitInvalidMessagePipe ParamTraitInvalidMessagePipe @@ -546,35 +558,43 @@ TEST_F(IPCChannelMojoTest, MAYBE_ParamTraitInvalidMessagePipe) { ListenerThatExpectsOK listener; CreateChannel(&listener); ASSERT_TRUE(ConnectChannel()); + ASSERT_TRUE(StartClient()); mojo::MessagePipeHandle invalid_handle; scoped_ptr<IPC::Message> message(new IPC::Message()); IPC::ParamTraits<mojo::MessagePipeHandle>::Write(message.get(), invalid_handle); - channel()->Send(message.release()); + this->channel()->Send(message.release()); base::MessageLoop::current()->Run(); - channel()->Close(); + this->channel()->Close(); EXPECT_TRUE(WaitForClientShutdown()); DestroyChannel(); } -DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(ParamTraitInvalidMessagePipeClient, - ParamTraitMessagePipeClient) { - RunTest(false); +MULTIPROCESS_IPC_TEST_CLIENT_MAIN(ParamTraitInvalidMessagePipeClient) { + ParamTraitMessagePipeClient(false, "ParamTraitInvalidMessagePipeClient"); + return 0; } -TEST_F(IPCChannelMojoTest, SendFailAfterClose) { +// Times out on Linux. crbug.com/585784 +#if defined(OS_LINUX) +#define MAYBE_SendFailAfterClose DISABLED_SendFailAfterClose +#else +#define MAYBE_SendFailAfterClose SendFailAfterClose +#endif +TEST_F(IPCChannelMojoTest, MAYBE_SendFailAfterClose) { InitWithMojo("IPCChannelMojoTestSendOkClient"); ListenerThatExpectsOK listener; CreateChannel(&listener); ASSERT_TRUE(ConnectChannel()); + ASSERT_TRUE(StartClient()); base::MessageLoop::current()->Run(); - channel()->Close(); - ASSERT_FALSE(channel()->Send(new IPC::Message())); + this->channel()->Close(); + ASSERT_FALSE(this->channel()->Send(new IPC::Message())); EXPECT_TRUE(WaitForClientShutdown()); DestroyChannel(); @@ -582,9 +602,12 @@ TEST_F(IPCChannelMojoTest, SendFailAfterClose) { class ListenerSendingOneOk : public IPC::Listener { public: - ListenerSendingOneOk() {} + ListenerSendingOneOk() { + } - bool OnMessageReceived(const IPC::Message& message) override { return true; } + bool OnMessageReceived(const IPC::Message& message) override { + return true; + } void OnChannelConnected(int32_t peer_pid) override { ListenerThatExpectsOK::SendOK(sender_); @@ -597,21 +620,86 @@ class ListenerSendingOneOk : public IPC::Listener { IPC::Sender* sender_; }; -DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(IPCChannelMojoTestSendOkClient, - ChannelClient) { +MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoTestSendOkClient) { ListenerSendingOneOk listener; - Connect(&listener); - listener.set_sender(channel()); + ChannelClient client(&listener, "IPCChannelMojoTestSendOkClient"); + client.Connect(); + listener.set_sender(client.channel()); + + base::MessageLoop::current()->Run(); + + client.Close(); + + return 0; +} + +#if defined(OS_WIN) +class IPCChannelMojoDeadHandleTest : public IPCChannelMojoTestBase { + protected: + scoped_ptr<IPC::ChannelFactory> CreateChannelFactory( + const IPC::ChannelHandle& handle, + base::SequencedTaskRunner* runner) override { + return IPC::ChannelMojo::CreateServerFactory(task_runner(), handle); + } + + bool DidStartClient() override { + IPCTestBase::DidStartClient(); + // const base::ProcessHandle client = client_process().Handle(); + // Forces GetFileHandleForProcess() fail. It happens occasionally + // in production, so we should exercise it somehow. + // TODO(morrita): figure out how to safely test this. See crbug.com/464109. + // ::CloseHandle(client); + return true; + } +}; + +// Times out on Linux. crbug.com/585784 +#if defined(OS_LINUX) +#define MAYBE_InvalidClientHandle DISABLED_InvalidClientHandle +#else +#define MAYBE_InvalidClientHandle InvalidClientHandle +#endif +TEST_F(IPCChannelMojoDeadHandleTest, MAYBE_InvalidClientHandle) { + // Any client type is fine as it is going to be killed anyway. + InitWithMojo("IPCChannelMojoTestDoNothingClient"); + + // Set up IPC channel and start client. + ListenerExpectingErrors listener; + CreateChannel(&listener); + ASSERT_TRUE(ConnectChannel()); + ASSERT_TRUE(StartClient()); base::MessageLoop::current()->Run(); - Close(); + this->channel()->Close(); + + // TODO(morrita): We need CloseHandle() call in DidStartClient(), + // which has been disabled since crrev.com/843113003, to + // make this fail. See crbug.com/464109. + // EXPECT_FALSE(WaitForClientShutdown()); + WaitForClientShutdown(); + EXPECT_TRUE(listener.has_error()); + + DestroyChannel(); +} + +MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoTestDoNothingClient) { + ListenerThatQuits listener; + ChannelClient client(&listener, "IPCChannelMojoTestDoNothingClient"); + client.Connect(); + + // Quits without running the message loop as this client won't + // receive any messages from the server. + + return 0; } +#endif #if defined(OS_POSIX) class ListenerThatExpectsFile : public IPC::Listener { public: - ListenerThatExpectsFile() : sender_(NULL) {} + ListenerThatExpectsFile() + : sender_(NULL) {} ~ListenerThatExpectsFile() override {} @@ -623,7 +711,9 @@ class ListenerThatExpectsFile : public IPC::Listener { return true; } - void OnChannelError() override { NOTREACHED(); } + void OnChannelError() override { + NOTREACHED(); + } void set_sender(IPC::Sender* sender) { sender_ = sender; } @@ -632,7 +722,8 @@ class ListenerThatExpectsFile : public IPC::Listener { }; // Times out on Android; see http://crbug.com/502290 -#if defined(OS_ANDROID) +// Times out on Linux. crbug.com/585784 +#if defined(OS_ANDROID) || defined(OS_LINUX) #define MAYBE_SendPlatformHandle DISABLED_SendPlatformHandle #else #define MAYBE_SendPlatformHandle SendPlatformHandle @@ -643,6 +734,7 @@ TEST_F(IPCChannelMojoTest, MAYBE_SendPlatformHandle) { ListenerThatExpectsOK listener; CreateChannel(&listener); ASSERT_TRUE(ConnectChannel()); + ASSERT_TRUE(StartClient()); base::File file(HandleSendingHelper::GetSendingFilePath(), base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE | @@ -650,21 +742,24 @@ TEST_F(IPCChannelMojoTest, MAYBE_SendPlatformHandle) { HandleSendingHelper::WriteFileThenSend(channel(), file); base::MessageLoop::current()->Run(); - channel()->Close(); + this->channel()->Close(); EXPECT_TRUE(WaitForClientShutdown()); DestroyChannel(); } -DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(IPCChannelMojoTestSendPlatformHandleClient, - ChannelClient) { +MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoTestSendPlatformHandleClient) { ListenerThatExpectsFile listener; - Connect(&listener); - listener.set_sender(channel()); + ChannelClient client( + &listener, "IPCChannelMojoTestSendPlatformHandleClient"); + client.Connect(); + listener.set_sender(client.channel()); base::MessageLoop::current()->Run(); - Close(); + client.Close(); + + return 0; } class ListenerThatExpectsFileAndPipe : public IPC::Listener { @@ -691,7 +786,8 @@ class ListenerThatExpectsFileAndPipe : public IPC::Listener { }; // Times out on Android; see http://crbug.com/502290 -#if defined(OS_ANDROID) +// Times out on Linux. crbug.com/585784 +#if defined(OS_ANDROID) || defined(OS_LINUX) #define MAYBE_SendPlatformHandleAndPipe DISABLED_SendPlatformHandleAndPipe #else #define MAYBE_SendPlatformHandleAndPipe SendPlatformHandleAndPipe @@ -702,6 +798,7 @@ TEST_F(IPCChannelMojoTest, MAYBE_SendPlatformHandleAndPipe) { ListenerThatExpectsOK listener; CreateChannel(&listener); ASSERT_TRUE(ConnectChannel()); + ASSERT_TRUE(StartClient()); base::File file(HandleSendingHelper::GetSendingFilePath(), base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE | @@ -710,22 +807,25 @@ TEST_F(IPCChannelMojoTest, MAYBE_SendPlatformHandleAndPipe) { HandleSendingHelper::WriteFileAndPipeThenSend(channel(), file, &pipe); base::MessageLoop::current()->Run(); - channel()->Close(); + this->channel()->Close(); EXPECT_TRUE(WaitForClientShutdown()); DestroyChannel(); } -DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT( - IPCChannelMojoTestSendPlatformHandleAndPipeClient, - ChannelClient) { +MULTIPROCESS_IPC_TEST_CLIENT_MAIN( + IPCChannelMojoTestSendPlatformHandleAndPipeClient) { ListenerThatExpectsFileAndPipe listener; - Connect(&listener); - listener.set_sender(channel()); + ChannelClient client(&listener, + "IPCChannelMojoTestSendPlatformHandleAndPipeClient"); + client.Connect(); + listener.set_sender(client.channel()); base::MessageLoop::current()->Run(); - Close(); + client.Close(); + + return 0; } #endif @@ -747,12 +847,19 @@ class ListenerThatVerifiesPeerPid : public IPC::Listener { } }; -TEST_F(IPCChannelMojoTest, VerifyGlobalPid) { +// Times out on Linux. crbug.com/585784 +#if defined(OS_LINUX) +#define MAYBE_VerifyGlobalPid DISABLED_VerifyGlobalPid +#else +#define MAYBE_VerifyGlobalPid VerifyGlobalPid +#endif +TEST_F(IPCChannelMojoTest, MAYBE_VerifyGlobalPid) { InitWithMojo("IPCChannelMojoTestVerifyGlobalPidClient"); ListenerThatVerifiesPeerPid listener; CreateChannel(&listener); ASSERT_TRUE(ConnectChannel()); + ASSERT_TRUE(StartClient()); base::MessageLoop::current()->Run(); channel()->Close(); @@ -761,17 +868,20 @@ TEST_F(IPCChannelMojoTest, VerifyGlobalPid) { DestroyChannel(); } -DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(IPCChannelMojoTestVerifyGlobalPidClient, - ChannelClient) { +MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoTestVerifyGlobalPidClient) { IPC::Channel::SetGlobalPid(kMagicChildId); ListenerThatQuits listener; - Connect(&listener); + ChannelClient client(&listener, + "IPCChannelMojoTestVerifyGlobalPidClient"); + client.Connect(); base::MessageLoop::current()->Run(); - Close(); + client.Close(); + + return 0; } -#endif // OS_LINUX +#endif // OS_LINUX } // namespace diff --git a/ipc/mojo/ipc_message_pipe_reader.cc b/ipc/mojo/ipc_message_pipe_reader.cc index 76e323b..ab5466e 100644 --- a/ipc/mojo/ipc_message_pipe_reader.cc +++ b/ipc/mojo/ipc_message_pipe_reader.cc @@ -21,10 +21,8 @@ namespace internal { MessagePipeReader::MessagePipeReader( mojom::ChannelAssociatedPtr sender, mojo::AssociatedInterfaceRequest<mojom::Channel> receiver, - base::ProcessId peer_pid, MessagePipeReader::Delegate* delegate) : delegate_(delegate), - peer_pid_(peer_pid), sender_(std::move(sender)), binding_(this, std::move(receiver)) { sender_.set_connection_error_handler( @@ -80,7 +78,6 @@ void MessagePipeReader::Receive(mojom::MessagePtr ipc_message) { ? "" : reinterpret_cast<const char*>(&ipc_message->data[0]), static_cast<uint32_t>(ipc_message->data.size())); - message.set_sender_pid(peer_pid_); DVLOG(4) << "Receive " << message.type() << ": " << message.size(); MojoResult write_result = ChannelMojo::WriteToMessageAttachmentSet( diff --git a/ipc/mojo/ipc_message_pipe_reader.h b/ipc/mojo/ipc_message_pipe_reader.h index 75fe7ad..38ca6a8 100644 --- a/ipc/mojo/ipc_message_pipe_reader.h +++ b/ipc/mojo/ipc_message_pipe_reader.h @@ -71,7 +71,6 @@ class MessagePipeReader : public mojom::Channel { // Note that MessagePipeReader doesn't delete |delegate|. MessagePipeReader(mojom::ChannelAssociatedPtr sender, mojo::AssociatedInterfaceRequest<mojom::Channel> receiver, - base::ProcessId peer_pid, Delegate* delegate); ~MessagePipeReader() override; @@ -85,8 +84,6 @@ class MessagePipeReader : public mojom::Channel { bool Send(scoped_ptr<Message> message); - base::ProcessId GetPeerPid() const { return peer_pid_; } - protected: void OnPipeClosed(); void OnPipeError(MojoResult error); @@ -96,7 +93,6 @@ class MessagePipeReader : public mojom::Channel { // |delegate_| is null once the message pipe is closed. Delegate* delegate_; - base::ProcessId peer_pid_; mojom::ChannelAssociatedPtr sender_; mojo::AssociatedBinding<mojom::Channel> binding_; base::ThreadChecker thread_checker_; diff --git a/ipc/mojo/ipc_mojo.gyp b/ipc/mojo/ipc_mojo.gyp index 75c85d9..cb22889 100644 --- a/ipc/mojo/ipc_mojo.gyp +++ b/ipc/mojo/ipc_mojo.gyp @@ -71,7 +71,10 @@ 'sources': [ 'run_all_unittests.cc', - "ipc_channel_mojo_unittest.cc", + # TODO(rockot): Re-enable these when we're ready to start using + # ChannelMojo again. They need to be updated to support multiprocess + # testing with the current Mojo EDK implementation. + #"ipc_channel_mojo_unittest.cc", 'ipc_mojo_bootstrap_unittest.cc', ], 'conditions': [ diff --git a/ipc/mojo/ipc_mojo_bootstrap.cc b/ipc/mojo/ipc_mojo_bootstrap.cc index a80b461..6ace754 100644 --- a/ipc/mojo/ipc_mojo_bootstrap.cc +++ b/ipc/mojo/ipc_mojo_bootstrap.cc @@ -45,7 +45,8 @@ MojoServerBootstrap::MojoServerBootstrap() = default; void MojoServerBootstrap::Connect() { DCHECK_EQ(state(), STATE_INITIALIZED); - bootstrap_.Bind(mojom::BootstrapPtrInfo(TakeHandle(), 0)); + bootstrap_.Bind( + mojom::BootstrapPtrInfo(mojo::edk::CreateParentMessagePipe(token()), 0)); bootstrap_.set_connection_error_handler( base::Bind(&MojoServerBootstrap::Fail, base::Unretained(this))); @@ -104,7 +105,7 @@ class MojoClientBootstrap : public MojoBootstrap, public mojom::Bootstrap { MojoClientBootstrap::MojoClientBootstrap() : binding_(this) {} void MojoClientBootstrap::Connect() { - binding_.Bind(TakeHandle()); + binding_.Bind(mojo::edk::CreateChildMessagePipe(token())); binding_.set_connection_error_handler( base::Bind(&MojoClientBootstrap::Fail, base::Unretained(this))); } @@ -125,17 +126,16 @@ void MojoClientBootstrap::Init(mojom::ChannelAssociatedRequest receive_channel, // MojoBootstrap // static -scoped_ptr<MojoBootstrap> MojoBootstrap::Create( - mojo::ScopedMessagePipeHandle handle, - Channel::Mode mode, - Delegate* delegate) { +scoped_ptr<MojoBootstrap> MojoBootstrap::Create(const std::string& token, + Channel::Mode mode, + Delegate* delegate) { CHECK(mode == Channel::MODE_CLIENT || mode == Channel::MODE_SERVER); scoped_ptr<MojoBootstrap> self = mode == Channel::MODE_CLIENT ? scoped_ptr<MojoBootstrap>(new MojoClientBootstrap()) : scoped_ptr<MojoBootstrap>(new MojoServerBootstrap()); - self->Init(std::move(handle), delegate); + self->Init(token, delegate); return self; } @@ -144,9 +144,8 @@ MojoBootstrap::MojoBootstrap() : delegate_(NULL), state_(STATE_INITIALIZED) { MojoBootstrap::~MojoBootstrap() {} -void MojoBootstrap::Init(mojo::ScopedMessagePipeHandle handle, - Delegate* delegate) { - handle_ = std::move(handle); +void MojoBootstrap::Init(const std::string& token, Delegate* delegate) { + token_ = token; delegate_ = delegate; } @@ -167,8 +166,4 @@ bool MojoBootstrap::HasFailed() const { return state() == STATE_ERROR; } -mojo::ScopedMessagePipeHandle MojoBootstrap::TakeHandle() { - return std::move(handle_); -} - } // namespace IPC diff --git a/ipc/mojo/ipc_mojo_bootstrap.h b/ipc/mojo/ipc_mojo_bootstrap.h index 23e0e91..4c97850 100644 --- a/ipc/mojo/ipc_mojo_bootstrap.h +++ b/ipc/mojo/ipc_mojo_bootstrap.h @@ -38,9 +38,9 @@ class IPC_MOJO_EXPORT MojoBootstrap { virtual void OnBootstrapError() = 0; }; - // Create the MojoBootstrap instance, using |handle| as the message pipe, in - // mode as specified by |mode|. The result is passed to |delegate|. - static scoped_ptr<MojoBootstrap> Create(mojo::ScopedMessagePipeHandle handle, + // Create the MojoBootstrap instance, using |token| to create the message + // pipe, in mode as specified by |mode|. The result is passed to |delegate|. + static scoped_ptr<MojoBootstrap> Create(const std::string& token, Channel::Mode mode, Delegate* delegate); @@ -66,12 +66,12 @@ class IPC_MOJO_EXPORT MojoBootstrap { State state() const { return state_; } void set_state(State state) { state_ = state; } - mojo::ScopedMessagePipeHandle TakeHandle(); + const std::string& token() { return token_; } private: - void Init(mojo::ScopedMessagePipeHandle, Delegate* delegate); + void Init(const std::string& token, Delegate* delegate); - mojo::ScopedMessagePipeHandle handle_; + std::string token_; Delegate* delegate_; State state_; diff --git a/ipc/mojo/ipc_mojo_bootstrap_unittest.cc b/ipc/mojo/ipc_mojo_bootstrap_unittest.cc index 66ccdea..efd2b80 100644 --- a/ipc/mojo/ipc_mojo_bootstrap_unittest.cc +++ b/ipc/mojo/ipc_mojo_bootstrap_unittest.cc @@ -57,6 +57,8 @@ void TestingDelegate::OnBootstrapError() { quit_callback_.Run(); } +const char kMojoChannelToken[] = "IPCMojoBootstrapTest token"; + // Times out on Android; see http://crbug.com/502290 #if defined(OS_ANDROID) #define MAYBE_Connect DISABLED_Connect @@ -67,10 +69,9 @@ TEST_F(IPCMojoBootstrapTest, MAYBE_Connect) { base::MessageLoop message_loop; base::RunLoop run_loop; TestingDelegate delegate(run_loop.QuitClosure()); - RUN_CHILD_ON_PIPE(IPCMojoBootstrapTestClient, pipe) scoped_ptr<IPC::MojoBootstrap> bootstrap = IPC::MojoBootstrap::Create( - mojo::MakeScopedHandle(mojo::MessagePipeHandle(pipe)), - IPC::Channel::MODE_SERVER, &delegate); + kMojoChannelToken, IPC::Channel::MODE_SERVER, &delegate); + RUN_CHILD_ON_PIPE(IPCMojoBootstrapTestClient, unused_pipe) bootstrap->Connect(); run_loop.Run(); @@ -91,14 +92,13 @@ namespace { // A long running process that connects to us. DEFINE_TEST_CLIENT_TEST_WITH_PIPE(IPCMojoBootstrapTestClient, - IPCMojoBootstrapTest, - pipe) { + IPCMojoBootstrapTest, + unused_pipe) { base::MessageLoop message_loop; base::RunLoop run_loop; TestingDelegate delegate(run_loop.QuitClosure()); scoped_ptr<IPC::MojoBootstrap> bootstrap = IPC::MojoBootstrap::Create( - mojo::MakeScopedHandle(mojo::MessagePipeHandle(pipe)), - IPC::Channel::MODE_CLIENT, &delegate); + kMojoChannelToken, IPC::Channel::MODE_CLIENT, &delegate); bootstrap->Connect(); diff --git a/ipc/mojo/ipc_mojo_handle_attachment.cc b/ipc/mojo/ipc_mojo_handle_attachment.cc index b2e16f1..ccce0d9 100644 --- a/ipc/mojo/ipc_mojo_handle_attachment.cc +++ b/ipc/mojo/ipc_mojo_handle_attachment.cc @@ -27,7 +27,8 @@ MessageAttachment::Type MojoHandleAttachment::GetType() const { base::PlatformFile MojoHandleAttachment::TakePlatformFile() { mojo::edk::ScopedPlatformHandle platform_handle; MojoResult unwrap_result = mojo::edk::PassWrappedPlatformHandle( - handle_.release().value(), &platform_handle); + handle_.get().value(), &platform_handle); + handle_.reset(); if (unwrap_result != MOJO_RESULT_OK) { LOG(ERROR) << "Pipe failed to covert handles. Closing: " << unwrap_result; return -1; diff --git a/ipc/mojo/ipc_mojo_perftest.cc b/ipc/mojo/ipc_mojo_perftest.cc index b1c6c86..92b79f8 100644 --- a/ipc/mojo/ipc_mojo_perftest.cc +++ b/ipc/mojo/ipc_mojo_perftest.cc @@ -17,22 +17,31 @@ namespace IPC { namespace { +const char kPerftestToken[] = "perftest-token"; + class MojoChannelPerfTest : public test::IPCChannelPerfTestBase { public: + MojoChannelPerfTest() { token_ = mojo::edk::GenerateRandomToken(); } + void TearDown() override { - ipc_support_.reset(); + { + base::AutoLock l(ipc_support_lock_); + ipc_support_.reset(); + } test::IPCChannelPerfTestBase::TearDown(); } scoped_ptr<ChannelFactory> CreateChannelFactory( const ChannelHandle& handle, base::SequencedTaskRunner* runner) override { - ipc_support_.reset(new mojo::edk::test::ScopedIPCSupport(io_task_runner())); - return ChannelMojo::CreateServerFactory( - helper_.StartChild("MojoPerfTestClient")); + EnsureIpcSupport(); + return ChannelMojo::CreateServerFactory(token_); } bool StartClient() override { + EnsureIpcSupport(); + helper_.StartChildWithExtraSwitch("MojoPerfTestClient", kPerftestToken, + token_); return true; } @@ -40,7 +49,17 @@ class MojoChannelPerfTest : public test::IPCChannelPerfTestBase { return helper_.WaitForChildTestShutdown(); } + void EnsureIpcSupport() { + base::AutoLock l(ipc_support_lock_); + if (!ipc_support_) { + ipc_support_.reset( + new mojo::edk::test::ScopedIPCSupport(io_task_runner())); + } + } + mojo::edk::test::MultiprocessTestHelper helper_; + std::string token_; + base::Lock ipc_support_lock_; scoped_ptr<mojo::edk::test::ScopedIPCSupport> ipc_support_; }; @@ -80,11 +99,8 @@ class MojoPerfTestClient : public test::PingPongTestClient { scoped_ptr<Channel> CreateChannel(Listener* listener) override; - int Run(MojoHandle handle); - private: mojo::edk::test::ScopedIPCSupport ipc_support_; - mojo::ScopedMessagePipeHandle handle_; }; MojoPerfTestClient::MojoPerfTestClient() @@ -93,19 +109,16 @@ MojoPerfTestClient::MojoPerfTestClient() } scoped_ptr<Channel> MojoPerfTestClient::CreateChannel(Listener* listener) { - return scoped_ptr<Channel>( - ChannelMojo::Create(std::move(handle_), Channel::MODE_CLIENT, listener)); -} - -int MojoPerfTestClient::Run(MojoHandle handle) { - handle_ = mojo::MakeScopedHandle(mojo::MessagePipeHandle(handle)); - return RunMain(); + return scoped_ptr<Channel>(ChannelMojo::Create( + base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( + kPerftestToken), + Channel::MODE_CLIENT, listener)); } MULTIPROCESS_TEST_MAIN(MojoPerfTestClientTestChildMain) { MojoPerfTestClient client; - int rv = mojo::edk::test::MultiprocessTestHelper::RunClientMain( - base::Bind(&MojoPerfTestClient::Run, base::Unretained(&client))); + + int rv = client.RunMain(); base::RunLoop run_loop; run_loop.RunUntilIdle(); |