From e6430e577f105ad8813c92e75c54660c4985026e Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Mon, 18 Sep 2017 14:34:04 +0200 Subject: BASELINE: Update Chromium to 61.0.3163.99 Change-Id: I8452f34574d88ca2b27af9bd56fc9ff3f16b1367 Reviewed-by: Alexandru Croitor --- chromium/ipc/BUILD.gn | 46 ++- chromium/ipc/DEPS | 6 +- chromium/ipc/OWNERS | 2 + chromium/ipc/README.md | 2 +- chromium/ipc/handle_attachment_fuchsia.cc | 43 ++ chromium/ipc/handle_attachment_fuchsia.h | 59 +++ chromium/ipc/handle_fuchsia.cc | 57 +++ chromium/ipc/handle_fuchsia.h | 61 +++ chromium/ipc/ipc.mojom | 1 + chromium/ipc/ipc_channel.cc | 2 +- chromium/ipc/ipc_channel_mojo_unittest.cc | 59 ++- chromium/ipc/ipc_channel_proxy.cc | 19 +- chromium/ipc/ipc_channel_proxy.h | 10 +- chromium/ipc/ipc_channel_proxy_unittest.cc | 24 +- chromium/ipc/ipc_channel_proxy_unittest_messages.h | 6 +- chromium/ipc/ipc_descriptors.h | 15 - chromium/ipc/ipc_fuzzing_tests.cc | 14 + chromium/ipc/ipc_message.cc | 2 +- chromium/ipc/ipc_message_attachment_set.cc | 1 + chromium/ipc/ipc_message_pipe_reader.h | 2 +- chromium/ipc/ipc_message_protobuf_utils.h | 72 ++++ .../ipc/ipc_message_protobuf_utils_unittest.cc | 193 +++++++++ chromium/ipc/ipc_message_start.h | 2 - chromium/ipc/ipc_message_unittest.cc | 17 +- chromium/ipc/ipc_message_utils.cc | 13 +- chromium/ipc/ipc_message_utils.h | 166 ++------ chromium/ipc/ipc_mojo_bootstrap.cc | 41 +- chromium/ipc/ipc_mojo_perftest.cc | 435 ++++++++++----------- chromium/ipc/ipc_param_traits.h | 11 + chromium/ipc/ipc_sync_channel.cc | 22 +- chromium/ipc/ipc_sync_channel_unittest.cc | 45 ++- chromium/ipc/ipc_sync_message.cc | 2 +- chromium/ipc/ipc_sync_message_filter.cc | 11 +- chromium/ipc/ipc_test.mojom | 2 + chromium/ipc/test_proto.proto | 20 + 35 files changed, 975 insertions(+), 508 deletions(-) create mode 100644 chromium/ipc/handle_attachment_fuchsia.cc create mode 100644 chromium/ipc/handle_attachment_fuchsia.h create mode 100644 chromium/ipc/handle_fuchsia.cc create mode 100644 chromium/ipc/handle_fuchsia.h delete mode 100644 chromium/ipc/ipc_descriptors.h create mode 100644 chromium/ipc/ipc_message_protobuf_utils.h create mode 100644 chromium/ipc/ipc_message_protobuf_utils_unittest.cc create mode 100644 chromium/ipc/test_proto.proto (limited to 'chromium/ipc') diff --git a/chromium/ipc/BUILD.gn b/chromium/ipc/BUILD.gn index a3aaaa3e990..5c2e20959df 100644 --- a/chromium/ipc/BUILD.gn +++ b/chromium/ipc/BUILD.gn @@ -7,6 +7,7 @@ import("//build/config/nacl/config.gni") import("//mojo/public/tools/bindings/mojom.gni") import("//testing/test.gni") import("//tools/ipc_fuzzer/ipc_fuzzer.gni") +import("//third_party/protobuf/proto_library.gni") declare_args() { # Enabling debug builds automatically sets enable_ipc_logging to true. @@ -40,7 +41,6 @@ component("ipc") { "ipc_channel_proxy.h", "ipc_channel_reader.cc", "ipc_channel_reader.h", - "ipc_descriptors.h", "ipc_export.h", "ipc_listener.h", "ipc_logging.cc", @@ -105,6 +105,15 @@ component("ipc") { ] } + if (is_fuchsia) { + sources += [ + "handle_attachment_fuchsia.cc", + "handle_attachment_fuchsia.h", + "handle_fuchsia.cc", + "handle_fuchsia.h", + ] + } + defines = [ "IPC_IMPLEMENTATION" ] public_deps = [ @@ -114,6 +123,17 @@ component("ipc") { "//mojo/public/cpp/bindings", "//mojo/public/cpp/system", ] + + if (!is_nacl_nonsfi) { + sources += [ + "ipc_message_protobuf_utils.h", + ] + + public_deps += [ + "//third_party/protobuf:protobuf_lite", + ] + } + deps = [ "//base", ] @@ -142,9 +162,7 @@ mojom("test_interfaces") { sources = [ "ipc_test.mojom", ] - - # TODO(crbug.com/714018): Convert the implementation to use OnceCallback. - use_once_callback = false + support_lazy_serialization = true } # This is provided as a separate target so other targets can provide param @@ -171,6 +189,12 @@ if (!is_ios) { ] } + proto_library("test_proto") { + sources = [ + "test_proto.proto", + ] + } + test("ipc_tests") { sources = [ "ipc_channel_mojo_unittest.cc", @@ -198,6 +222,7 @@ if (!is_ios) { ":ipc", ":run_all_unittests", ":test_interfaces", + ":test_proto", ":test_support", "//base", "//base:i18n", @@ -211,6 +236,19 @@ if (!is_ios) { if (is_mac) { deps += [ "//sandbox/mac:seatbelt" ] } + + if (is_fuchsia) { + sources -= [ + # No AF_UNIX domain sockets on Fuchsia. + "sync_socket_unittest.cc", + ] + } + + if (!is_nacl_nonsfi) { + sources += [ + "ipc_message_protobuf_utils_unittest.cc", + ] + } } test("ipc_perftests") { diff --git a/chromium/ipc/DEPS b/chromium/ipc/DEPS index 5f929e98738..f8d30bb7b47 100644 --- a/chromium/ipc/DEPS +++ b/chromium/ipc/DEPS @@ -20,5 +20,9 @@ specific_include_rules = { "run_all_(unit|perf)tests\.cc": [ "+mojo/edk/embedder", "+mojo/edk/test", - ] + ], + "ipc_message_protobuf_utils\.h": [ + # Support serializing RepeatedField / RepeatedPtrField: + "+third_party/protobuf/src/google/protobuf/repeated_field.h", + ], } diff --git a/chromium/ipc/OWNERS b/chromium/ipc/OWNERS index b8baa34ff13..0617e7bf9d3 100644 --- a/chromium/ipc/OWNERS +++ b/chromium/ipc/OWNERS @@ -8,6 +8,8 @@ tsepez@chromium.org # new sandbox escapes. per-file ipc_message_start.h=set noparent per-file ipc_message_start.h=file://ipc/SECURITY_OWNERS +per-file *_messages*.h=set noparent +per-file *_messages*.h=file://ipc/SECURITY_OWNERS per-file *.mojom=set noparent per-file *.mojom=file://ipc/SECURITY_OWNERS per-file *_param_traits*.*=set noparent diff --git a/chromium/ipc/README.md b/chromium/ipc/README.md index 2b1f9f20b14..be5624dca39 100644 --- a/chromium/ipc/README.md +++ b/chromium/ipc/README.md @@ -604,7 +604,7 @@ and add a typemap like [url_request.typemap](https://cs.chromium.org/chromium/sr to define the mapping: ``` -mojom = "//content/common/url_loader.mojom" +mojom = "//content/public/common/url_loader.mojom" public_headers = [ "//content/common/resource_request.h" ] traits_headers = [ "//content/common/resource_messages.h" ] ... diff --git a/chromium/ipc/handle_attachment_fuchsia.cc b/chromium/ipc/handle_attachment_fuchsia.cc new file mode 100644 index 00000000000..2778002b1ae --- /dev/null +++ b/chromium/ipc/handle_attachment_fuchsia.cc @@ -0,0 +1,43 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ipc/handle_attachment_fuchsia.h" + +#include +#include + +namespace IPC { +namespace internal { + +HandleAttachmentFuchsia::HandleAttachmentFuchsia( + const mx_handle_t& handle, + HandleFuchsia::Permissions permissions) + : handle_(MX_HANDLE_INVALID), + permissions_(HandleFuchsia::INVALID), + owns_handle_(true) { + mx_handle_t duplicated_handle; + if (mx_handle_duplicate(handle, MX_RIGHT_SAME_RIGHTS, &duplicated_handle) == + MX_OK) { + handle_ = duplicated_handle; + permissions_ = permissions; + } +} + +HandleAttachmentFuchsia::HandleAttachmentFuchsia(const mx_handle_t& handle, + FromWire from_wire) + : handle_(handle), + permissions_(HandleFuchsia::INVALID), + owns_handle_(true) {} + +HandleAttachmentFuchsia::~HandleAttachmentFuchsia() { + if (handle_ != MX_HANDLE_INVALID && owns_handle_) + mx_handle_close(handle_); +} + +MessageAttachment::Type HandleAttachmentFuchsia::GetType() const { + return Type::FUCHSIA_HANDLE; +} + +} // namespace internal +} // namespace IPC diff --git a/chromium/ipc/handle_attachment_fuchsia.h b/chromium/ipc/handle_attachment_fuchsia.h new file mode 100644 index 00000000000..a01c8028174 --- /dev/null +++ b/chromium/ipc/handle_attachment_fuchsia.h @@ -0,0 +1,59 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IPC_HANDLE_ATTACHMENT_FUCHSIA_H_ +#define IPC_HANDLE_ATTACHMENT_FUCHSIA_H_ + +#include + +#include "base/process/process_handle.h" +#include "ipc/handle_fuchsia.h" +#include "ipc/ipc_export.h" +#include "ipc/ipc_message_attachment.h" + +namespace IPC { +namespace internal { + +// This class represents a Fuchsia mx_handle_t attached to a Chrome IPC message. +class IPC_EXPORT HandleAttachmentFuchsia : public MessageAttachment { + public: + // This constructor makes a copy of |handle| and takes ownership of the + // result. Should only be called by the sender of a Chrome IPC message. + HandleAttachmentFuchsia(const mx_handle_t& handle, + HandleFuchsia::Permissions permissions); + + enum FromWire { + FROM_WIRE, + }; + // This constructor takes ownership of |handle|. Should only be called by the + // receiver of a Chrome IPC message. + HandleAttachmentFuchsia(const mx_handle_t& handle, FromWire from_wire); + + Type GetType() const override; + + mx_handle_t get_handle() const { return handle_; } + + // The caller of this method has taken ownership of |handle_|. + void reset_handle_ownership() { + owns_handle_ = false; + handle_ = MX_HANDLE_INVALID; + } + + private: + ~HandleAttachmentFuchsia() override; + mx_handle_t handle_; + HandleFuchsia::Permissions permissions_; + + // In the sender process, the attachment owns the mx_handle_t of a newly + // created message. The attachment broker will eventually take ownership, and + // set this member to |false|. In the destination process, the attachment owns + // the handle until a call to ParamTraits::Read() takes + // ownership. + bool owns_handle_; +}; + +} // namespace internal +} // namespace IPC + +#endif // IPC_HANDLE_ATTACHMENT_FUCHSIA_H_ diff --git a/chromium/ipc/handle_fuchsia.cc b/chromium/ipc/handle_fuchsia.cc new file mode 100644 index 00000000000..8b3cc5154d3 --- /dev/null +++ b/chromium/ipc/handle_fuchsia.cc @@ -0,0 +1,57 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ipc/handle_fuchsia.h" + +#include + +#include "base/logging.h" +#include "base/memory/ref_counted.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/stringprintf.h" +#include "ipc/handle_attachment_fuchsia.h" +#include "ipc/ipc_message.h" + +namespace IPC { + +HandleFuchsia::HandleFuchsia() + : handle_(MX_HANDLE_INVALID), permissions_(INVALID) {} + +HandleFuchsia::HandleFuchsia(const mx_handle_t& handle, Permissions permissions) + : handle_(handle), permissions_(permissions) {} + +// static +void ParamTraits::Write(base::Pickle* m, const param_type& p) { + scoped_refptr attachment( + new IPC::internal::HandleAttachmentFuchsia(p.get_handle(), + p.get_permissions())); + if (!m->WriteAttachment(std::move(attachment))) + NOTREACHED(); +} + +// static +bool ParamTraits::Read(const base::Pickle* m, + base::PickleIterator* iter, + param_type* r) { + scoped_refptr base_attachment; + if (!m->ReadAttachment(iter, &base_attachment)) + return false; + MessageAttachment* attachment = + static_cast(base_attachment.get()); + if (attachment->GetType() != MessageAttachment::Type::FUCHSIA_HANDLE) + return false; + IPC::internal::HandleAttachmentFuchsia* handle_attachment = + static_cast(attachment); + r->set_handle(handle_attachment->get_handle()); + handle_attachment->reset_handle_ownership(); + return true; +} + +// static +void ParamTraits::Log(const param_type& p, std::string* l) { + l->append(base::StringPrintf("0x%x", p.get_handle())); + l->append(base::IntToString(p.get_permissions())); +} + +} // namespace IPC diff --git a/chromium/ipc/handle_fuchsia.h b/chromium/ipc/handle_fuchsia.h new file mode 100644 index 00000000000..2ff6b53927d --- /dev/null +++ b/chromium/ipc/handle_fuchsia.h @@ -0,0 +1,61 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IPC_HANDLE_FUCHSIA_H_ +#define IPC_HANDLE_FUCHSIA_H_ + +#include + +#include + +#include "ipc/ipc_export.h" +#include "ipc/ipc_param_traits.h" + +namespace base { +class Pickle; +class PickleIterator; +} // namespace base + +namespace IPC { + +class IPC_EXPORT HandleFuchsia { + public: + enum Permissions { + // A placeholder value to be used by the receiving IPC channel, since the + // permissions information is only used by the broker process. + INVALID, + // The new mx_handle_t will have the same permissions as the old + // mx_handle_t. + DUPLICATE, + // The new mx_handle_t will have file read and write permissions. + FILE_READ_WRITE, + MAX_PERMISSIONS = FILE_READ_WRITE + }; + + // Default constructor makes an invalid mx_handle_t. + HandleFuchsia(); + HandleFuchsia(const mx_handle_t& handle, Permissions permissions); + + mx_handle_t get_handle() const { return handle_; } + void set_handle(mx_handle_t handle) { handle_ = handle; } + Permissions get_permissions() const { return permissions_; } + + private: + mx_handle_t handle_; + Permissions permissions_; +}; + +template <> +struct IPC_EXPORT ParamTraits { + typedef HandleFuchsia param_type; + static void Write(base::Pickle* m, const param_type& p); + static bool Read(const base::Pickle* m, + base::PickleIterator* iter, + param_type* p); + static void Log(const param_type& p, std::string* l); +}; + +} // namespace IPC + +#endif // IPC_HANDLE_FUCHSIA_H_ diff --git a/chromium/ipc/ipc.mojom b/chromium/ipc/ipc.mojom index 0a4fcfa84e6..f986c470d58 100644 --- a/chromium/ipc/ipc.mojom +++ b/chromium/ipc/ipc.mojom @@ -15,6 +15,7 @@ struct SerializedHandle { PLATFORM_FILE, WIN_HANDLE, MACH_PORT, + FUCHSIA_HANDLE, }; Type type; diff --git a/chromium/ipc/ipc_channel.cc b/chromium/ipc/ipc_channel.cc index 2d510478cc3..177b967601b 100644 --- a/chromium/ipc/ipc_channel.cc +++ b/chromium/ipc/ipc_channel.cc @@ -17,7 +17,7 @@ namespace { // Global atomic used to guarantee channel IDs are unique. -base::StaticAtomicSequenceNumber g_last_id; +base::AtomicSequenceNumber g_last_id; } // namespace diff --git a/chromium/ipc/ipc_channel_mojo_unittest.cc b/chromium/ipc/ipc_channel_mojo_unittest.cc index f3499b794c1..f0fc0c307ef 100644 --- a/chromium/ipc/ipc_channel_mojo_unittest.cc +++ b/chromium/ipc/ipc_channel_mojo_unittest.cc @@ -244,15 +244,14 @@ class HandleSendingHelper { mojo::ScopedMessagePipeHandle pipe; EXPECT_TRUE( IPC::MojoMessageHelper::ReadMessagePipeFrom(&message, iter, &pipe)); - std::string content(GetSendingFileContent().size(), ' '); + std::vector content; - uint32_t num_bytes = static_cast(content.size()); ASSERT_EQ(MOJO_RESULT_OK, mojo::Wait(pipe.get(), MOJO_HANDLE_SIGNAL_READABLE)); EXPECT_EQ(MOJO_RESULT_OK, - mojo::ReadMessageRaw(pipe.get(), &content[0], &num_bytes, nullptr, - nullptr, 0)); - EXPECT_EQ(content, GetSendingFileContent()); + mojo::ReadMessageRaw(pipe.get(), &content, nullptr, 0)); + EXPECT_EQ(std::string(content.begin(), content.end()), + GetSendingFileContent()); } #if defined(OS_POSIX) @@ -354,13 +353,11 @@ DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(IPCChannelMojoTestSendMessagePipeClient) { } void ReadOK(mojo::MessagePipeHandle pipe) { - std::string should_be_ok("xx"); - uint32_t num_bytes = static_cast(should_be_ok.size()); + std::vector should_be_ok; CHECK_EQ(MOJO_RESULT_OK, mojo::Wait(pipe, MOJO_HANDLE_SIGNAL_READABLE)); CHECK_EQ(MOJO_RESULT_OK, - mojo::ReadMessageRaw(pipe, &should_be_ok[0], &num_bytes, nullptr, - nullptr, 0)); - EXPECT_EQ(should_be_ok, std::string("OK")); + mojo::ReadMessageRaw(pipe, &should_be_ok, nullptr, 0)); + EXPECT_EQ("OK", std::string(should_be_ok.begin(), should_be_ok.end())); } void WriteOK(mojo::MessagePipeHandle pipe) { @@ -548,18 +545,16 @@ class ListenerWithSimpleAssociatedInterface next_expected_value_ = value; } - void GetExpectedValue(const GetExpectedValueCallback& callback) override { + void GetExpectedValue(GetExpectedValueCallback callback) override { NOTREACHED(); } - void RequestValue(const RequestValueCallback& callback) override { - NOTREACHED(); - } + void RequestValue(RequestValueCallback callback) override { NOTREACHED(); } - void RequestQuit(const RequestQuitCallback& callback) override { + void RequestQuit(RequestQuitCallback callback) override { EXPECT_EQ(kNumMessages, num_messages_received_); received_quit_ = true; - callback.Run(); + std::move(callback).Run(); base::MessageLoop::current()->QuitWhenIdle(); } @@ -738,17 +733,15 @@ class ListenerWithSimpleProxyAssociatedInterface next_expected_value_ = value; } - void GetExpectedValue(const GetExpectedValueCallback& callback) override { - callback.Run(next_expected_value_); + void GetExpectedValue(GetExpectedValueCallback callback) override { + std::move(callback).Run(next_expected_value_); } - void RequestValue(const RequestValueCallback& callback) override { - NOTREACHED(); - } + void RequestValue(RequestValueCallback callback) override { NOTREACHED(); } - void RequestQuit(const RequestQuitCallback& callback) override { + void RequestQuit(RequestQuitCallback callback) override { received_quit_ = true; - callback.Run(); + std::move(callback).Run(); binding_.Close(); base::MessageLoop::current()->QuitWhenIdle(); } @@ -871,8 +864,8 @@ class ListenerWithIndirectProxyAssociatedInterface } // IPC::mojom::PingReceiver: - void Ping(const PingCallback& callback) override { - callback.Run(); + void Ping(PingCallback callback) override { + std::move(callback).Run(); ping_handler_.Run(); } @@ -953,17 +946,17 @@ class ListenerWithSyncAssociatedInterface next_expected_value_ = value; } - void GetExpectedValue(const GetExpectedValueCallback& callback) override { - callback.Run(next_expected_value_); + void GetExpectedValue(GetExpectedValueCallback callback) override { + std::move(callback).Run(next_expected_value_); } - void RequestValue(const RequestValueCallback& callback) override { - callback.Run(response_value_); + void RequestValue(RequestValueCallback callback) override { + std::move(callback).Run(response_value_); } - void RequestQuit(const RequestQuitCallback& callback) override { + void RequestQuit(RequestQuitCallback callback) override { quit_closure_.Run(); - callback.Run(); + std::move(callback).Run(); } // IPC::Listener: @@ -1080,7 +1073,7 @@ class SimpleTestClientImpl : public IPC::mojom::SimpleTestClient, private: // IPC::mojom::SimpleTestClient: - void RequestValue(const RequestValueCallback& callback) override { + void RequestValue(RequestValueCallback callback) override { int32_t response = 0; if (use_sync_sender_) { std::unique_ptr reply(new IPC::SyncMessage( @@ -1091,7 +1084,7 @@ class SimpleTestClientImpl : public IPC::mojom::SimpleTestClient, EXPECT_TRUE(driver_->RequestValue(&response)); } - callback.Run(response); + std::move(callback).Run(response); DCHECK(run_loop_); run_loop_->Quit(); diff --git a/chromium/ipc/ipc_channel_proxy.cc b/chromium/ipc/ipc_channel_proxy.cc index 616a99404cc..f48e44ce2c0 100644 --- a/chromium/ipc/ipc_channel_proxy.cc +++ b/chromium/ipc/ipc_channel_proxy.cc @@ -439,7 +439,7 @@ ChannelProxy::ChannelProxy( } ChannelProxy::~ChannelProxy() { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); Close(); } @@ -463,7 +463,7 @@ void ChannelProxy::Init(const IPC::ChannelHandle& channel_handle, void ChannelProxy::Init(std::unique_ptr factory, bool create_pipe_now) { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(!did_init_); if (create_pipe_now) { @@ -503,7 +503,7 @@ void ChannelProxy::Flush() { } void ChannelProxy::Close() { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); // Clear the backpointer to the listener so that any pending calls to // Context::OnDispatchMessage or OnDispatchError will be ignored. It is @@ -517,6 +517,12 @@ void ChannelProxy::Close() { } bool ChannelProxy::Send(Message* message) { + DCHECK(!message->is_sync()) << "Need to use IPC::SyncChannel"; + SendInternal(message); + return true; +} + +void ChannelProxy::SendInternal(Message* message) { DCHECK(did_init_); // TODO(alexeypa): add DCHECK(CalledOnValidThread()) here. Currently there are @@ -535,17 +541,16 @@ bool ChannelProxy::Send(Message* message) { #endif context_->Send(message); - return true; } void ChannelProxy::AddFilter(MessageFilter* filter) { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); context_->AddFilter(filter); } void ChannelProxy::RemoveFilter(MessageFilter* filter) { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); context_->ipc_task_runner()->PostTask( FROM_HERE, base::Bind(&Context::OnRemoveFilter, context_, @@ -567,7 +572,7 @@ void ChannelProxy::GetGenericRemoteAssociatedInterface( } void ChannelProxy::ClearIPCTaskRunner() { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); context()->ClearIPCTaskRunner(); } diff --git a/chromium/ipc/ipc_channel_proxy.h b/chromium/ipc/ipc_channel_proxy.h index 2825226e9c7..f95e4dde1e0 100644 --- a/chromium/ipc/ipc_channel_proxy.h +++ b/chromium/ipc/ipc_channel_proxy.h @@ -14,8 +14,8 @@ #include "base/callback.h" #include "base/memory/ref_counted.h" +#include "base/sequence_checker.h" #include "base/synchronization/lock.h" -#include "base/threading/non_thread_safe.h" #include "build/build_config.h" #include "ipc/ipc_channel.h" #include "ipc/ipc_channel_handle.h" @@ -72,7 +72,7 @@ class MessageFilterRouter; // |channel_lifetime_lock_| is used to protect it. The locking overhead is only // paid if the underlying channel supports thread-safe |Send|. // -class IPC_EXPORT ChannelProxy : public Sender, public base::NonThreadSafe { +class IPC_EXPORT ChannelProxy : public Sender { public: #if defined(ENABLE_IPC_FUZZER) // Interface for a filter to be imposed on outgoing messages which can @@ -377,9 +377,11 @@ class IPC_EXPORT ChannelProxy : public Sender, public base::NonThreadSafe { } #endif - protected: bool did_init() const { return did_init_; } + // A Send() which doesn't DCHECK if the message is synchronous. + void SendInternal(Message* message); + private: friend class IpcSecurityTestUtil; @@ -404,6 +406,8 @@ class IPC_EXPORT ChannelProxy : public Sender, public base::NonThreadSafe { #if defined(ENABLE_IPC_FUZZER) OutgoingMessageFilter* outgoing_message_filter_; #endif + + SEQUENCE_CHECKER(sequence_checker_); }; } // namespace IPC diff --git a/chromium/ipc/ipc_channel_proxy_unittest.cc b/chromium/ipc/ipc_channel_proxy_unittest.cc index f0590999e82..01b895582cb 100644 --- a/chromium/ipc/ipc_channel_proxy_unittest.cc +++ b/chromium/ipc/ipc_channel_proxy_unittest.cc @@ -90,7 +90,7 @@ class ChannelReflectorListener : public IPC::Listener { IPC_BEGIN_MESSAGE_MAP(ChannelReflectorListener, message) IPC_MESSAGE_HANDLER(TestMsg_Bounce, OnTestBounce) IPC_MESSAGE_HANDLER(TestMsg_SendBadMessage, OnSendBadMessage) - IPC_MESSAGE_HANDLER(UtilityMsg_Bounce, OnUtilityBounce) + IPC_MESSAGE_HANDLER(AutomationMsg_Bounce, OnAutomationBounce) IPC_MESSAGE_HANDLER(WorkerMsg_Bounce, OnBounce) IPC_MESSAGE_HANDLER(WorkerMsg_Quit, OnQuit) IPC_END_MESSAGE_MAP() @@ -105,9 +105,7 @@ class ChannelReflectorListener : public IPC::Listener { channel_->Send(new TestMsg_BadMessage(BadType())); } - void OnUtilityBounce() { - channel_->Send(new UtilityMsg_Bounce()); - } + void OnAutomationBounce() { channel_->Send(new AutomationMsg_Bounce()); } void OnBounce() { channel_->Send(new WorkerMsg_Bounce()); @@ -282,17 +280,17 @@ class IPCChannelProxyTest : public IPCChannelMojoTestBase { TEST_F(IPCChannelProxyTest, MessageClassFilters) { // Construct a filter per message class. - std::vector > class_filters; - class_filters.push_back(make_scoped_refptr( - new MessageCountFilter(TestMsgStart))); - class_filters.push_back(make_scoped_refptr( - new MessageCountFilter(UtilityMsgStart))); + std::vector> class_filters; + class_filters.push_back( + make_scoped_refptr(new MessageCountFilter(TestMsgStart))); + class_filters.push_back( + make_scoped_refptr(new MessageCountFilter(AutomationMsgStart))); for (size_t i = 0; i < class_filters.size(); ++i) channel_proxy()->AddFilter(class_filters[i].get()); // Send a message for each class; each filter should receive just one message. - sender()->Send(new TestMsg_Bounce()); - sender()->Send(new UtilityMsg_Bounce()); + sender()->Send(new TestMsg_Bounce); + sender()->Send(new AutomationMsg_Bounce); // Send some messages not assigned to a specific or valid message class. sender()->Send(new WorkerMsg_Bounce); @@ -320,7 +318,7 @@ TEST_F(IPCChannelProxyTest, GlobalAndMessageClassFilters) { sender()->Send(new TestMsg_Bounce); // A message of a different class should be seen only by the global filter. - sender()->Send(new UtilityMsg_Bounce); + sender()->Send(new AutomationMsg_Bounce); // Flush all messages. SendQuitMessageAndWaitForIdle(); @@ -347,7 +345,7 @@ TEST_F(IPCChannelProxyTest, FilterRemoval) { // Send some messages; they should not be seen by either filter. sender()->Send(new TestMsg_Bounce); - sender()->Send(new UtilityMsg_Bounce); + sender()->Send(new AutomationMsg_Bounce); // Ensure that the filters were removed and did not receive any messages. SendQuitMessageAndWaitForIdle(); diff --git a/chromium/ipc/ipc_channel_proxy_unittest_messages.h b/chromium/ipc/ipc_channel_proxy_unittest_messages.h index 288ce5353d3..ae4505982b7 100644 --- a/chromium/ipc/ipc_channel_proxy_unittest_messages.h +++ b/chromium/ipc/ipc_channel_proxy_unittest_messages.h @@ -30,15 +30,15 @@ struct ParamTraits { #endif // IPC_CHANNEL_PROXY_UNITTEST_MESSAGES_H_ - +#undef IPC_MESSAGE_START #define IPC_MESSAGE_START TestMsgStart IPC_MESSAGE_CONTROL0(TestMsg_Bounce) IPC_MESSAGE_CONTROL0(TestMsg_SendBadMessage) IPC_MESSAGE_CONTROL1(TestMsg_BadMessage, BadType) #undef IPC_MESSAGE_START -#define IPC_MESSAGE_START UtilityMsgStart -IPC_MESSAGE_CONTROL0(UtilityMsg_Bounce) +#define IPC_MESSAGE_START AutomationMsgStart +IPC_MESSAGE_CONTROL0(AutomationMsg_Bounce) #undef IPC_MESSAGE_START #define IPC_MESSAGE_START WorkerMsgStart diff --git a/chromium/ipc/ipc_descriptors.h b/chromium/ipc/ipc_descriptors.h deleted file mode 100644 index 7a4a7b19a5c..00000000000 --- a/chromium/ipc/ipc_descriptors.h +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef IPC_IPC_DESCRIPTORS_H_ -#define IPC_IPC_DESCRIPTORS_H_ - -// This is a list of global descriptor keys to be used with the -// base::GlobalDescriptors object (see base/posix/global_descriptors.h) -enum { - // The first key that can be use to register descriptors. - kIPCDescriptorMax = 0 -}; - -#endif // IPC_IPC_DESCRIPTORS_H_ diff --git a/chromium/ipc/ipc_fuzzing_tests.cc b/chromium/ipc/ipc_fuzzing_tests.cc index 8e385bc34fe..5744135c56a 100644 --- a/chromium/ipc/ipc_fuzzing_tests.cc +++ b/chromium/ipc/ipc_fuzzing_tests.cc @@ -126,6 +126,20 @@ TEST(IPCMessageIntegrity, ReadVectorTooLarge2) { EXPECT_FALSE(ReadParam(&m, &iter, &vec)); } +// This test needs ~20 seconds in Debug mode, or ~4 seconds in Release mode. +// See http://crbug.com/741866 for details. +TEST(IPCMessageIntegrity, DISABLED_ReadVectorTooLarge3) { + base::Pickle pickle; + IPC::WriteParam(&pickle, 256 * 1024 * 1024); + IPC::WriteParam(&pickle, 0); + IPC::WriteParam(&pickle, 1); + IPC::WriteParam(&pickle, 2); + + base::PickleIterator iter(pickle); + std::vector vec; + EXPECT_FALSE(IPC::ReadParam(&pickle, &iter, &vec)); +} + class SimpleListener : public IPC::Listener { public: SimpleListener() : other_(NULL) { diff --git a/chromium/ipc/ipc_message.cc b/chromium/ipc/ipc_message.cc index f66b4fe882c..8f408eaf51f 100644 --- a/chromium/ipc/ipc_message.cc +++ b/chromium/ipc/ipc_message.cc @@ -21,7 +21,7 @@ namespace { -base::StaticAtomicSequenceNumber g_ref_num; +base::AtomicSequenceNumber g_ref_num; // Create a reference number for identifying IPC messages in traces. The return // values has the reference number stored in the upper 24 bits, leaving the low diff --git a/chromium/ipc/ipc_message_attachment_set.cc b/chromium/ipc/ipc_message_attachment_set.cc index b9a990da8bb..58dd6cae4a1 100644 --- a/chromium/ipc/ipc_message_attachment_set.cc +++ b/chromium/ipc/ipc_message_attachment_set.cc @@ -75,6 +75,7 @@ bool MessageAttachmentSet::AddAttachment( case MessageAttachment::Type::MOJO_HANDLE: case MessageAttachment::Type::WIN_HANDLE: case MessageAttachment::Type::MACH_PORT: + case MessageAttachment::Type::FUCHSIA_HANDLE: attachments_.push_back(attachment); *index = attachments_.size() - 1; return true; diff --git a/chromium/ipc/ipc_message_pipe_reader.h b/chromium/ipc/ipc_message_pipe_reader.h index b441960e3e1..ceb62feec76 100644 --- a/chromium/ipc/ipc_message_pipe_reader.h +++ b/chromium/ipc/ipc_message_pipe_reader.h @@ -74,7 +74,7 @@ class IPC_EXPORT MessagePipeReader : public NON_EXPORTED_BASE(mojom::Channel) { void Close(); // Return true if the MessagePipe is alive. - bool IsValid() { return sender_; } + bool IsValid() { return sender_.is_bound(); } // Sends an IPC::Message to the other end of the pipe. Safe to call from any // thread. diff --git a/chromium/ipc/ipc_message_protobuf_utils.h b/chromium/ipc/ipc_message_protobuf_utils.h new file mode 100644 index 00000000000..8cacfe8d933 --- /dev/null +++ b/chromium/ipc/ipc_message_protobuf_utils.h @@ -0,0 +1,72 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IPC_IPC_MESSAGE_PROTOBUF_UTILS_H_ +#define IPC_IPC_MESSAGE_PROTOBUF_UTILS_H_ + +#include "build/build_config.h" + +#if defined(OS_NACL_NONSFI) +static_assert(false, + "ipc_message_protobuf_utils is not able to work with " + "nacl_nonsfi configuration."); +#endif + +#include "base/pickle.h" +#include "ipc/ipc_param_traits.h" +#include "ipc/ipc_message_utils.h" +#include "third_party/protobuf/src/google/protobuf/repeated_field.h" + +namespace IPC { + +template +struct RepeatedFieldParamTraits { + typedef RepeatedFieldLike param_type; + static void GetSize(base::PickleSizer* sizer, const param_type& p) { + GetParamSize(sizer, p.size()); + for (int i = 0; i < p.size(); i++) + GetParamSize(sizer, p.Get(i)); + } + static void Write(base::Pickle* m, const param_type& p) { + WriteParam(m, p.size()); + for (int i = 0; i < p.size(); i++) + WriteParam(m, p.Get(i)); + } + static bool Read(const base::Pickle* m, + base::PickleIterator* iter, + param_type* r) { + int size; + // ReadLength() checks for < 0 itself. + if (!iter->ReadLength(&size)) + return false; + // Avoid integer overflow / assertion failure in Reserve() function. + if (INT_MAX / sizeof(StorageType) <= static_cast(size)) + return false; + r->Reserve(size); + for (int i = 0; i < size; i++) { + if (!ReadParam(m, iter, r->Add())) + return false; + } + return true; + } + static void Log(const param_type& p, std::string* l) { + for (int i = 0; i < p.size(); ++i) { + if (i != 0) + l->append(" "); + LogParam(p.Get(i), l); + } + } +}; + +template +struct ParamTraits> : + RepeatedFieldParamTraits, P> {}; + +template +struct ParamTraits> : + RepeatedFieldParamTraits, void*> {}; + +} // namespace IPC + +#endif // IPC_IPC_MESSAGE_PROTOBUF_UTILS_H_ diff --git a/chromium/ipc/ipc_message_protobuf_utils_unittest.cc b/chromium/ipc/ipc_message_protobuf_utils_unittest.cc new file mode 100644 index 00000000000..5c01a7f1e09 --- /dev/null +++ b/chromium/ipc/ipc_message_protobuf_utils_unittest.cc @@ -0,0 +1,193 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "build/build_config.h" + +#if defined(OS_NACL_NONSFI) +static_assert(false, + "ipc_message_protobuf_utils is not able to work with nacl_nonsfi " + "configuration."); +#endif + +#include "ipc/ipc_message_protobuf_utils.h" + +#include + +#include "ipc/test_proto.pb.h" +#include "ipc/ipc_message.h" +#include "ipc/ipc_message_utils.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace IPC { + +template <> +struct ParamTraits { + typedef ipc_message_utils_test::TestMessage1 param_type; + static void GetSize(base::PickleSizer* sizer, const param_type& p) { + GetParamSize(sizer, p.number()); + } + static void Write(base::Pickle* m, const param_type& p) { + WriteParam(m, p.number()); + } + static bool Read(const base::Pickle* m, + base::PickleIterator* iter, + param_type* r) { + int number; + if (!iter->ReadInt(&number)) + return false; + r->set_number(number); + return true; + } +}; + +template <> +struct ParamTraits { + typedef ipc_message_utils_test::TestMessage2 param_type; + static void GetSize(base::PickleSizer* sizer, const param_type& p) { + GetParamSize(sizer, p.numbers()); + GetParamSize(sizer, p.strings()); + GetParamSize(sizer, p.messages()); + } + static void Write(base::Pickle* m, const param_type& p) { + WriteParam(m, p.numbers()); + WriteParam(m, p.strings()); + WriteParam(m, p.messages()); + } + static bool Read(const base::Pickle* m, + base::PickleIterator* iter, + param_type* r) { + return ReadParam(m, iter, r->mutable_numbers()) && + ReadParam(m, iter, r->mutable_strings()) && + ReadParam(m, iter, r->mutable_messages()); + } +}; + +namespace { + +template +void AssertEqual(const P1& left, const P2& right) { + ASSERT_EQ(left, right); +} + +template<> +void AssertEqual(const int& left, + const ipc_message_utils_test::TestMessage1& right) { + ASSERT_EQ(left, right.number()); +} + +template class RepeatedFieldLike, class P1, class P2> +void AssertRepeatedFieldEquals(std::initializer_list expected, + const RepeatedFieldLike& fields) { + ASSERT_EQ(static_cast(expected.size()), fields.size()); + auto it = expected.begin(); + int i = 0; + for (; it != expected.end(); it++, i++) { + AssertEqual(*it, fields.Get(i)); + } +} + +TEST(IPCMessageRepeatedFieldUtilsTest, RepeatedFieldShouldBeSerialized) { + ipc_message_utils_test::TestMessage2 message; + message.add_numbers(1); + message.add_numbers(100); + message.add_strings("abc"); + message.add_strings("def"); + message.add_messages()->set_number(1000); + message.add_messages()->set_number(10000); + + base::Pickle pickle; + IPC::WriteParam(&pickle, message); + + base::PickleSizer sizer; + IPC::GetParamSize(&sizer, message); + + ASSERT_EQ(sizer.payload_size(), pickle.payload_size()); + + base::PickleIterator iter(pickle); + ipc_message_utils_test::TestMessage2 output; + ASSERT_TRUE(IPC::ReadParam(&pickle, &iter, &output)); + + AssertRepeatedFieldEquals({1, 100}, output.numbers()); + AssertRepeatedFieldEquals({"abc", "def"}, output.strings()); + AssertRepeatedFieldEquals({1000, 10000}, output.messages()); +} + +TEST(IPCMessageRepeatedFieldUtilsTest, + PartialEmptyRepeatedFieldShouldBeSerialized) { + ipc_message_utils_test::TestMessage2 message; + message.add_numbers(1); + message.add_numbers(100); + message.add_messages()->set_number(1000); + message.add_messages()->set_number(10000); + + base::Pickle pickle; + IPC::WriteParam(&pickle, message); + + base::PickleSizer sizer; + IPC::GetParamSize(&sizer, message); + + ASSERT_EQ(sizer.payload_size(), pickle.payload_size()); + + base::PickleIterator iter(pickle); + ipc_message_utils_test::TestMessage2 output; + ASSERT_TRUE(IPC::ReadParam(&pickle, &iter, &output)); + + AssertRepeatedFieldEquals({1, 100}, output.numbers()); + ASSERT_EQ(0, output.strings_size()); + AssertRepeatedFieldEquals({1000, 10000}, output.messages()); +} + +TEST(IPCMessageRepeatedFieldUtilsTest, EmptyRepeatedFieldShouldBeSerialized) { + ipc_message_utils_test::TestMessage2 message; + + base::Pickle pickle; + IPC::WriteParam(&pickle, message); + + base::PickleSizer sizer; + IPC::GetParamSize(&sizer, message); + + ASSERT_EQ(sizer.payload_size(), pickle.payload_size()); + + base::PickleIterator iter(pickle); + ipc_message_utils_test::TestMessage2 output; + ASSERT_TRUE(IPC::ReadParam(&pickle, &iter, &output)); + + ASSERT_EQ(0, output.numbers_size()); + ASSERT_EQ(0, output.strings_size()); + ASSERT_EQ(0, output.messages_size()); +} + +TEST(IPCMessageRepeatedFieldUtilsTest, + InvalidPickleShouldNotCrashRepeatedFieldDeserialization) { + base::Pickle pickle; + IPC::WriteParam(&pickle, INT_MAX); + IPC::WriteParam(&pickle, 0); + IPC::WriteParam(&pickle, INT_MAX); + IPC::WriteParam(&pickle, std::string()); + IPC::WriteParam(&pickle, 0); + + base::PickleIterator iter(pickle); + ipc_message_utils_test::TestMessage2 output; + ASSERT_FALSE(IPC::ReadParam(&pickle, &iter, &output)); +} + +// This test needs ~20 seconds in Debug mode, or ~4 seconds in Release mode. +// See http://crbug.com/741866 for details. +TEST(IPCMessageRepeatedFieldUtilsTest, + DISABLED_InvalidPickleShouldNotCrashRepeatedFieldDeserialization2) { + base::Pickle pickle; + IPC::WriteParam(&pickle, 256 * 1024 * 1024); + IPC::WriteParam(&pickle, 0); + IPC::WriteParam(&pickle, INT_MAX); + IPC::WriteParam(&pickle, std::string()); + IPC::WriteParam(&pickle, 0); + + base::PickleIterator iter(pickle); + ipc_message_utils_test::TestMessage2 output; + ASSERT_FALSE(IPC::ReadParam(&pickle, &iter, &output)); +} + +} // namespace + +} // namespace IPC diff --git a/chromium/ipc/ipc_message_start.h b/chromium/ipc/ipc_message_start.h index e3fda0e957c..dba1acb4202 100644 --- a/chromium/ipc/ipc_message_start.h +++ b/chromium/ipc/ipc_message_start.h @@ -19,7 +19,6 @@ enum IPCMessageStart { DevToolsMsgStart, WorkerMsgStart, NaClMsgStart, - UtilityMsgStart, GpuChannelMsgStart, MediaMsgStart, ServiceMsgStart, @@ -90,7 +89,6 @@ enum IPCMessageStart { ChromeUtilityExtensionsMsgStart, PlatformNotificationMsgStart, PDFMsgStart, - ManifestManagerMsgStart, LayoutTestMsgStart, NetworkHintsMsgStart, BluetoothMsgStart, diff --git a/chromium/ipc/ipc_message_unittest.cc b/chromium/ipc/ipc_message_unittest.cc index 8e59e00c859..4e5bf07a23b 100644 --- a/chromium/ipc/ipc_message_unittest.cc +++ b/chromium/ipc/ipc_message_unittest.cc @@ -10,6 +10,7 @@ #include #include +#include #include "base/memory/ptr_util.h" #include "base/strings/utf_string_conversions.h" @@ -89,21 +90,21 @@ TEST(IPCMessageTest, ListValue) { TEST(IPCMessageTest, DictionaryValue) { base::DictionaryValue input; input.Set("null", base::MakeUnique()); - input.Set("bool", new base::Value(true)); - input.Set("int", new base::Value(42)); + input.SetBoolean("bool", true); + input.SetInteger("int", 42); input.SetIntegerWithoutPathExpansion("int.with.dot", 43); - std::unique_ptr subdict(new base::DictionaryValue()); - subdict->Set("str", new base::Value("forty two")); - subdict->Set("bool", new base::Value(false)); + auto subdict = base::MakeUnique(); + subdict->SetString("str", "forty two"); + subdict->SetBoolean("bool", false); - std::unique_ptr sublist(new base::ListValue()); + auto sublist = base::MakeUnique(); sublist->AppendDouble(42.42); sublist->AppendString("forty"); sublist->AppendString("two"); - subdict->Set("list", sublist.release()); + subdict->Set("list", std::move(sublist)); - input.Set("dict", subdict.release()); + input.Set("dict", std::move(subdict)); IPC::Message msg(1, 2, IPC::Message::PRIORITY_NORMAL); IPC::WriteParam(&msg, input); diff --git a/chromium/ipc/ipc_message_utils.cc b/chromium/ipc/ipc_message_utils.cc index 8179cd4dfb2..c851d8a599e 100644 --- a/chromium/ipc/ipc_message_utils.cc +++ b/chromium/ipc/ipc_message_utils.cc @@ -38,6 +38,10 @@ #include "ipc/ipc_platform_file.h" #endif +#if defined(OS_FUCHSIA) +#include "ipc/handle_fuchsia.h" +#endif + namespace IPC { namespace { @@ -419,7 +423,7 @@ void ParamTraits::Log(const param_type& p, std::string* l) { l->append(base::UintToString(p)); } -#if defined(OS_WIN) || defined(OS_LINUX) || \ +#if defined(OS_WIN) || defined(OS_LINUX) || defined(OS_FUCHSIA) || \ (defined(OS_ANDROID) && defined(ARCH_CPU_64_BITS)) void ParamTraits::Log(const param_type& p, std::string* l) { l->append(base::Int64ToString(static_cast(p))); @@ -753,6 +757,10 @@ bool ParamTraits::Read(const base::Pickle* m, HandleWin handle_win; if (!ReadParam(m, iter, &handle_win)) return false; +#elif defined(OS_FUCHSIA) + HandleFuchsia handle_fuchsia; + if (!ReadParam(m, iter, &handle_fuchsia)) + return false; #else scoped_refptr attachment; if (!m->ReadAttachment(iter, &attachment)) @@ -776,6 +784,9 @@ bool ParamTraits::Read(const base::Pickle* m, #elif defined(OS_WIN) *r = base::SharedMemoryHandle(handle_win.get_handle(), static_cast(size), guid); +#elif defined(OS_FUCHSIA) + *r = base::SharedMemoryHandle(handle_fuchsia.get_handle(), + static_cast(size), guid); #else *r = base::SharedMemoryHandle( base::FileDescriptor( diff --git a/chromium/ipc/ipc_message_utils.h b/chromium/ipc/ipc_message_utils.h index 84324ebaf41..348ff7eb61a 100644 --- a/chromium/ipc/ipc_message_utils.h +++ b/chromium/ipc/ipc_message_utils.h @@ -208,10 +208,10 @@ struct ParamTraits { // very few IPCs that cross this boundary. // 2) We also need to keep it for Linux for two reasons: int64_t is typedef'd // to long, and gfx::PluginWindow is long and is used in one GPU IPC. -// 3) Android 64 bit also has int64_t typedef'd to long. +// 3) Android 64 bit and Fuchsia also have int64_t typedef'd to long. // Since we want to support Android 32<>64 bit IPC, as long as we don't have // these traits for 32 bit ARM then that'll catch any errors. -#if defined(OS_WIN) || defined(OS_LINUX) || \ +#if defined(OS_WIN) || defined(OS_LINUX) || defined(OS_FUCHSIA) || \ (defined(OS_ANDROID) && defined(ARCH_CPU_64_BITS)) template <> struct ParamTraits { @@ -724,149 +724,63 @@ struct ParamTraits> { } }; -template -struct ParamTraits> { - typedef std::tuple param_type; - static void GetSize(base::PickleSizer* sizer, const param_type& p) { - GetParamSize(sizer, std::get<0>(p)); - } - static void Write(base::Pickle* m, const param_type& p) { - WriteParam(m, std::get<0>(p)); - } - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r) { - return ReadParam(m, iter, &std::get<0>(*r)); - } - static void Log(const param_type& p, std::string* l) { - LogParam(std::get<0>(p), l); - } -}; +template +struct TupleParamTraitsHelper { + using Next = TupleParamTraitsHelper; -template -struct ParamTraits> { - typedef std::tuple param_type; - static void GetSize(base::PickleSizer* sizer, const param_type& p) { - GetParamSize(sizer, std::get<0>(p)); - GetParamSize(sizer, std::get<1>(p)); - } - static void Write(base::Pickle* m, const param_type& p) { - WriteParam(m, std::get<0>(p)); - WriteParam(m, std::get<1>(p)); + static void GetSize(base::PickleSizer* sizer, const T& p) { + GetParamSize(sizer, std::get(p)); + Next::GetSize(sizer, p); } - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r) { - return (ReadParam(m, iter, &std::get<0>(*r)) && - ReadParam(m, iter, &std::get<1>(*r))); - } - static void Log(const param_type& p, std::string* l) { - LogParam(std::get<0>(p), l); - l->append(", "); - LogParam(std::get<1>(p), l); - } -}; -template -struct ParamTraits> { - typedef std::tuple param_type; - static void GetSize(base::PickleSizer* sizer, const param_type& p) { - GetParamSize(sizer, std::get<0>(p)); - GetParamSize(sizer, std::get<1>(p)); - GetParamSize(sizer, std::get<2>(p)); - } - static void Write(base::Pickle* m, const param_type& p) { - WriteParam(m, std::get<0>(p)); - WriteParam(m, std::get<1>(p)); - WriteParam(m, std::get<2>(p)); + static void Write(base::Pickle* m, const T& p) { + WriteParam(m, std::get(p)); + Next::Write(m, p); } - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r) { - return (ReadParam(m, iter, &std::get<0>(*r)) && - ReadParam(m, iter, &std::get<1>(*r)) && - ReadParam(m, iter, &std::get<2>(*r))); + + static bool Read(const base::Pickle* m, base::PickleIterator* iter, T* r) { + return ReadParam(m, iter, &std::get(*r)) && Next::Read(m, iter, r); } - static void Log(const param_type& p, std::string* l) { - LogParam(std::get<0>(p), l); - l->append(", "); - LogParam(std::get<1>(p), l); - l->append(", "); - LogParam(std::get<2>(p), l); + + static void Log(const T& p, std::string* l) { + LogParam(std::get(p), l); + if (index < count - 1) + l->append(", "); + Next::Log(p, l); } }; -template -struct ParamTraits> { - typedef std::tuple param_type; - static void GetSize(base::PickleSizer* sizer, const param_type& p) { - GetParamSize(sizer, std::get<0>(p)); - GetParamSize(sizer, std::get<1>(p)); - GetParamSize(sizer, std::get<2>(p)); - GetParamSize(sizer, std::get<3>(p)); - } - static void Write(base::Pickle* m, const param_type& p) { - WriteParam(m, std::get<0>(p)); - WriteParam(m, std::get<1>(p)); - WriteParam(m, std::get<2>(p)); - WriteParam(m, std::get<3>(p)); - } - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r) { - return (ReadParam(m, iter, &std::get<0>(*r)) && - ReadParam(m, iter, &std::get<1>(*r)) && - ReadParam(m, iter, &std::get<2>(*r)) && - ReadParam(m, iter, &std::get<3>(*r))); - } - static void Log(const param_type& p, std::string* l) { - LogParam(std::get<0>(p), l); - l->append(", "); - LogParam(std::get<1>(p), l); - l->append(", "); - LogParam(std::get<2>(p), l); - l->append(", "); - LogParam(std::get<3>(p), l); +template +struct TupleParamTraitsHelper { + static void GetSize(base::PickleSizer* sizer, const T& p) {} + static void Write(base::Pickle* m, const T& p) {} + static bool Read(const base::Pickle* m, base::PickleIterator* iter, T* r) { + return true; } + static void Log(const T& p, std::string* l) {} }; -template -struct ParamTraits> { - typedef std::tuple param_type; +template +struct ParamTraits> { + using param_type = std::tuple; + using Helper = + TupleParamTraitsHelper::value>; + static void GetSize(base::PickleSizer* sizer, const param_type& p) { - GetParamSize(sizer, std::get<0>(p)); - GetParamSize(sizer, std::get<1>(p)); - GetParamSize(sizer, std::get<2>(p)); - GetParamSize(sizer, std::get<3>(p)); - GetParamSize(sizer, std::get<4>(p)); + Helper::GetSize(sizer, p); } + static void Write(base::Pickle* m, const param_type& p) { - WriteParam(m, std::get<0>(p)); - WriteParam(m, std::get<1>(p)); - WriteParam(m, std::get<2>(p)); - WriteParam(m, std::get<3>(p)); - WriteParam(m, std::get<4>(p)); + Helper::Write(m, p); } + static bool Read(const base::Pickle* m, base::PickleIterator* iter, param_type* r) { - return (ReadParam(m, iter, &std::get<0>(*r)) && - ReadParam(m, iter, &std::get<1>(*r)) && - ReadParam(m, iter, &std::get<2>(*r)) && - ReadParam(m, iter, &std::get<3>(*r)) && - ReadParam(m, iter, &std::get<4>(*r))); - } - static void Log(const param_type& p, std::string* l) { - LogParam(std::get<0>(p), l); - l->append(", "); - LogParam(std::get<1>(p), l); - l->append(", "); - LogParam(std::get<2>(p), l); - l->append(", "); - LogParam(std::get<3>(p), l); - l->append(", "); - LogParam(std::get<4>(p), l); + return Helper::Read(m, iter, r); } + + static void Log(const param_type& p, std::string* l) { Helper::Log(p, l); } }; template diff --git a/chromium/ipc/ipc_mojo_bootstrap.cc b/chromium/ipc/ipc_mojo_bootstrap.cc index 5361d8e0bff..afd0e3cc075 100644 --- a/chromium/ipc/ipc_mojo_bootstrap.cc +++ b/chromium/ipc/ipc_mojo_bootstrap.cc @@ -18,6 +18,7 @@ #include "base/memory/ptr_util.h" #include "base/single_thread_task_runner.h" #include "base/synchronization/lock.h" +#include "base/threading/thread_checker.h" #include "base/threading/thread_task_runner_handle.h" #include "mojo/public/cpp/bindings/associated_group.h" #include "mojo/public/cpp/bindings/associated_group_controller.h" @@ -208,7 +209,7 @@ class ChannelAssociatedGroupController mojo::InterfaceEndpointController* AttachEndpointClient( const mojo::ScopedInterfaceEndpointHandle& handle, mojo::InterfaceEndpointClient* client, - scoped_refptr runner) override { + scoped_refptr runner) override { const mojo::InterfaceId id = handle.id(); DCHECK(mojo::IsValidInterfaceId(id)); @@ -249,6 +250,8 @@ class ChannelAssociatedGroupController } } + bool PrefersSerializedMessages() override { return true; } + private: class Endpoint; class ControlMessageProxyThunk; @@ -343,7 +346,7 @@ class ChannelAssociatedGroupController disconnect_reason_ = disconnect_reason; } - base::SingleThreadTaskRunner* task_runner() const { + base::SequencedTaskRunner* task_runner() const { return task_runner_.get(); } @@ -353,11 +356,11 @@ class ChannelAssociatedGroupController } void AttachClient(mojo::InterfaceEndpointClient* client, - scoped_refptr runner) { + scoped_refptr runner) { controller_->lock_.AssertAcquired(); DCHECK(!client_); DCHECK(!closed_); - DCHECK(runner->BelongsToCurrentThread()); + DCHECK(runner->RunsTasksInCurrentSequence()); task_runner_ = std::move(runner); client_ = client; @@ -366,7 +369,7 @@ class ChannelAssociatedGroupController void DetachClient() { controller_->lock_.AssertAcquired(); DCHECK(client_); - DCHECK(task_runner_->BelongsToCurrentThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); DCHECK(!closed_); task_runner_ = nullptr; @@ -400,20 +403,20 @@ class ChannelAssociatedGroupController // mojo::InterfaceEndpointController: bool SendMessage(mojo::Message* message) override { - DCHECK(task_runner_->BelongsToCurrentThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); message->set_interface_id(id_); return controller_->SendMessage(message); } void AllowWokenUpBySyncWatchOnSameThread() override { - DCHECK(task_runner_->BelongsToCurrentThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); EnsureSyncWatcherExists(); sync_watcher_->AllowWokenUpBySyncWatchOnSameThread(); } bool SyncWatch(const bool* should_stop) override { - DCHECK(task_runner_->BelongsToCurrentThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); // It's not legal to make sync calls from the master endpoint's thread, // and in fact they must only happen from the proxy task runner. @@ -436,7 +439,7 @@ class ChannelAssociatedGroupController } void OnSyncMessageEventReady() { - DCHECK(task_runner_->BelongsToCurrentThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); scoped_refptr keepalive(this); scoped_refptr controller_keepalive( @@ -483,7 +486,7 @@ class ChannelAssociatedGroupController } void EnsureSyncWatcherExists() { - DCHECK(task_runner_->BelongsToCurrentThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); if (sync_watcher_) return; @@ -519,7 +522,7 @@ class ChannelAssociatedGroupController bool handle_created_ = false; base::Optional disconnect_reason_; mojo::InterfaceEndpointClient* client_ = nullptr; - scoped_refptr task_runner_; + scoped_refptr task_runner_; std::unique_ptr sync_watcher_; std::unique_ptr sync_message_event_; std::queue> sync_messages_; @@ -626,7 +629,7 @@ class ChannelAssociatedGroupController void NotifyEndpointOfError(Endpoint* endpoint, bool force_async) { lock_.AssertAcquired(); DCHECK(endpoint->task_runner() && endpoint->client()); - if (endpoint->task_runner()->BelongsToCurrentThread() && !force_async) { + if (endpoint->task_runner()->RunsTasksInCurrentSequence() && !force_async) { mojo::InterfaceEndpointClient* client = endpoint->client(); base::Optional reason( endpoint->disconnect_reason()); @@ -636,9 +639,9 @@ class ChannelAssociatedGroupController } else { endpoint->task_runner()->PostTask( FROM_HERE, - base::Bind(&ChannelAssociatedGroupController - ::NotifyEndpointOfErrorOnEndpointThread, this, endpoint->id(), - endpoint)); + base::Bind(&ChannelAssociatedGroupController:: + NotifyEndpointOfErrorOnEndpointThread, + this, endpoint->id(), base::Unretained(endpoint))); } } @@ -651,7 +654,7 @@ class ChannelAssociatedGroupController if (!endpoint->client()) return; - DCHECK(endpoint->task_runner()->BelongsToCurrentThread()); + DCHECK(endpoint->task_runner()->RunsTasksInCurrentSequence()); NotifyEndpointOfError(endpoint, false /* force_async */); } @@ -709,7 +712,7 @@ class ChannelAssociatedGroupController return true; mojo::InterfaceEndpointClient* client = endpoint->client(); - if (!client || !endpoint->task_runner()->BelongsToCurrentThread()) { + if (!client || !endpoint->task_runner()->RunsTasksInCurrentSequence()) { // No client has been bound yet or the client runs tasks on another // thread. We assume the other thread must always be the one on which // |proxy_task_runner_| runs tasks, since that's the only valid scenario. @@ -765,7 +768,7 @@ class ChannelAssociatedGroupController if (!client) return; - DCHECK(endpoint->task_runner()->BelongsToCurrentThread()); + DCHECK(endpoint->task_runner()->RunsTasksInCurrentSequence()); // Sync messages should never make their way to this method. DCHECK(!message.has_flag(mojo::Message::kFlagIsSync)); @@ -794,7 +797,7 @@ class ChannelAssociatedGroupController if (!client) return; - DCHECK(endpoint->task_runner()->BelongsToCurrentThread()); + DCHECK(endpoint->task_runner()->RunsTasksInCurrentSequence()); MessageWrapper message_wrapper = endpoint->PopSyncMessage(message_id); // The message must have already been dequeued by the endpoint waking up diff --git a/chromium/ipc/ipc_mojo_perftest.cc b/chromium/ipc/ipc_mojo_perftest.cc index d02acda9760..8513e08b286 100644 --- a/chromium/ipc/ipc_mojo_perftest.cc +++ b/chromium/ipc/ipc_mojo_perftest.cc @@ -10,11 +10,13 @@ #include "base/process/process_metrics.h" #include "base/run_loop.h" #include "base/strings/stringprintf.h" +#include "base/synchronization/waitable_event.h" #include "base/test/perf_time_logger.h" #include "base/test/test_io_thread.h" #include "base/threading/thread_task_runner_handle.h" #include "build/build_config.h" #include "ipc/ipc_channel_mojo.h" +#include "ipc/ipc_sync_channel.h" #include "ipc/ipc_test.mojom.h" #include "ipc/ipc_test_base.h" #include "mojo/edk/embedder/embedder.h" @@ -24,52 +26,18 @@ #include "mojo/public/cpp/bindings/binding.h" #include "mojo/public/cpp/system/message_pipe.h" -namespace IPC { -namespace { - -// This class simply collects stats about abstract "events" (each of which has a -// start time and an end time). -class EventTimeTracker { - public: - explicit EventTimeTracker(const char* name) - : name_(name), - count_(0) { - } - - void AddEvent(const base::TimeTicks& start, const base::TimeTicks& end) { - DCHECK(end >= start); - count_++; - base::TimeDelta duration = end - start; - total_duration_ += duration; - max_duration_ = std::max(max_duration_, duration); - } - - void ShowResults() const { - VLOG(1) << name_ << " count: " << count_; - VLOG(1) << name_ << " total duration: " - << total_duration_.InMillisecondsF() << " ms"; - VLOG(1) << name_ << " average duration: " - << (total_duration_.InMillisecondsF() / static_cast(count_)) - << " ms"; - VLOG(1) << name_ << " maximum duration: " - << max_duration_.InMillisecondsF() << " ms"; - } +#define IPC_MESSAGE_IMPL +#include "ipc/ipc_message_macros.h" - void Reset() { - count_ = 0; - total_duration_ = base::TimeDelta(); - max_duration_ = base::TimeDelta(); - } - - private: - const std::string name_; +#define IPC_MESSAGE_START TestMsgStart - uint64_t count_; - base::TimeDelta total_duration_; - base::TimeDelta max_duration_; +IPC_MESSAGE_CONTROL0(TestMsg_Hello) +IPC_MESSAGE_CONTROL0(TestMsg_Quit) +IPC_MESSAGE_CONTROL1(TestMsg_Ping, std::string) +IPC_SYNC_MESSAGE_CONTROL1_1(TestMsg_SyncPing, std::string, std::string) - DISALLOW_COPY_AND_ASSIGN(EventTimeTracker); -}; +namespace IPC { +namespace { class PerformanceChannelListener : public Listener { public: @@ -78,14 +46,12 @@ class PerformanceChannelListener : public Listener { sender_(NULL), msg_count_(0), msg_size_(0), - count_down_(0), - latency_tracker_("Server messages") { + sync_(false), + count_down_(0) { VLOG(1) << "Server listener up"; } - ~PerformanceChannelListener() override { - VLOG(1) << "Server listener down"; - } + ~PerformanceChannelListener() override { VLOG(1) << "Server listener down"; } void Init(Sender* sender) { DCHECK(!sender_); @@ -93,10 +59,11 @@ class PerformanceChannelListener : public Listener { } // Call this before running the message loop. - void SetTestParams(int msg_count, size_t msg_size) { + void SetTestParams(int msg_count, size_t msg_size, bool sync) { DCHECK_EQ(0, count_down_); msg_count_ = msg_count; msg_size_ = msg_size; + sync_ = sync; count_down_ = msg_count_; payload_ = std::string(msg_size_, 'a'); } @@ -104,60 +71,61 @@ class PerformanceChannelListener : public Listener { bool OnMessageReceived(const Message& message) override { CHECK(sender_); - base::PickleIterator iter(message); - int64_t time_internal; - EXPECT_TRUE(iter.ReadInt64(&time_internal)); - int msgid; - EXPECT_TRUE(iter.ReadInt(&msgid)); - std::string reflected_payload; - EXPECT_TRUE(iter.ReadString(&reflected_payload)); - - // Include message deserialization in latency. - base::TimeTicks now = base::TimeTicks::Now(); - - if (reflected_payload == "hello") { - // Start timing on hello. - latency_tracker_.Reset(); - DCHECK(!perf_logger_.get()); - std::string test_name = - base::StringPrintf("IPC_%s_Perf_%dx_%u", - label_.c_str(), - msg_count_, - static_cast(msg_size_)); - perf_logger_.reset(new base::PerfTimeLogger(test_name.c_str())); + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(PerformanceChannelListener, message) + IPC_MESSAGE_HANDLER(TestMsg_Hello, OnHello) + IPC_MESSAGE_HANDLER(TestMsg_Ping, OnPing) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + return handled; + } + + void OnHello() { + // Start timing on hello. + DCHECK(!perf_logger_.get()); + std::string test_name = + base::StringPrintf("IPC_%s_Perf_%dx_%u", label_.c_str(), msg_count_, + static_cast(msg_size_)); + perf_logger_.reset(new base::PerfTimeLogger(test_name.c_str())); + if (sync_) { + for (int i = 0; i < count_down_; ++i) { + std::string response; + sender_->Send(new TestMsg_SyncPing(payload_, &response)); + DCHECK_EQ(response, payload_); + } + perf_logger_.reset(); + base::MessageLoop::current()->QuitWhenIdle(); } else { - DCHECK_EQ(payload_.size(), reflected_payload.size()); + SendPong(); + } + } - latency_tracker_.AddEvent( - base::TimeTicks::FromInternalValue(time_internal), now); + void OnPing(const std::string& payload) { + // Include message deserialization in latency. + DCHECK_EQ(payload_.size(), payload.size()); - CHECK(count_down_ > 0); - count_down_--; - if (count_down_ == 0) { - perf_logger_.reset(); // Stop the perf timer now. - latency_tracker_.ShowResults(); - base::MessageLoop::current()->QuitWhenIdle(); - return true; - } + CHECK(count_down_ > 0); + count_down_--; + if (count_down_ == 0) { + perf_logger_.reset(); // Stop the perf timer now. + base::MessageLoop::current()->QuitWhenIdle(); + return; } - Message* msg = new Message(0, 2, Message::PRIORITY_NORMAL); - msg->WriteInt64(base::TimeTicks::Now().ToInternalValue()); - msg->WriteInt(count_down_); - msg->WriteString(payload_); - sender_->Send(msg); - return true; + SendPong(); } + void SendPong() { sender_->Send(new TestMsg_Ping(payload_)); } + private: std::string label_; Sender* sender_; int msg_count_; size_t msg_size_; + bool sync_; int count_down_; std::string payload_; - EventTimeTracker latency_tracker_; std::unique_ptr perf_logger_; }; @@ -166,59 +134,46 @@ class PerformanceChannelListener : public Listener { // "quit" is sent, it will exit. class ChannelReflectorListener : public Listener { public: - ChannelReflectorListener() - : channel_(NULL), - latency_tracker_("Client messages") { + ChannelReflectorListener() : channel_(NULL) { VLOG(1) << "Client listener up"; } - ~ChannelReflectorListener() override { - VLOG(1) << "Client listener down"; - latency_tracker_.ShowResults(); - } + ~ChannelReflectorListener() override { VLOG(1) << "Client listener down"; } - void Init(Channel* channel) { + void Init(Sender* channel) { DCHECK(!channel_); channel_ = channel; } bool OnMessageReceived(const Message& message) override { CHECK(channel_); + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(ChannelReflectorListener, message) + IPC_MESSAGE_HANDLER(TestMsg_Hello, OnHello) + IPC_MESSAGE_HANDLER(TestMsg_Ping, OnPing) + IPC_MESSAGE_HANDLER(TestMsg_SyncPing, OnSyncPing) + IPC_MESSAGE_HANDLER(TestMsg_Quit, OnQuit) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + return handled; + } - base::PickleIterator iter(message); - int64_t time_internal; - EXPECT_TRUE(iter.ReadInt64(&time_internal)); - int msgid; - EXPECT_TRUE(iter.ReadInt(&msgid)); - base::StringPiece payload; - EXPECT_TRUE(iter.ReadStringPiece(&payload)); - - // Include message deserialization in latency. - base::TimeTicks now = base::TimeTicks::Now(); + void OnHello() { channel_->Send(new TestMsg_Hello); } - if (payload == "hello") { - latency_tracker_.Reset(); - } else if (payload == "quit") { - latency_tracker_.ShowResults(); - base::MessageLoop::current()->QuitWhenIdle(); - return true; - } else { - // Don't track hello and quit messages. - latency_tracker_.AddEvent( - base::TimeTicks::FromInternalValue(time_internal), now); - } + void OnPing(const std::string& payload) { + channel_->Send(new TestMsg_Ping(payload)); + } - Message* msg = new Message(0, 2, Message::PRIORITY_NORMAL); - msg->WriteInt64(base::TimeTicks::Now().ToInternalValue()); - msg->WriteInt(msgid); - msg->WriteString(payload); - channel_->Send(msg); - return true; + void OnSyncPing(const std::string& payload, std::string* response) { + *response = payload; } + void OnQuit() { base::MessageLoop::current()->QuitWhenIdle(); } + + void Send(IPC::Message* message) { channel_->Send(message); } + private: - Channel* channel_; - EventTimeTracker latency_tracker_; + Sender* channel_; }; // This class locks the current thread to a particular CPU core. This is @@ -273,8 +228,7 @@ class LockThreadAffinity { class PingPongTestParams { public: PingPongTestParams(size_t size, int count) - : message_size_(size), message_count_(count) { - } + : message_size_(size), message_count_(count) {} size_t message_size() const { return message_size_; } int message_count() const { return message_count_; } @@ -285,8 +239,8 @@ class PingPongTestParams { }; std::vector GetDefaultTestParams() { - // Test several sizes. We use 12^N for message size, and limit the message - // count to keep the test duration reasonable. +// Test several sizes. We use 12^N for message size, and limit the message +// count to keep the test duration reasonable. #ifdef NDEBUG const int kMultiplier = 100; #else @@ -311,79 +265,70 @@ class MojoChannelPerfTest : public IPCChannelMojoTestBase { MojoChannelPerfTest() = default; ~MojoChannelPerfTest() override = default; - void RunTestChannelPingPong() { + void RunTestChannelProxyPingPong() { + io_thread_.reset(new base::TestIOThread(base::TestIOThread::kAutoStart)); + Init("MojoPerfTestClient"); // Set up IPC channel and start client. - PerformanceChannelListener listener("Channel"); - CreateChannel(&listener); - listener.Init(channel()); - ASSERT_TRUE(ConnectChannel()); + PerformanceChannelListener listener("ChannelProxy"); + auto channel_proxy = IPC::ChannelProxy::Create( + TakeHandle().release(), IPC::Channel::MODE_SERVER, &listener, + io_thread_->task_runner()); + listener.Init(channel_proxy.get()); LockThreadAffinity thread_locker(kSharedCore); std::vector params = GetDefaultTestParams(); for (size_t i = 0; i < params.size(); i++) { listener.SetTestParams(params[i].message_count(), - params[i].message_size()); + params[i].message_size(), false); // This initial message will kick-start the ping-pong of messages. - Message* message = - new Message(0, 2, Message::PRIORITY_NORMAL); - message->WriteInt64(base::TimeTicks::Now().ToInternalValue()); - message->WriteInt(-1); - message->WriteString("hello"); - sender()->Send(message); + channel_proxy->Send(new TestMsg_Hello); // Run message loop. base::RunLoop().Run(); } // Send quit message. - Message* message = new Message(0, 2, Message::PRIORITY_NORMAL); - message->WriteInt64(base::TimeTicks::Now().ToInternalValue()); - message->WriteInt(-1); - message->WriteString("quit"); - sender()->Send(message); + channel_proxy->Send(new TestMsg_Quit); EXPECT_TRUE(WaitForClientShutdown()); - DestroyChannel(); -} + channel_proxy.reset(); - void RunTestChannelProxyPingPong() { + io_thread_.reset(); + } + + void RunTestChannelProxySyncPing() { io_thread_.reset(new base::TestIOThread(base::TestIOThread::kAutoStart)); Init("MojoPerfTestClient"); // Set up IPC channel and start client. PerformanceChannelListener listener("ChannelProxy"); - auto channel_proxy = IPC::ChannelProxy::Create( + base::WaitableEvent shutdown_event( + base::WaitableEvent::ResetPolicy::MANUAL, + base::WaitableEvent::InitialState::NOT_SIGNALED); + auto channel_proxy = IPC::SyncChannel::Create( TakeHandle().release(), IPC::Channel::MODE_SERVER, &listener, - io_thread_->task_runner()); + io_thread_->task_runner(), false, &shutdown_event); listener.Init(channel_proxy.get()); LockThreadAffinity thread_locker(kSharedCore); std::vector params = GetDefaultTestParams(); for (size_t i = 0; i < params.size(); i++) { listener.SetTestParams(params[i].message_count(), - params[i].message_size()); + params[i].message_size(), true); // This initial message will kick-start the ping-pong of messages. - Message* message = new Message(0, 2, Message::PRIORITY_NORMAL); - message->WriteInt64(base::TimeTicks::Now().ToInternalValue()); - message->WriteInt(-1); - message->WriteString("hello"); - channel_proxy->Send(message); + channel_proxy->Send(new TestMsg_Hello); // Run message loop. base::RunLoop().Run(); } // Send quit message. - Message* message = new Message(0, 2, Message::PRIORITY_NORMAL); - message->WriteInt64(base::TimeTicks::Now().ToInternalValue()); - message->WriteInt(-1); - message->WriteString("quit"); - channel_proxy->Send(message); + channel_proxy->Send(new TestMsg_Quit); EXPECT_TRUE(WaitForClientShutdown()); channel_proxy.reset(); @@ -401,13 +346,6 @@ class MojoChannelPerfTest : public IPCChannelMojoTestBase { std::unique_ptr io_thread_; }; -TEST_F(MojoChannelPerfTest, ChannelPingPong) { - RunTestChannelPingPong(); - - base::RunLoop run_loop; - run_loop.RunUntilIdle(); -} - TEST_F(MojoChannelPerfTest, ChannelProxyPingPong) { RunTestChannelProxyPingPong(); @@ -415,24 +353,16 @@ TEST_F(MojoChannelPerfTest, ChannelProxyPingPong) { run_loop.RunUntilIdle(); } -// Test to see how many channels we can create. -TEST_F(MojoChannelPerfTest, DISABLED_MaxChannelCount) { -#if defined(OS_POSIX) - LOG(INFO) << "base::GetMaxFds " << base::GetMaxFds(); - base::SetFdLimit(20000); -#endif +TEST_F(MojoChannelPerfTest, ChannelProxySyncPing) { + RunTestChannelProxySyncPing(); - std::vector channels; - for (size_t i = 0; i < 10000; ++i) { - LOG(INFO) << "channels size: " << channels.size(); - channels.push_back(new mojo::edk::PlatformChannelPair()); - } + base::RunLoop run_loop; + run_loop.RunUntilIdle(); } class MojoPerfTestClient { public: - MojoPerfTestClient() - : listener_(new ChannelReflectorListener()) { + MojoPerfTestClient() : listener_(new ChannelReflectorListener()) { mojo::edk::test::MultiprocessTestHelper::ChildSetup(); } @@ -441,17 +371,19 @@ class MojoPerfTestClient { int Run(MojoHandle handle) { handle_ = mojo::MakeScopedHandle(mojo::MessagePipeHandle(handle)); LockThreadAffinity thread_locker(kSharedCore); - std::unique_ptr channel = ChannelMojo::Create( - std::move(handle_), Channel::MODE_CLIENT, listener_.get()); + base::TestIOThread io_thread(base::TestIOThread::kAutoStart); + + std::unique_ptr channel = + IPC::ChannelProxy::Create(handle_.release(), Channel::MODE_CLIENT, + listener_.get(), io_thread.task_runner()); listener_->Init(channel.get()); - CHECK(channel->Connect()); base::RunLoop().Run(); return 0; } private: - base::MessageLoopForIO main_message_loop_; + base::MessageLoop main_message_loop_; std::unique_ptr listener_; std::unique_ptr channel_; mojo::ScopedMessagePipeHandle handle_; @@ -479,14 +411,16 @@ class ReflectorImpl : public IPC::mojom::Reflector { private: // IPC::mojom::Reflector: - void Ping(const std::string& value, const PingCallback& callback) override { - callback.Run(value); + void Ping(const std::string& value, PingCallback callback) override { + std::move(callback).Run(value); } - void Quit() override { - base::MessageLoop::current()->QuitWhenIdle(); + void SyncPing(const std::string& value, PingCallback callback) override { + std::move(callback).Run(value); } + void Quit() override { base::MessageLoop::current()->QuitWhenIdle(); } + mojo::Binding binding_; }; @@ -500,15 +434,13 @@ class MojoInterfacePerfTest : public mojo::edk::test::MojoTestBase { mojo::MessagePipeHandle mp_handle(mp); mojo::ScopedMessagePipeHandle scoped_mp(mp_handle); - ping_receiver_.Bind(IPC::mojom::ReflectorPtrInfo( - std::move(scoped_mp), 0u)); + ping_receiver_.Bind(IPC::mojom::ReflectorPtrInfo(std::move(scoped_mp), 0u)); LockThreadAffinity thread_locker(kSharedCore); std::vector params = GetDefaultTestParams(); for (size_t i = 0; i < params.size(); i++) { - ping_receiver_->Ping( - "hello", - base::Bind(&MojoInterfacePerfTest::OnPong, base::Unretained(this))); + ping_receiver_->Ping("hello", base::Bind(&MojoInterfacePerfTest::OnPong, + base::Unretained(this))); message_count_ = count_down_ = params[i].message_count(); payload_ = std::string(params[i].message_size(), 'a'); @@ -524,10 +456,8 @@ class MojoInterfacePerfTest : public mojo::edk::test::MojoTestBase { if (value == "hello") { DCHECK(!perf_logger_.get()); std::string test_name = - base::StringPrintf("IPC_%s_Perf_%dx_%zu", - label_.c_str(), - message_count_, - payload_.size()); + base::StringPrintf("IPC_%s_Perf_%dx_%zu", label_.c_str(), + message_count_, payload_.size()); perf_logger_.reset(new base::PerfTimeLogger(test_name.c_str())); } else { DCHECK_EQ(payload_.size(), value.size()); @@ -541,9 +471,18 @@ class MojoInterfacePerfTest : public mojo::edk::test::MojoTestBase { } } - ping_receiver_->Ping( - payload_, - base::Bind(&MojoInterfacePerfTest::OnPong, base::Unretained(this))); + if (sync_) { + for (int i = 0; i < count_down_; ++i) { + std::string response; + ping_receiver_->SyncPing(payload_, &response); + DCHECK_EQ(response, payload_); + } + perf_logger_.reset(); + base::MessageLoop::current()->QuitWhenIdle(); + } else { + ping_receiver_->Ping(payload_, base::Bind(&MojoInterfacePerfTest::OnPong, + base::Unretained(this))); + } } static int RunPingPongClient(MojoHandle mp) { @@ -562,6 +501,8 @@ class MojoInterfacePerfTest : public mojo::edk::test::MojoTestBase { return 0; } + bool sync_ = false; + private: int message_count_; int count_down_; @@ -573,6 +514,31 @@ class MojoInterfacePerfTest : public mojo::edk::test::MojoTestBase { DISALLOW_COPY_AND_ASSIGN(MojoInterfacePerfTest); }; +enum class InProcessMessageMode { + kSerialized, + kUnserialized, +}; + +class MojoInProcessInterfacePerfTest + : public MojoInterfacePerfTest, + public testing::WithParamInterface { + public: + MojoInProcessInterfacePerfTest() { + switch (GetParam()) { + case InProcessMessageMode::kSerialized: + mojo::Connector::OverrideDefaultSerializationBehaviorForTesting( + mojo::Connector::OutgoingSerializationMode::kEager, + mojo::Connector::IncomingSerializationMode::kDispatchAsIs); + break; + case InProcessMessageMode::kUnserialized: + mojo::Connector::OverrideDefaultSerializationBehaviorForTesting( + mojo::Connector::OutgoingSerializationMode::kLazy, + mojo::Connector::IncomingSerializationMode::kDispatchAsIs); + break; + } + } +}; + DEFINE_TEST_CLIENT_WITH_PIPE(PingPongClient, MojoInterfacePerfTest, h) { base::MessageLoop main_message_loop; return RunPingPongClient(h); @@ -581,14 +547,22 @@ DEFINE_TEST_CLIENT_WITH_PIPE(PingPongClient, MojoInterfacePerfTest, h) { // Similar to MojoChannelPerfTest above, but uses a Mojo interface instead of // raw IPC::Messages. TEST_F(MojoInterfacePerfTest, MultiprocessPingPong) { - RUN_CHILD_ON_PIPE(PingPongClient, h) + RunTestClient("PingPongClient", [&](MojoHandle h) { + base::MessageLoop main_message_loop; + RunPingPongServer(h, "Multiprocess"); + }); +} + +TEST_F(MojoInterfacePerfTest, MultiprocessSyncPing) { + sync_ = true; + RunTestClient("PingPongClient", [&](MojoHandle h) { base::MessageLoop main_message_loop; - RunPingPongServer(h, "MultiProcess"); - END_CHILD() + RunPingPongServer(h, "MultiprocessSync"); + }); } // A single process version of the above test. -TEST_F(MojoInterfacePerfTest, SingleProcessMultiThreadPingPong) { +TEST_P(MojoInProcessInterfacePerfTest, MultiThreadPingPong) { MojoHandle server_handle, client_handle; CreateMessagePipe(&server_handle, &client_handle); @@ -602,7 +576,7 @@ TEST_F(MojoInterfacePerfTest, SingleProcessMultiThreadPingPong) { RunPingPongServer(server_handle, "SingleProcess"); } -TEST_F(MojoInterfacePerfTest, SingleProcessSingleThreadPingPong) { +TEST_P(MojoInProcessInterfacePerfTest, SingleThreadPingPong) { MojoHandle server_handle, client_handle; CreateMessagePipe(&server_handle, &client_handle); @@ -615,6 +589,11 @@ TEST_F(MojoInterfacePerfTest, SingleProcessSingleThreadPingPong) { RunPingPongServer(server_handle, "SingleProcess"); } +INSTANTIATE_TEST_CASE_P(, + MojoInProcessInterfacePerfTest, + testing::Values(InProcessMessageMode::kSerialized, + InProcessMessageMode::kUnserialized)); + class CallbackPerfTest : public testing::Test { public: CallbackPerfTest() @@ -641,8 +620,7 @@ class CallbackPerfTest : public testing::Test { void Ping(const std::string& value) { main_message_loop_.task_runner()->PostTask( FROM_HERE, - base::Bind(&CallbackPerfTest::OnPong, base::Unretained(this), - value)); + base::Bind(&CallbackPerfTest::OnPong, base::Unretained(this), value)); } void OnPong(const std::string& value) { @@ -650,8 +628,7 @@ class CallbackPerfTest : public testing::Test { DCHECK(!perf_logger_.get()); std::string test_name = base::StringPrintf("Callback_MultiProcess_Perf_%dx_%zu", - message_count_, - payload_.size()); + message_count_, payload_.size()); perf_logger_.reset(new base::PerfTimeLogger(test_name.c_str())); } else { DCHECK_EQ(payload_.size(), value.size()); @@ -674,15 +651,14 @@ class CallbackPerfTest : public testing::Test { LockThreadAffinity thread_locker(kSharedCore); std::vector params = GetDefaultTestParams(); base::Callback&)> ping = - base::Bind(&CallbackPerfTest::SingleThreadPingNoPostTask, - base::Unretained(this)); + const base::Callback&)> + ping = base::Bind(&CallbackPerfTest::SingleThreadPingNoPostTask, + base::Unretained(this)); for (size_t i = 0; i < params.size(); i++) { payload_ = std::string(params[i].message_size(), 'a'); std::string test_name = base::StringPrintf("Callback_SingleThreadPostTask_Perf_%dx_%zu", - params[i].message_count(), - payload_.size()); + params[i].message_count(), payload_.size()); perf_logger_.reset(new base::PerfTimeLogger(test_name.c_str())); for (int j = 0; j < params[i].message_count(); ++j) { ping.Run(payload_, @@ -693,13 +669,13 @@ class CallbackPerfTest : public testing::Test { } } - void SingleThreadPingNoPostTask(const std::string& value, - const base::Callback& pong) { + void SingleThreadPingNoPostTask( + const std::string& value, + const base::Callback& pong) { pong.Run(value); } - void SingleThreadPongNoPostTask(const std::string& value) { - } + void SingleThreadPongNoPostTask(const std::string& value) {} void RunSingleThreadPostTaskPingPongServer() { LockThreadAffinity thread_locker(kSharedCore); @@ -707,9 +683,8 @@ class CallbackPerfTest : public testing::Test { for (size_t i = 0; i < params.size(); i++) { std::string hello("hello"); base::MessageLoop::current()->task_runner()->PostTask( - FROM_HERE, - base::Bind(&CallbackPerfTest::SingleThreadPingPostTask, - base::Unretained(this), hello)); + FROM_HERE, base::Bind(&CallbackPerfTest::SingleThreadPingPostTask, + base::Unretained(this), hello)); message_count_ = count_down_ = params[i].message_count(); payload_ = std::string(params[i].message_size(), 'a'); @@ -719,10 +694,8 @@ class CallbackPerfTest : public testing::Test { void SingleThreadPingPostTask(const std::string& value) { base::MessageLoop::current()->task_runner()->PostTask( - FROM_HERE, - base::Bind(&CallbackPerfTest::SingleThreadPongPostTask, - base::Unretained(this), - value)); + FROM_HERE, base::Bind(&CallbackPerfTest::SingleThreadPongPostTask, + base::Unretained(this), value)); } void SingleThreadPongPostTask(const std::string& value) { @@ -730,8 +703,7 @@ class CallbackPerfTest : public testing::Test { DCHECK(!perf_logger_.get()); std::string test_name = base::StringPrintf("Callback_SingleThreadNoPostTask_Perf_%dx_%zu", - message_count_, - payload_.size()); + message_count_, payload_.size()); perf_logger_.reset(new base::PerfTimeLogger(test_name.c_str())); } else { DCHECK_EQ(payload_.size(), value.size()); @@ -746,9 +718,8 @@ class CallbackPerfTest : public testing::Test { } base::MessageLoop::current()->task_runner()->PostTask( - FROM_HERE, - base::Bind(&CallbackPerfTest::SingleThreadPingPostTask, - base::Unretained(this), payload_)); + FROM_HERE, base::Bind(&CallbackPerfTest::SingleThreadPingPostTask, + base::Unretained(this), payload_)); } private: diff --git a/chromium/ipc/ipc_param_traits.h b/chromium/ipc/ipc_param_traits.h index 45e975c30a7..9aaeb5e506b 100644 --- a/chromium/ipc/ipc_param_traits.h +++ b/chromium/ipc/ipc_param_traits.h @@ -9,8 +9,19 @@ // a data type is read, written and logged in the IPC system. namespace IPC { +namespace internal { + +template +struct AlwaysFalse { + static const bool value = false; +}; + +} // namespace internal template struct ParamTraits { + static_assert(internal::AlwaysFalse

::value, + "Cannot find the IPC::ParamTraits specialization. Did you " + "forget to include the corresponding header file?"); }; template diff --git a/chromium/ipc/ipc_sync_channel.cc b/chromium/ipc/ipc_sync_channel.cc index 36effbca032..05272a1ae91 100644 --- a/chromium/ipc/ipc_sync_channel.cc +++ b/chromium/ipc/ipc_sync_channel.cc @@ -599,7 +599,7 @@ bool SyncChannel::Send(Message* message) { "line", IPC_MESSAGE_ID_LINE(message->type())); #endif if (!message->is_sync()) { - ChannelProxy::Send(message); + ChannelProxy::SendInternal(message); return true; } @@ -614,7 +614,7 @@ bool SyncChannel::Send(Message* message) { return false; } - ChannelProxy::Send(message); + ChannelProxy::SendInternal(message); // Wait for reply, or for any other incoming synchronous messages. // |this| might get deleted, so only call static functions at this point. @@ -646,15 +646,14 @@ void SyncChannel::WaitForReply(mojo::SyncHandleRegistry* registry, bool dispatch = false; bool send_done = false; bool should_pump_messages = false; - bool registered = registry->RegisterEvent( - context->GetSendDoneEvent(), base::Bind(&OnEventReady, &send_done)); - DCHECK(registered); + base::Closure on_send_done_callback = base::Bind(&OnEventReady, &send_done); + registry->RegisterEvent(context->GetSendDoneEvent(), on_send_done_callback); + base::Closure on_pump_messages_callback; if (pump_messages_event) { - registered = registry->RegisterEvent( - pump_messages_event, - base::Bind(&OnEventReady, &should_pump_messages)); - DCHECK(registered); + on_pump_messages_callback = + base::Bind(&OnEventReady, &should_pump_messages); + registry->RegisterEvent(pump_messages_event, on_pump_messages_callback); } const bool* stop_flags[] = { &dispatch, &send_done, &should_pump_messages }; @@ -662,9 +661,10 @@ void SyncChannel::WaitForReply(mojo::SyncHandleRegistry* registry, registry->Wait(stop_flags, 3); context->received_sync_msgs()->UnblockDispatch(); - registry->UnregisterEvent(context->GetSendDoneEvent()); + registry->UnregisterEvent(context->GetSendDoneEvent(), + on_send_done_callback); if (pump_messages_event) - registry->UnregisterEvent(pump_messages_event); + registry->UnregisterEvent(pump_messages_event, on_pump_messages_callback); if (dispatch) { // We're waiting for a reply, but we received a blocking synchronous call. diff --git a/chromium/ipc/ipc_sync_channel_unittest.cc b/chromium/ipc/ipc_sync_channel_unittest.cc index 63d5e464219..5d6588fceed 100644 --- a/chromium/ipc/ipc_sync_channel_unittest.cc +++ b/chromium/ipc/ipc_sync_channel_unittest.cc @@ -81,8 +81,6 @@ class Worker : public Listener, public Sender { // Shutdown() must be called before destruction. CHECK(is_shutdown_); } - void AddRef() { } - void Release() { } bool Send(Message* msg) override { return channel_->Send(msg); } void WaitForChannelCreation() { channel_created_->Wait(); } void CloseChannel() { @@ -92,7 +90,7 @@ class Worker : public Listener, public Sender { void Start() { StartThread(&listener_thread_, base::MessageLoop::TYPE_DEFAULT); ListenerThread()->task_runner()->PostTask( - FROM_HERE, base::Bind(&Worker::OnStart, this)); + FROM_HERE, base::Bind(&Worker::OnStart, base::Unretained(this))); } void Shutdown() { // The IPC thread needs to outlive SyncChannel. We can't do this in @@ -104,8 +102,9 @@ class Worker : public Listener, public Sender { ipc_done(base::WaitableEvent::ResetPolicy::AUTOMATIC, base::WaitableEvent::InitialState::NOT_SIGNALED); ListenerThread()->task_runner()->PostTask( - FROM_HERE, base::Bind(&Worker::OnListenerThreadShutdown1, this, - &listener_done, &ipc_done)); + FROM_HERE, + base::Bind(&Worker::OnListenerThreadShutdown1, base::Unretained(this), + &listener_done, &ipc_done)); listener_done.Wait(); ipc_done.Wait(); ipc_thread_.Stop(); @@ -207,8 +206,9 @@ class Worker : public Listener, public Sender { base::RunLoop().RunUntilIdle(); ipc_thread_.task_runner()->PostTask( - FROM_HERE, base::Bind(&Worker::OnIPCThreadShutdown, this, - listener_event, ipc_event)); + FROM_HERE, + base::Bind(&Worker::OnIPCThreadShutdown, base::Unretained(this), + listener_event, ipc_event)); } void OnIPCThreadShutdown(WaitableEvent* listener_event, @@ -217,8 +217,8 @@ class Worker : public Listener, public Sender { ipc_event->Signal(); listener_thread_.task_runner()->PostTask( - FROM_HERE, - base::Bind(&Worker::OnListenerThreadShutdown2, this, listener_event)); + FROM_HERE, base::Bind(&Worker::OnListenerThreadShutdown2, + base::Unretained(this), listener_event)); } void OnListenerThreadShutdown2(WaitableEvent* listener_event) { @@ -1018,7 +1018,7 @@ class DoneEventRaceServer : public Worker { void Run() override { base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::Bind(&NestedCallback, this)); + FROM_HERE, base::Bind(&NestedCallback, base::Unretained(this))); base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( FROM_HERE, base::Bind(&TimeoutCallback), base::TimeDelta::FromSeconds(9)); @@ -1117,8 +1117,9 @@ class ServerSendAfterClose : public Worker { bool SendDummy() { ListenerThread()->task_runner()->PostTask( - FROM_HERE, base::Bind(base::IgnoreResult(&ServerSendAfterClose::Send), - this, new SyncChannelTestMsg_NoArgs)); + FROM_HERE, + base::Bind(base::IgnoreResult(&ServerSendAfterClose::Send), + base::Unretained(this), new SyncChannelTestMsg_NoArgs)); return true; } @@ -1186,7 +1187,8 @@ class RestrictedDispatchServer : public Worker { // Signal the event after the message has been sent on the channel, on the // IPC thread. ipc_thread().task_runner()->PostTask( - FROM_HERE, base::Bind(&RestrictedDispatchServer::OnPingSent, this)); + FROM_HERE, base::Bind(&RestrictedDispatchServer::OnPingSent, + base::Unretained(this))); } void OnPingTTL(int ping, int* out) { @@ -1267,7 +1269,8 @@ class RestrictedDispatchClient : public Worker { channel()->SetRestrictDispatchChannelGroup(1); server_->ListenerThread()->task_runner()->PostTask( - FROM_HERE, base::Bind(&RestrictedDispatchServer::OnDoPing, server_, 1)); + FROM_HERE, base::Bind(&RestrictedDispatchServer::OnDoPing, + base::Unretained(server_), 1)); sent_ping_event_->Wait(); Send(new SyncChannelTestMsg_NoArgs); if (ping_ == 1) @@ -1280,7 +1283,8 @@ class RestrictedDispatchClient : public Worker { this, ipc_thread().task_runner(), true, shutdown_event()); server_->ListenerThread()->task_runner()->PostTask( - FROM_HERE, base::Bind(&RestrictedDispatchServer::OnDoPing, server_, 2)); + FROM_HERE, base::Bind(&RestrictedDispatchServer::OnDoPing, + base::Unretained(server_), 2)); sent_ping_event_->Wait(); // Check that the incoming message is *not* dispatched when sending on the // non restricted channel. @@ -1305,8 +1309,8 @@ class RestrictedDispatchClient : public Worker { // Check that the incoming message on the non-restricted channel is // dispatched when sending on the restricted channel. server2_->ListenerThread()->task_runner()->PostTask( - FROM_HERE, - base::Bind(&NonRestrictedDispatchServer::OnDoPingTTL, server2_, 3)); + FROM_HERE, base::Bind(&NonRestrictedDispatchServer::OnDoPingTTL, + base::Unretained(server2_), 3)); int value = 0; Send(new SyncChannelTestMsg_PingTTL(4, &value)); if (ping_ == 3 && value == 4) @@ -1539,11 +1543,12 @@ class RestrictedDispatchDeadlockClient1 : public Worker { void Run() override { server_ready_event_->Wait(); server_->ListenerThread()->task_runner()->PostTask( - FROM_HERE, - base::Bind(&RestrictedDispatchDeadlockServer::OnDoServerTask, server_)); + FROM_HERE, base::Bind(&RestrictedDispatchDeadlockServer::OnDoServerTask, + base::Unretained(server_))); peer_->ListenerThread()->task_runner()->PostTask( FROM_HERE, - base::Bind(&RestrictedDispatchDeadlockClient2::OnDoClient2Task, peer_)); + base::Bind(&RestrictedDispatchDeadlockClient2::OnDoClient2Task, + base::Unretained(peer_))); events_[0]->Wait(); events_[1]->Wait(); DCHECK(received_msg_ == false); diff --git a/chromium/ipc/ipc_sync_message.cc b/chromium/ipc/ipc_sync_message.cc index ba87de8f22e..34cb875db2f 100644 --- a/chromium/ipc/ipc_sync_message.cc +++ b/chromium/ipc/ipc_sync_message.cc @@ -14,7 +14,7 @@ namespace { -base::StaticAtomicSequenceNumber g_next_id; +base::AtomicSequenceNumber g_next_id; } // namespace diff --git a/chromium/ipc/ipc_sync_message_filter.cc b/chromium/ipc/ipc_sync_message_filter.cc index 15ffdbc6ff7..86d4ce11df5 100644 --- a/chromium/ipc/ipc_sync_message_filter.cc +++ b/chromium/ipc/ipc_sync_message_filter.cc @@ -73,9 +73,10 @@ bool SyncMessageFilter::Send(Message* message) { bool shutdown = false; scoped_refptr registry = mojo::SyncHandleRegistry::current(); - registry->RegisterEvent(shutdown_event_, - base::Bind(&OnEventReady, &shutdown)); - registry->RegisterEvent(&done_event, base::Bind(&OnEventReady, &done)); + auto on_shutdown_callback = base::Bind(&OnEventReady, &shutdown); + auto on_done_callback = base::Bind(&OnEventReady, &done); + registry->RegisterEvent(shutdown_event_, on_shutdown_callback); + registry->RegisterEvent(&done_event, on_done_callback); const bool* stop_flags[] = { &done, &shutdown }; registry->Wait(stop_flags, 2); @@ -84,8 +85,8 @@ bool SyncMessageFilter::Send(Message* message) { "SyncMessageFilter::Send", &done_event); } - registry->UnregisterEvent(shutdown_event_); - registry->UnregisterEvent(&done_event); + registry->UnregisterEvent(shutdown_event_, on_shutdown_callback); + registry->UnregisterEvent(&done_event, on_done_callback); { base::AutoLock auto_lock(lock_); diff --git a/chromium/ipc/ipc_test.mojom b/chromium/ipc/ipc_test.mojom index 8af397a3a42..33181b82659 100644 --- a/chromium/ipc/ipc_test.mojom +++ b/chromium/ipc/ipc_test.mojom @@ -31,6 +31,8 @@ interface IndirectTestDriver { interface Reflector { Ping(string value) => (string value); + [Sync] + SyncPing(string value) => (string response); Quit(); }; diff --git a/chromium/ipc/test_proto.proto b/chromium/ipc/test_proto.proto new file mode 100644 index 00000000000..98525edee21 --- /dev/null +++ b/chromium/ipc/test_proto.proto @@ -0,0 +1,20 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +syntax = "proto2"; +option optimize_for = LITE_RUNTIME; +package ipc_message_utils_test; + +// This is a simple dummy protocol buffer that is used for testing handling of +// protocol buffers in ipc_message_utils. + +message TestMessage1 { + optional int32 number = 1; +} + +message TestMessage2 { + repeated int32 numbers = 1; + repeated string strings = 2; + repeated TestMessage1 messages = 3; +} -- cgit v1.2.1