summaryrefslogtreecommitdiff
path: root/chromium/ipc
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@theqtcompany.com>2016-05-09 14:22:11 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2016-05-09 15:11:45 +0000
commit2ddb2d3e14eef3de7dbd0cef553d669b9ac2361c (patch)
treee75f511546c5fd1a173e87c1f9fb11d7ac8d1af3 /chromium/ipc
parenta4f3d46271c57e8155ba912df46a05559d14726e (diff)
downloadqtwebengine-chromium-2ddb2d3e14eef3de7dbd0cef553d669b9ac2361c.tar.gz
BASELINE: Update Chromium to 51.0.2704.41
Also adds in all smaller components by reversing logic for exclusion. Change-Id: Ibf90b506e7da088ea2f65dcf23f2b0992c504422 Reviewed-by: Joerg Bornemann <joerg.bornemann@theqtcompany.com>
Diffstat (limited to 'chromium/ipc')
-rw-r--r--chromium/ipc/BUILD.gn30
-rw-r--r--chromium/ipc/OWNERS1
-rw-r--r--chromium/ipc/attachment_broker.cc33
-rw-r--r--chromium/ipc/attachment_broker.h16
-rw-r--r--chromium/ipc/attachment_broker_mac_unittest.cc103
-rw-r--r--chromium/ipc/attachment_broker_privileged.cc46
-rw-r--r--chromium/ipc/attachment_broker_privileged.h20
-rw-r--r--chromium/ipc/attachment_broker_privileged_mac.cc143
-rw-r--r--chromium/ipc/attachment_broker_privileged_mac.h11
-rw-r--r--chromium/ipc/attachment_broker_privileged_mac_unittest.cc30
-rw-r--r--chromium/ipc/attachment_broker_privileged_win.cc12
-rw-r--r--chromium/ipc/attachment_broker_privileged_win_unittest.cc30
-rw-r--r--chromium/ipc/attachment_broker_unprivileged.cc68
-rw-r--r--chromium/ipc/attachment_broker_unprivileged.h18
-rw-r--r--chromium/ipc/attachment_broker_unprivileged_mac.cc33
-rw-r--r--chromium/ipc/export_template.h163
-rw-r--r--chromium/ipc/handle_attachment_win.cc4
-rw-r--r--chromium/ipc/handle_attachment_win.h7
-rw-r--r--chromium/ipc/handle_win.cc12
-rw-r--r--chromium/ipc/handle_win.h7
-rw-r--r--chromium/ipc/ipc.gyp22
-rw-r--r--chromium/ipc/ipc.gypi5
-rw-r--r--chromium/ipc/ipc_channel.h15
-rw-r--r--chromium/ipc/ipc_channel_common.cc8
-rw-r--r--chromium/ipc/ipc_channel_nacl.cc2
-rw-r--r--chromium/ipc/ipc_channel_posix.cc9
-rw-r--r--chromium/ipc/ipc_channel_posix.h1
-rw-r--r--chromium/ipc/ipc_channel_posix_unittest.cc34
-rw-r--r--chromium/ipc/ipc_channel_proxy.cc16
-rw-r--r--chromium/ipc/ipc_channel_proxy.h8
-rw-r--r--chromium/ipc/ipc_channel_proxy_unittest_messages.h6
-rw-r--r--chromium/ipc/ipc_channel_reader.cc45
-rw-r--r--chromium/ipc/ipc_channel_reader.h3
-rw-r--r--chromium/ipc/ipc_channel_unittest.cc16
-rw-r--r--chromium/ipc/ipc_channel_win.cc2
-rw-r--r--chromium/ipc/ipc_endpoint.h2
-rw-r--r--chromium/ipc/ipc_message.cc10
-rw-r--r--chromium/ipc/ipc_message.h10
-rw-r--r--chromium/ipc/ipc_message_attachment.h6
-rw-r--r--chromium/ipc/ipc_message_macros.h859
-rw-r--r--chromium/ipc/ipc_message_null_macros.h4
-rw-r--r--chromium/ipc/ipc_message_start.h9
-rw-r--r--chromium/ipc/ipc_message_templates.h215
-rw-r--r--chromium/ipc/ipc_message_templates_impl.h112
-rw-r--r--chromium/ipc/ipc_message_utils.cc320
-rw-r--r--chromium/ipc/ipc_message_utils.h593
-rw-r--r--chromium/ipc/ipc_message_utils_impl.h51
-rw-r--r--chromium/ipc/ipc_message_utils_unittest.cc43
-rw-r--r--chromium/ipc/ipc_perftest_support.cc9
-rw-r--r--chromium/ipc/ipc_perftest_support.h14
-rw-r--r--chromium/ipc/ipc_platform_file.cc31
-rw-r--r--chromium/ipc/ipc_platform_file.h28
-rw-r--r--chromium/ipc/ipc_send_fds_test.cc3
-rw-r--r--chromium/ipc/ipc_sync_channel.cc31
-rw-r--r--chromium/ipc/ipc_sync_channel.h4
-rw-r--r--chromium/ipc/ipc_sync_channel_unittest.cc150
-rw-r--r--chromium/ipc/ipc_sync_message_filter.cc11
-rw-r--r--chromium/ipc/ipc_test_base.h13
-rw-r--r--chromium/ipc/ipc_test_sink.h11
-rw-r--r--chromium/ipc/ipc_tests_apk.isolate1
-rw-r--r--chromium/ipc/mach_port_attachment_mac.cc3
-rw-r--r--chromium/ipc/mach_port_attachment_mac.h7
-rw-r--r--chromium/ipc/mach_port_mac.cc12
-rw-r--r--chromium/ipc/mach_port_mac.h6
-rw-r--r--chromium/ipc/message_router.cc55
-rw-r--r--chromium/ipc/message_router.h71
-rw-r--r--chromium/ipc/mojo/BUILD.gn35
-rw-r--r--chromium/ipc/mojo/DEPS2
-rw-r--r--chromium/ipc/mojo/async_handle_waiter.cc171
-rw-r--r--chromium/ipc/mojo/async_handle_waiter.h53
-rw-r--r--chromium/ipc/mojo/async_handle_waiter_unittest.cc260
-rw-r--r--chromium/ipc/mojo/client_channel.mojom9
-rw-r--r--chromium/ipc/mojo/ipc.mojom31
-rw-r--r--chromium/ipc/mojo/ipc_channel_mojo.cc615
-rw-r--r--chromium/ipc/mojo/ipc_channel_mojo.h119
-rw-r--r--chromium/ipc/mojo/ipc_channel_mojo_unittest.cc375
-rw-r--r--chromium/ipc/mojo/ipc_message_pipe_reader.cc275
-rw-r--r--chromium/ipc/mojo/ipc_message_pipe_reader.h91
-rw-r--r--chromium/ipc/mojo/ipc_mojo.gyp27
-rw-r--r--chromium/ipc/mojo/ipc_mojo_bootstrap.cc199
-rw-r--r--chromium/ipc/mojo/ipc_mojo_bootstrap.h51
-rw-r--r--chromium/ipc/mojo/ipc_mojo_bootstrap_unittest.cc67
-rw-r--r--chromium/ipc/mojo/ipc_mojo_handle_attachment.cc11
-rw-r--r--chromium/ipc/mojo/ipc_mojo_message_helper.cc12
-rw-r--r--chromium/ipc/mojo/ipc_mojo_message_helper.h4
-rw-r--r--chromium/ipc/mojo/ipc_mojo_perftest.cc100
-rw-r--r--chromium/ipc/mojo/run_all_perftests.cc17
-rw-r--r--chromium/ipc/mojo/run_all_unittests.cc11
-rw-r--r--chromium/ipc/mojo/scoped_ipc_support.cc156
-rw-r--r--chromium/ipc/mojo/scoped_ipc_support.h12
-rw-r--r--chromium/ipc/param_traits_macros.h44
-rw-r--r--chromium/ipc/param_traits_read_macros.h28
-rw-r--r--chromium/ipc/param_traits_size_macros.h40
-rw-r--r--chromium/ipc/param_traits_write_macros.h9
-rw-r--r--chromium/ipc/unix_domain_socket_util.cc113
-rw-r--r--chromium/ipc/unix_domain_socket_util.h2
-rw-r--r--chromium/ipc/unix_domain_socket_util_unittest.cc1
97 files changed, 3097 insertions, 3516 deletions
diff --git a/chromium/ipc/BUILD.gn b/chromium/ipc/BUILD.gn
index 1dddc13484c..c3d3bb45b10 100644
--- a/chromium/ipc/BUILD.gn
+++ b/chromium/ipc/BUILD.gn
@@ -26,6 +26,7 @@ component("ipc") {
"brokerable_attachment.h",
"brokerable_attachment_mac.cc",
"brokerable_attachment_win.cc",
+ "export_template.h",
"handle_attachment_win.cc",
"handle_attachment_win.h",
"handle_win.cc",
@@ -65,6 +66,8 @@ component("ipc") {
"ipc_message_generator.h",
"ipc_message_macros.h",
"ipc_message_start.h",
+ "ipc_message_templates.h",
+ "ipc_message_templates_impl.h",
"ipc_message_utils.cc",
"ipc_message_utils.h",
"ipc_platform_file.cc",
@@ -88,6 +91,8 @@ component("ipc") {
"message_filter.h",
"message_filter_router.cc",
"message_filter_router.h",
+ "message_router.cc",
+ "message_router.h",
"param_traits_log_macros.h",
"param_traits_macros.h",
"param_traits_read_macros.h",
@@ -144,13 +149,6 @@ source_set("param_traits") {
]
}
-group("ipc_tests_run") {
- testonly = true
- deps = [
- ":ipc_tests",
- ]
-}
-
test("ipc_tests") {
sources = [
"attachment_broker_mac_unittest.cc",
@@ -179,18 +177,16 @@ test("ipc_tests") {
sources -= [ "unix_domain_socket_util_unittest.cc" ]
}
+ if (is_android) {
+ # These multiprocess tests don't work on Android.
+ sources -= [ "ipc_channel_unittest.cc" ]
+ }
+
# TODO(brettw) hook up Android testing.
#if (is_android && gtest_target_type == "shared_library") {
# deps += "/testing/android/native_test.gyp:native_testNative_code"
#}
- # TODO(brettw) hook up tcmalloc to this target.
- #if (is_posix && !is_mac && !is_android) {
- # if (use_allocator!="none") {
- # deps += "/base/allocator"
- # }
- #}
-
deps = [
":ipc",
":test_support",
@@ -213,12 +209,6 @@ test("ipc_perftests") {
# deps += "/testing/android/native_test.gyp:native_testNative_code"
#}
- # TODO(brettw) hook up tcmalloc to this target.
- #if (is_posix && !is_mac && !is_android) {
- # if (use_allocator!="none") {
- # deps += "//base/allocator"
- # }
- #}
deps = [
":ipc",
":test_support",
diff --git a/chromium/ipc/OWNERS b/chromium/ipc/OWNERS
index 54320464d06..76fd94129fb 100644
--- a/chromium/ipc/OWNERS
+++ b/chromium/ipc/OWNERS
@@ -1,4 +1,3 @@
-agl@chromium.org
cpu@chromium.org
darin@chromium.org
jam@chromium.org
diff --git a/chromium/ipc/attachment_broker.cc b/chromium/ipc/attachment_broker.cc
index 50e3e2d9ae7..f53a4cf0123 100644
--- a/chromium/ipc/attachment_broker.cc
+++ b/chromium/ipc/attachment_broker.cc
@@ -18,9 +18,6 @@ namespace IPC {
// static
void AttachmentBroker::SetGlobal(AttachmentBroker* broker) {
- CHECK(!g_attachment_broker || !broker)
- << "Global attachment broker address: " << broker
- << ". New attachment broker address: " << broker;
g_attachment_broker = broker;
}
@@ -61,6 +58,16 @@ void AttachmentBroker::AddObserver(
info.runner = runner;
info.unique_id = ++last_unique_id_;
observers_.push_back(info);
+
+ // Give the observer a chance to handle attachments that arrived while the
+ // observer was handling the message that caused it to register, but our
+ // mutex was not yet locked.
+ for (const auto& attachment : attachments_) {
+ info.runner->PostTask(
+ FROM_HERE,
+ base::Bind(&AttachmentBroker::NotifyObserver, base::Unretained(this),
+ info.unique_id, attachment->GetIdentifier()));
+ }
}
}
@@ -74,7 +81,9 @@ void AttachmentBroker::RemoveObserver(AttachmentBroker::Observer* observer) {
observers_.erase(it);
}
-void AttachmentBroker::RegisterCommunicationChannel(Endpoint* endpoint) {
+void AttachmentBroker::RegisterCommunicationChannel(
+ Endpoint* endpoint,
+ scoped_refptr<base::SingleThreadTaskRunner> runner) {
NOTREACHED();
}
@@ -82,6 +91,20 @@ void AttachmentBroker::DeregisterCommunicationChannel(Endpoint* endpoint) {
NOTREACHED();
}
+void AttachmentBroker::RegisterBrokerCommunicationChannel(Endpoint* endpoint) {
+ NOTREACHED();
+}
+
+void AttachmentBroker::DeregisterBrokerCommunicationChannel(
+ Endpoint* endpoint) {
+ NOTREACHED();
+}
+
+bool AttachmentBroker::IsPrivilegedBroker() {
+ NOTREACHED();
+ return false;
+}
+
void AttachmentBroker::HandleReceivedAttachment(
const scoped_refptr<BrokerableAttachment>& attachment) {
{
@@ -127,6 +150,8 @@ void AttachmentBroker::NotifyObserver(
}
AttachmentBroker::ObserverInfo::ObserverInfo() {}
+AttachmentBroker::ObserverInfo::ObserverInfo(const ObserverInfo& other) =
+ default;
AttachmentBroker::ObserverInfo::~ObserverInfo() {}
} // namespace IPC
diff --git a/chromium/ipc/attachment_broker.h b/chromium/ipc/attachment_broker.h
index 4cf1ab5de58..70383edf713 100644
--- a/chromium/ipc/attachment_broker.h
+++ b/chromium/ipc/attachment_broker.h
@@ -27,6 +27,7 @@
namespace base {
class SequencedTaskRunner;
+class SingleThreadTaskRunner;
};
namespace IPC {
@@ -94,9 +95,21 @@ class IPC_EXPORT AttachmentBroker : public Listener {
// communicates attachment information with the broker process. In the broker
// process, these channels must be registered and deregistered with the
// Attachment Broker as they are created and destroyed.
- virtual void RegisterCommunicationChannel(Endpoint* endpoint);
+ //
+ // Invocations of Send() on |endpoint| will occur on thread bound to |runner|.
+ virtual void RegisterCommunicationChannel(
+ Endpoint* endpoint,
+ scoped_refptr<base::SingleThreadTaskRunner> runner);
virtual void DeregisterCommunicationChannel(Endpoint* endpoint);
+ // In each unprivileged process, exactly one channel should be used to
+ // communicate brokerable attachments with the broker process.
+ virtual void RegisterBrokerCommunicationChannel(Endpoint* endpoint);
+ virtual void DeregisterBrokerCommunicationChannel(Endpoint* endpoint);
+
+ // True if and only if this broker is privileged.
+ virtual bool IsPrivilegedBroker();
+
protected:
using AttachmentVector = std::vector<scoped_refptr<BrokerableAttachment>>;
@@ -134,6 +147,7 @@ class IPC_EXPORT AttachmentBroker : public Listener {
struct ObserverInfo {
ObserverInfo();
+ ObserverInfo(const ObserverInfo& other);
~ObserverInfo();
Observer* observer;
diff --git a/chromium/ipc/attachment_broker_mac_unittest.cc b/chromium/ipc/attachment_broker_mac_unittest.cc
index bf994b77db2..b569706ef8b 100644
--- a/chromium/ipc/attachment_broker_mac_unittest.cc
+++ b/chromium/ipc/attachment_broker_mac_unittest.cc
@@ -9,12 +9,15 @@
#include <stddef.h>
#include <sys/mman.h>
+#include <tuple>
+
#include "base/command_line.h"
#include "base/files/file_util.h"
#include "base/files/scoped_file.h"
#include "base/files/scoped_temp_dir.h"
#include "base/mac/mac_util.h"
#include "base/mac/mach_logging.h"
+#include "base/memory/free_deleter.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/shared_memory.h"
#include "base/strings/string_number_conversions.h"
@@ -111,7 +114,7 @@ base::SharedMemoryHandle GetSharedMemoryHandleFromMsg1(
return base::SharedMemoryHandle();
}
- return base::get<1>(p);
+ return std::get<1>(p);
}
// |message| must be deserializable as a TestSharedMemoryHandleMsg2. Returns
@@ -132,8 +135,8 @@ bool GetSharedMemoryHandlesFromMsg2(const IPC::Message& message,
return false;
}
- *handle1 = base::get<0>(p);
- *handle2 = base::get<1>(p);
+ *handle1 = std::get<0>(p);
+ *handle2 = std::get<1>(p);
return true;
}
@@ -419,6 +422,12 @@ class IPCAttachmentBrokerMacTest : public IPCTestBase {
// Setup shared between tests.
void CommonSetUp(const char* name) {
+ PreConnectSetUp(name);
+ PostConnectSetUp();
+ }
+
+ // All of setup before the channel is connected.
+ void PreConnectSetUp(const char* name) {
Init(name);
MachPreForkSetUp();
@@ -427,7 +436,11 @@ class IPCAttachmentBrokerMacTest : public IPCTestBase {
broker_->AddObserver(&observer_, task_runner());
CreateChannel(&proxy_listener_);
- broker_->DesignateBrokerCommunicationChannel(channel());
+ broker_->RegisterBrokerCommunicationChannel(channel());
+ }
+
+ // All of setup including the connection and everything after.
+ void PostConnectSetUp() {
ASSERT_TRUE(ConnectChannel());
ASSERT_TRUE(StartClient());
@@ -561,7 +574,7 @@ int CommonPrivilegedProcessMain(OnMessageReceivedCallback callback,
scoped_ptr<IPC::Channel> channel(IPC::Channel::CreateClient(
IPCTestBase::GetChannelName(channel_name), &listener));
- globals->broker->RegisterCommunicationChannel(channel.get());
+ globals->broker->RegisterCommunicationChannel(channel.get(), nullptr);
CHECK(channel->Connect());
globals->initial_resident_size = GetResidentSize();
@@ -595,10 +608,6 @@ int CommonPrivilegedProcessMain(OnMessageReceivedCallback callback,
// it. The SharedMemoryHandle is sent to the privileged process using Chrome
// IPC. The privileged process checks that it received the same memory region.
TEST_F(IPCAttachmentBrokerMacTest, SendSharedMemoryHandle) {
- // Mach-based SharedMemory isn't support on OSX 10.6.
- if (base::mac::IsOSSnowLeopard())
- return;
-
CommonSetUp("SendSharedMemoryHandle");
SendMessage1(kDataBuffer1);
@@ -621,10 +630,6 @@ MULTIPROCESS_IPC_TEST_CLIENT_MAIN(SendSharedMemoryHandle) {
// Similar to SendSharedMemoryHandle, but sends a very long shared memory
// region.
TEST_F(IPCAttachmentBrokerMacTest, SendSharedMemoryHandleLong) {
- // Mach-based SharedMemory isn't support on OSX 10.6.
- if (base::mac::IsOSSnowLeopard())
- return;
-
CommonSetUp("SendSharedMemoryHandleLong");
std::string buffer(1 << 23, 'a');
@@ -649,10 +654,6 @@ MULTIPROCESS_IPC_TEST_CLIENT_MAIN(SendSharedMemoryHandleLong) {
// Similar to SendSharedMemoryHandle, but sends two different shared memory
// regions in two messages.
TEST_F(IPCAttachmentBrokerMacTest, SendTwoMessagesDifferentSharedMemoryHandle) {
- // Mach-based SharedMemory isn't support on OSX 10.6.
- if (base::mac::IsOSSnowLeopard())
- return;
-
CommonSetUp("SendTwoMessagesDifferentSharedMemoryHandle");
SendMessage1(kDataBuffer1);
@@ -685,10 +686,6 @@ MULTIPROCESS_IPC_TEST_CLIENT_MAIN(SendTwoMessagesDifferentSharedMemoryHandle) {
// Similar to SendSharedMemoryHandle, but sends the same shared memory region in
// two messages.
TEST_F(IPCAttachmentBrokerMacTest, SendTwoMessagesSameSharedMemoryHandle) {
- // Mach-based SharedMemory isn't support on OSX 10.6.
- if (base::mac::IsOSSnowLeopard())
- return;
-
CommonSetUp("SendTwoMessagesSameSharedMemoryHandle");
{
@@ -735,10 +732,6 @@ MULTIPROCESS_IPC_TEST_CLIENT_MAIN(SendTwoMessagesSameSharedMemoryHandle) {
// memory regions.
TEST_F(IPCAttachmentBrokerMacTest,
SendOneMessageWithTwoDifferentSharedMemoryHandles) {
- // Mach-based SharedMemory isn't support on OSX 10.6.
- if (base::mac::IsOSSnowLeopard())
- return;
-
CommonSetUp("SendOneMessageWithTwoDifferentSharedMemoryHandles");
{
@@ -782,10 +775,6 @@ MULTIPROCESS_IPC_TEST_CLIENT_MAIN(
// same memory region twice.
TEST_F(IPCAttachmentBrokerMacTest,
SendOneMessageWithTwoSameSharedMemoryHandles) {
- // Mach-based SharedMemory isn't support on OSX 10.6.
- if (base::mac::IsOSSnowLeopard())
- return;
-
CommonSetUp("SendOneMessageWithTwoSameSharedMemoryHandles");
{
@@ -825,10 +814,6 @@ MULTIPROCESS_IPC_TEST_CLIENT_MAIN(
// Sends one message with two Posix FDs and two Mach ports.
TEST_F(IPCAttachmentBrokerMacTest, SendPosixFDAndMachPort) {
- // Mach-based SharedMemory isn't support on OSX 10.6.
- if (base::mac::IsOSSnowLeopard())
- return;
-
base::ScopedTempDir temp_dir;
ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
base::FilePath fp1, fp2;
@@ -868,16 +853,16 @@ void SendPosixFDAndMachPortCallback(IPC::Sender* sender,
return;
}
- base::SharedMemoryHandle handle1 = base::get<1>(p);
- base::SharedMemoryHandle handle2 = base::get<3>(p);
+ base::SharedMemoryHandle handle1 = std::get<1>(p);
+ base::SharedMemoryHandle handle2 = std::get<3>(p);
bool success1 = CheckContentsOfSharedMemoryHandle(handle1, kDataBuffer1) &&
CheckContentsOfSharedMemoryHandle(handle2, kDataBuffer2);
if (!success1)
LOG(ERROR) << "SharedMemoryHandles have wrong contents.";
bool success2 =
- CheckContentsOfFileDescriptor(base::get<0>(p), kDataBuffer3) &&
- CheckContentsOfFileDescriptor(base::get<2>(p), kDataBuffer4);
+ CheckContentsOfFileDescriptor(std::get<0>(p), kDataBuffer3) &&
+ CheckContentsOfFileDescriptor(std::get<2>(p), kDataBuffer4);
if (!success2)
LOG(ERROR) << "FileDescriptors have wrong contents.";
@@ -893,16 +878,12 @@ MULTIPROCESS_IPC_TEST_CLIENT_MAIN(SendPosixFDAndMachPort) {
// process. This is an unrealistic scenario, but simulates an unprivileged
// process sending an attachment to another unprivileged process.
TEST_F(IPCAttachmentBrokerMacTest, SendSharedMemoryHandleToSelf) {
- // Mach-based SharedMemory isn't support on OSX 10.6.
- if (base::mac::IsOSSnowLeopard())
- return;
-
SetBroker(new MockBroker);
- CommonSetUp("SendSharedMemoryHandleToSelf");
-
+ PreConnectSetUp("SendSharedMemoryHandleToSelf");
// Technically, the channel is an endpoint, but we need the proxy listener to
// receive the messages so that it can quit the message loop.
channel()->SetAttachmentBrokerEndpoint(false);
+ PostConnectSetUp();
get_proxy_listener()->set_listener(get_broker());
{
@@ -955,10 +936,6 @@ MULTIPROCESS_IPC_TEST_CLIENT_MAIN(SendSharedMemoryHandleToSelf) {
// Similar to SendSharedMemoryHandle, but uses a ChannelProxy instead of a
// Channel.
TEST_F(IPCAttachmentBrokerMacTest, SendSharedMemoryHandleChannelProxy) {
- // Mach-based SharedMemory isn't support on OSX 10.6.
- if (base::mac::IsOSSnowLeopard())
- return;
-
Init("SendSharedMemoryHandleChannelProxy");
MachPreForkSetUp();
@@ -971,8 +948,12 @@ TEST_F(IPCAttachmentBrokerMacTest, SendSharedMemoryHandleChannelProxy) {
options.message_loop_type = base::MessageLoop::TYPE_IO;
thread->StartWithOptions(options);
- CreateChannelProxy(get_proxy_listener(), thread->task_runner().get());
- get_broker()->DesignateBrokerCommunicationChannel(channel_proxy());
+ set_channel_proxy(std::unique_ptr<IPC::ChannelProxy>(new IPC::ChannelProxy(
+ get_proxy_listener(), thread->task_runner().get())));
+ get_broker()->RegisterBrokerCommunicationChannel(channel_proxy());
+ channel_proxy()->Init(
+ CreateChannelFactory(GetTestChannelHandle(), thread->task_runner().get()),
+ true);
ASSERT_TRUE(StartClient());
@@ -1011,10 +992,6 @@ MULTIPROCESS_IPC_TEST_CLIENT_MAIN(SendSharedMemoryHandleChannelProxy) {
// Similar to SendSharedMemoryHandle, but first makes a copy of the handle using
// ShareToProcess().
TEST_F(IPCAttachmentBrokerMacTest, ShareToProcess) {
- // Mach-based SharedMemory isn't support on OSX 10.6.
- if (base::mac::IsOSSnowLeopard())
- return;
-
CommonSetUp("ShareToProcess");
{
@@ -1045,10 +1022,6 @@ MULTIPROCESS_IPC_TEST_CLIENT_MAIN(ShareToProcess) {
// Similar to ShareToProcess, but instead shares the memory object only with
// read permissions.
TEST_F(IPCAttachmentBrokerMacTest, ShareReadOnlyToProcess) {
- // Mach-based SharedMemory isn't support on OSX 10.6.
- if (base::mac::IsOSSnowLeopard())
- return;
-
CommonSetUp("ShareReadOnlyToProcess");
{
@@ -1098,16 +1071,12 @@ MULTIPROCESS_IPC_TEST_CLIENT_MAIN(ShareReadOnlyToProcess) {
// Similar to SendSharedMemoryHandleToSelf, but the child process pretends to
// not have the task port for the parent process.
TEST_F(IPCAttachmentBrokerMacTest, SendSharedMemoryHandleToSelfDelayedPort) {
- // Mach-based SharedMemory isn't support on OSX 10.6.
- if (base::mac::IsOSSnowLeopard())
- return;
-
SetBroker(new MockBroker);
- CommonSetUp("SendSharedMemoryHandleToSelfDelayedPort");
-
+ PreConnectSetUp("SendSharedMemoryHandleToSelfDelayedPort");
// Technically, the channel is an endpoint, but we need the proxy listener to
// receive the messages so that it can quit the message loop.
channel()->SetAttachmentBrokerEndpoint(false);
+ PostConnectSetUp();
get_proxy_listener()->set_listener(get_broker());
{
@@ -1198,10 +1167,6 @@ MULTIPROCESS_IPC_TEST_CLIENT_MAIN(SendSharedMemoryHandleToSelfDelayedPort) {
// resident memory at different points in time, and that measurement is
// non-deterministic.
TEST_F(IPCAttachmentBrokerMacTest, MemoryUsageLargeMessage) {
- // Mach-based SharedMemory isn't support on OSX 10.6.
- if (base::mac::IsOSSnowLeopard())
- return;
-
CommonSetUp("MemoryUsageLargeMessage");
std::string test_string(g_large_message_size, 'a');
@@ -1252,10 +1217,6 @@ MULTIPROCESS_IPC_TEST_CLIENT_MAIN(MemoryUsageLargeMessage) {
// resident memory at different points in time, and that measurement is
// non-deterministic.
TEST_F(IPCAttachmentBrokerMacTest, MemoryUsageManyMessages) {
- // Mach-based SharedMemory isn't support on OSX 10.6.
- if (base::mac::IsOSSnowLeopard())
- return;
-
CommonSetUp("MemoryUsageManyMessages");
for (int i = 0; i < g_large_message_count; ++i) {
diff --git a/chromium/ipc/attachment_broker_privileged.cc b/chromium/ipc/attachment_broker_privileged.cc
index 85c1ac949cd..9f41892f721 100644
--- a/chromium/ipc/attachment_broker_privileged.cc
+++ b/chromium/ipc/attachment_broker_privileged.cc
@@ -6,7 +6,9 @@
#include <algorithm>
+#include "base/bind.h"
#include "base/lazy_instance.h"
+#include "base/location.h"
#include "base/metrics/histogram_macros.h"
#include "build/build_config.h"
#include "ipc/ipc_endpoint.h"
@@ -67,9 +69,7 @@ scoped_ptr<AttachmentBrokerPrivileged> CreateBroker() {
// the global broker.
class AttachmentBrokerMakeOnce {
public:
- AttachmentBrokerMakeOnce() {
- attachment_broker_.reset(CreateBroker().release());
- }
+ AttachmentBrokerMakeOnce() : attachment_broker_(CreateBroker()) {}
private:
scoped_ptr<IPC::AttachmentBrokerPrivileged> attachment_broker_;
@@ -112,31 +112,57 @@ void AttachmentBrokerPrivileged::CreateBrokerForSingleProcessTests() {
}
void AttachmentBrokerPrivileged::RegisterCommunicationChannel(
- Endpoint* endpoint) {
+ Endpoint* endpoint,
+ scoped_refptr<base::SingleThreadTaskRunner> runner) {
base::AutoLock auto_lock(*get_lock());
endpoint->SetAttachmentBrokerEndpoint(true);
- auto it = std::find(endpoints_.begin(), endpoints_.end(), endpoint);
+ auto it = std::find_if(endpoints_.begin(), endpoints_.end(),
+ [endpoint](const EndpointRunnerPair& pair) {
+ return pair.first == endpoint;
+ });
DCHECK(endpoints_.end() == it);
- endpoints_.push_back(endpoint);
+ endpoints_.push_back(std::make_pair(endpoint, runner));
}
void AttachmentBrokerPrivileged::DeregisterCommunicationChannel(
Endpoint* endpoint) {
base::AutoLock auto_lock(*get_lock());
- auto it = std::find(endpoints_.begin(), endpoints_.end(), endpoint);
+ auto it = std::find_if(endpoints_.begin(), endpoints_.end(),
+ [endpoint](const EndpointRunnerPair& pair) {
+ return pair.first == endpoint;
+ });
if (it != endpoints_.end())
endpoints_.erase(it);
}
-Sender* AttachmentBrokerPrivileged::GetSenderWithProcessId(base::ProcessId id) {
+bool AttachmentBrokerPrivileged::IsPrivilegedBroker() {
+ return true;
+}
+
+AttachmentBrokerPrivileged::EndpointRunnerPair
+AttachmentBrokerPrivileged::GetSenderWithProcessId(base::ProcessId id) {
get_lock()->AssertAcquired();
auto it = std::find_if(endpoints_.begin(), endpoints_.end(),
- [id](Endpoint* c) { return c->GetPeerPID() == id; });
+ [id](const EndpointRunnerPair& pair) {
+ return pair.first->GetPeerPID() == id;
+ });
if (it == endpoints_.end())
- return nullptr;
+ return std::make_pair(nullptr, nullptr);
return *it;
}
+void AttachmentBrokerPrivileged::SendMessageToEndpoint(EndpointRunnerPair pair,
+ Message* message) {
+ if (!pair.second || pair.second->BelongsToCurrentThread()) {
+ pair.first->Send(message);
+ } else {
+ pair.second->PostTask(
+ FROM_HERE,
+ base::Bind(&AttachmentBrokerPrivileged::SendMessageToEndpoint,
+ base::Unretained(this), pair, message));
+ }
+}
+
void AttachmentBrokerPrivileged::LogError(UMAError error) {
UMA_HISTOGRAM_ENUMERATION(
"IPC.AttachmentBrokerPrivileged.BrokerAttachmentError", error, ERROR_MAX);
diff --git a/chromium/ipc/attachment_broker_privileged.h b/chromium/ipc/attachment_broker_privileged.h
index 686bb9d282a..1fff37f387b 100644
--- a/chromium/ipc/attachment_broker_privileged.h
+++ b/chromium/ipc/attachment_broker_privileged.h
@@ -5,9 +5,11 @@
#ifndef IPC_ATTACHMENT_BROKER_PRIVILEGED_H_
#define IPC_ATTACHMENT_BROKER_PRIVILEGED_H_
+#include <utility>
#include <vector>
#include "base/macros.h"
+#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "build/build_config.h"
#include "ipc/attachment_broker.h"
@@ -48,16 +50,26 @@ class IPC_EXPORT AttachmentBrokerPrivileged : public IPC::AttachmentBroker {
static void CreateBrokerForSingleProcessTests();
// AttachmentBroker overrides.
- void RegisterCommunicationChannel(Endpoint* endpoint) override;
+ void RegisterCommunicationChannel(
+ Endpoint* endpoint,
+ scoped_refptr<base::SingleThreadTaskRunner> runner) override;
void DeregisterCommunicationChannel(Endpoint* endpoint) override;
+ bool IsPrivilegedBroker() override;
protected:
+ using EndpointRunnerPair =
+ std::pair<Endpoint*, scoped_refptr<base::SingleThreadTaskRunner>>;
+
// Returns the sender whose peer's process id is |id|.
// Returns nullptr if no sender is found.
// The lock returned by get_lock() must already be acquired before calling
// this method. The return value is only guaranteed to be valid while the lock
// is held.
- Sender* GetSenderWithProcessId(base::ProcessId id);
+ EndpointRunnerPair GetSenderWithProcessId(base::ProcessId id);
+
+ // Sends a message to the endpoint, dispatching onto another thread if
+ // necessary.
+ void SendMessageToEndpoint(EndpointRunnerPair pair, Message* message);
// Errors that can be reported by subclasses.
// These match tools/metrics/histograms.xml.
@@ -104,7 +116,9 @@ class IPC_EXPORT AttachmentBrokerPrivileged : public IPC::AttachmentBroker {
void LogError(UMAError error);
private:
- std::vector<Endpoint*> endpoints_;
+ // A vector of Endpoints, and the SingleThreadTaskRunner that should be used
+ // to invoke Send() on each Endpoint.
+ std::vector<EndpointRunnerPair> endpoints_;
DISALLOW_COPY_AND_ASSIGN(AttachmentBrokerPrivileged);
};
diff --git a/chromium/ipc/attachment_broker_privileged_mac.cc b/chromium/ipc/attachment_broker_privileged_mac.cc
index c5bed27c68d..fdf4715b348 100644
--- a/chromium/ipc/attachment_broker_privileged_mac.cc
+++ b/chromium/ipc/attachment_broker_privileged_mac.cc
@@ -6,6 +6,9 @@
#include <stdint.h>
+#include <tuple>
+
+#include "base/mac/mach_port_util.h"
#include "base/mac/scoped_mach_port.h"
#include "base/memory/shared_memory.h"
#include "base/process/port_provider_mac.h"
@@ -16,49 +19,6 @@
#include "ipc/ipc_channel.h"
#include "ipc/mach_port_attachment_mac.h"
-namespace {
-
-// Struct for sending a complex Mach message.
-struct MachSendComplexMessage {
- mach_msg_header_t header;
- mach_msg_body_t body;
- mach_msg_port_descriptor_t data;
-};
-
-// Sends a Mach port to |endpoint|. Assumes that |endpoint| is a send once
-// right. Takes ownership of |endpoint|.
-kern_return_t SendMachPort(mach_port_t endpoint,
- mach_port_t port_to_send,
- int disposition) {
- MachSendComplexMessage send_msg;
- send_msg.header.msgh_bits =
- MACH_MSGH_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE, 0) | MACH_MSGH_BITS_COMPLEX;
- send_msg.header.msgh_size = sizeof(send_msg);
- send_msg.header.msgh_remote_port = endpoint;
- send_msg.header.msgh_local_port = MACH_PORT_NULL;
- send_msg.header.msgh_reserved = 0;
- send_msg.header.msgh_id = 0;
- send_msg.body.msgh_descriptor_count = 1;
- send_msg.data.name = port_to_send;
- send_msg.data.disposition = disposition;
- send_msg.data.type = MACH_MSG_PORT_DESCRIPTOR;
-
- kern_return_t kr =
- mach_msg(&send_msg.header, MACH_SEND_MSG | MACH_SEND_TIMEOUT,
- send_msg.header.msgh_size,
- 0, // receive limit
- MACH_PORT_NULL, // receive name
- 0, // timeout
- MACH_PORT_NULL); // notification port
-
- if (kr != KERN_SUCCESS)
- mach_port_deallocate(mach_task_self(), endpoint);
-
- return kr;
-}
-
-} // namespace
-
namespace IPC {
AttachmentBrokerPrivilegedMac::AttachmentBrokerPrivilegedMac(
@@ -183,7 +143,7 @@ void AttachmentBrokerPrivilegedMac::OnDuplicateMachPort(
return;
}
IPC::internal::MachPortAttachmentMac::WireFormat wire_format =
- base::get<0>(param);
+ std::get<0>(param);
if (wire_format.destination_process == base::kNullProcessId) {
LogError(NO_DESTINATION);
@@ -214,8 +174,9 @@ bool AttachmentBrokerPrivilegedMac::RouteWireFormatToAnother(
// Another process is the destination.
base::ProcessId dest = wire_format.destination_process;
base::AutoLock auto_lock(*get_lock());
- Sender* sender = GetSenderWithProcessId(dest);
- if (!sender) {
+ AttachmentBrokerPrivileged::EndpointRunnerPair pair =
+ GetSenderWithProcessId(dest);
+ if (!pair.first) {
// Assuming that this message was not sent from a malicious process, the
// channel endpoint that would have received this message will block
// forever.
@@ -226,65 +187,11 @@ bool AttachmentBrokerPrivilegedMac::RouteWireFormatToAnother(
}
LogError(DESTINATION_FOUND);
- sender->Send(new AttachmentBrokerMsg_MachPortHasBeenDuplicated(wire_format));
+ SendMessageToEndpoint(
+ pair, new AttachmentBrokerMsg_MachPortHasBeenDuplicated(wire_format));
return true;
}
-mach_port_name_t AttachmentBrokerPrivilegedMac::CreateIntermediateMachPort(
- mach_port_t task_port,
- base::mac::ScopedMachSendRight port_to_insert) {
- DCHECK_NE(mach_task_self(), task_port);
- DCHECK_NE(static_cast<mach_port_name_t>(MACH_PORT_NULL), task_port);
-
- // Make a port with receive rights in the destination task.
- mach_port_name_t endpoint;
- kern_return_t kr =
- mach_port_allocate(task_port, MACH_PORT_RIGHT_RECEIVE, &endpoint);
- if (kr != KERN_SUCCESS) {
- LogError(ERROR_MAKE_RECEIVE_PORT);
- return MACH_PORT_NULL;
- }
-
- // Change its message queue limit so that it accepts one message.
- mach_port_limits limits = {};
- limits.mpl_qlimit = 1;
- kr = mach_port_set_attributes(task_port, endpoint, MACH_PORT_LIMITS_INFO,
- reinterpret_cast<mach_port_info_t>(&limits),
- MACH_PORT_LIMITS_INFO_COUNT);
- if (kr != KERN_SUCCESS) {
- LogError(ERROR_SET_ATTRIBUTES);
- mach_port_deallocate(task_port, endpoint);
- return MACH_PORT_NULL;
- }
-
- // Get a send right.
- mach_port_t send_once_right;
- mach_msg_type_name_t send_right_type;
- kr =
- mach_port_extract_right(task_port, endpoint, MACH_MSG_TYPE_MAKE_SEND_ONCE,
- &send_once_right, &send_right_type);
- if (kr != KERN_SUCCESS) {
- LogError(ERROR_EXTRACT_DEST_RIGHT);
- mach_port_deallocate(task_port, endpoint);
- return MACH_PORT_NULL;
- }
- DCHECK_EQ(static_cast<mach_msg_type_name_t>(MACH_MSG_TYPE_PORT_SEND_ONCE),
- send_right_type);
-
- // This call takes ownership of |send_once_right|.
- kr = SendMachPort(
- send_once_right, port_to_insert.get(), MACH_MSG_TYPE_COPY_SEND);
- if (kr != KERN_SUCCESS) {
- LogError(ERROR_SEND_MACH_PORT);
- mach_port_deallocate(task_port, endpoint);
- return MACH_PORT_NULL;
- }
-
- // Endpoint is intentionally leaked into the destination task. An IPC must be
- // sent to the destination task so that it can clean up this port.
- return endpoint;
-}
-
base::mac::ScopedMachSendRight AttachmentBrokerPrivilegedMac::ExtractNamedRight(
mach_port_t task_port,
mach_port_name_t named_right) {
@@ -324,7 +231,9 @@ void AttachmentBrokerPrivilegedMac::SendPrecursorsForProcess(
if (!to_self) {
base::AutoLock auto_lock(*get_lock());
- if (!GetSenderWithProcessId(pid)) {
+ AttachmentBrokerPrivileged::EndpointRunnerPair pair =
+ GetSenderWithProcessId(pid);
+ if (!pair.first) {
// If there is no sender, then the destination process is no longer
// running, or never existed to begin with.
LogError(DESTINATION_NOT_FOUND);
@@ -365,8 +274,28 @@ bool AttachmentBrokerPrivilegedMac::SendPrecursor(
base::mac::ScopedMachSendRight port_to_insert = precursor->TakePort();
mach_port_name_t intermediate_port = MACH_PORT_NULL;
if (port_to_insert.get() != MACH_PORT_NULL) {
- intermediate_port = CreateIntermediateMachPort(
- task_port, base::mac::ScopedMachSendRight(port_to_insert.release()));
+ base::MachCreateError error_code;
+ intermediate_port = base::CreateIntermediateMachPort(
+ task_port, base::mac::ScopedMachSendRight(port_to_insert.release()),
+ &error_code);
+ if (intermediate_port == MACH_PORT_NULL) {
+ UMAError uma_error;
+ switch (error_code) {
+ case base::MachCreateError::ERROR_MAKE_RECEIVE_PORT:
+ uma_error = ERROR_MAKE_RECEIVE_PORT;
+ break;
+ case base::MachCreateError::ERROR_SET_ATTRIBUTES:
+ uma_error = ERROR_SET_ATTRIBUTES;
+ break;
+ case base::MachCreateError::ERROR_EXTRACT_DEST_RIGHT:
+ uma_error = ERROR_EXTRACT_DEST_RIGHT;
+ break;
+ case base::MachCreateError::ERROR_SEND_MACH_PORT:
+ uma_error = ERROR_SEND_MACH_PORT;
+ break;
+ }
+ LogError(uma_error);
+ }
}
return RouteWireFormatToAnother(
CopyWireFormat(wire_format, intermediate_port));
@@ -394,7 +323,9 @@ void AttachmentBrokerPrivilegedMac::ProcessExtractorsForProcess(
{
base::AutoLock auto_lock(*get_lock());
- if (!GetSenderWithProcessId(pid)) {
+ AttachmentBrokerPrivileged::EndpointRunnerPair pair =
+ GetSenderWithProcessId(pid);
+ if (!pair.first) {
// If there is no sender, then the source process is no longer running.
LogError(ERROR_SOURCE_NOT_FOUND);
delete it->second;
diff --git a/chromium/ipc/attachment_broker_privileged_mac.h b/chromium/ipc/attachment_broker_privileged_mac.h
index c13cba01ead..0393fe1d91a 100644
--- a/chromium/ipc/attachment_broker_privileged_mac.h
+++ b/chromium/ipc/attachment_broker_privileged_mac.h
@@ -141,17 +141,6 @@ class IPC_EXPORT AttachmentBrokerPrivilegedMac
MachPortWireFormat DuplicateMachPort(const MachPortWireFormat& wire_format,
base::ProcessId source_process);
- // |task_port| is the task port of another process.
- // |port_to_insert| must be a send right in the current task's name space.
- // Creates an intermediate Mach port in |pid| and sends |port_to_insert| as a
- // mach_msg to the intermediate Mach port.
- // Returns the intermediate port on success, and MACH_PORT_NULL on failure.
- // This method takes ownership of |port_to_insert|. On success, ownership is
- // passed to the intermediate Mach port.
- mach_port_name_t CreateIntermediateMachPort(
- mach_port_t task_port,
- base::mac::ScopedMachSendRight port_to_insert);
-
// Extracts a copy of the send right to |named_right| from |task_port|.
// Returns MACH_PORT_NULL on error.
base::mac::ScopedMachSendRight ExtractNamedRight(
diff --git a/chromium/ipc/attachment_broker_privileged_mac_unittest.cc b/chromium/ipc/attachment_broker_privileged_mac_unittest.cc
index 15aecb66211..53981943bba 100644
--- a/chromium/ipc/attachment_broker_privileged_mac_unittest.cc
+++ b/chromium/ipc/attachment_broker_privileged_mac_unittest.cc
@@ -14,6 +14,7 @@
#include "base/command_line.h"
#include "base/mac/mac_util.h"
#include "base/mac/mach_logging.h"
+#include "base/mac/mach_port_util.h"
#include "base/mac/scoped_mach_port.h"
#include "base/macros.h"
#include "base/memory/shared_memory.h"
@@ -181,10 +182,6 @@ class AttachmentBrokerPrivilegedMacMultiProcessTest
// The attachment broker inserts a right for a memory object into the
// destination task.
TEST_F(AttachmentBrokerPrivilegedMacMultiProcessTest, InsertRight) {
- // Mach-based SharedMemory isn't support on OSX 10.6.
- if (base::mac::IsOSSnowLeopard())
- return;
-
SetUpChild("InsertRightClient");
mach_msg_type_number_t original_name_count = GetActiveNameCount();
IPC::AttachmentBrokerPrivilegedMac broker(&port_provider_);
@@ -198,9 +195,10 @@ TEST_F(AttachmentBrokerPrivilegedMacMultiProcessTest, InsertRight) {
// port.
IncrementMachRefCount(shared_memory->handle().GetMemoryObject(),
MACH_PORT_RIGHT_SEND);
- mach_port_name_t inserted_memory_object = broker.CreateIntermediateMachPort(
- client_task_port_.get(), base::mac::ScopedMachSendRight(
- shared_memory->handle().GetMemoryObject()));
+ mach_port_name_t inserted_memory_object = base::CreateIntermediateMachPort(
+ client_task_port_.get(),
+ base::mac::ScopedMachSendRight(shared_memory->handle().GetMemoryObject()),
+ nullptr);
EXPECT_NE(inserted_memory_object,
static_cast<mach_port_name_t>(MACH_PORT_NULL));
SendUInt32(client_port_.get(), inserted_memory_object);
@@ -248,10 +246,6 @@ MULTIPROCESS_TEST_MAIN(InsertRightClient) {
// The attachment broker inserts the right for a memory object into the
// destination task twice.
TEST_F(AttachmentBrokerPrivilegedMacMultiProcessTest, InsertSameRightTwice) {
- // Mach-based SharedMemory isn't support on OSX 10.6.
- if (base::mac::IsOSSnowLeopard())
- return;
-
SetUpChild("InsertSameRightTwiceClient");
mach_msg_type_number_t original_name_count = GetActiveNameCount();
IPC::AttachmentBrokerPrivilegedMac broker(&port_provider_);
@@ -266,10 +260,11 @@ TEST_F(AttachmentBrokerPrivilegedMacMultiProcessTest, InsertSameRightTwice) {
for (int i = 0; i < 2; ++i) {
IncrementMachRefCount(shared_memory->handle().GetMemoryObject(),
MACH_PORT_RIGHT_SEND);
- mach_port_name_t inserted_memory_object = broker.CreateIntermediateMachPort(
+ mach_port_name_t inserted_memory_object = base::CreateIntermediateMachPort(
client_task_port_.get(),
base::mac::ScopedMachSendRight(
- shared_memory->handle().GetMemoryObject()));
+ shared_memory->handle().GetMemoryObject()),
+ nullptr);
EXPECT_NE(inserted_memory_object,
static_cast<mach_port_name_t>(MACH_PORT_NULL));
SendUInt32(client_port_.get(), inserted_memory_object);
@@ -344,10 +339,6 @@ MULTIPROCESS_TEST_MAIN(InsertSameRightTwiceClient) {
// The attachment broker inserts the rights for two memory objects into the
// destination task.
TEST_F(AttachmentBrokerPrivilegedMacMultiProcessTest, InsertTwoRights) {
- // Mach-based SharedMemory isn't support on OSX 10.6.
- if (base::mac::IsOSSnowLeopard())
- return;
-
SetUpChild("InsertTwoRightsClient");
mach_msg_type_number_t original_name_count = GetActiveNameCount();
IPC::AttachmentBrokerPrivilegedMac broker(&port_provider_);
@@ -362,10 +353,11 @@ TEST_F(AttachmentBrokerPrivilegedMacMultiProcessTest, InsertTwoRights) {
// port.
IncrementMachRefCount(shared_memory->handle().GetMemoryObject(),
MACH_PORT_RIGHT_SEND);
- mach_port_name_t inserted_memory_object = broker.CreateIntermediateMachPort(
+ mach_port_name_t inserted_memory_object = base::CreateIntermediateMachPort(
client_task_port_.get(),
base::mac::ScopedMachSendRight(
- shared_memory->handle().GetMemoryObject()));
+ shared_memory->handle().GetMemoryObject()),
+ nullptr);
EXPECT_NE(inserted_memory_object,
static_cast<mach_port_name_t>(MACH_PORT_NULL));
SendUInt32(client_port_.get(), inserted_memory_object);
diff --git a/chromium/ipc/attachment_broker_privileged_win.cc b/chromium/ipc/attachment_broker_privileged_win.cc
index c749a09c980..06470128df9 100644
--- a/chromium/ipc/attachment_broker_privileged_win.cc
+++ b/chromium/ipc/attachment_broker_privileged_win.cc
@@ -6,6 +6,8 @@
#include <windows.h>
+#include <tuple>
+
#include "base/process/process.h"
#include "ipc/attachment_broker_messages.h"
#include "ipc/brokerable_attachment.h"
@@ -59,7 +61,7 @@ void AttachmentBrokerPrivilegedWin::OnDuplicateWinHandle(
if (!AttachmentBrokerMsg_DuplicateWinHandle::Read(&message, &param))
return;
IPC::internal::HandleAttachmentWin::WireFormat wire_format =
- base::get<0>(param);
+ std::get<0>(param);
if (wire_format.destination_process == base::kNullProcessId) {
LogError(NO_DESTINATION);
@@ -84,8 +86,9 @@ void AttachmentBrokerPrivilegedWin::RouteDuplicatedHandle(
// Another process is the destination.
base::ProcessId dest = wire_format.destination_process;
base::AutoLock auto_lock(*get_lock());
- Sender* sender = GetSenderWithProcessId(dest);
- if (!sender) {
+ AttachmentBrokerPrivileged::EndpointRunnerPair pair =
+ GetSenderWithProcessId(dest);
+ if (!pair.first) {
// Assuming that this message was not sent from a malicious process, the
// channel endpoint that would have received this message will block
// forever.
@@ -96,7 +99,8 @@ void AttachmentBrokerPrivilegedWin::RouteDuplicatedHandle(
}
LogError(DESTINATION_FOUND);
- sender->Send(new AttachmentBrokerMsg_WinHandleHasBeenDuplicated(wire_format));
+ SendMessageToEndpoint(
+ pair, new AttachmentBrokerMsg_WinHandleHasBeenDuplicated(wire_format));
}
AttachmentBrokerPrivilegedWin::HandleWireFormat
diff --git a/chromium/ipc/attachment_broker_privileged_win_unittest.cc b/chromium/ipc/attachment_broker_privileged_win_unittest.cc
index b25214d9d95..36a7c68e175 100644
--- a/chromium/ipc/attachment_broker_privileged_win_unittest.cc
+++ b/chromium/ipc/attachment_broker_privileged_win_unittest.cc
@@ -6,6 +6,8 @@
#include <windows.h>
+#include <tuple>
+
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
@@ -76,7 +78,7 @@ ScopedHandle GetHandleFromTestHandleWinMsg(const IPC::Message& message) {
return ScopedHandle(nullptr);
}
- IPC::HandleWin handle_win = base::get<1>(p);
+ IPC::HandleWin handle_win = std::get<1>(p);
return ScopedHandle(handle_win.get_handle());
}
@@ -97,7 +99,7 @@ scoped_ptr<base::SharedMemory> GetSharedMemoryFromSharedMemoryHandleMsg1(
return nullptr;
}
- base::SharedMemoryHandle handle = base::get<0>(p);
+ base::SharedMemoryHandle handle = std::get<0>(p);
scoped_ptr<base::SharedMemory> shared_memory(
new base::SharedMemory(handle, false));
@@ -123,9 +125,9 @@ bool GetHandleFromTestTwoHandleWinMsg(const IPC::Message& message,
return false;
}
- IPC::HandleWin handle_win = base::get<0>(p);
+ IPC::HandleWin handle_win = std::get<0>(p);
*h1 = handle_win.get_handle();
- handle_win = base::get<1>(p);
+ handle_win = std::get<1>(p);
*h2 = handle_win.get_handle();
return true;
}
@@ -263,11 +265,21 @@ class IPCAttachmentBrokerPrivilegedWinTest : public IPCTestBase {
}
void CommonSetUp() {
+ PreConnectSetUp();
+ PostConnectSetUp();
+ }
+
+ // All of setup before the channel is connected.
+ void PreConnectSetUp() {
if (!broker_.get())
set_broker(new IPC::AttachmentBrokerUnprivilegedWin);
broker_->AddObserver(&observer_, task_runner());
CreateChannel(&proxy_listener_);
- broker_->DesignateBrokerCommunicationChannel(channel());
+ broker_->RegisterBrokerCommunicationChannel(channel());
+ }
+
+ // All of setup including the connection and everything after.
+ void PostConnectSetUp() {
ASSERT_TRUE(ConnectChannel());
ASSERT_TRUE(StartClient());
@@ -388,10 +400,12 @@ TEST_F(IPCAttachmentBrokerPrivilegedWinTest, SendHandleToSelf) {
Init("SendHandleToSelf");
set_broker(new MockBroker);
- CommonSetUp();
+
+ PreConnectSetUp();
// Technically, the channel is an endpoint, but we need the proxy listener to
// receive the messages so that it can quit the message loop.
channel()->SetAttachmentBrokerEndpoint(false);
+ PostConnectSetUp();
get_proxy_listener()->set_listener(get_broker());
HANDLE h = CreateTempFile();
@@ -470,7 +484,7 @@ TEST_F(IPCAttachmentBrokerPrivilegedWinTest, SendHandleTwice) {
// An unprivileged process makes a shared memory region and sends it to the
// privileged process.
-TEST_F(IPCAttachmentBrokerPrivilegedWinTest, DISABLED_SendSharedMemoryHandle) {
+TEST_F(IPCAttachmentBrokerPrivilegedWinTest, SendSharedMemoryHandle) {
Init("SendSharedMemoryHandle");
CommonSetUp();
@@ -504,7 +518,7 @@ int CommonPrivilegedProcessMain(OnMessageReceivedCallback callback,
IPC::AttachmentBrokerPrivilegedWin broker;
scoped_ptr<IPC::Channel> channel(IPC::Channel::CreateClient(
IPCTestBase::GetChannelName(channel_name), &listener));
- broker.RegisterCommunicationChannel(channel.get());
+ broker.RegisterCommunicationChannel(channel.get(), nullptr);
CHECK(channel->Connect());
while (true) {
diff --git a/chromium/ipc/attachment_broker_unprivileged.cc b/chromium/ipc/attachment_broker_unprivileged.cc
index 9286a890057..c1e4c4ac7c1 100644
--- a/chromium/ipc/attachment_broker_unprivileged.cc
+++ b/chromium/ipc/attachment_broker_unprivileged.cc
@@ -4,6 +4,7 @@
#include "ipc/attachment_broker_unprivileged.h"
+#include "base/lazy_instance.h"
#include "base/metrics/histogram_macros.h"
#include "build/build_config.h"
#include "ipc/ipc_channel.h"
@@ -19,18 +20,15 @@
namespace IPC {
-AttachmentBrokerUnprivileged::AttachmentBrokerUnprivileged()
- : sender_(nullptr) {
- IPC::AttachmentBroker::SetGlobal(this);
-}
-
-AttachmentBrokerUnprivileged::~AttachmentBrokerUnprivileged() {
- IPC::AttachmentBroker::SetGlobal(nullptr);
-}
+namespace {
-// static
-scoped_ptr<AttachmentBrokerUnprivileged>
-AttachmentBrokerUnprivileged::CreateBroker() {
+// On platforms that support attachment brokering, returns a new instance of
+// a platform-specific attachment broker. Otherwise returns |nullptr|.
+// The caller takes ownership of the newly created instance, and is
+// responsible for ensuring that the attachment broker lives longer than
+// every IPC::Channel. The new instance automatically registers itself as the
+// global attachment broker.
+scoped_ptr<AttachmentBrokerUnprivileged> CreateBroker() {
#if defined(OS_WIN)
return scoped_ptr<AttachmentBrokerUnprivileged>(
new IPC::AttachmentBrokerUnprivilegedWin);
@@ -42,7 +40,42 @@ AttachmentBrokerUnprivileged::CreateBroker() {
#endif
}
-void AttachmentBrokerUnprivileged::DesignateBrokerCommunicationChannel(
+// This class is wrapped in a LazyInstance to ensure that its constructor is
+// only called once. The constructor creates an attachment broker and sets it as
+// the global broker.
+class AttachmentBrokerMakeOnce {
+ public:
+ AttachmentBrokerMakeOnce() {
+ // Single process tests can cause an attachment broker to already exist.
+ if (AttachmentBroker::GetGlobal())
+ return;
+ attachment_broker_ = CreateBroker();
+ }
+
+ private:
+ scoped_ptr<IPC::AttachmentBrokerUnprivileged> attachment_broker_;
+};
+
+base::LazyInstance<AttachmentBrokerMakeOnce>::Leaky
+ g_attachment_broker_make_once = LAZY_INSTANCE_INITIALIZER;
+
+} // namespace
+
+AttachmentBrokerUnprivileged::AttachmentBrokerUnprivileged()
+ : sender_(nullptr) {
+ IPC::AttachmentBroker::SetGlobal(this);
+}
+
+AttachmentBrokerUnprivileged::~AttachmentBrokerUnprivileged() {
+ IPC::AttachmentBroker::SetGlobal(nullptr);
+}
+
+// static
+void AttachmentBrokerUnprivileged::CreateBrokerIfNeeded() {
+ g_attachment_broker_make_once.Get();
+}
+
+void AttachmentBrokerUnprivileged::RegisterBrokerCommunicationChannel(
Endpoint* endpoint) {
DCHECK(endpoint);
DCHECK(!sender_);
@@ -50,6 +83,17 @@ void AttachmentBrokerUnprivileged::DesignateBrokerCommunicationChannel(
endpoint->SetAttachmentBrokerEndpoint(true);
}
+void AttachmentBrokerUnprivileged::DeregisterBrokerCommunicationChannel(
+ Endpoint* endpoint) {
+ DCHECK(endpoint);
+ DCHECK_EQ(endpoint, sender_);
+ sender_ = nullptr;
+}
+
+bool AttachmentBrokerUnprivileged::IsPrivilegedBroker() {
+ return false;
+}
+
void AttachmentBrokerUnprivileged::LogError(UMAError error) {
UMA_HISTOGRAM_ENUMERATION(
"IPC.AttachmentBrokerUnprivileged.BrokerAttachmentError", error,
diff --git a/chromium/ipc/attachment_broker_unprivileged.h b/chromium/ipc/attachment_broker_unprivileged.h
index b572ff8266a..f6d520de6e3 100644
--- a/chromium/ipc/attachment_broker_unprivileged.h
+++ b/chromium/ipc/attachment_broker_unprivileged.h
@@ -22,17 +22,15 @@ class IPC_EXPORT AttachmentBrokerUnprivileged : public IPC::AttachmentBroker {
AttachmentBrokerUnprivileged();
~AttachmentBrokerUnprivileged() override;
- // On platforms that support attachment brokering, returns a new instance of
- // a platform-specific attachment broker. Otherwise returns |nullptr|.
- // The caller takes ownership of the newly created instance, and is
- // responsible for ensuring that the attachment broker lives longer than
- // every IPC::Channel. The new instance automatically registers itself as the
- // global attachment broker.
- static scoped_ptr<AttachmentBrokerUnprivileged> CreateBroker();
+ // If there is no global attachment broker, makes a new
+ // AttachmentBrokerUnprivileged and sets it as the global attachment broker.
+ // This method is thread safe.
+ static void CreateBrokerIfNeeded();
- // In each unprivileged process, exactly one channel should be used to
- // communicate brokerable attachments with the broker process.
- void DesignateBrokerCommunicationChannel(Endpoint* endpoint);
+ // AttachmentBroker:
+ void RegisterBrokerCommunicationChannel(Endpoint* endpoint) override;
+ void DeregisterBrokerCommunicationChannel(Endpoint* endpoint) override;
+ bool IsPrivilegedBroker() override;
protected:
IPC::Sender* get_sender() { return sender_; }
diff --git a/chromium/ipc/attachment_broker_unprivileged_mac.cc b/chromium/ipc/attachment_broker_unprivileged_mac.cc
index 4e766887d9a..4f37698cdf2 100644
--- a/chromium/ipc/attachment_broker_unprivileged_mac.cc
+++ b/chromium/ipc/attachment_broker_unprivileged_mac.cc
@@ -6,6 +6,7 @@
#include <mach/mach.h>
+#include "base/mac/mach_port_util.h"
#include "base/mac/scoped_mach_port.h"
#include "base/process/process.h"
#include "ipc/attachment_broker_messages.h"
@@ -13,36 +14,6 @@
#include "ipc/ipc_sender.h"
#include "ipc/mach_port_attachment_mac.h"
-namespace {
-
-// Struct for receiving a complex message.
-struct MachReceiveComplexMessage {
- mach_msg_header_t header;
- mach_msg_body_t body;
- mach_msg_port_descriptor_t data;
- mach_msg_trailer_t trailer;
-};
-
-// Receives a Mach port from |port_to_listen_on|, which should have exactly one
-// queued message. Returns |MACH_PORT_NULL| on any error.
-base::mac::ScopedMachSendRight ReceiveMachPort(mach_port_t port_to_listen_on) {
- MachReceiveComplexMessage recv_msg;
- mach_msg_header_t* recv_hdr = &recv_msg.header;
- recv_hdr->msgh_local_port = port_to_listen_on;
- recv_hdr->msgh_size = sizeof(recv_msg);
-
- kern_return_t kr =
- mach_msg(recv_hdr, MACH_RCV_MSG | MACH_RCV_TIMEOUT, 0,
- recv_hdr->msgh_size, port_to_listen_on, 0, MACH_PORT_NULL);
- if (kr != KERN_SUCCESS)
- return base::mac::ScopedMachSendRight(MACH_PORT_NULL);
- if (recv_msg.header.msgh_id != 0)
- return base::mac::ScopedMachSendRight(MACH_PORT_NULL);
- return base::mac::ScopedMachSendRight(recv_msg.data.name);
-}
-
-} // namespace
-
namespace IPC {
AttachmentBrokerUnprivilegedMac::AttachmentBrokerUnprivilegedMac() {}
@@ -93,7 +64,7 @@ void AttachmentBrokerUnprivilegedMac::OnMachPortHasBeenDuplicated(
base::mac::ScopedMachReceiveRight message_port(wire_format.mach_port);
base::mac::ScopedMachSendRight memory_object(
- ReceiveMachPort(message_port.get()));
+ base::ReceiveMachPort(message_port.get()));
LogError(memory_object.get() == MACH_PORT_NULL ? ERR_RECEIVE_MACH_MESSAGE
: SUCCESS);
diff --git a/chromium/ipc/export_template.h b/chromium/ipc/export_template.h
new file mode 100644
index 00000000000..e743e1936f7
--- /dev/null
+++ b/chromium/ipc/export_template.h
@@ -0,0 +1,163 @@
+// Copyright 2015 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_EXPORT_TEMPLATE_H_
+#define IPC_EXPORT_TEMPLATE_H_
+
+// Synopsis
+//
+// This header provides macros for using FOO_EXPORT macros with explicit
+// template instantiation declarations and definitions.
+// Generally, the FOO_EXPORT macros are used at declarations,
+// and GCC requires them to be used at explicit instantiation declarations,
+// but MSVC requires __declspec(dllexport) to be used at the explicit
+// instantiation definitions instead.
+
+// Usage
+//
+// In a header file, write:
+//
+// extern template class EXPORT_TEMPLATE_DECLARE(FOO_EXPORT) foo<bar>;
+//
+// In a source file, write:
+//
+// template class EXPORT_TEMPLATE_DEFINE(FOO_EXPORT) foo<bar>;
+
+// Implementation notes
+//
+// The implementation of this header uses some subtle macro semantics to
+// detect what the provided FOO_EXPORT value was defined as and then
+// to dispatch to appropriate macro definitions. Unfortunately,
+// MSVC's C preprocessor is rather non-compliant and requires special
+// care to make it work.
+//
+// Issue 1.
+//
+// #define F(x)
+// F()
+//
+// MSVC emits warning C4003 ("not enough actual parameters for macro
+// 'F'), even though it's a valid macro invocation. This affects the
+// macros below that take just an "export" parameter, because export
+// may be empty.
+//
+// As a workaround, we can add a dummy parameter and arguments:
+//
+// #define F(x,_)
+// F(,)
+//
+// Issue 2.
+//
+// #define F(x) G##x
+// #define Gj() ok
+// F(j())
+//
+// The correct replacement for "F(j())" is "ok", but MSVC replaces it
+// with "Gj()". As a workaround, we can pass the result to an
+// identity macro to force MSVC to look for replacements again. (This
+// is why EXPORT_TEMPLATE_STYLE_3 exists.)
+
+#define EXPORT_TEMPLATE_DECLARE(export) \
+ EXPORT_TEMPLATE_INVOKE(DECLARE, EXPORT_TEMPLATE_STYLE(export, ), export)
+#define EXPORT_TEMPLATE_DEFINE(export) \
+ EXPORT_TEMPLATE_INVOKE(DEFINE, EXPORT_TEMPLATE_STYLE(export, ), export)
+
+// INVOKE is an internal helper macro to perform parameter replacements
+// and token pasting to chain invoke another macro. E.g.,
+// EXPORT_TEMPLATE_INVOKE(DECLARE, DEFAULT, FOO_EXPORT)
+// will export to call
+// EXPORT_TEMPLATE_DECLARE_DEFAULT(FOO_EXPORT, )
+// (but with FOO_EXPORT expanded too).
+#define EXPORT_TEMPLATE_INVOKE(which, style, export) \
+ EXPORT_TEMPLATE_INVOKE_2(which, style, export)
+#define EXPORT_TEMPLATE_INVOKE_2(which, style, export) \
+ EXPORT_TEMPLATE_##which##_##style(export, )
+
+// Default style is to apply the FOO_EXPORT macro at declaration sites.
+#define EXPORT_TEMPLATE_DECLARE_DEFAULT(export, _) export
+#define EXPORT_TEMPLATE_DEFINE_DEFAULT(export, _)
+
+// The "MSVC hack" style is used when FOO_EXPORT is defined
+// as __declspec(dllexport), which MSVC requires to be used at
+// definition sites instead.
+#define EXPORT_TEMPLATE_DECLARE_MSVC_HACK(export, _)
+#define EXPORT_TEMPLATE_DEFINE_MSVC_HACK(export, _) export
+
+// EXPORT_TEMPLATE_STYLE is an internal helper macro that identifies which
+// export style needs to be used for the provided FOO_EXPORT macro definition.
+// "", "__attribute__(...)", and "__declspec(dllimport)" are mapped
+// to "DEFAULT"; while "__declspec(dllexport)" is mapped to "MSVC_HACK".
+//
+// It's implemented with token pasting to transform the __attribute__ and
+// __declspec annotations into macro invocations. E.g., if FOO_EXPORT is
+// defined as "__declspec(dllimport)", it undergoes the following sequence of
+// macro substitutions:
+// EXPORT_TEMPLATE_STYLE(FOO_EXPORT, )
+// EXPORT_TEMPLATE_STYLE_2(__declspec(dllimport), )
+// EXPORT_TEMPLATE_STYLE_3(EXPORT_TEMPLATE_STYLE_MATCH__declspec(dllimport))
+// EXPORT_TEMPLATE_STYLE_MATCH__declspec(dllimport)
+// EXPORT_TEMPLATE_STYLE_MATCH_DECLSPEC_dllimport
+// DEFAULT
+#define EXPORT_TEMPLATE_STYLE(export, _) EXPORT_TEMPLATE_STYLE_2(export, )
+#define EXPORT_TEMPLATE_STYLE_2(export, _) \
+ EXPORT_TEMPLATE_STYLE_3( \
+ EXPORT_TEMPLATE_STYLE_MATCH_foj3FJo5StF0OvIzl7oMxA##export)
+#define EXPORT_TEMPLATE_STYLE_3(style) style
+
+// Internal helper macros for EXPORT_TEMPLATE_STYLE.
+//
+// XXX: C++ reserves all identifiers containing "__" for the implementation,
+// but "__attribute__" and "__declspec" already contain "__" and the token-paste
+// operator can only add characters; not remove them. To minimize the risk of
+// conflict with implementations, we include "foj3FJo5StF0OvIzl7oMxA" (a random
+// 128-bit string, encoded in Base64) in the macro name.
+#define EXPORT_TEMPLATE_STYLE_MATCH_foj3FJo5StF0OvIzl7oMxA DEFAULT
+#define EXPORT_TEMPLATE_STYLE_MATCH_foj3FJo5StF0OvIzl7oMxA__attribute__(...) \
+ DEFAULT
+#define EXPORT_TEMPLATE_STYLE_MATCH_foj3FJo5StF0OvIzl7oMxA__declspec(arg) \
+ EXPORT_TEMPLATE_STYLE_MATCH_DECLSPEC_##arg
+
+// Internal helper macros for EXPORT_TEMPLATE_STYLE.
+#define EXPORT_TEMPLATE_STYLE_MATCH_DECLSPEC_dllexport MSVC_HACK
+#define EXPORT_TEMPLATE_STYLE_MATCH_DECLSPEC_dllimport DEFAULT
+
+// Sanity checks.
+//
+// EXPORT_TEMPLATE_TEST uses the same macro invocation pattern as
+// EXPORT_TEMPLATE_DECLARE and EXPORT_TEMPLATE_DEFINE do to check that they're
+// working correctly. When they're working correctly, the sequence of macro
+// replacements should go something like:
+//
+// EXPORT_TEMPLATE_TEST(DEFAULT, __declspec(dllimport));
+//
+// static_assert(EXPORT_TEMPLATE_INVOKE(TEST_DEFAULT,
+// EXPORT_TEMPLATE_STYLE(__declspec(dllimport), ),
+// __declspec(dllimport)), "__declspec(dllimport)");
+//
+// static_assert(EXPORT_TEMPLATE_INVOKE(TEST_DEFAULT,
+// DEFAULT, __declspec(dllimport)), "__declspec(dllimport)");
+//
+// static_assert(EXPORT_TEMPLATE_TEST_DEFAULT_DEFAULT(
+// __declspec(dllimport)), "__declspec(dllimport)");
+//
+// static_assert(true, "__declspec(dllimport)");
+//
+// When they're not working correctly, a syntax error should occur instead.
+#define EXPORT_TEMPLATE_TEST(want, export) \
+ static_assert(EXPORT_TEMPLATE_INVOKE( \
+ TEST_##want, EXPORT_TEMPLATE_STYLE(export, ), export), \
+ #export)
+#define EXPORT_TEMPLATE_TEST_DEFAULT_DEFAULT(...) true
+#define EXPORT_TEMPLATE_TEST_MSVC_HACK_MSVC_HACK(...) true
+
+EXPORT_TEMPLATE_TEST(DEFAULT, );
+EXPORT_TEMPLATE_TEST(DEFAULT, __attribute__((visibility("default"))));
+EXPORT_TEMPLATE_TEST(MSVC_HACK, __declspec(dllexport));
+EXPORT_TEMPLATE_TEST(DEFAULT, __declspec(dllimport));
+
+#undef EXPORT_TEMPLATE_TEST
+#undef EXPORT_TEMPLATE_TEST_DEFAULT_DEFAULT
+#undef EXPORT_TEMPLATE_TEST_MSVC_HACK_MSVC_HACK
+
+#endif // IPC_EXPORT_TEMPLATE_H_
diff --git a/chromium/ipc/handle_attachment_win.cc b/chromium/ipc/handle_attachment_win.cc
index 39c4ef78c7f..cb6a7bacfc2 100644
--- a/chromium/ipc/handle_attachment_win.cc
+++ b/chromium/ipc/handle_attachment_win.cc
@@ -24,6 +24,10 @@ 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/chromium/ipc/handle_attachment_win.h b/chromium/ipc/handle_attachment_win.h
index 5e04bdb3626..ff0ce91a851 100644
--- a/chromium/ipc/handle_attachment_win.h
+++ b/chromium/ipc/handle_attachment_win.h
@@ -58,6 +58,13 @@ 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/chromium/ipc/handle_win.cc b/chromium/ipc/handle_win.cc
index f964c832057..60fa54c7cd1 100644
--- a/chromium/ipc/handle_win.cc
+++ b/chromium/ipc/handle_win.cc
@@ -21,7 +21,7 @@ HandleWin::HandleWin(const HANDLE& handle, Permissions permissions)
: handle_(handle), permissions_(permissions) {}
// static
-void ParamTraits<HandleWin>::Write(Message* m, const param_type& p) {
+void ParamTraits<HandleWin>::Write(base::Pickle* m, const param_type& p) {
scoped_refptr<IPC::internal::HandleAttachmentWin> attachment(
new IPC::internal::HandleAttachmentWin(p.get_handle(),
p.get_permissions()));
@@ -30,16 +30,18 @@ void ParamTraits<HandleWin>::Write(Message* m, const param_type& p) {
}
// static
-bool ParamTraits<HandleWin>::Read(const Message* m,
+bool ParamTraits<HandleWin>::Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
- scoped_refptr<MessageAttachment> attachment;
- if (!m->ReadAttachment(iter, &attachment))
+ scoped_refptr<base::Pickle::Attachment> base_attachment;
+ if (!m->ReadAttachment(iter, &base_attachment))
return false;
+ MessageAttachment* attachment =
+ static_cast<MessageAttachment*>(base_attachment.get());
if (attachment->GetType() != MessageAttachment::TYPE_BROKERABLE_ATTACHMENT)
return false;
BrokerableAttachment* brokerable_attachment =
- static_cast<BrokerableAttachment*>(attachment.get());
+ static_cast<BrokerableAttachment*>(attachment);
if (brokerable_attachment->GetBrokerableType() !=
BrokerableAttachment::WIN_HANDLE) {
return false;
diff --git a/chromium/ipc/handle_win.h b/chromium/ipc/handle_win.h
index 38cddae10b1..2fb5b5415ac 100644
--- a/chromium/ipc/handle_win.h
+++ b/chromium/ipc/handle_win.h
@@ -13,6 +13,7 @@
#include "ipc/ipc_param_traits.h"
namespace base {
+class Pickle;
class PickleIterator;
} // namespace base
@@ -56,8 +57,10 @@ class IPC_EXPORT HandleWin {
template <>
struct IPC_EXPORT ParamTraits<HandleWin> {
typedef HandleWin param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, base::PickleIterator* iter, param_type* p);
+ 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);
};
diff --git a/chromium/ipc/ipc.gyp b/chromium/ipc/ipc.gyp
index 05b99895112..b78bbf1674b 100644
--- a/chromium/ipc/ipc.gyp
+++ b/chromium/ipc/ipc.gyp
@@ -81,19 +81,14 @@
],
}],
['OS == "android"', {
+ 'sources!': [
+ # These multiprocess tests don't work on Android.
+ 'ipc_channel_unittest.cc',
+ ],
'dependencies': [
'../testing/android/native_test.gyp:native_test_native_code',
],
}],
- ['os_posix == 1 and OS != "mac" and OS != "android"', {
- 'conditions': [
- ['use_allocator!="none"', {
- 'dependencies': [
- '../base/allocator/allocator.gyp:allocator',
- ],
- }],
- ],
- }]
],
},
{
@@ -123,15 +118,6 @@
'../testing/android/native_test.gyp:native_test_native_code',
],
}],
- ['os_posix == 1 and OS != "mac" and OS != "android"', {
- 'conditions': [
- ['use_allocator!="none"', {
- 'dependencies': [
- '../base/allocator/allocator.gyp:allocator',
- ],
- }],
- ],
- }]
],
},
{
diff --git a/chromium/ipc/ipc.gypi b/chromium/ipc/ipc.gypi
index dbd2099e4c3..da570d230bf 100644
--- a/chromium/ipc/ipc.gypi
+++ b/chromium/ipc/ipc.gypi
@@ -30,6 +30,7 @@
'brokerable_attachment.h',
'brokerable_attachment_mac.cc',
'brokerable_attachment_win.cc',
+ 'export_template.h',
'handle_attachment_win.cc',
'handle_attachment_win.h',
'handle_win.cc',
@@ -69,6 +70,8 @@
'ipc_message_generator.h',
'ipc_message_macros.h',
'ipc_message_start.h',
+ 'ipc_message_templates.h',
+ 'ipc_message_templates_impl.h',
'ipc_message_utils.cc',
'ipc_message_utils.h',
'ipc_param_traits.h',
@@ -93,6 +96,8 @@
'message_filter.h',
'message_filter_router.cc',
'message_filter_router.h',
+ 'message_router.cc',
+ 'message_router.h',
'param_traits_log_macros.h',
'param_traits_macros.h',
'param_traits_read_macros.h',
diff --git a/chromium/ipc/ipc_channel.h b/chromium/ipc/ipc_channel.h
index dd882bb5cc0..a008e7e15d5 100644
--- a/chromium/ipc/ipc_channel.h
+++ b/chromium/ipc/ipc_channel.h
@@ -12,6 +12,7 @@
#include "base/compiler_specific.h"
#include "base/files/scoped_file.h"
+#include "base/memory/scoped_ptr.h"
#include "base/process/process.h"
#include "build/build_config.h"
#include "ipc/ipc_channel_handle.h"
@@ -164,6 +165,9 @@ class IPC_EXPORT Channel : public Endpoint {
// connect to a pre-existing pipe. Note, calling Connect()
// will not block the calling thread and may complete
// asynchronously.
+ //
+ // The subclass implementation must call WillConnect() at the beginning of its
+ // implementation.
virtual bool Connect() WARN_UNUSED_RESULT = 0;
// Close this Channel explicitly. May be called multiple times.
@@ -223,6 +227,7 @@ class IPC_EXPORT Channel : public Endpoint {
// message from client to server we need to send the PID from the global
// PID namespace.
static void SetGlobalPid(int pid);
+ static int GetGlobalPid();
#endif
#if defined(OS_ANDROID)
@@ -253,6 +258,16 @@ class IPC_EXPORT Channel : public Endpoint {
void* buffer_;
size_t length_;
};
+
+ // Endpoint overrides.
+ void OnSetAttachmentBrokerEndpoint() override;
+
+ // Subclasses must call this method at the beginning of their implementation
+ // of Connect().
+ void WillConnect();
+
+ private:
+ bool did_start_connect_ = false;
};
#if defined(OS_POSIX)
diff --git a/chromium/ipc/ipc_channel_common.cc b/chromium/ipc/ipc_channel_common.cc
index c12a360b64c..69abc3412b7 100644
--- a/chromium/ipc/ipc_channel_common.cc
+++ b/chromium/ipc/ipc_channel_common.cc
@@ -52,5 +52,13 @@ bool Channel::IsSendThreadSafe() const {
return false;
}
+void Channel::OnSetAttachmentBrokerEndpoint() {
+ CHECK(!did_start_connect_);
+}
+
+void Channel::WillConnect() {
+ did_start_connect_ = true;
+}
+
} // namespace IPC
diff --git a/chromium/ipc/ipc_channel_nacl.cc b/chromium/ipc/ipc_channel_nacl.cc
index 84d77f68d07..3515202182c 100644
--- a/chromium/ipc/ipc_channel_nacl.cc
+++ b/chromium/ipc/ipc_channel_nacl.cc
@@ -155,6 +155,8 @@ base::ProcessId ChannelNacl::GetSelfPID() const {
}
bool ChannelNacl::Connect() {
+ WillConnect();
+
if (pipe_ == -1) {
DLOG(WARNING) << "Channel creation failed: " << pipe_name_;
return false;
diff --git a/chromium/ipc/ipc_channel_posix.cc b/chromium/ipc/ipc_channel_posix.cc
index f53a8fe36ec..4b6d7facb7a 100644
--- a/chromium/ipc/ipc_channel_posix.cc
+++ b/chromium/ipc/ipc_channel_posix.cc
@@ -338,6 +338,8 @@ bool ChannelPosix::CreatePipe(
}
bool ChannelPosix::Connect() {
+ WillConnect();
+
if (!server_listen_pipe_.is_valid() && !pipe_.is_valid()) {
DLOG(WARNING) << "Channel creation failed: " << pipe_name_;
return false;
@@ -613,6 +615,10 @@ bool ChannelPosix::IsNamedServerInitialized(
void ChannelPosix::SetGlobalPid(int pid) {
global_pid_ = pid;
}
+// static
+int ChannelPosix::GetGlobalPid() {
+ return global_pid_;
+}
#endif // OS_LINUX
// Called by libevent when we can read from the pipe without blocking.
@@ -1125,6 +1131,9 @@ bool Channel::IsNamedServerInitialized(
void Channel::SetGlobalPid(int pid) {
ChannelPosix::SetGlobalPid(pid);
}
+int Channel::GetGlobalPid() {
+ return ChannelPosix::GetGlobalPid();
+}
#endif // OS_LINUX
} // namespace IPC
diff --git a/chromium/ipc/ipc_channel_posix.h b/chromium/ipc/ipc_channel_posix.h
index ddeb60ea365..14bb95c48e2 100644
--- a/chromium/ipc/ipc_channel_posix.h
+++ b/chromium/ipc/ipc_channel_posix.h
@@ -65,6 +65,7 @@ class IPC_EXPORT ChannelPosix : public Channel,
static bool IsNamedServerInitialized(const std::string& channel_id);
#if defined(OS_LINUX)
static void SetGlobalPid(int pid);
+ static int GetGlobalPid();
#endif // OS_LINUX
private:
diff --git a/chromium/ipc/ipc_channel_posix_unittest.cc b/chromium/ipc/ipc_channel_posix_unittest.cc
index c122b719508..29f0d392d69 100644
--- a/chromium/ipc/ipc_channel_posix_unittest.cc
+++ b/chromium/ipc/ipc_channel_posix_unittest.cc
@@ -148,39 +148,11 @@ void IPCChannelPosixTest::SetUpSocket(IPC::ChannelHandle *handle,
IPC::Channel::Mode mode) {
const std::string& name = handle->name;
- int socket_fd = socket(PF_UNIX, SOCK_STREAM, 0);
- ASSERT_GE(socket_fd, 0) << name;
- ASSERT_GE(fcntl(socket_fd, F_SETFL, O_NONBLOCK), 0);
- struct sockaddr_un server_address = { 0 };
- memset(&server_address, 0, sizeof(server_address));
- server_address.sun_family = AF_UNIX;
- int path_len = snprintf(server_address.sun_path, IPC::kMaxSocketNameLength,
- "%s", name.c_str());
- DCHECK_EQ(static_cast<int>(name.length()), path_len);
- size_t server_address_len = offsetof(struct sockaddr_un,
- sun_path) + path_len + 1;
-
+ int socket_fd = 0;
if (mode == IPC::Channel::MODE_NAMED_SERVER) {
- // Only one server at a time. Cleanup garbage if it exists.
- unlink(name.c_str());
- // Make sure the path we need exists.
- base::FilePath path(name);
- base::FilePath dir_path = path.DirName();
- ASSERT_TRUE(base::CreateDirectory(dir_path));
- ASSERT_GE(bind(socket_fd,
- reinterpret_cast<struct sockaddr *>(&server_address),
- server_address_len), 0) << server_address.sun_path
- << ": " << strerror(errno)
- << "(" << errno << ")";
- ASSERT_GE(listen(socket_fd, SOMAXCONN), 0) << server_address.sun_path
- << ": " << strerror(errno)
- << "(" << errno << ")";
+ IPC::CreateServerUnixDomainSocket(base::FilePath(name), &socket_fd);
} else if (mode == IPC::Channel::MODE_NAMED_CLIENT) {
- ASSERT_GE(connect(socket_fd,
- reinterpret_cast<struct sockaddr *>(&server_address),
- server_address_len), 0) << server_address.sun_path
- << ": " << strerror(errno)
- << "(" << errno << ")";
+ IPC::CreateClientUnixDomainSocket(base::FilePath(name), &socket_fd);
} else {
FAIL() << "Unknown mode " << mode;
}
diff --git a/chromium/ipc/ipc_channel_proxy.cc b/chromium/ipc/ipc_channel_proxy.cc
index 5e702617e0d..2ebc9040a1e 100644
--- a/chromium/ipc/ipc_channel_proxy.cc
+++ b/chromium/ipc/ipc_channel_proxy.cc
@@ -263,24 +263,13 @@ void ChannelProxy::Context::AddFilter(MessageFilter* filter) {
// Called on the listener's thread
void ChannelProxy::Context::OnDispatchMessage(const Message& message) {
-#if defined(IPC_MESSAGE_LOG_ENABLED)
- Logging* logger = Logging::GetInstance();
- std::string name;
- logger->GetMessageText(message.type(), &name, &message, NULL);
- TRACE_EVENT1("ipc", "ChannelProxy::Context::OnDispatchMessage",
- "name", name);
-#else
- TRACE_EVENT2("ipc", "ChannelProxy::Context::OnDispatchMessage",
- "class", IPC_MESSAGE_ID_CLASS(message.type()),
- "line", IPC_MESSAGE_ID_LINE(message.type()));
-#endif
-
if (!listener_)
return;
OnDispatchConnected();
#ifdef IPC_MESSAGE_LOG_ENABLED
+ Logging* logger = Logging::GetInstance();
if (message.type() == IPC_LOGGING_ID) {
logger->OnReceivedLoggingMessage(message);
return;
@@ -483,7 +472,7 @@ void ChannelProxy::RemoveFilter(MessageFilter* filter) {
context_->ipc_task_runner()->PostTask(
FROM_HERE, base::Bind(&Context::OnRemoveFilter, context_.get(),
- make_scoped_refptr(filter)));
+ base::RetainedRef(filter)));
}
void ChannelProxy::ClearIPCTaskRunner() {
@@ -497,6 +486,7 @@ base::ProcessId ChannelProxy::GetPeerPID() const {
}
void ChannelProxy::OnSetAttachmentBrokerEndpoint() {
+ CHECK(!did_init_);
context()->set_attachment_broker_endpoint(is_attachment_broker_endpoint());
}
diff --git a/chromium/ipc/ipc_channel_proxy.h b/chromium/ipc/ipc_channel_proxy.h
index 9fdffb1ca57..495c5eb8a52 100644
--- a/chromium/ipc/ipc_channel_proxy.h
+++ b/chromium/ipc/ipc_channel_proxy.h
@@ -97,6 +97,11 @@ class IPC_EXPORT ChannelProxy : public Endpoint, public base::NonThreadSafe {
Listener* listener,
const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner);
+ // Constructs a ChannelProxy without initializing it.
+ ChannelProxy(
+ Listener* listener,
+ const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner);
+
~ChannelProxy() override;
// Initializes the channel proxy. Only call this once to initialize a channel
@@ -159,9 +164,6 @@ class IPC_EXPORT ChannelProxy : public Endpoint, public base::NonThreadSafe {
// to the internal state.
ChannelProxy(Context* context);
- ChannelProxy(
- Listener* listener,
- const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner);
// Used internally to hold state that is referenced on the IPC thread.
class Context : public base::RefCountedThreadSafe<Context>,
diff --git a/chromium/ipc/ipc_channel_proxy_unittest_messages.h b/chromium/ipc/ipc_channel_proxy_unittest_messages.h
index 20405eda0ef..288ce5353d3 100644
--- a/chromium/ipc/ipc_channel_proxy_unittest_messages.h
+++ b/chromium/ipc/ipc_channel_proxy_unittest_messages.h
@@ -17,8 +17,10 @@ namespace IPC {
template <>
struct ParamTraits<BadType> {
- static void Write(Message* m, const BadType& p) {}
- static bool Read(const Message* m, base::PickleIterator* iter, BadType* r) {
+ static void Write(base::Pickle* m, const BadType& p) {}
+ static bool Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ BadType* r) {
return false;
}
static void Log(const BadType& p, std::string* l) {}
diff --git a/chromium/ipc/ipc_channel_reader.cc b/chromium/ipc/ipc_channel_reader.cc
index 9c6af49f2f1..e11fb93aea4 100644
--- a/chromium/ipc/ipc_channel_reader.cc
+++ b/chromium/ipc/ipc_channel_reader.cc
@@ -18,6 +18,30 @@
namespace IPC {
namespace internal {
+#ifdef IPC_MESSAGE_LOG_ENABLED
+
+namespace {
+std::string GetMessageText(const Message& message) {
+ std::string name;
+ Logging::GetInstance()->GetMessageText(
+ message.type(), &name, &message, nullptr);
+ return name;
+}
+} // namespace
+
+#define EMIT_TRACE_EVENT(message) \
+ TRACE_EVENT_WITH_FLOW1( \
+ "ipc,toplevel", "ChannelReader::DispatchInputData", \
+ (message).flags(), TRACE_EVENT_FLAG_FLOW_IN, "name", \
+ GetMessageText(message));
+#else
+#define EMIT_TRACE_EVENT(message) \
+ TRACE_EVENT_WITH_FLOW2("ipc,toplevel", "ChannelReader::DispatchInputData", \
+ (message).flags(), TRACE_EVENT_FLAG_FLOW_IN, "class", \
+ IPC_MESSAGE_ID_CLASS((message).type()), "line", \
+ IPC_MESSAGE_ID_LINE((message).type()));
+#endif // IPC_MESSAGE_LOG_ENABLED
+
ChannelReader::ChannelReader(Listener* listener)
: listener_(listener),
max_input_buffer_size_(Channel::kMaximumReadBufferSize) {
@@ -74,7 +98,7 @@ void ChannelReader::CleanUp() {
}
void ChannelReader::DispatchMessage(Message* m) {
- EmitLogBeforeDispatch(*m);
+ EMIT_TRACE_EVENT(*m);
listener_->OnMessageReceived(*m);
HandleDispatchError(*m);
}
@@ -167,7 +191,7 @@ bool ChannelReader::HandleTranslatedMessage(
const AttachmentIdVector& attachment_ids) {
// Immediately handle internal messages.
if (IsInternalMessage(*translated_message)) {
- EmitLogBeforeDispatch(*translated_message);
+ EMIT_TRACE_EVENT(*translated_message);
HandleInternalMessage(*translated_message);
HandleDispatchError(*translated_message);
return true;
@@ -180,7 +204,7 @@ bool ChannelReader::HandleTranslatedMessage(
// Ideally, the log would have been emitted prior to dispatching the
// message, but that would require this class to know more about the
// internals of attachment brokering, which should be avoided.
- EmitLogBeforeDispatch(*translated_message);
+ EMIT_TRACE_EVENT(*translated_message);
HandleDispatchError(*translated_message);
return true;
}
@@ -223,21 +247,6 @@ void ChannelReader::HandleDispatchError(const Message& message) {
listener_->OnBadMessageReceived(message);
}
-void ChannelReader::EmitLogBeforeDispatch(const Message& message) {
-#ifdef IPC_MESSAGE_LOG_ENABLED
- std::string name;
- Logging::GetInstance()->GetMessageText(message.type(), &name, &message, NULL);
- TRACE_EVENT_WITH_FLOW1("ipc,toplevel", "ChannelReader::DispatchInputData",
- message.flags(), TRACE_EVENT_FLAG_FLOW_IN, "name",
- name);
-#else
- TRACE_EVENT_WITH_FLOW2("ipc,toplevel", "ChannelReader::DispatchInputData",
- message.flags(), TRACE_EVENT_FLAG_FLOW_IN, "class",
- IPC_MESSAGE_ID_CLASS(message.type()), "line",
- IPC_MESSAGE_ID_LINE(message.type()));
-#endif
-}
-
bool ChannelReader::DispatchAttachmentBrokerMessage(const Message& message) {
#if USE_ATTACHMENT_BROKER
if (IsAttachmentBrokerEndpoint() && GetAttachmentBroker()) {
diff --git a/chromium/ipc/ipc_channel_reader.h b/chromium/ipc/ipc_channel_reader.h
index ca2bd9476e5..2ee50af5362 100644
--- a/chromium/ipc/ipc_channel_reader.h
+++ b/chromium/ipc/ipc_channel_reader.h
@@ -158,9 +158,6 @@ class IPC_EXPORT ChannelReader : public SupportsAttachmentBrokering,
// If there was a dispatch error, informs |listener_|.
void HandleDispatchError(const Message& message);
- // Emits logging associated with a Message that is about to be dispatched.
- void EmitLogBeforeDispatch(const Message& message);
-
// Attachment broker messages should be dispatched out of band, since there
// are no ordering restrictions on them, and they may be required to dispatch
// the messages waiting in |queued_messages_|.
diff --git a/chromium/ipc/ipc_channel_unittest.cc b/chromium/ipc/ipc_channel_unittest.cc
index 0a49ca9abe0..134bec26edc 100644
--- a/chromium/ipc/ipc_channel_unittest.cc
+++ b/chromium/ipc/ipc_channel_unittest.cc
@@ -24,12 +24,7 @@ namespace {
class IPCChannelTest : public IPCTestBase {
};
-#if defined(OS_ANDROID)
-#define MAYBE_ChannelTest DISABLED_ChannelTest
-#else
-#define MAYBE_ChannelTest ChannelTest
-#endif
-TEST_F(IPCChannelTest, MAYBE_ChannelTest) {
+TEST_F(IPCChannelTest, ChannelTest) {
Init("GenericClient");
// Set up IPC channel and start client.
@@ -91,12 +86,7 @@ TEST_F(IPCChannelTest, ChannelTestExistingPipe) {
}
#endif // defined (OS_WIN)
-#if defined(OS_ANDROID)
-#define MAYBE_ChannelProxyTest DISABLED_ChannelProxyTest
-#else
-#define MAYBE_ChannelProxyTest ChannelProxyTest
-#endif
-TEST_F(IPCChannelTest, MAYBE_ChannelProxyTest) {
+TEST_F(IPCChannelTest, ChannelProxyTest) {
Init("GenericClient");
base::Thread thread("ChannelProxyTestServer");
@@ -133,7 +123,7 @@ class ChannelListenerWithOnConnectedSend : public IPC::TestChannelListener {
}
};
-#if defined(OS_WIN) || defined(OS_ANDROID)
+#if defined(OS_WIN)
// Acting flakey in Windows. http://crbug.com/129595
#define MAYBE_SendMessageInChannelConnected DISABLED_SendMessageInChannelConnected
#else
diff --git a/chromium/ipc/ipc_channel_win.cc b/chromium/ipc/ipc_channel_win.cc
index 62918627c17..057b9a50787 100644
--- a/chromium/ipc/ipc_channel_win.cc
+++ b/chromium/ipc/ipc_channel_win.cc
@@ -392,6 +392,8 @@ bool ChannelWin::CreatePipe(const IPC::ChannelHandle &channel_handle,
}
bool ChannelWin::Connect() {
+ WillConnect();
+
DLOG_IF(WARNING, thread_check_.get()) << "Connect called more than once";
if (!thread_check_.get())
diff --git a/chromium/ipc/ipc_endpoint.h b/chromium/ipc/ipc_endpoint.h
index 2ace1fe999c..3315f54e8a6 100644
--- a/chromium/ipc/ipc_endpoint.h
+++ b/chromium/ipc/ipc_endpoint.h
@@ -32,7 +32,7 @@ class IPC_EXPORT Endpoint : public Sender {
// A callback that indicates that is_attachment_broker_endpoint() has been
// changed.
- virtual void OnSetAttachmentBrokerEndpoint(){};
+ virtual void OnSetAttachmentBrokerEndpoint() = 0;
// Whether this channel is used as an endpoint for sending and receiving
// brokerable attachment messages to/from the broker process.
diff --git a/chromium/ipc/ipc_message.cc b/chromium/ipc/ipc_message.cc
index 71f72997452..289f08dab06 100644
--- a/chromium/ipc/ipc_message.cc
+++ b/chromium/ipc/ipc_message.cc
@@ -240,11 +240,13 @@ bool Message::AddPlaceholderBrokerableAttachmentWithId(
return attachment_set()->AddAttachment(attachment);
}
-bool Message::WriteAttachment(scoped_refptr<MessageAttachment> attachment) {
+bool Message::WriteAttachment(
+ scoped_refptr<base::Pickle::Attachment> attachment) {
bool brokerable;
size_t index;
- bool success =
- attachment_set()->AddAttachment(attachment, &index, &brokerable);
+ bool success = attachment_set()->AddAttachment(
+ make_scoped_refptr(static_cast<MessageAttachment*>(attachment.get())),
+ &index, &brokerable);
DCHECK(success);
// Write the type of descriptor.
@@ -264,7 +266,7 @@ bool Message::WriteAttachment(scoped_refptr<MessageAttachment> attachment) {
bool Message::ReadAttachment(
base::PickleIterator* iter,
- scoped_refptr<MessageAttachment>* attachment) const {
+ scoped_refptr<base::Pickle::Attachment>* attachment) const {
bool brokerable;
if (!iter->ReadBool(&brokerable))
return false;
diff --git a/chromium/ipc/ipc_message.h b/chromium/ipc/ipc_message.h
index a6c641d7104..56c3a46b5e9 100644
--- a/chromium/ipc/ipc_message.h
+++ b/chromium/ipc/ipc_message.h
@@ -221,13 +221,15 @@ class IPC_EXPORT Message : public base::Pickle {
// WriteAttachment appends |attachment| to the end of the set. It returns
// false iff the set is full.
- bool WriteAttachment(scoped_refptr<MessageAttachment> attachment);
+ bool WriteAttachment(
+ scoped_refptr<base::Pickle::Attachment> attachment) override;
// ReadAttachment parses an attachment given the parsing state |iter| and
// writes it to |*attachment|. It returns true on success.
- bool ReadAttachment(base::PickleIterator* iter,
- scoped_refptr<MessageAttachment>* attachment) const;
+ bool ReadAttachment(
+ base::PickleIterator* iter,
+ scoped_refptr<base::Pickle::Attachment>* attachment) const override;
// Returns true if there are any attachment in this message.
- bool HasAttachments() const;
+ bool HasAttachments() const override;
// Returns true if there are any MojoHandleAttachments in this message.
bool HasMojoHandles() const;
// Whether the message has any brokerable attachments.
diff --git a/chromium/ipc/ipc_message_attachment.h b/chromium/ipc/ipc_message_attachment.h
index dda06300012..7f7137d87b2 100644
--- a/chromium/ipc/ipc_message_attachment.h
+++ b/chromium/ipc/ipc_message_attachment.h
@@ -8,6 +8,7 @@
#include "base/files/file.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "base/pickle.h"
#include "build/build_config.h"
#include "ipc/ipc_export.h"
@@ -15,8 +16,7 @@ namespace IPC {
// Auxiliary data sent with |Message|. This can be a platform file descriptor
// or a mojo |MessagePipe|. |GetType()| returns the type of the subclass.
-class IPC_EXPORT MessageAttachment
- : public base::RefCountedThreadSafe<MessageAttachment> {
+class IPC_EXPORT MessageAttachment : public base::Pickle::Attachment {
public:
enum Type {
TYPE_PLATFORM_FILE, // The instance is |PlatformFileAttachment|.
@@ -33,7 +33,7 @@ class IPC_EXPORT MessageAttachment
protected:
friend class base::RefCountedThreadSafe<MessageAttachment>;
MessageAttachment();
- virtual ~MessageAttachment();
+ ~MessageAttachment() override;
DISALLOW_COPY_AND_ASSIGN(MessageAttachment);
};
diff --git a/chromium/ipc/ipc_message_macros.h b/chromium/ipc/ipc_message_macros.h
index f9fc28e6c94..38f428e90aa 100644
--- a/chromium/ipc/ipc_message_macros.h
+++ b/chromium/ipc/ipc_message_macros.h
@@ -45,6 +45,11 @@
// // Generate destructors.
// #include "ipc/struct_destructor_macros.h"
// #include "path/to/YYY_message_generator.h"
+// // Generate param traits size methods.
+// #include "ipc/param_traits_size_macros.h"
+// namespace IPC {
+// #include "path/to/YYY_message_generator.h"
+// } // namespace IPC
// // Generate param traits write methods.
// #include "ipc/param_traits_write_macros.h"
// namespace IPC {
@@ -196,14 +201,14 @@
#include <stdint.h>
+#include <tuple>
+
#include "base/profiler/scoped_profile.h"
+#include "ipc/export_template.h"
+#include "ipc/ipc_message_templates.h"
#include "ipc/ipc_message_utils.h"
#include "ipc/param_traits_macros.h"
-#if defined(IPC_MESSAGE_IMPL)
-#include "ipc/ipc_message_utils_impl.h"
-#endif
-
// Convenience macro for defining structs without inheritance. Should not need
// to be subsequently redefined.
#define IPC_STRUCT_BEGIN(struct_name) \
@@ -222,566 +227,63 @@
#define IPC_STRUCT_MEMBER(type, name, ...) type name;
#define IPC_STRUCT_END() };
-// Message macros collect specific numbers of arguments and funnel them into
-// the common message generation macro. These should never be redefined.
-#define IPC_MESSAGE_CONTROL0(msg_class) \
- IPC_MESSAGE_DECL(EMPTY, CONTROL, msg_class, 0, 0, (), ())
-
-#define IPC_MESSAGE_CONTROL1(msg_class, type1) \
- IPC_MESSAGE_DECL(ASYNC, CONTROL, msg_class, 1, 0, (type1), ())
-
-#define IPC_MESSAGE_CONTROL2(msg_class, type1, type2) \
- IPC_MESSAGE_DECL(ASYNC, CONTROL, msg_class, 2, 0, (type1, type2), ())
-
-#define IPC_MESSAGE_CONTROL3(msg_class, type1, type2, type3) \
- IPC_MESSAGE_DECL(ASYNC, CONTROL, msg_class, 3, 0, (type1, type2, type3), ())
-
-#define IPC_MESSAGE_CONTROL4(msg_class, type1, type2, type3, type4) \
- IPC_MESSAGE_DECL(ASYNC, CONTROL, msg_class, 4, 0, (type1, type2, type3, type4), ())
-
-#define IPC_MESSAGE_CONTROL5(msg_class, type1, type2, type3, type4, type5) \
- IPC_MESSAGE_DECL(ASYNC, CONTROL, msg_class, 5, 0, (type1, type2, type3, type4, type5), ())
-
-#define IPC_MESSAGE_ROUTED0(msg_class) \
- IPC_MESSAGE_DECL(EMPTY, ROUTED, msg_class, 0, 0, (), ())
-
-#define IPC_MESSAGE_ROUTED1(msg_class, type1) \
- IPC_MESSAGE_DECL(ASYNC, ROUTED, msg_class, 1, 0, (type1), ())
-
-#define IPC_MESSAGE_ROUTED2(msg_class, type1, type2) \
- IPC_MESSAGE_DECL(ASYNC, ROUTED, msg_class, 2, 0, (type1, type2), ())
-
-#define IPC_MESSAGE_ROUTED3(msg_class, type1, type2, type3) \
- IPC_MESSAGE_DECL(ASYNC, ROUTED, msg_class, 3, 0, (type1, type2, type3), ())
-
-#define IPC_MESSAGE_ROUTED4(msg_class, type1, type2, type3, type4) \
- IPC_MESSAGE_DECL(ASYNC, ROUTED, msg_class, 4, 0, (type1, type2, type3, type4), ())
-
-#define IPC_MESSAGE_ROUTED5(msg_class, type1, type2, type3, type4, type5) \
- IPC_MESSAGE_DECL(ASYNC, ROUTED, msg_class, 5, 0, (type1, type2, type3, type4, type5), ())
-
-#define IPC_SYNC_MESSAGE_CONTROL0_0(msg_class) \
- IPC_MESSAGE_DECL(SYNC, CONTROL, msg_class, 0, 0, (), ())
-
-#define IPC_SYNC_MESSAGE_CONTROL0_1(msg_class, type1_out) \
- IPC_MESSAGE_DECL(SYNC, CONTROL, msg_class, 0, 1, (), (type1_out))
-
-#define IPC_SYNC_MESSAGE_CONTROL0_2(msg_class, type1_out, type2_out) \
- IPC_MESSAGE_DECL(SYNC, CONTROL, msg_class, 0, 2, (), (type1_out, type2_out))
-
-#define IPC_SYNC_MESSAGE_CONTROL0_3(msg_class, type1_out, type2_out, type3_out) \
- IPC_MESSAGE_DECL(SYNC, CONTROL, msg_class, 0, 3, (), (type1_out, type2_out, type3_out))
-
-#define IPC_SYNC_MESSAGE_CONTROL0_4(msg_class, type1_out, type2_out, type3_out, type4_out) \
- IPC_MESSAGE_DECL(SYNC, CONTROL, msg_class, 0, 4, (), (type1_out, type2_out, type3_out, type4_out))
-
-#define IPC_SYNC_MESSAGE_CONTROL1_0(msg_class, type1_in) \
- IPC_MESSAGE_DECL(SYNC, CONTROL, msg_class, 1, 0, (type1_in), ())
-
-#define IPC_SYNC_MESSAGE_CONTROL1_1(msg_class, type1_in, type1_out) \
- IPC_MESSAGE_DECL(SYNC, CONTROL, msg_class, 1, 1, (type1_in), (type1_out))
-
-#define IPC_SYNC_MESSAGE_CONTROL1_2(msg_class, type1_in, type1_out, type2_out) \
- IPC_MESSAGE_DECL(SYNC, CONTROL, msg_class, 1, 2, (type1_in), (type1_out, type2_out))
-
-#define IPC_SYNC_MESSAGE_CONTROL1_3(msg_class, type1_in, type1_out, type2_out, type3_out) \
- IPC_MESSAGE_DECL(SYNC, CONTROL, msg_class, 1, 3, (type1_in), (type1_out, type2_out, type3_out))
-
-#define IPC_SYNC_MESSAGE_CONTROL1_4(msg_class, type1_in, type1_out, type2_out, type3_out, type4_out) \
- IPC_MESSAGE_DECL(SYNC, CONTROL, msg_class, 1, 4, (type1_in), (type1_out, type2_out, type3_out, type4_out))
-
-#define IPC_SYNC_MESSAGE_CONTROL2_0(msg_class, type1_in, type2_in) \
- IPC_MESSAGE_DECL(SYNC, CONTROL, msg_class, 2, 0, (type1_in, type2_in), ())
-
-#define IPC_SYNC_MESSAGE_CONTROL2_1(msg_class, type1_in, type2_in, type1_out) \
- IPC_MESSAGE_DECL(SYNC, CONTROL, msg_class, 2, 1, (type1_in, type2_in), (type1_out))
-
-#define IPC_SYNC_MESSAGE_CONTROL2_2(msg_class, type1_in, type2_in, type1_out, type2_out) \
- IPC_MESSAGE_DECL(SYNC, CONTROL, msg_class, 2, 2, (type1_in, type2_in), (type1_out, type2_out))
-
-#define IPC_SYNC_MESSAGE_CONTROL2_3(msg_class, type1_in, type2_in, type1_out, type2_out, type3_out) \
- IPC_MESSAGE_DECL(SYNC, CONTROL, msg_class, 2, 3, (type1_in, type2_in), (type1_out, type2_out, type3_out))
+// Message macros collect arguments and funnel them into the common message
+// generation macro. These should never be redefined.
-#define IPC_SYNC_MESSAGE_CONTROL2_4(msg_class, type1_in, type2_in, type1_out, type2_out, type3_out, type4_out) \
- IPC_MESSAGE_DECL(SYNC, CONTROL, msg_class, 2, 4, (type1_in, type2_in), (type1_out, type2_out, type3_out, type4_out))
+// Asynchronous messages have only in parameters and are declared like:
+// IPC_MESSAGE_CONTROL(FooMsg, int, float)
+#define IPC_MESSAGE_CONTROL(msg_class, ...) \
+ IPC_MESSAGE_DECL(msg_class, CONTROL, IPC_TUPLE(__VA_ARGS__), void)
+#define IPC_MESSAGE_ROUTED(msg_class, ...) \
+ IPC_MESSAGE_DECL(msg_class, ROUTED, IPC_TUPLE(__VA_ARGS__), void)
-#define IPC_SYNC_MESSAGE_CONTROL3_0(msg_class, type1_in, type2_in, type3_in) \
- IPC_MESSAGE_DECL(SYNC, CONTROL, msg_class, 3, 0, (type1_in, type2_in, type3_in), ())
-
-#define IPC_SYNC_MESSAGE_CONTROL3_1(msg_class, type1_in, type2_in, type3_in, type1_out) \
- IPC_MESSAGE_DECL(SYNC, CONTROL, msg_class, 3, 1, (type1_in, type2_in, type3_in), (type1_out))
-
-#define IPC_SYNC_MESSAGE_CONTROL3_2(msg_class, type1_in, type2_in, type3_in, type1_out, type2_out) \
- IPC_MESSAGE_DECL(SYNC, CONTROL, msg_class, 3, 2, (type1_in, type2_in, type3_in), (type1_out, type2_out))
-
-#define IPC_SYNC_MESSAGE_CONTROL3_3(msg_class, type1_in, type2_in, type3_in, type1_out, type2_out, type3_out) \
- IPC_MESSAGE_DECL(SYNC, CONTROL, msg_class, 3, 3, (type1_in, type2_in, type3_in), (type1_out, type2_out, type3_out))
-
-#define IPC_SYNC_MESSAGE_CONTROL3_4(msg_class, type1_in, type2_in, type3_in, type1_out, type2_out, type3_out, type4_out) \
- IPC_MESSAGE_DECL(SYNC, CONTROL, msg_class, 3, 4, (type1_in, type2_in, type3_in), (type1_out, type2_out, type3_out, type4_out))
-
-#define IPC_SYNC_MESSAGE_CONTROL4_0(msg_class, type1_in, type2_in, type3_in, type4_in) \
- IPC_MESSAGE_DECL(SYNC, CONTROL, msg_class, 4, 0, (type1_in, type2_in, type3_in, type4_in), ())
-
-#define IPC_SYNC_MESSAGE_CONTROL4_1(msg_class, type1_in, type2_in, type3_in, type4_in, type1_out) \
- IPC_MESSAGE_DECL(SYNC, CONTROL, msg_class, 4, 1, (type1_in, type2_in, type3_in, type4_in), (type1_out))
-
-#define IPC_SYNC_MESSAGE_CONTROL4_2(msg_class, type1_in, type2_in, type3_in, type4_in, type1_out, type2_out) \
- IPC_MESSAGE_DECL(SYNC, CONTROL, msg_class, 4, 2, (type1_in, type2_in, type3_in, type4_in), (type1_out, type2_out))
-
-#define IPC_SYNC_MESSAGE_CONTROL4_3(msg_class, type1_in, type2_in, type3_in, type4_in, type1_out, type2_out, type3_out) \
- IPC_MESSAGE_DECL(SYNC, CONTROL, msg_class, 4, 3, (type1_in, type2_in, type3_in, type4_in), (type1_out, type2_out, type3_out))
-
-#define IPC_SYNC_MESSAGE_CONTROL4_4(msg_class, type1_in, type2_in, type3_in, type4_in, type1_out, type2_out, type3_out, type4_out) \
- IPC_MESSAGE_DECL(SYNC, CONTROL, msg_class, 4, 4, (type1_in, type2_in, type3_in, type4_in), (type1_out, type2_out, type3_out, type4_out))
-
-#define IPC_SYNC_MESSAGE_CONTROL5_0(msg_class, type1_in, type2_in, type3_in, type4_in, type5_in) \
- IPC_MESSAGE_DECL(SYNC, CONTROL, msg_class, 5, 0, (type1_in, type2_in, type3_in, type4_in, type5_in), ())
-
-#define IPC_SYNC_MESSAGE_CONTROL5_1(msg_class, type1_in, type2_in, type3_in, type4_in, type5_in, type1_out) \
- IPC_MESSAGE_DECL(SYNC, CONTROL, msg_class, 5, 1, (type1_in, type2_in, type3_in, type4_in, type5_in), (type1_out))
-
-#define IPC_SYNC_MESSAGE_CONTROL5_2(msg_class, type1_in, type2_in, type3_in, type4_in, type5_in, type1_out, type2_out) \
- IPC_MESSAGE_DECL(SYNC, CONTROL, msg_class, 5, 2, (type1_in, type2_in, type3_in, type4_in, type5_in), (type1_out, type2_out))
-
-#define IPC_SYNC_MESSAGE_CONTROL5_3(msg_class, type1_in, type2_in, type3_in, type4_in, type5_in, type1_out, type2_out, type3_out) \
- IPC_MESSAGE_DECL(SYNC, CONTROL, msg_class, 5, 3, (type1_in, type2_in, type3_in, type4_in, type5_in), (type1_out, type2_out, type3_out))
-
-#define IPC_SYNC_MESSAGE_ROUTED0_0(msg_class) \
- IPC_MESSAGE_DECL(SYNC, ROUTED, msg_class, 0, 0, (), ())
-
-#define IPC_SYNC_MESSAGE_ROUTED0_1(msg_class, type1_out) \
- IPC_MESSAGE_DECL(SYNC, ROUTED, msg_class, 0, 1, (), (type1_out))
-
-#define IPC_SYNC_MESSAGE_ROUTED0_2(msg_class, type1_out, type2_out) \
- IPC_MESSAGE_DECL(SYNC, ROUTED, msg_class, 0, 2, (), (type1_out, type2_out))
-
-#define IPC_SYNC_MESSAGE_ROUTED0_3(msg_class, type1_out, type2_out, type3_out) \
- IPC_MESSAGE_DECL(SYNC, ROUTED, msg_class, 0, 3, (), (type1_out, type2_out, type3_out))
-
-#define IPC_SYNC_MESSAGE_ROUTED0_4(msg_class, type1_out, type2_out, type3_out, type4_out) \
- IPC_MESSAGE_DECL(SYNC, ROUTED, msg_class, 0, 4, (), (type1_out, type2_out, type3_out, type4_out))
-
-#define IPC_SYNC_MESSAGE_ROUTED1_0(msg_class, type1_in) \
- IPC_MESSAGE_DECL(SYNC, ROUTED, msg_class, 1, 0, (type1_in), ())
-
-#define IPC_SYNC_MESSAGE_ROUTED1_1(msg_class, type1_in, type1_out) \
- IPC_MESSAGE_DECL(SYNC, ROUTED, msg_class, 1, 1, (type1_in), (type1_out))
-
-#define IPC_SYNC_MESSAGE_ROUTED1_2(msg_class, type1_in, type1_out, type2_out) \
- IPC_MESSAGE_DECL(SYNC, ROUTED, msg_class, 1, 2, (type1_in), (type1_out, type2_out))
-
-#define IPC_SYNC_MESSAGE_ROUTED1_3(msg_class, type1_in, type1_out, type2_out, type3_out) \
- IPC_MESSAGE_DECL(SYNC, ROUTED, msg_class, 1, 3, (type1_in), (type1_out, type2_out, type3_out))
-
-#define IPC_SYNC_MESSAGE_ROUTED1_4(msg_class, type1_in, type1_out, type2_out, type3_out, type4_out) \
- IPC_MESSAGE_DECL(SYNC, ROUTED, msg_class, 1, 4, (type1_in), (type1_out, type2_out, type3_out, type4_out))
-
-#define IPC_SYNC_MESSAGE_ROUTED2_0(msg_class, type1_in, type2_in) \
- IPC_MESSAGE_DECL(SYNC, ROUTED, msg_class, 2, 0, (type1_in, type2_in), ())
-
-#define IPC_SYNC_MESSAGE_ROUTED2_1(msg_class, type1_in, type2_in, type1_out) \
- IPC_MESSAGE_DECL(SYNC, ROUTED, msg_class, 2, 1, (type1_in, type2_in), (type1_out))
-
-#define IPC_SYNC_MESSAGE_ROUTED2_2(msg_class, type1_in, type2_in, type1_out, type2_out) \
- IPC_MESSAGE_DECL(SYNC, ROUTED, msg_class, 2, 2, (type1_in, type2_in), (type1_out, type2_out))
-
-#define IPC_SYNC_MESSAGE_ROUTED2_3(msg_class, type1_in, type2_in, type1_out, type2_out, type3_out) \
- IPC_MESSAGE_DECL(SYNC, ROUTED, msg_class, 2, 3, (type1_in, type2_in), (type1_out, type2_out, type3_out))
-
-#define IPC_SYNC_MESSAGE_ROUTED2_4(msg_class, type1_in, type2_in, type1_out, type2_out, type3_out, type4_out) \
- IPC_MESSAGE_DECL(SYNC, ROUTED, msg_class, 2, 4, (type1_in, type2_in), (type1_out, type2_out, type3_out, type4_out))
-
-#define IPC_SYNC_MESSAGE_ROUTED3_0(msg_class, type1_in, type2_in, type3_in) \
- IPC_MESSAGE_DECL(SYNC, ROUTED, msg_class, 3, 0, (type1_in, type2_in, type3_in), ())
-
-#define IPC_SYNC_MESSAGE_ROUTED3_1(msg_class, type1_in, type2_in, type3_in, type1_out) \
- IPC_MESSAGE_DECL(SYNC, ROUTED, msg_class, 3, 1, (type1_in, type2_in, type3_in), (type1_out))
-
-#define IPC_SYNC_MESSAGE_ROUTED3_2(msg_class, type1_in, type2_in, type3_in, type1_out, type2_out) \
- IPC_MESSAGE_DECL(SYNC, ROUTED, msg_class, 3, 2, (type1_in, type2_in, type3_in), (type1_out, type2_out))
-
-#define IPC_SYNC_MESSAGE_ROUTED3_3(msg_class, type1_in, type2_in, type3_in, type1_out, type2_out, type3_out) \
- IPC_MESSAGE_DECL(SYNC, ROUTED, msg_class, 3, 3, (type1_in, type2_in, type3_in), (type1_out, type2_out, type3_out))
-
-#define IPC_SYNC_MESSAGE_ROUTED3_4(msg_class, type1_in, type2_in, type3_in, type1_out, type2_out, type3_out, type4_out) \
- IPC_MESSAGE_DECL(SYNC, ROUTED, msg_class, 3, 4, (type1_in, type2_in, type3_in), (type1_out, type2_out, type3_out, type4_out))
-
-#define IPC_SYNC_MESSAGE_ROUTED4_0(msg_class, type1_in, type2_in, type3_in, type4_in) \
- IPC_MESSAGE_DECL(SYNC, ROUTED, msg_class, 4, 0, (type1_in, type2_in, type3_in, type4_in), ())
-
-#define IPC_SYNC_MESSAGE_ROUTED4_1(msg_class, type1_in, type2_in, type3_in, type4_in, type1_out) \
- IPC_MESSAGE_DECL(SYNC, ROUTED, msg_class, 4, 1, (type1_in, type2_in, type3_in, type4_in), (type1_out))
-
-#define IPC_SYNC_MESSAGE_ROUTED4_2(msg_class, type1_in, type2_in, type3_in, type4_in, type1_out, type2_out) \
- IPC_MESSAGE_DECL(SYNC, ROUTED, msg_class, 4, 2, (type1_in, type2_in, type3_in, type4_in), (type1_out, type2_out))
-
-#define IPC_SYNC_MESSAGE_ROUTED4_3(msg_class, type1_in, type2_in, type3_in, type4_in, type1_out, type2_out, type3_out) \
- IPC_MESSAGE_DECL(SYNC, ROUTED, msg_class, 4, 3, (type1_in, type2_in, type3_in, type4_in), (type1_out, type2_out, type3_out))
-
-#define IPC_SYNC_MESSAGE_ROUTED4_4(msg_class, type1_in, type2_in, type3_in, type4_in, type1_out, type2_out, type3_out, type4_out) \
- IPC_MESSAGE_DECL(SYNC, ROUTED, msg_class, 4, 4, (type1_in, type2_in, type3_in, type4_in), (type1_out, type2_out, type3_out, type4_out))
-
-#define IPC_SYNC_MESSAGE_ROUTED5_0(msg_class, type1_in, type2_in, type3_in, type4_in, type5_in) \
- IPC_MESSAGE_DECL(SYNC, ROUTED, msg_class, 5, 0, (type1_in, type2_in, type3_in, type4_in, type5_in), ())
-
-#define IPC_SYNC_MESSAGE_ROUTED5_1(msg_class, type1_in, type2_in, type3_in, type4_in, type5_in, type1_out) \
- IPC_MESSAGE_DECL(SYNC, ROUTED, msg_class, 5, 1, (type1_in, type2_in, type3_in, type4_in, type5_in), (type1_out))
-
-#define IPC_SYNC_MESSAGE_ROUTED5_2(msg_class, type1_in, type2_in, type3_in, type4_in, type5_in, type1_out, type2_out) \
- IPC_MESSAGE_DECL(SYNC, ROUTED, msg_class, 5, 2, (type1_in, type2_in, type3_in, type4_in, type5_in), (type1_out, type2_out))
-
-#define IPC_SYNC_MESSAGE_ROUTED5_3(msg_class, type1_in, type2_in, type3_in, type4_in, type5_in, type1_out, type2_out, type3_out) \
- IPC_MESSAGE_DECL(SYNC, ROUTED, msg_class, 5, 3, (type1_in, type2_in, type3_in, type4_in, type5_in), (type1_out, type2_out, type3_out))
-
-// The following macros define the common set of methods provided by ASYNC
-// message classes.
-// This macro is for all the async IPCs that don't pass an extra parameter using
-// IPC_BEGIN_MESSAGE_MAP_WITH_PARAM.
-#define IPC_ASYNC_MESSAGE_METHODS_GENERIC \
- template<class T, class S, class P, class Method> \
- static bool Dispatch(const Message* msg, T* obj, S* sender, P* parameter, \
- Method func) { \
- Schema::Param p; \
- if (Read(msg, &p)) { \
- base::DispatchToMethod(obj, func, p); \
- return true; \
- } \
- return false; \
- }
-
-// The following macros are for for async IPCs which have a dispatcher with an
-// extra parameter specified using IPC_BEGIN_MESSAGE_MAP_WITH_PARAM.
-#define IPC_ASYNC_MESSAGE_METHODS_1 \
- IPC_ASYNC_MESSAGE_METHODS_GENERIC \
- template<class T, class S, class P, typename TA> \
- static bool Dispatch(const Message* msg, T* obj, S* sender, P* parameter, \
- void (T::*func)(P*, TA)) { \
- Schema::Param p; \
- if (Read(msg, &p)) { \
- (obj->*func)(parameter, base::get<0>(p)); \
- return true; \
- } \
- return false; \
- }
-#define IPC_ASYNC_MESSAGE_METHODS_2 \
- IPC_ASYNC_MESSAGE_METHODS_GENERIC \
- template<class T, class S, class P, typename TA, typename TB> \
- static bool Dispatch(const Message* msg, T* obj, S* sender, P* parameter, \
- void (T::*func)(P*, TA, TB)) { \
- Schema::Param p; \
- if (Read(msg, &p)) { \
- (obj->*func)(parameter, base::get<0>(p), base::get<1>(p)); \
- return true; \
- } \
- return false; \
- }
-#define IPC_ASYNC_MESSAGE_METHODS_3 \
- IPC_ASYNC_MESSAGE_METHODS_GENERIC \
- template<class T, class S, class P, typename TA, typename TB, typename TC> \
- static bool Dispatch(const Message* msg, T* obj, S* sender, P* parameter, \
- void (T::*func)(P*, TA, TB, TC)) { \
- Schema::Param p; \
- if (Read(msg, &p)) { \
- (obj->*func)(parameter, base::get<0>(p), base::get<1>(p), \
- base::get<2>(p)); \
- return true; \
- } \
- return false; \
- }
-#define IPC_ASYNC_MESSAGE_METHODS_4 \
- IPC_ASYNC_MESSAGE_METHODS_GENERIC \
- template<class T, class S, class P, typename TA, typename TB, typename TC, \
- typename TD> \
- static bool Dispatch(const Message* msg, T* obj, S* sender, P* parameter, \
- void (T::*func)(P*, TA, TB, TC, TD)) { \
- Schema::Param p; \
- if (Read(msg, &p)) { \
- (obj->*func)(parameter, base::get<0>(p), base::get<1>(p), \
- base::get<2>(p), base::get<3>(p)); \
- return true; \
- } \
- return false; \
- }
-#define IPC_ASYNC_MESSAGE_METHODS_5 \
- IPC_ASYNC_MESSAGE_METHODS_GENERIC \
- template<class T, class S, class P, typename TA, typename TB, typename TC, \
- typename TD, typename TE> \
- static bool Dispatch(const Message* msg, T* obj, S* sender, P* parameter, \
- void (T::*func)(P*, TA, TB, TC, TD, TE)) { \
- Schema::Param p; \
- if (Read(msg, &p)) { \
- (obj->*func)(parameter, base::get<0>(p), base::get<1>(p), \
- base::get<2>(p), base::get<3>(p), base::get<4>(p)); \
- return true; \
- } \
- return false; \
- }
-
-// The following macros define the common set of methods provided by SYNC
-// message classes.
-#define IPC_SYNC_MESSAGE_METHODS_GENERIC \
- template<class T, class S, class P, class Method> \
- static bool Dispatch(const Message* msg, T* obj, S* sender, P* parameter, \
- Method func) { \
- Schema::SendParam send_params; \
- bool ok = ReadSendParam(msg, &send_params); \
- return Schema::DispatchWithSendParams(ok, send_params, msg, obj, sender, \
- func); \
- } \
- template<class T, class P, class Method> \
- static bool DispatchDelayReply(const Message* msg, T* obj, P* parameter, \
- Method func) { \
- Schema::SendParam send_params; \
- bool ok = ReadSendParam(msg, &send_params); \
- return Schema::DispatchDelayReplyWithSendParams(ok, send_params, msg, \
- obj, func); \
- }
-#define IPC_SYNC_MESSAGE_METHODS_0 \
- IPC_SYNC_MESSAGE_METHODS_GENERIC
-#define IPC_SYNC_MESSAGE_METHODS_1 \
- IPC_SYNC_MESSAGE_METHODS_GENERIC \
- template<typename TA> \
- static void WriteReplyParams(Message* reply, TA a) { \
- Schema::WriteReplyParams(reply, a); \
- }
-#define IPC_SYNC_MESSAGE_METHODS_2 \
- IPC_SYNC_MESSAGE_METHODS_GENERIC \
- template<typename TA, typename TB> \
- static void WriteReplyParams(Message* reply, TA a, TB b) { \
- Schema::WriteReplyParams(reply, a, b); \
- }
-#define IPC_SYNC_MESSAGE_METHODS_3 \
- IPC_SYNC_MESSAGE_METHODS_GENERIC \
- template<typename TA, typename TB, typename TC> \
- static void WriteReplyParams(Message* reply, TA a, TB b, TC c) { \
- Schema::WriteReplyParams(reply, a, b, c); \
- }
-#define IPC_SYNC_MESSAGE_METHODS_4 \
- IPC_SYNC_MESSAGE_METHODS_GENERIC \
- template<typename TA, typename TB, typename TC, typename TD> \
- static void WriteReplyParams(Message* reply, TA a, TB b, TC c, TD d) { \
- Schema::WriteReplyParams(reply, a, b, c, d); \
- }
-#define IPC_SYNC_MESSAGE_METHODS_5 \
- IPC_SYNC_MESSAGE_METHODS_GENERIC \
- template<typename TA, typename TB, typename TC, typename TD, typename TE> \
- static void WriteReplyParams(Message* reply, TA a, TB b, TC c, TD d, TE e) { \
- Schema::WriteReplyParams(reply, a, b, c, d, e); \
- }
-
-// Common message macro which dispatches into one of the 6 (sync x kind)
-// routines. There is a way that these 6 cases can be lumped together,
-// but the macros get very complicated in that case.
-// Note: intended be redefined to generate other information.
-#define IPC_MESSAGE_DECL(sync, kind, msg_class, \
- in_cnt, out_cnt, in_list, out_list) \
- IPC_##sync##_##kind##_DECL(msg_class, in_cnt, out_cnt, in_list, out_list) \
- IPC_MESSAGE_EXTRA(sync, kind, msg_class, in_cnt, out_cnt, in_list, out_list)
-
-#define IPC_EMPTY_CONTROL_DECL(msg_class, in_cnt, out_cnt, in_list, out_list) \
- class IPC_MESSAGE_EXPORT msg_class : public IPC::Message { \
- public: \
- typedef IPC::Message Schema; \
- enum { ID = IPC_MESSAGE_ID() }; \
- msg_class() : IPC::Message(MSG_ROUTING_CONTROL, ID, PRIORITY_NORMAL) {} \
- static void Log(std::string* name, const Message* msg, std::string* l); \
- };
-
-#define IPC_EMPTY_ROUTED_DECL(msg_class, in_cnt, out_cnt, in_list, out_list) \
- class IPC_MESSAGE_EXPORT msg_class : public IPC::Message { \
- public: \
- typedef IPC::Message Schema; \
- enum { ID = IPC_MESSAGE_ID() }; \
- msg_class(int32_t routing_id) \
- : IPC::Message(routing_id, ID, PRIORITY_NORMAL) {} \
- static void Log(std::string* name, const Message* msg, std::string* l); \
- };
-
-#define IPC_ASYNC_CONTROL_DECL(msg_class, in_cnt, out_cnt, in_list, out_list) \
- class IPC_MESSAGE_EXPORT msg_class : public IPC::Message { \
- public: \
- typedef IPC::MessageSchema<IPC_TUPLE_IN_##in_cnt in_list> Schema; \
- typedef Schema::Param Param; \
- enum { ID = IPC_MESSAGE_ID() }; \
- msg_class(IPC_TYPE_IN_##in_cnt in_list); \
- ~msg_class() override; \
- static bool Read(const Message* msg, Schema::Param* p); \
- static void Log(std::string* name, const Message* msg, std::string* l); \
- IPC_ASYNC_MESSAGE_METHODS_##in_cnt \
- };
-
-#define IPC_ASYNC_ROUTED_DECL(msg_class, in_cnt, out_cnt, in_list, out_list) \
- class IPC_MESSAGE_EXPORT msg_class : public IPC::Message { \
- public: \
- typedef IPC::MessageSchema<IPC_TUPLE_IN_##in_cnt in_list> Schema; \
- typedef Schema::Param Param; \
- enum { ID = IPC_MESSAGE_ID() }; \
- msg_class(int32_t routing_id IPC_COMMA_##in_cnt \
- IPC_TYPE_IN_##in_cnt in_list); \
- ~msg_class() override; \
- static bool Read(const Message* msg, Schema::Param* p); \
- static void Log(std::string* name, const Message* msg, std::string* l); \
- IPC_ASYNC_MESSAGE_METHODS_##in_cnt \
- };
-
-#define IPC_SYNC_CONTROL_DECL(msg_class, in_cnt, out_cnt, in_list, out_list) \
- class IPC_MESSAGE_EXPORT msg_class : public IPC::SyncMessage { \
- public: \
- typedef IPC::SyncMessageSchema<IPC_TUPLE_IN_##in_cnt in_list, \
- IPC_TUPLE_OUT_##out_cnt out_list> Schema; \
- typedef Schema::ReplyParam ReplyParam; \
- typedef Schema::SendParam SendParam; \
- enum { ID = IPC_MESSAGE_ID() }; \
- msg_class(IPC_TYPE_IN_##in_cnt in_list \
- IPC_COMMA_AND_##in_cnt(IPC_COMMA_##out_cnt) \
- IPC_TYPE_OUT_##out_cnt out_list); \
- ~msg_class() override; \
- static bool ReadSendParam(const Message* msg, Schema::SendParam* p); \
- static bool ReadReplyParam( \
- const Message* msg, \
- base::TupleTypes<ReplyParam>::ValueTuple* p); \
- static void Log(std::string* name, const Message* msg, std::string* l); \
- IPC_SYNC_MESSAGE_METHODS_##out_cnt \
- };
-
-#define IPC_SYNC_ROUTED_DECL(msg_class, in_cnt, out_cnt, in_list, out_list) \
- class IPC_MESSAGE_EXPORT msg_class : public IPC::SyncMessage { \
- public: \
- typedef IPC::SyncMessageSchema<IPC_TUPLE_IN_##in_cnt in_list, \
- IPC_TUPLE_OUT_##out_cnt out_list> Schema; \
- typedef Schema::ReplyParam ReplyParam; \
- typedef Schema::SendParam SendParam; \
- enum { ID = IPC_MESSAGE_ID() }; \
- msg_class(int32_t routing_id \
- IPC_COMMA_OR_##in_cnt(IPC_COMMA_##out_cnt) \
- IPC_TYPE_IN_##in_cnt in_list \
- IPC_COMMA_AND_##in_cnt(IPC_COMMA_##out_cnt) \
- IPC_TYPE_OUT_##out_cnt out_list); \
- ~msg_class() override; \
- static bool ReadSendParam(const Message* msg, Schema::SendParam* p); \
- static bool ReadReplyParam( \
- const Message* msg, \
- base::TupleTypes<ReplyParam>::ValueTuple* p); \
- static void Log(std::string* name, const Message* msg, std::string* l); \
- IPC_SYNC_MESSAGE_METHODS_##out_cnt \
- };
+// Synchronous messages have both in and out parameters, so the lists need to
+// be parenthesized to disambiguate:
+// IPC_SYNC_MESSAGE_CONTROL(BarMsg, (int, int), (bool))
+//
+// Implementation detail: The parentheses supplied by the caller for
+// disambiguation are also used to trigger the IPC_TUPLE invocations below,
+// so "IPC_TUPLE in" and "IPC_TUPLE out" are intentional.
+#define IPC_SYNC_MESSAGE_CONTROL(msg_class, in, out) \
+ IPC_MESSAGE_DECL(msg_class, CONTROL, IPC_TUPLE in, IPC_TUPLE out)
+#define IPC_SYNC_MESSAGE_ROUTED(msg_class, in, out) \
+ IPC_MESSAGE_DECL(msg_class, ROUTED, IPC_TUPLE in, IPC_TUPLE out)
+
+#define IPC_TUPLE(...) IPC::CheckedTuple<__VA_ARGS__>::Tuple
+
+#define IPC_MESSAGE_DECL(msg_name, kind, in_tuple, out_tuple) \
+ struct IPC_MESSAGE_EXPORT msg_name##_Meta { \
+ using InTuple = in_tuple; \
+ using OutTuple = out_tuple; \
+ enum { ID = IPC_MESSAGE_ID() }; \
+ static const IPC::MessageKind kKind = IPC::MessageKind::kind; \
+ static const char kName[]; \
+ }; \
+ extern template class EXPORT_TEMPLATE_DECLARE(IPC_MESSAGE_EXPORT) \
+ IPC::MessageT<msg_name##_Meta>; \
+ using msg_name = IPC::MessageT<msg_name##_Meta>; \
+ IPC_MESSAGE_EXTRA(msg_name)
#if defined(IPC_MESSAGE_IMPL)
-// "Implementation" inclusion produces constructors, destructors, and
-// logging functions, except for the no-arg special cases, where the
-// implementation occurs in the declaration, and there is no special
-// logging function.
-#define IPC_MESSAGE_EXTRA(sync, kind, msg_class, \
- in_cnt, out_cnt, in_list, out_list) \
- IPC_##sync##_##kind##_IMPL(msg_class, in_cnt, out_cnt, in_list, out_list) \
- IPC_##sync##_MESSAGE_LOG(msg_class)
-
-#define IPC_EMPTY_CONTROL_IMPL(msg_class, in_cnt, out_cnt, in_list, out_list)
-#define IPC_EMPTY_ROUTED_IMPL(msg_class, in_cnt, out_cnt, in_list, out_list)
-
-#define IPC_ASYNC_CONTROL_IMPL(msg_class, in_cnt, out_cnt, in_list, out_list) \
- msg_class::msg_class(IPC_TYPE_IN_##in_cnt in_list) : \
- IPC::Message(MSG_ROUTING_CONTROL, ID, PRIORITY_NORMAL) { \
- Schema::Write(this, IPC_NAME_IN_##in_cnt in_list); \
- } \
- msg_class::~msg_class() {} \
- bool msg_class::Read(const Message* msg, Schema::Param* p) { \
- return Schema::Read(msg, p); \
- }
-
-#define IPC_ASYNC_ROUTED_IMPL(msg_class, in_cnt, out_cnt, in_list, out_list) \
- msg_class::msg_class(int32_t routing_id IPC_COMMA_##in_cnt \
- IPC_TYPE_IN_##in_cnt in_list) : \
- IPC::Message(routing_id, ID, PRIORITY_NORMAL) { \
- Schema::Write(this, IPC_NAME_IN_##in_cnt in_list); \
- } \
- msg_class::~msg_class() {} \
- bool msg_class::Read(const Message* msg, Schema::Param* p) { \
- return Schema::Read(msg, p); \
- }
-
-#define IPC_SYNC_CONTROL_IMPL(msg_class, in_cnt, out_cnt, in_list, out_list) \
- msg_class::msg_class(IPC_TYPE_IN_##in_cnt in_list \
- IPC_COMMA_AND_##in_cnt(IPC_COMMA_##out_cnt) \
- IPC_TYPE_OUT_##out_cnt out_list) : \
- IPC::SyncMessage(MSG_ROUTING_CONTROL, ID, PRIORITY_NORMAL, \
- new IPC::ParamDeserializer<Schema::ReplyParam>( \
- IPC_NAME_OUT_##out_cnt out_list)) { \
- Schema::Write(this, IPC_NAME_IN_##in_cnt in_list); \
- } \
- msg_class::~msg_class() {} \
- bool msg_class::ReadSendParam(const Message* msg, Schema::SendParam* p) { \
- return Schema::ReadSendParam(msg, p); \
- } \
- bool msg_class::ReadReplyParam( \
- const Message* msg, \
- base::TupleTypes<ReplyParam>::ValueTuple* p) { \
- return Schema::ReadReplyParam(msg, p); \
- }
-
-#define IPC_SYNC_ROUTED_IMPL(msg_class, in_cnt, out_cnt, in_list, out_list) \
- msg_class::msg_class(int32_t routing_id \
- IPC_COMMA_OR_##in_cnt(IPC_COMMA_##out_cnt) \
- IPC_TYPE_IN_##in_cnt in_list \
- IPC_COMMA_AND_##in_cnt(IPC_COMMA_##out_cnt) \
- IPC_TYPE_OUT_##out_cnt out_list) : \
- IPC::SyncMessage(routing_id, ID, PRIORITY_NORMAL, \
- new IPC::ParamDeserializer<Schema::ReplyParam>( \
- IPC_NAME_OUT_##out_cnt out_list)) { \
- Schema::Write(this, IPC_NAME_IN_##in_cnt in_list); \
- } \
- msg_class::~msg_class() {} \
- bool msg_class::ReadSendParam(const Message* msg, Schema::SendParam* p) { \
- return Schema::ReadSendParam(msg, p); \
- } \
- bool msg_class::ReadReplyParam( \
- const Message* msg, \
- base::TupleTypes<ReplyParam>::ValueTuple* p) { \
- return Schema::ReadReplyParam(msg, p); \
- }
-
-#define IPC_EMPTY_MESSAGE_LOG(msg_class) \
- void msg_class::Log(std::string* name, \
- const Message* msg, \
- std::string* l) { \
- if (name) \
- *name = #msg_class; \
- }
-
-#define IPC_ASYNC_MESSAGE_LOG(msg_class) \
- void msg_class::Log(std::string* name, \
- const Message* msg, \
- std::string* l) { \
- if (name) \
- *name = #msg_class; \
- if (!msg || !l) \
- return; \
- Schema::Param p; \
- if (Schema::Read(msg, &p)) \
- IPC::LogParam(p, l); \
- }
-
-#define IPC_SYNC_MESSAGE_LOG(msg_class) \
- void msg_class::Log(std::string* name, \
- const Message* msg, \
- std::string* l) { \
- if (name) \
- *name = #msg_class; \
- if (!msg || !l) \
- return; \
- if (msg->is_sync()) { \
- base::TupleTypes<Schema::SendParam>::ValueTuple p; \
- if (Schema::ReadSendParam(msg, &p)) \
- IPC::LogParam(p, l); \
- AddOutputParamsToLog(msg, l); \
- } else { \
- base::TupleTypes<Schema::ReplyParam>::ValueTuple p; \
- if (Schema::ReadReplyParam(msg, &p)) \
- IPC::LogParam(p, l); \
- } \
- }
+// "Implementation" inclusion provides the explicit template definition
+// for msg_name.
+#define IPC_MESSAGE_EXTRA(msg_name) \
+ const char msg_name##_Meta::kName[] = #msg_name; \
+ IPC_MESSAGE_DEFINE_KIND(msg_name) \
+ template class EXPORT_TEMPLATE_DEFINE(IPC_MESSAGE_EXPORT) \
+ IPC::MessageT<msg_name##_Meta>;
+
+// MSVC has an intentionally non-compliant "feature" that results in LNK2005
+// ("symbol already defined") errors if we provide an out-of-line definition
+// for kKind. Microsoft's official response is to test for _MSC_EXTENSIONS:
+// https://connect.microsoft.com/VisualStudio/feedback/details/786583/
+#if defined(_MSC_EXTENSIONS)
+#define IPC_MESSAGE_DEFINE_KIND(msg_name)
+#else
+#define IPC_MESSAGE_DEFINE_KIND(msg_name) \
+ const IPC::MessageKind msg_name##_Meta::kKind;
+#endif
#elif defined(IPC_MESSAGE_MACROS_LOG_ENABLED)
@@ -790,95 +292,22 @@
#endif
// "Log table" inclusion produces extra logging registration code.
-#define IPC_MESSAGE_EXTRA(sync, kind, msg_class, \
- in_cnt, out_cnt, in_list, out_list) \
- class LoggerRegisterHelper##msg_class { \
- public: \
- LoggerRegisterHelper##msg_class() { \
- const uint32_t msg_id = static_cast<uint32_t>(msg_class::ID); \
- IPC_LOG_TABLE_ADD_ENTRY(msg_id, msg_class::Log); \
- } \
- }; \
- LoggerRegisterHelper##msg_class g_LoggerRegisterHelper##msg_class;
+#define IPC_MESSAGE_EXTRA(msg_name) \
+ class LoggerRegisterHelper##msg_name { \
+ public: \
+ LoggerRegisterHelper##msg_name() { \
+ const uint32_t msg_id = static_cast<uint32_t>(msg_name::ID); \
+ IPC_LOG_TABLE_ADD_ENTRY(msg_id, msg_name::Log); \
+ } \
+ }; \
+ LoggerRegisterHelper##msg_name g_LoggerRegisterHelper##msg_name;
#else
// Normal inclusion produces nothing extra.
-#define IPC_MESSAGE_EXTRA(sync, kind, msg_class, \
- in_cnt, out_cnt, in_list, out_list)
-
-#endif // defined(IPC_MESSAGE_IMPL)
-
-// Handle variable sized argument lists. These are usually invoked by token
-// pasting against the argument counts.
-#define IPC_TYPE_IN_0()
-#define IPC_TYPE_IN_1(t1) const t1& arg1
-#define IPC_TYPE_IN_2(t1, t2) const t1& arg1, const t2& arg2
-#define IPC_TYPE_IN_3(t1, t2, t3) const t1& arg1, const t2& arg2, const t3& arg3
-#define IPC_TYPE_IN_4(t1, t2, t3, t4) const t1& arg1, const t2& arg2, const t3& arg3, const t4& arg4
-#define IPC_TYPE_IN_5(t1, t2, t3, t4, t5) const t1& arg1, const t2& arg2, const t3& arg3, const t4& arg4, const t5& arg5
-
-#define IPC_TYPE_OUT_0()
-#define IPC_TYPE_OUT_1(t1) t1* arg6
-#define IPC_TYPE_OUT_2(t1, t2) t1* arg6, t2* arg7
-#define IPC_TYPE_OUT_3(t1, t2, t3) t1* arg6, t2* arg7, t3* arg8
-#define IPC_TYPE_OUT_4(t1, t2, t3, t4) t1* arg6, t2* arg7, t3* arg8, \
- t4* arg9
-
-#define IPC_TUPLE_IN_0() base::Tuple<>
-#define IPC_TUPLE_IN_1(t1) base::Tuple<t1>
-#define IPC_TUPLE_IN_2(t1, t2) base::Tuple<t1, t2>
-#define IPC_TUPLE_IN_3(t1, t2, t3) base::Tuple<t1, t2, t3>
-#define IPC_TUPLE_IN_4(t1, t2, t3, t4) base::Tuple<t1, t2, t3, t4>
-#define IPC_TUPLE_IN_5(t1, t2, t3, t4, t5) base::Tuple<t1, t2, t3, t4, t5>
-
-#define IPC_TUPLE_OUT_0() base::Tuple<>
-#define IPC_TUPLE_OUT_1(t1) base::Tuple<t1&>
-#define IPC_TUPLE_OUT_2(t1, t2) base::Tuple<t1&, t2&>
-#define IPC_TUPLE_OUT_3(t1, t2, t3) base::Tuple<t1&, t2&, t3&>
-#define IPC_TUPLE_OUT_4(t1, t2, t3, t4) base::Tuple<t1&, t2&, t3&, t4&>
-
-#define IPC_NAME_IN_0() base::MakeTuple()
-#define IPC_NAME_IN_1(t1) base::MakeRefTuple(arg1)
-#define IPC_NAME_IN_2(t1, t2) base::MakeRefTuple(arg1, arg2)
-#define IPC_NAME_IN_3(t1, t2, t3) base::MakeRefTuple(arg1, arg2, arg3)
-#define IPC_NAME_IN_4(t1, t2, t3, t4) base::MakeRefTuple(arg1, arg2, \
- arg3, arg4)
-#define IPC_NAME_IN_5(t1, t2, t3, t4, t5) base::MakeRefTuple(arg1, arg2, \
- arg3, arg4, arg5)
-
-#define IPC_NAME_OUT_0() base::MakeTuple()
-#define IPC_NAME_OUT_1(t1) base::MakeRefTuple(*arg6)
-#define IPC_NAME_OUT_2(t1, t2) base::MakeRefTuple(*arg6, *arg7)
-#define IPC_NAME_OUT_3(t1, t2, t3) base::MakeRefTuple(*arg6, *arg7, \
- *arg8)
-#define IPC_NAME_OUT_4(t1, t2, t3, t4) base::MakeRefTuple(*arg6, *arg7, \
- *arg8, *arg9)
-
-// There are places where the syntax requires a comma if there are input args,
-// if there are input args and output args, or if there are input args or
-// output args. These macros allow generation of the comma as needed; invoke
-// by token pasting against the argument counts.
-#define IPC_COMMA_0
-#define IPC_COMMA_1 ,
-#define IPC_COMMA_2 ,
-#define IPC_COMMA_3 ,
-#define IPC_COMMA_4 ,
-#define IPC_COMMA_5 ,
-
-#define IPC_COMMA_AND_0(x)
-#define IPC_COMMA_AND_1(x) x
-#define IPC_COMMA_AND_2(x) x
-#define IPC_COMMA_AND_3(x) x
-#define IPC_COMMA_AND_4(x) x
-#define IPC_COMMA_AND_5(x) x
-
-#define IPC_COMMA_OR_0(x) x
-#define IPC_COMMA_OR_1(x) ,
-#define IPC_COMMA_OR_2(x) ,
-#define IPC_COMMA_OR_3(x) ,
-#define IPC_COMMA_OR_4(x) ,
-#define IPC_COMMA_OR_5(x) ,
+#define IPC_MESSAGE_EXTRA(msg_name)
+
+#endif // defined(IPC_MESSAGE_IMPL)
// Message IDs
// Note: we currently use __LINE__ to give unique IDs to messages within
@@ -906,6 +335,7 @@
{ \
typedef class_name _IpcMessageHandlerClass ALLOW_UNUSED_TYPE; \
void* param__ = NULL; \
+ (void)param__; \
const IPC::Message& ipc_message__ = msg; \
switch (ipc_message__.type()) {
@@ -973,8 +403,145 @@
}
// This corresponds to an enum value from IPCMessageStart.
-#define IPC_MESSAGE_CLASS(message) \
- IPC_MESSAGE_ID_CLASS(message.type())
+#define IPC_MESSAGE_CLASS(message) IPC_MESSAGE_ID_CLASS((message).type())
+
+// Deprecated legacy macro names.
+// TODO(mdempsky): Replace uses with generic names.
+
+#define IPC_MESSAGE_CONTROL0(msg) IPC_MESSAGE_CONTROL(msg)
+#define IPC_MESSAGE_CONTROL1(msg, a) IPC_MESSAGE_CONTROL(msg, a)
+#define IPC_MESSAGE_CONTROL2(msg, a, b) IPC_MESSAGE_CONTROL(msg, a, b)
+#define IPC_MESSAGE_CONTROL3(msg, a, b, c) IPC_MESSAGE_CONTROL(msg, a, b, c)
+#define IPC_MESSAGE_CONTROL4(msg, a, b, c, d) \
+ IPC_MESSAGE_CONTROL(msg, a, b, c, d)
+#define IPC_MESSAGE_CONTROL5(msg, a, b, c, d, e) \
+ IPC_MESSAGE_CONTROL(msg, a, b, c, d, e)
+
+#define IPC_MESSAGE_ROUTED0(msg) IPC_MESSAGE_ROUTED(msg)
+#define IPC_MESSAGE_ROUTED1(msg, a) IPC_MESSAGE_ROUTED(msg, a)
+#define IPC_MESSAGE_ROUTED2(msg, a, b) IPC_MESSAGE_ROUTED(msg, a, b)
+#define IPC_MESSAGE_ROUTED3(msg, a, b, c) IPC_MESSAGE_ROUTED(msg, a, b, c)
+#define IPC_MESSAGE_ROUTED4(msg, a, b, c, d) IPC_MESSAGE_ROUTED(msg, a, b, c, d)
+#define IPC_MESSAGE_ROUTED5(msg, a, b, c, d, e) \
+ IPC_MESSAGE_ROUTED(msg, a, b, c, d, e)
+
+#define IPC_SYNC_MESSAGE_CONTROL0_0(msg) IPC_SYNC_MESSAGE_CONTROL(msg, (), ())
+#define IPC_SYNC_MESSAGE_CONTROL0_1(msg, a) \
+ IPC_SYNC_MESSAGE_CONTROL(msg, (), (a))
+#define IPC_SYNC_MESSAGE_CONTROL0_2(msg, a, b) \
+ IPC_SYNC_MESSAGE_CONTROL(msg, (), (a, b))
+#define IPC_SYNC_MESSAGE_CONTROL0_3(msg, a, b, c) \
+ IPC_SYNC_MESSAGE_CONTROL(msg, (), (a, b, c))
+#define IPC_SYNC_MESSAGE_CONTROL0_4(msg, a, b, c, d) \
+ IPC_SYNC_MESSAGE_CONTROL(msg, (), (a, b, c, d))
+#define IPC_SYNC_MESSAGE_CONTROL1_0(msg, a) \
+ IPC_SYNC_MESSAGE_CONTROL(msg, (a), ())
+#define IPC_SYNC_MESSAGE_CONTROL1_1(msg, a, b) \
+ IPC_SYNC_MESSAGE_CONTROL(msg, (a), (b))
+#define IPC_SYNC_MESSAGE_CONTROL1_2(msg, a, b, c) \
+ IPC_SYNC_MESSAGE_CONTROL(msg, (a), (b, c))
+#define IPC_SYNC_MESSAGE_CONTROL1_3(msg, a, b, c, d) \
+ IPC_SYNC_MESSAGE_CONTROL(msg, (a), (b, c, d))
+#define IPC_SYNC_MESSAGE_CONTROL1_4(msg, a, b, c, d, e) \
+ IPC_SYNC_MESSAGE_CONTROL(msg, (a), (b, c, d, e))
+#define IPC_SYNC_MESSAGE_CONTROL2_0(msg, a, b) \
+ IPC_SYNC_MESSAGE_CONTROL(msg, (a, b), ())
+#define IPC_SYNC_MESSAGE_CONTROL2_1(msg, a, b, c) \
+ IPC_SYNC_MESSAGE_CONTROL(msg, (a, b), (c))
+#define IPC_SYNC_MESSAGE_CONTROL2_2(msg, a, b, c, d) \
+ IPC_SYNC_MESSAGE_CONTROL(msg, (a, b), (c, d))
+#define IPC_SYNC_MESSAGE_CONTROL2_3(msg, a, b, c, d, e) \
+ IPC_SYNC_MESSAGE_CONTROL(msg, (a, b), (c, d, e))
+#define IPC_SYNC_MESSAGE_CONTROL2_4(msg, a, b, c, d, e, f) \
+ IPC_SYNC_MESSAGE_CONTROL(msg, (a, b), (c, d, e, f))
+#define IPC_SYNC_MESSAGE_CONTROL3_0(msg, a, b, c) \
+ IPC_SYNC_MESSAGE_CONTROL(msg, (a, b, c), ())
+#define IPC_SYNC_MESSAGE_CONTROL3_1(msg, a, b, c, d) \
+ IPC_SYNC_MESSAGE_CONTROL(msg, (a, b, c), (d))
+#define IPC_SYNC_MESSAGE_CONTROL3_2(msg, a, b, c, d, e) \
+ IPC_SYNC_MESSAGE_CONTROL(msg, (a, b, c), (d, e))
+#define IPC_SYNC_MESSAGE_CONTROL3_3(msg, a, b, c, d, e, f) \
+ IPC_SYNC_MESSAGE_CONTROL(msg, (a, b, c), (d, e, f))
+#define IPC_SYNC_MESSAGE_CONTROL3_4(msg, a, b, c, d, e, f, g) \
+ IPC_SYNC_MESSAGE_CONTROL(msg, (a, b, c), (d, e, f, g))
+#define IPC_SYNC_MESSAGE_CONTROL4_0(msg, a, b, c, d) \
+ IPC_SYNC_MESSAGE_CONTROL(msg, (a, b, c, d), ())
+#define IPC_SYNC_MESSAGE_CONTROL4_1(msg, a, b, c, d, e) \
+ IPC_SYNC_MESSAGE_CONTROL(msg, (a, b, c, d), (e))
+#define IPC_SYNC_MESSAGE_CONTROL4_2(msg, a, b, c, d, e, f) \
+ IPC_SYNC_MESSAGE_CONTROL(msg, (a, b, c, d), (e, f))
+#define IPC_SYNC_MESSAGE_CONTROL4_3(msg, a, b, c, d, e, f, g) \
+ IPC_SYNC_MESSAGE_CONTROL(msg, (a, b, c, d), (e, f, g))
+#define IPC_SYNC_MESSAGE_CONTROL4_4(msg, a, b, c, d, e, f, g, h) \
+ IPC_SYNC_MESSAGE_CONTROL(msg, (a, b, c, d), (e, f, g, h))
+#define IPC_SYNC_MESSAGE_CONTROL5_0(msg, a, b, c, d, e) \
+ IPC_SYNC_MESSAGE_CONTROL(msg, (a, b, c, d, e), ())
+#define IPC_SYNC_MESSAGE_CONTROL5_1(msg, a, b, c, d, e, f) \
+ IPC_SYNC_MESSAGE_CONTROL(msg, (a, b, c, d, e), (f))
+#define IPC_SYNC_MESSAGE_CONTROL5_2(msg, a, b, c, d, e, f, g) \
+ IPC_SYNC_MESSAGE_CONTROL(msg, (a, b, c, d, e), (f, g))
+#define IPC_SYNC_MESSAGE_CONTROL5_3(msg, a, b, c, d, e, f, g, h) \
+ IPC_SYNC_MESSAGE_CONTROL(msg, (a, b, c, d, e), (f, g, h))
+#define IPC_SYNC_MESSAGE_CONTROL5_4(msg, a, b, c, d, e, f, g, h, i) \
+ IPC_SYNC_MESSAGE_CONTROL(msg, (a, b, c, d, e), (f, g, h, i))
+
+#define IPC_SYNC_MESSAGE_ROUTED0_0(msg) IPC_SYNC_MESSAGE_ROUTED(msg, (), ())
+#define IPC_SYNC_MESSAGE_ROUTED0_1(msg, a) IPC_SYNC_MESSAGE_ROUTED(msg, (), (a))
+#define IPC_SYNC_MESSAGE_ROUTED0_2(msg, a, b) \
+ IPC_SYNC_MESSAGE_ROUTED(msg, (), (a, b))
+#define IPC_SYNC_MESSAGE_ROUTED0_3(msg, a, b, c) \
+ IPC_SYNC_MESSAGE_ROUTED(msg, (), (a, b, c))
+#define IPC_SYNC_MESSAGE_ROUTED0_4(msg, a, b, c, d) \
+ IPC_SYNC_MESSAGE_ROUTED(msg, (), (a, b, c, d))
+#define IPC_SYNC_MESSAGE_ROUTED1_0(msg, a) IPC_SYNC_MESSAGE_ROUTED(msg, (a), ())
+#define IPC_SYNC_MESSAGE_ROUTED1_1(msg, a, b) \
+ IPC_SYNC_MESSAGE_ROUTED(msg, (a), (b))
+#define IPC_SYNC_MESSAGE_ROUTED1_2(msg, a, b, c) \
+ IPC_SYNC_MESSAGE_ROUTED(msg, (a), (b, c))
+#define IPC_SYNC_MESSAGE_ROUTED1_3(msg, a, b, c, d) \
+ IPC_SYNC_MESSAGE_ROUTED(msg, (a), (b, c, d))
+#define IPC_SYNC_MESSAGE_ROUTED1_4(msg, a, b, c, d, e) \
+ IPC_SYNC_MESSAGE_ROUTED(msg, (a), (b, c, d, e))
+#define IPC_SYNC_MESSAGE_ROUTED2_0(msg, a, b) \
+ IPC_SYNC_MESSAGE_ROUTED(msg, (a, b), ())
+#define IPC_SYNC_MESSAGE_ROUTED2_1(msg, a, b, c) \
+ IPC_SYNC_MESSAGE_ROUTED(msg, (a, b), (c))
+#define IPC_SYNC_MESSAGE_ROUTED2_2(msg, a, b, c, d) \
+ IPC_SYNC_MESSAGE_ROUTED(msg, (a, b), (c, d))
+#define IPC_SYNC_MESSAGE_ROUTED2_3(msg, a, b, c, d, e) \
+ IPC_SYNC_MESSAGE_ROUTED(msg, (a, b), (c, d, e))
+#define IPC_SYNC_MESSAGE_ROUTED2_4(msg, a, b, c, d, e, f) \
+ IPC_SYNC_MESSAGE_ROUTED(msg, (a, b), (c, d, e, f))
+#define IPC_SYNC_MESSAGE_ROUTED3_0(msg, a, b, c) \
+ IPC_SYNC_MESSAGE_ROUTED(msg, (a, b, c), ())
+#define IPC_SYNC_MESSAGE_ROUTED3_1(msg, a, b, c, d) \
+ IPC_SYNC_MESSAGE_ROUTED(msg, (a, b, c), (d))
+#define IPC_SYNC_MESSAGE_ROUTED3_2(msg, a, b, c, d, e) \
+ IPC_SYNC_MESSAGE_ROUTED(msg, (a, b, c), (d, e))
+#define IPC_SYNC_MESSAGE_ROUTED3_3(msg, a, b, c, d, e, f) \
+ IPC_SYNC_MESSAGE_ROUTED(msg, (a, b, c), (d, e, f))
+#define IPC_SYNC_MESSAGE_ROUTED3_4(msg, a, b, c, d, e, f, g) \
+ IPC_SYNC_MESSAGE_ROUTED(msg, (a, b, c), (d, e, f, g))
+#define IPC_SYNC_MESSAGE_ROUTED4_0(msg, a, b, c, d) \
+ IPC_SYNC_MESSAGE_ROUTED(msg, (a, b, c, d), ())
+#define IPC_SYNC_MESSAGE_ROUTED4_1(msg, a, b, c, d, e) \
+ IPC_SYNC_MESSAGE_ROUTED(msg, (a, b, c, d), (e))
+#define IPC_SYNC_MESSAGE_ROUTED4_2(msg, a, b, c, d, e, f) \
+ IPC_SYNC_MESSAGE_ROUTED(msg, (a, b, c, d), (e, f))
+#define IPC_SYNC_MESSAGE_ROUTED4_3(msg, a, b, c, d, e, f, g) \
+ IPC_SYNC_MESSAGE_ROUTED(msg, (a, b, c, d), (e, f, g))
+#define IPC_SYNC_MESSAGE_ROUTED4_4(msg, a, b, c, d, e, f, g, h) \
+ IPC_SYNC_MESSAGE_ROUTED(msg, (a, b, c, d), (e, f, g, h))
+#define IPC_SYNC_MESSAGE_ROUTED5_0(msg, a, b, c, d, e) \
+ IPC_SYNC_MESSAGE_ROUTED(msg, (a, b, c, d, e), ())
+#define IPC_SYNC_MESSAGE_ROUTED5_1(msg, a, b, c, d, e, f) \
+ IPC_SYNC_MESSAGE_ROUTED(msg, (a, b, c, d, e), (f))
+#define IPC_SYNC_MESSAGE_ROUTED5_2(msg, a, b, c, d, e, f, g) \
+ IPC_SYNC_MESSAGE_ROUTED(msg, (a, b, c, d, e), (f, g))
+#define IPC_SYNC_MESSAGE_ROUTED5_3(msg, a, b, c, d, e, f, g, h) \
+ IPC_SYNC_MESSAGE_ROUTED(msg, (a, b, c, d, e), (f, g, h))
+#define IPC_SYNC_MESSAGE_ROUTED5_4(msg, a, b, c, d, e, f, g, h, i) \
+ IPC_SYNC_MESSAGE_ROUTED(msg, (a, b, c, d, e), (f, g, h, i))
#endif // IPC_IPC_MESSAGE_MACROS_H_
diff --git a/chromium/ipc/ipc_message_null_macros.h b/chromium/ipc/ipc_message_null_macros.h
index 5a1ff4f4fa7..6eab78419be 100644
--- a/chromium/ipc/ipc_message_null_macros.h
+++ b/chromium/ipc/ipc_message_null_macros.h
@@ -24,6 +24,4 @@
#define IPC_STRUCT_TRAITS_PARENT(type)
#define IPC_STRUCT_TRAITS_END()
#define IPC_ENUM_TRAITS_VALIDATE(enum_name, validation_expression)
-#define IPC_MESSAGE_DECL(sync, kind, msg_class, \
- in_cnt, out_cnt, in_list, out_list)
-
+#define IPC_MESSAGE_DECL(...)
diff --git a/chromium/ipc/ipc_message_start.h b/chromium/ipc/ipc_message_start.h
index 8197ac62970..c3abddc0ae2 100644
--- a/chromium/ipc/ipc_message_start.h
+++ b/chromium/ipc/ipc_message_start.h
@@ -11,17 +11,18 @@
enum IPCMessageStart {
AutomationMsgStart = 0,
FrameMsgStart,
+ PageMsgStart,
ViewMsgStart,
InputMsgStart,
- PluginMsgStart,
- PluginProcessMsgStart,
ProfileImportMsgStart,
TestMsgStart,
DevToolsMsgStart,
WorkerMsgStart,
NaClMsgStart,
UtilityMsgStart,
+ GpuChannelMsgStart,
GpuMsgStart,
+ MediaMsgStart,
ServiceMsgStart,
PpapiMsgStart,
FirefoxImporterUnittestMsgStart,
@@ -75,7 +76,6 @@ enum IPCMessageStart {
AppShimMsgStart,
WebRtcLoggingMsgStart,
TtsMsgStart,
- MemoryBenchmarkMsgStart,
WebSocketMsgStart,
NaClHostMsgStart,
WebRTCIdentityMsgStart,
@@ -103,7 +103,6 @@ enum IPCMessageStart {
PlatformNotificationMsgStart,
CredentialManagerMsgStart,
PDFMsgStart,
- WebCacheMsgStart,
ManifestManagerMsgStart,
ExtensionUtilityMsgStart,
GeofencingMsgStart,
@@ -135,6 +134,8 @@ enum IPCMessageStart {
StartupMetricMsgStart,
ArcCameraMsgStart,
DWriteFontProxyMsgStart,
+ MediaPlayerDelegateMsgStart,
+ SurfaceViewManagerMsgStart,
LastIPCMsgStart // Must come last.
};
diff --git a/chromium/ipc/ipc_message_templates.h b/chromium/ipc/ipc_message_templates.h
new file mode 100644
index 00000000000..f5c28cca4a6
--- /dev/null
+++ b/chromium/ipc/ipc_message_templates.h
@@ -0,0 +1,215 @@
+// Copyright 2015 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_TEMPLATES_H_
+#define IPC_IPC_MESSAGE_TEMPLATES_H_
+
+#include <stdint.h>
+
+#include <tuple>
+#include <type_traits>
+
+#include "base/logging.h"
+#include "base/trace_event/trace_event.h"
+#include "base/tuple.h"
+#include "build/build_config.h"
+#include "ipc/ipc_message.h"
+#include "ipc/ipc_message_utils.h"
+
+namespace IPC {
+
+// This function is for all the async IPCs that don't pass an extra parameter
+// using IPC_BEGIN_MESSAGE_MAP_WITH_PARAM.
+template <typename ObjT, typename Method, typename P, typename Tuple>
+void DispatchToMethod(ObjT* obj, Method method, P*, const Tuple& tuple) {
+ base::DispatchToMethod(obj, method, tuple);
+}
+
+template <typename ObjT,
+ typename Method,
+ typename P,
+ typename Tuple,
+ size_t... Ns>
+void DispatchToMethodImpl(ObjT* obj,
+ Method method,
+ P* parameter,
+ const Tuple& tuple,
+ base::IndexSequence<Ns...>) {
+ // TODO(mdempsky): Apply UnwrapTraits like base::DispatchToMethod?
+ (obj->*method)(parameter, std::get<Ns>(tuple)...);
+}
+
+// The following function is for async IPCs which have a dispatcher with an
+// extra parameter specified using IPC_BEGIN_MESSAGE_MAP_WITH_PARAM.
+template <typename ObjT, typename P, typename... Args, typename... Ts>
+typename std::enable_if<sizeof...(Args) == sizeof...(Ts)>::type
+DispatchToMethod(ObjT* obj,
+ void (ObjT::*method)(P*, Args...),
+ P* parameter,
+ const std::tuple<Ts...>& tuple) {
+ DispatchToMethodImpl(obj, method, parameter, tuple,
+ base::MakeIndexSequence<sizeof...(Ts)>());
+}
+
+enum class MessageKind {
+ CONTROL,
+ ROUTED,
+};
+
+// Routing is a helper struct so MessageT's private common constructor has a
+// different type signature than the public "int32_t routing_id" one.
+struct Routing {
+ explicit Routing(int32_t id) : id(id) {}
+ int32_t id;
+};
+
+// We want to restrict MessageT's constructors so that a routing_id is always
+// provided for ROUTED messages and never provided for CONTROL messages, so
+// use the SFINAE technique from N4387's "Implementation Hint" section.
+#if defined(COMPILER_MSVC)
+// MSVC 2013 doesn't support default arguments for template member functions
+// of templated classes, so there we have to rely on the DCHECKs instead.
+// TODO(mdempsky): Reevaluate once MSVC 2015.
+#define IPC_MESSAGET_SFINAE(x)
+#else
+#define IPC_MESSAGET_SFINAE(x) \
+ template <bool X = (x), typename std::enable_if<X, bool>::type = false>
+#endif
+
+// MessageT is the common template used for all user-defined message types.
+// It's intended to be used via the macros defined in ipc_message_macros.h.
+template <typename Meta,
+ typename InTuple = typename Meta::InTuple,
+ typename OutTuple = typename Meta::OutTuple>
+class MessageT;
+
+// Asynchronous message partial specialization.
+template <typename Meta, typename... Ins>
+class MessageT<Meta, std::tuple<Ins...>, void> : public Message {
+ public:
+ using Param = std::tuple<Ins...>;
+ enum { ID = Meta::ID };
+
+ // TODO(mdempsky): Remove. Uses of MyMessage::Schema::Param can be replaced
+ // with just MyMessage::Param.
+ using Schema = MessageT;
+
+ IPC_MESSAGET_SFINAE(Meta::kKind == MessageKind::CONTROL)
+ MessageT(const Ins&... ins) : MessageT(Routing(MSG_ROUTING_CONTROL), ins...) {
+ DCHECK(Meta::kKind == MessageKind::CONTROL) << Meta::kName;
+ }
+
+ IPC_MESSAGET_SFINAE(Meta::kKind == MessageKind::ROUTED)
+ MessageT(int32_t routing_id, const Ins&... ins)
+ : MessageT(Routing(routing_id), ins...) {
+ DCHECK(Meta::kKind == MessageKind::ROUTED) << Meta::kName;
+ }
+
+ static bool Read(const Message* msg, Param* p);
+ static void Log(std::string* name, const Message* msg, std::string* l);
+
+ template <class T, class S, class P, class Method>
+ static bool Dispatch(const Message* msg,
+ T* obj,
+ S* sender,
+ P* parameter,
+ Method func) {
+ TRACE_EVENT0("ipc", Meta::kName);
+ Param p;
+ if (Read(msg, &p)) {
+ DispatchToMethod(obj, func, parameter, p);
+ return true;
+ }
+ return false;
+ }
+
+ private:
+ MessageT(Routing routing, const Ins&... ins);
+};
+
+// Synchronous message partial specialization.
+template <typename Meta, typename... Ins, typename... Outs>
+class MessageT<Meta, std::tuple<Ins...>, std::tuple<Outs...>>
+ : public SyncMessage {
+ public:
+ using SendParam = std::tuple<Ins...>;
+ using ReplyParam = std::tuple<Outs...>;
+ enum { ID = Meta::ID };
+
+ // TODO(mdempsky): Remove. Uses of MyMessage::Schema::{Send,Reply}Param can
+ // be replaced with just MyMessage::{Send,Reply}Param.
+ using Schema = MessageT;
+
+ IPC_MESSAGET_SFINAE(Meta::kKind == MessageKind::CONTROL)
+ MessageT(const Ins&... ins, Outs*... outs)
+ : MessageT(Routing(MSG_ROUTING_CONTROL), ins..., outs...) {
+ DCHECK(Meta::kKind == MessageKind::CONTROL) << Meta::kName;
+ }
+
+ IPC_MESSAGET_SFINAE(Meta::kKind == MessageKind::ROUTED)
+ MessageT(int32_t routing_id, const Ins&... ins, Outs*... outs)
+ : MessageT(Routing(routing_id), ins..., outs...) {
+ DCHECK(Meta::kKind == MessageKind::ROUTED) << Meta::kName;
+ }
+
+ static bool ReadSendParam(const Message* msg, SendParam* p);
+ static bool ReadReplyParam(const Message* msg, ReplyParam* p);
+ static void WriteReplyParams(Message* reply, const Outs&... outs);
+ static void Log(std::string* name, const Message* msg, std::string* l);
+
+ template <class T, class S, class P, class Method>
+ static bool Dispatch(const Message* msg,
+ T* obj,
+ S* sender,
+ P* parameter,
+ Method func) {
+ TRACE_EVENT0("ipc", Meta::kName);
+ SendParam send_params;
+ bool ok = ReadSendParam(msg, &send_params);
+ Message* reply = SyncMessage::GenerateReply(msg);
+ if (ok) {
+ ReplyParam reply_params;
+ base::DispatchToMethod(obj, func, send_params, &reply_params);
+ WriteParam(reply, reply_params);
+ LogReplyParamsToMessage(reply_params, msg);
+ } else {
+ NOTREACHED() << "Error deserializing message " << msg->type();
+ reply->set_reply_error();
+ }
+ sender->Send(reply);
+ return ok;
+ }
+
+ template <class T, class P, class Method>
+ static bool DispatchDelayReply(const Message* msg,
+ T* obj,
+ P* parameter,
+ Method func) {
+ TRACE_EVENT0("ipc", Meta::kName);
+ SendParam send_params;
+ bool ok = ReadSendParam(msg, &send_params);
+ Message* reply = SyncMessage::GenerateReply(msg);
+ if (ok) {
+ std::tuple<Message&> t = std::tie(*reply);
+ ConnectMessageAndReply(msg, reply);
+ base::DispatchToMethod(obj, func, send_params, &t);
+ } else {
+ NOTREACHED() << "Error deserializing message " << msg->type();
+ reply->set_reply_error();
+ obj->Send(reply);
+ }
+ return ok;
+ }
+
+ private:
+ MessageT(Routing routing, const Ins&... ins, Outs*... outs);
+};
+
+} // namespace IPC
+
+#if defined(IPC_MESSAGE_IMPL)
+#include "ipc/ipc_message_templates_impl.h"
+#endif
+
+#endif // IPC_IPC_MESSAGE_TEMPLATES_H_
diff --git a/chromium/ipc/ipc_message_templates_impl.h b/chromium/ipc/ipc_message_templates_impl.h
new file mode 100644
index 00000000000..192d2efb93e
--- /dev/null
+++ b/chromium/ipc/ipc_message_templates_impl.h
@@ -0,0 +1,112 @@
+// Copyright 2015 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_TEMPLATES_IMPL_H_
+#define IPC_IPC_MESSAGE_TEMPLATES_IMPL_H_
+
+#include <tuple>
+
+namespace IPC {
+
+template <typename... Ts>
+class ParamDeserializer : public MessageReplyDeserializer {
+ public:
+ explicit ParamDeserializer(const std::tuple<Ts&...>& out) : out_(out) {}
+
+ bool SerializeOutputParameters(const IPC::Message& msg,
+ base::PickleIterator iter) override {
+ return ReadParam(&msg, &iter, &out_);
+ }
+
+ std::tuple<Ts&...> out_;
+};
+
+template <typename Meta, typename... Ins>
+MessageT<Meta, std::tuple<Ins...>, void>::MessageT(Routing routing,
+ const Ins&... ins)
+ : Message(routing.id, ID, PRIORITY_NORMAL) {
+ WriteParam(this, std::tie(ins...));
+}
+
+template <typename Meta, typename... Ins>
+bool MessageT<Meta, std::tuple<Ins...>, void>::Read(const Message* msg,
+ Param* p) {
+ base::PickleIterator iter(*msg);
+ return ReadParam(msg, &iter, p);
+}
+
+template <typename Meta, typename... Ins>
+void MessageT<Meta, std::tuple<Ins...>, void>::Log(std::string* name,
+ const Message* msg,
+ std::string* l) {
+ if (name)
+ *name = Meta::kName;
+ if (!msg || !l)
+ return;
+ Param p;
+ if (Read(msg, &p))
+ LogParam(p, l);
+}
+
+template <typename Meta, typename... Ins, typename... Outs>
+MessageT<Meta, std::tuple<Ins...>, std::tuple<Outs...>>::MessageT(
+ Routing routing,
+ const Ins&... ins,
+ Outs*... outs)
+ : SyncMessage(
+ routing.id,
+ ID,
+ PRIORITY_NORMAL,
+ new ParamDeserializer<Outs...>(std::tie(*outs...))) {
+ WriteParam(this, std::tie(ins...));
+}
+
+template <typename Meta, typename... Ins, typename... Outs>
+bool MessageT<Meta, std::tuple<Ins...>, std::tuple<Outs...>>::ReadSendParam(
+ const Message* msg,
+ SendParam* p) {
+ base::PickleIterator iter = SyncMessage::GetDataIterator(msg);
+ return ReadParam(msg, &iter, p);
+}
+
+template <typename Meta, typename... Ins, typename... Outs>
+bool MessageT<Meta, std::tuple<Ins...>, std::tuple<Outs...>>::ReadReplyParam(
+ const Message* msg,
+ ReplyParam* p) {
+ base::PickleIterator iter = SyncMessage::GetDataIterator(msg);
+ return ReadParam(msg, &iter, p);
+}
+
+template <typename Meta, typename... Ins, typename... Outs>
+void MessageT<Meta,
+ std::tuple<Ins...>,
+ std::tuple<Outs...>>::WriteReplyParams(Message* reply,
+ const Outs&... outs) {
+ WriteParam(reply, std::tie(outs...));
+}
+
+template <typename Meta, typename... Ins, typename... Outs>
+void MessageT<Meta, std::tuple<Ins...>, std::tuple<Outs...>>::Log(
+ std::string* name,
+ const Message* msg,
+ std::string* l) {
+ if (name)
+ *name = Meta::kName;
+ if (!msg || !l)
+ return;
+ if (msg->is_sync()) {
+ SendParam p;
+ if (ReadSendParam(msg, &p))
+ LogParam(p, l);
+ AddOutputParamsToLog(msg, l);
+ } else {
+ ReplyParam p;
+ if (ReadReplyParam(msg, &p))
+ LogParam(p, l);
+ }
+}
+
+} // namespace IPC
+
+#endif // IPC_IPC_MESSAGE_TEMPLATES_IMPL_H_
diff --git a/chromium/ipc/ipc_message_utils.cc b/chromium/ipc/ipc_message_utils.cc
index ea88b55a2a5..9edc3bbd4cd 100644
--- a/chromium/ipc/ipc_message_utils.cc
+++ b/chromium/ipc/ipc_message_utils.cc
@@ -67,12 +67,78 @@ void LogBytes(const std::vector<CharType>& data, std::string* out) {
#endif
}
-bool ReadValue(const Message* m,
+bool ReadValue(const base::Pickle* m,
base::PickleIterator* iter,
base::Value** value,
int recursion);
-void WriteValue(Message* m, const base::Value* value, int recursion) {
+void GetValueSize(base::PickleSizer* sizer,
+ const base::Value* value,
+ int recursion) {
+ if (recursion > kMaxRecursionDepth) {
+ LOG(WARNING) << "Max recursion depth hit in GetValueSize.";
+ return;
+ }
+
+ sizer->AddInt();
+ switch (value->GetType()) {
+ case base::Value::TYPE_NULL:
+ break;
+ case base::Value::TYPE_BOOLEAN:
+ sizer->AddBool();
+ break;
+ case base::Value::TYPE_INTEGER:
+ sizer->AddInt();
+ break;
+ case base::Value::TYPE_DOUBLE:
+ sizer->AddDouble();
+ break;
+ case base::Value::TYPE_STRING: {
+ const base::StringValue* result;
+ value->GetAsString(&result);
+ if (value->GetAsString(&result)) {
+ DCHECK(result);
+ GetParamSize(sizer, result->GetString());
+ } else {
+ std::string str;
+ bool as_string_result = value->GetAsString(&str);
+ DCHECK(as_string_result);
+ GetParamSize(sizer, str);
+ }
+ break;
+ }
+ case base::Value::TYPE_BINARY: {
+ const base::BinaryValue* binary =
+ static_cast<const base::BinaryValue*>(value);
+ sizer->AddData(static_cast<int>(binary->GetSize()));
+ break;
+ }
+ case base::Value::TYPE_DICTIONARY: {
+ sizer->AddInt();
+ const base::DictionaryValue* dict =
+ static_cast<const base::DictionaryValue*>(value);
+ for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd();
+ it.Advance()) {
+ GetParamSize(sizer, it.key());
+ GetValueSize(sizer, &it.value(), recursion + 1);
+ }
+ break;
+ }
+ case base::Value::TYPE_LIST: {
+ sizer->AddInt();
+ const base::ListValue* list = static_cast<const base::ListValue*>(value);
+ for (base::ListValue::const_iterator it = list->begin();
+ it != list->end(); ++it) {
+ GetValueSize(sizer, *it, recursion + 1);
+ }
+ break;
+ }
+ default:
+ NOTREACHED() << "Invalid base::Value type.";
+ }
+}
+
+void WriteValue(base::Pickle* m, const base::Value* value, int recursion) {
bool result;
if (recursion > kMaxRecursionDepth) {
LOG(WARNING) << "Max recursion depth hit in WriteValue.";
@@ -145,7 +211,7 @@ void WriteValue(Message* m, const base::Value* value, int recursion) {
// Helper for ReadValue that reads a DictionaryValue into a pre-allocated
// object.
-bool ReadDictionaryValue(const Message* m,
+bool ReadDictionaryValue(const base::Pickle* m,
base::PickleIterator* iter,
base::DictionaryValue* value,
int recursion) {
@@ -167,7 +233,7 @@ bool ReadDictionaryValue(const Message* m,
// Helper for ReadValue that reads a ReadListValue into a pre-allocated
// object.
-bool ReadListValue(const Message* m,
+bool ReadListValue(const base::Pickle* m,
base::PickleIterator* iter,
base::ListValue* value,
int recursion) {
@@ -185,7 +251,7 @@ bool ReadListValue(const Message* m,
return true;
}
-bool ReadValue(const Message* m,
+bool ReadValue(const base::Pickle* m,
base::PickleIterator* iter,
base::Value** value,
int recursion) {
@@ -271,6 +337,8 @@ LogData::LogData()
dispatch(0) {
}
+LogData::LogData(const LogData& other) = default;
+
LogData::~LogData() {
}
@@ -278,13 +346,18 @@ void ParamTraits<bool>::Log(const param_type& p, std::string* l) {
l->append(p ? "true" : "false");
}
-void ParamTraits<signed char>::Write(Message* m, const param_type& p) {
+void ParamTraits<signed char>::GetSize(base::PickleSizer* sizer,
+ const param_type& p) {
+ sizer->AddBytes(sizeof(param_type));
+}
+
+void ParamTraits<signed char>::Write(base::Pickle* m, const param_type& p) {
m->WriteBytes(&p, sizeof(param_type));
}
-bool ParamTraits<signed char>::Read(const Message* m,
- base::PickleIterator* iter,
- param_type* r) {
+bool ParamTraits<signed char>::Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* r) {
const char* data;
if (!iter->ReadBytes(&data, sizeof(param_type)))
return false;
@@ -296,11 +369,16 @@ void ParamTraits<signed char>::Log(const param_type& p, std::string* l) {
l->append(base::IntToString(p));
}
-void ParamTraits<unsigned char>::Write(Message* m, const param_type& p) {
+void ParamTraits<unsigned char>::GetSize(base::PickleSizer* sizer,
+ const param_type& p) {
+ sizer->AddBytes(sizeof(param_type));
+}
+
+void ParamTraits<unsigned char>::Write(base::Pickle* m, const param_type& p) {
m->WriteBytes(&p, sizeof(param_type));
}
-bool ParamTraits<unsigned char>::Read(const Message* m,
+bool ParamTraits<unsigned char>::Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
const char* data;
@@ -314,11 +392,16 @@ void ParamTraits<unsigned char>::Log(const param_type& p, std::string* l) {
l->append(base::UintToString(p));
}
-void ParamTraits<unsigned short>::Write(Message* m, const param_type& p) {
+void ParamTraits<unsigned short>::GetSize(base::PickleSizer* sizer,
+ const param_type& p) {
+ sizer->AddBytes(sizeof(param_type));
+}
+
+void ParamTraits<unsigned short>::Write(base::Pickle* m, const param_type& p) {
m->WriteBytes(&p, sizeof(param_type));
}
-bool ParamTraits<unsigned short>::Read(const Message* m,
+bool ParamTraits<unsigned short>::Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
const char* data;
@@ -340,6 +423,8 @@ void ParamTraits<unsigned int>::Log(const param_type& p, std::string* l) {
l->append(base::UintToString(p));
}
+#if defined(OS_WIN) || defined(OS_LINUX) || \
+ (defined(OS_ANDROID) && defined(ARCH_CPU_64_BITS))
void ParamTraits<long>::Log(const param_type& p, std::string* l) {
l->append(base::Int64ToString(static_cast<int64_t>(p)));
}
@@ -347,6 +432,7 @@ void ParamTraits<long>::Log(const param_type& p, std::string* l) {
void ParamTraits<unsigned long>::Log(const param_type& p, std::string* l) {
l->append(base::Uint64ToString(static_cast<uint64_t>(p)));
}
+#endif
void ParamTraits<long long>::Log(const param_type& p, std::string* l) {
l->append(base::Int64ToString(static_cast<int64_t>(p)));
@@ -360,11 +446,16 @@ void ParamTraits<float>::Log(const param_type& p, std::string* l) {
l->append(base::StringPrintf("%e", p));
}
-void ParamTraits<double>::Write(Message* m, const param_type& p) {
+void ParamTraits<double>::GetSize(base::PickleSizer* sizer,
+ const param_type& p) {
+ sizer->AddBytes(sizeof(param_type));
+}
+
+void ParamTraits<double>::Write(base::Pickle* m, const param_type& p) {
m->WriteBytes(reinterpret_cast<const char*>(&p), sizeof(param_type));
}
-bool ParamTraits<double>::Read(const Message* m,
+bool ParamTraits<double>::Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
const char *data;
@@ -389,7 +480,13 @@ void ParamTraits<base::string16>::Log(const param_type& p, std::string* l) {
l->append(base::UTF16ToUTF8(p));
}
-void ParamTraits<std::vector<char> >::Write(Message* m, const param_type& p) {
+void ParamTraits<std::vector<char>>::GetSize(base::PickleSizer* sizer,
+ const param_type& p) {
+ sizer->AddData(static_cast<int>(p.size()));
+}
+
+void ParamTraits<std::vector<char>>::Write(base::Pickle* m,
+ const param_type& p) {
if (p.empty()) {
m->WriteData(NULL, 0);
} else {
@@ -397,7 +494,7 @@ void ParamTraits<std::vector<char> >::Write(Message* m, const param_type& p) {
}
}
-bool ParamTraits<std::vector<char>>::Read(const Message* m,
+bool ParamTraits<std::vector<char>>::Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
const char *data;
@@ -414,8 +511,13 @@ void ParamTraits<std::vector<char> >::Log(const param_type& p, std::string* l) {
LogBytes(p, l);
}
-void ParamTraits<std::vector<unsigned char> >::Write(Message* m,
- const param_type& p) {
+void ParamTraits<std::vector<unsigned char>>::GetSize(base::PickleSizer* sizer,
+ const param_type& p) {
+ sizer->AddData(static_cast<int>(p.size()));
+}
+
+void ParamTraits<std::vector<unsigned char>>::Write(base::Pickle* m,
+ const param_type& p) {
if (p.empty()) {
m->WriteData(NULL, 0);
} else {
@@ -424,7 +526,7 @@ void ParamTraits<std::vector<unsigned char> >::Write(Message* m,
}
}
-bool ParamTraits<std::vector<unsigned char>>::Read(const Message* m,
+bool ParamTraits<std::vector<unsigned char>>::Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
const char *data;
@@ -442,7 +544,15 @@ void ParamTraits<std::vector<unsigned char> >::Log(const param_type& p,
LogBytes(p, l);
}
-void ParamTraits<std::vector<bool> >::Write(Message* m, const param_type& p) {
+void ParamTraits<std::vector<bool>>::GetSize(base::PickleSizer* sizer,
+ const param_type& p) {
+ GetParamSize(sizer, static_cast<int>(p.size()));
+ for (size_t i = 0; i < p.size(); ++i)
+ GetParamSize(sizer, static_cast<bool>(p[i]));
+}
+
+void ParamTraits<std::vector<bool>>::Write(base::Pickle* m,
+ const param_type& p) {
WriteParam(m, static_cast<int>(p.size()));
// Cast to bool below is required because libc++'s
// vector<bool>::const_reference is different from bool, and we want to avoid
@@ -451,7 +561,7 @@ void ParamTraits<std::vector<bool> >::Write(Message* m, const param_type& p) {
WriteParam(m, static_cast<bool>(p[i]));
}
-bool ParamTraits<std::vector<bool>>::Read(const Message* m,
+bool ParamTraits<std::vector<bool>>::Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
int size;
@@ -477,13 +587,13 @@ void ParamTraits<std::vector<bool> >::Log(const param_type& p, std::string* l) {
}
void ParamTraits<BrokerableAttachment::AttachmentId>::Write(
- Message* m,
+ base::Pickle* m,
const param_type& p) {
m->WriteBytes(p.nonce, BrokerableAttachment::kNonceSize);
}
bool ParamTraits<BrokerableAttachment::AttachmentId>::Read(
- const Message* m,
+ const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
const char* data;
@@ -498,12 +608,17 @@ void ParamTraits<BrokerableAttachment::AttachmentId>::Log(const param_type& p,
l->append(base::HexEncode(p.nonce, BrokerableAttachment::kNonceSize));
}
-void ParamTraits<base::DictionaryValue>::Write(Message* m,
+void ParamTraits<base::DictionaryValue>::GetSize(base::PickleSizer* sizer,
+ const param_type& p) {
+ GetValueSize(sizer, &p, 0);
+}
+
+void ParamTraits<base::DictionaryValue>::Write(base::Pickle* m,
const param_type& p) {
WriteValue(m, &p, 0);
}
-bool ParamTraits<base::DictionaryValue>::Read(const Message* m,
+bool ParamTraits<base::DictionaryValue>::Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
int type;
@@ -521,7 +636,8 @@ void ParamTraits<base::DictionaryValue>::Log(const param_type& p,
}
#if defined(OS_POSIX)
-void ParamTraits<base::FileDescriptor>::Write(Message* m, const param_type& p) {
+void ParamTraits<base::FileDescriptor>::Write(base::Pickle* m,
+ const param_type& p) {
const bool valid = p.fd >= 0;
WriteParam(m, valid);
@@ -538,7 +654,7 @@ void ParamTraits<base::FileDescriptor>::Write(Message* m, const param_type& p) {
}
}
-bool ParamTraits<base::FileDescriptor>::Read(const Message* m,
+bool ParamTraits<base::FileDescriptor>::Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
*r = base::FileDescriptor();
@@ -551,11 +667,13 @@ bool ParamTraits<base::FileDescriptor>::Read(const Message* m,
if (!valid)
return true;
- scoped_refptr<MessageAttachment> attachment;
+ scoped_refptr<base::Pickle::Attachment> attachment;
if (!m->ReadAttachment(iter, &attachment))
return false;
- *r = base::FileDescriptor(attachment->TakePlatformFile(), true);
+ *r = base::FileDescriptor(
+ static_cast<MessageAttachment*>(attachment.get())->TakePlatformFile(),
+ true);
return true;
}
@@ -570,7 +688,7 @@ void ParamTraits<base::FileDescriptor>::Log(const param_type& p,
#endif // defined(OS_POSIX)
#if defined(OS_MACOSX) && !defined(OS_IOS)
-void ParamTraits<base::SharedMemoryHandle>::Write(Message* m,
+void ParamTraits<base::SharedMemoryHandle>::Write(base::Pickle* m,
const param_type& p) {
m->WriteInt(p.GetType());
@@ -584,7 +702,7 @@ void ParamTraits<base::SharedMemoryHandle>::Write(Message* m,
size_t size = 0;
bool result = p.GetSize(&size);
DCHECK(result);
- ParamTraits<size_t>::Write(m, size);
+ ParamTraits<uint32_t>::Write(m, static_cast<uint32_t>(size));
// If the caller intended to pass ownership to the IPC stack, release a
// reference.
@@ -595,7 +713,7 @@ void ParamTraits<base::SharedMemoryHandle>::Write(Message* m,
}
}
-bool ParamTraits<base::SharedMemoryHandle>::Read(const Message* m,
+bool ParamTraits<base::SharedMemoryHandle>::Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
base::SharedMemoryHandle::TypeWireFormat type;
@@ -632,11 +750,12 @@ bool ParamTraits<base::SharedMemoryHandle>::Read(const Message* m,
if (!ParamTraits<MachPortMac>::Read(m, iter, &mach_port_mac))
return false;
- size_t size;
- if (!ParamTraits<size_t>::Read(m, iter, &size))
+ uint32_t size;
+ if (!ParamTraits<uint32_t>::Read(m, iter, &size))
return false;
- *r = base::SharedMemoryHandle(mach_port_mac.get_mach_port(), size,
+ *r = base::SharedMemoryHandle(mach_port_mac.get_mach_port(),
+ static_cast<size_t>(size),
base::GetCurrentProcId());
return true;
}
@@ -658,19 +777,24 @@ void ParamTraits<base::SharedMemoryHandle>::Log(const param_type& p,
}
#elif defined(OS_WIN)
-void ParamTraits<base::SharedMemoryHandle>::Write(Message* m,
+void ParamTraits<base::SharedMemoryHandle>::Write(base::Pickle* m,
const param_type& p) {
m->WriteBool(p.NeedsBrokering());
if (p.NeedsBrokering()) {
HandleWin handle_win(p.GetHandle(), HandleWin::DUPLICATE);
ParamTraits<HandleWin>::Write(m, handle_win);
+
+ // If the caller intended to pass ownership to the IPC stack, release a
+ // reference.
+ if (p.OwnershipPassesToIPC() && p.BelongsToCurrentProcess())
+ p.Close();
} else {
m->WriteInt(HandleToLong(p.GetHandle()));
}
}
-bool ParamTraits<base::SharedMemoryHandle>::Read(const Message* m,
+bool ParamTraits<base::SharedMemoryHandle>::Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
bool needs_brokering;
@@ -702,11 +826,16 @@ void ParamTraits<base::SharedMemoryHandle>::Log(const param_type& p,
}
#endif // defined(OS_MACOSX) && !defined(OS_IOS)
-void ParamTraits<base::FilePath>::Write(Message* m, const param_type& p) {
+void ParamTraits<base::FilePath>::GetSize(base::PickleSizer* sizer,
+ const param_type& p) {
+ p.GetSizeForPickle(sizer);
+}
+
+void ParamTraits<base::FilePath>::Write(base::Pickle* m, const param_type& p) {
p.WriteToPickle(m);
}
-bool ParamTraits<base::FilePath>::Read(const Message* m,
+bool ParamTraits<base::FilePath>::Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
return r->ReadFromPickle(iter);
@@ -716,11 +845,16 @@ void ParamTraits<base::FilePath>::Log(const param_type& p, std::string* l) {
ParamTraits<base::FilePath::StringType>::Log(p.value(), l);
}
-void ParamTraits<base::ListValue>::Write(Message* m, const param_type& p) {
+void ParamTraits<base::ListValue>::GetSize(base::PickleSizer* sizer,
+ const param_type& p) {
+ GetValueSize(sizer, &p, 0);
+}
+
+void ParamTraits<base::ListValue>::Write(base::Pickle* m, const param_type& p) {
WriteValue(m, &p, 0);
}
-bool ParamTraits<base::ListValue>::Read(const Message* m,
+bool ParamTraits<base::ListValue>::Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
int type;
@@ -736,13 +870,19 @@ void ParamTraits<base::ListValue>::Log(const param_type& p, std::string* l) {
l->append(json);
}
-void ParamTraits<base::NullableString16>::Write(Message* m,
+void ParamTraits<base::NullableString16>::GetSize(base::PickleSizer* sizer,
+ const param_type& p) {
+ GetParamSize(sizer, p.string());
+ GetParamSize(sizer, p.is_null());
+}
+
+void ParamTraits<base::NullableString16>::Write(base::Pickle* m,
const param_type& p) {
WriteParam(m, p.string());
WriteParam(m, p.is_null());
}
-bool ParamTraits<base::NullableString16>::Read(const Message* m,
+bool ParamTraits<base::NullableString16>::Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
base::string16 string;
@@ -764,7 +904,16 @@ void ParamTraits<base::NullableString16>::Log(const param_type& p,
l->append(")");
}
-void ParamTraits<base::File::Info>::Write(Message* m,
+void ParamTraits<base::File::Info>::GetSize(base::PickleSizer* sizer,
+ const param_type& p) {
+ GetParamSize(sizer, p.size);
+ GetParamSize(sizer, p.is_directory);
+ GetParamSize(sizer, p.last_modified.ToDoubleT());
+ GetParamSize(sizer, p.last_accessed.ToDoubleT());
+ GetParamSize(sizer, p.creation_time.ToDoubleT());
+}
+
+void ParamTraits<base::File::Info>::Write(base::Pickle* m,
const param_type& p) {
WriteParam(m, p.size);
WriteParam(m, p.is_directory);
@@ -773,7 +922,7 @@ void ParamTraits<base::File::Info>::Write(Message* m,
WriteParam(m, p.creation_time.ToDoubleT());
}
-bool ParamTraits<base::File::Info>::Read(const Message* m,
+bool ParamTraits<base::File::Info>::Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* p) {
double last_modified, last_accessed, creation_time;
@@ -804,11 +953,16 @@ void ParamTraits<base::File::Info>::Log(const param_type& p,
l->append(")");
}
-void ParamTraits<base::Time>::Write(Message* m, const param_type& p) {
+void ParamTraits<base::Time>::GetSize(base::PickleSizer* sizer,
+ const param_type& p) {
+ sizer->AddInt64();
+}
+
+void ParamTraits<base::Time>::Write(base::Pickle* m, const param_type& p) {
ParamTraits<int64_t>::Write(m, p.ToInternalValue());
}
-bool ParamTraits<base::Time>::Read(const Message* m,
+bool ParamTraits<base::Time>::Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
int64_t value;
@@ -822,11 +976,16 @@ void ParamTraits<base::Time>::Log(const param_type& p, std::string* l) {
ParamTraits<int64_t>::Log(p.ToInternalValue(), l);
}
-void ParamTraits<base::TimeDelta>::Write(Message* m, const param_type& p) {
+void ParamTraits<base::TimeDelta>::GetSize(base::PickleSizer* sizer,
+ const param_type& p) {
+ sizer->AddInt64();
+}
+
+void ParamTraits<base::TimeDelta>::Write(base::Pickle* m, const param_type& p) {
ParamTraits<int64_t>::Write(m, p.ToInternalValue());
}
-bool ParamTraits<base::TimeDelta>::Read(const Message* m,
+bool ParamTraits<base::TimeDelta>::Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
int64_t value;
@@ -841,11 +1000,16 @@ void ParamTraits<base::TimeDelta>::Log(const param_type& p, std::string* l) {
ParamTraits<int64_t>::Log(p.ToInternalValue(), l);
}
-void ParamTraits<base::TimeTicks>::Write(Message* m, const param_type& p) {
+void ParamTraits<base::TimeTicks>::GetSize(base::PickleSizer* sizer,
+ const param_type& p) {
+ sizer->AddInt64();
+}
+
+void ParamTraits<base::TimeTicks>::Write(base::Pickle* m, const param_type& p) {
ParamTraits<int64_t>::Write(m, p.ToInternalValue());
}
-bool ParamTraits<base::TimeTicks>::Read(const Message* m,
+bool ParamTraits<base::TimeTicks>::Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
int64_t value;
@@ -860,7 +1024,8 @@ void ParamTraits<base::TimeTicks>::Log(const param_type& p, std::string* l) {
ParamTraits<int64_t>::Log(p.ToInternalValue(), l);
}
-void ParamTraits<IPC::ChannelHandle>::Write(Message* m, const param_type& p) {
+void ParamTraits<IPC::ChannelHandle>::Write(base::Pickle* m,
+ const param_type& p) {
#if defined(OS_WIN)
// On Windows marshalling pipe handle is not supported.
DCHECK(p.pipe.handle == NULL);
@@ -871,7 +1036,7 @@ void ParamTraits<IPC::ChannelHandle>::Write(Message* m, const param_type& p) {
#endif
}
-bool ParamTraits<IPC::ChannelHandle>::Read(const Message* m,
+bool ParamTraits<IPC::ChannelHandle>::Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
return ReadParam(m, iter, &r->name)
@@ -891,7 +1056,20 @@ void ParamTraits<IPC::ChannelHandle>::Log(const param_type& p,
l->append(")");
}
-void ParamTraits<LogData>::Write(Message* m, const param_type& p) {
+void ParamTraits<LogData>::GetSize(base::PickleSizer* sizer,
+ const param_type& p) {
+ GetParamSize(sizer, p.channel);
+ GetParamSize(sizer, p.routing_id);
+ GetParamSize(sizer, p.type);
+ GetParamSize(sizer, p.flags);
+ GetParamSize(sizer, p.sent);
+ GetParamSize(sizer, p.receive);
+ GetParamSize(sizer, p.dispatch);
+ GetParamSize(sizer, p.message_name);
+ GetParamSize(sizer, p.params);
+}
+
+void ParamTraits<LogData>::Write(base::Pickle* m, const param_type& p) {
WriteParam(m, p.channel);
WriteParam(m, p.routing_id);
WriteParam(m, p.type);
@@ -903,7 +1081,7 @@ void ParamTraits<LogData>::Write(Message* m, const param_type& p) {
WriteParam(m, p.params);
}
-bool ParamTraits<LogData>::Read(const Message* m,
+bool ParamTraits<LogData>::Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
return
@@ -922,7 +1100,7 @@ void ParamTraits<LogData>::Log(const param_type& p, std::string* l) {
// Doesn't make sense to implement this!
}
-void ParamTraits<Message>::Write(Message* m, const Message& p) {
+void ParamTraits<Message>::Write(base::Pickle* m, const Message& p) {
#if defined(OS_POSIX)
// We don't serialize the file descriptors in the nested message, so there
// better not be any.
@@ -945,7 +1123,7 @@ void ParamTraits<Message>::Write(Message* m, const Message& p) {
m->WriteData(p.payload(), static_cast<uint32_t>(p.payload_size()));
}
-bool ParamTraits<Message>::Read(const Message* m,
+bool ParamTraits<Message>::Read(const base::Pickle* m,
base::PickleIterator* iter,
Message* r) {
uint32_t routing_id, type, flags;
@@ -968,13 +1146,18 @@ void ParamTraits<Message>::Log(const Message& p, std::string* l) {
}
#if defined(OS_WIN)
+void ParamTraits<HANDLE>::GetSize(base::PickleSizer* sizer,
+ const param_type& p) {
+ sizer->AddInt();
+}
+
// Note that HWNDs/HANDLE/HCURSOR/HACCEL etc are always 32 bits, even on 64
// bit systems. That's why we use the Windows macros to convert to 32 bits.
-void ParamTraits<HANDLE>::Write(Message* m, const param_type& p) {
+void ParamTraits<HANDLE>::Write(base::Pickle* m, const param_type& p) {
m->WriteInt(HandleToLong(p));
}
-bool ParamTraits<HANDLE>::Read(const Message* m,
+bool ParamTraits<HANDLE>::Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
int32_t temp;
@@ -988,11 +1171,16 @@ void ParamTraits<HANDLE>::Log(const param_type& p, std::string* l) {
l->append(base::StringPrintf("0x%p", p));
}
-void ParamTraits<LOGFONT>::Write(Message* m, const param_type& p) {
+void ParamTraits<LOGFONT>::GetSize(base::PickleSizer* sizer,
+ const param_type& p) {
+ sizer->AddData(sizeof(LOGFONT));
+}
+
+void ParamTraits<LOGFONT>::Write(base::Pickle* m, const param_type& p) {
m->WriteData(reinterpret_cast<const char*>(&p), sizeof(LOGFONT));
}
-bool ParamTraits<LOGFONT>::Read(const Message* m,
+bool ParamTraits<LOGFONT>::Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
const char *data;
@@ -1013,11 +1201,15 @@ void ParamTraits<LOGFONT>::Log(const param_type& p, std::string* l) {
l->append(base::StringPrintf("<LOGFONT>"));
}
-void ParamTraits<MSG>::Write(Message* m, const param_type& p) {
+void ParamTraits<MSG>::GetSize(base::PickleSizer* sizer, const param_type& p) {
+ sizer->AddData(sizeof(MSG));
+}
+
+void ParamTraits<MSG>::Write(base::Pickle* m, const param_type& p) {
m->WriteData(reinterpret_cast<const char*>(&p), sizeof(MSG));
}
-bool ParamTraits<MSG>::Read(const Message* m,
+bool ParamTraits<MSG>::Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
const char *data;
diff --git a/chromium/ipc/ipc_message_utils.h b/chromium/ipc/ipc_message_utils.h
index 69ea7cb6d8a..cf4fa8fb14c 100644
--- a/chromium/ipc/ipc_message_utils.h
+++ b/chromium/ipc/ipc_message_utils.h
@@ -13,6 +13,7 @@
#include <map>
#include <set>
#include <string>
+#include <tuple>
#include <vector>
#include "base/containers/small_map.h"
@@ -24,36 +25,12 @@
#include "base/strings/string16.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
-#include "base/tuple.h"
#include "build/build_config.h"
#include "ipc/brokerable_attachment.h"
#include "ipc/ipc_message_start.h"
#include "ipc/ipc_param_traits.h"
#include "ipc/ipc_sync_message.h"
-#if defined(COMPILER_GCC)
-// GCC "helpfully" tries to inline template methods in release mode. Except we
-// want the majority of the template junk being expanded once in the
-// implementation file (and only provide the definitions in
-// ipc_message_utils_impl.h in those files) and exported, instead of expanded
-// at every call site. Special note: GCC happily accepts the attribute before
-// the method declaration, but only acts on it if it is after.
-#if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100) >= 40500
-// Starting in gcc 4.5, the noinline no longer implies the concept covered by
-// the introduced noclone attribute, which will create specialized versions of
-// functions/methods when certain types are constant.
-// www.gnu.org/software/gcc/gcc-4.5/changes.html
-#define IPC_MSG_NOINLINE __attribute__((noinline, noclone));
-#else
-#define IPC_MSG_NOINLINE __attribute__((noinline));
-#endif
-#elif defined(COMPILER_MSVC)
-// MSVC++ doesn't do this.
-#define IPC_MSG_NOINLINE
-#else
-#error "Please add the noinline property for your new compiler here."
-#endif
-
namespace base {
class DictionaryValue;
class FilePath;
@@ -77,6 +54,7 @@ struct ChannelHandle;
// How we send IPC message logs across channels.
struct IPC_EXPORT LogData {
LogData();
+ LogData(const LogData& other);
~LogData();
std::string channel;
@@ -99,15 +77,36 @@ struct IPC_EXPORT LogData {
struct NoParams {
};
+// Specializations are checked by 'IPC checker' part of find-bad-constructs
+// Clang plugin (see WriteParam() below for the details).
+template <typename... Ts>
+struct CheckedTuple {
+ typedef std::tuple<Ts...> Tuple;
+};
+
+template <class P>
+static inline void GetParamSize(base::PickleSizer* sizer, const P& p) {
+ typedef typename SimilarTypeTraits<P>::Type Type;
+ ParamTraits<Type>::GetSize(sizer, static_cast<const Type&>(p));
+}
+
+// This function is checked by 'IPC checker' part of find-bad-constructs
+// Clang plugin to make it's not called on the following types:
+// 1. long / unsigned long (but not typedefs to)
+// 2. intmax_t, uintmax_t, intptr_t, uintptr_t, wint_t,
+// size_t, rsize_t, ssize_t, ptrdiff_t, dev_t, off_t, clock_t,
+// time_t, suseconds_t (including typedefs to)
+// 3. Any template referencing types above (e.g. std::vector<size_t>)
template <class P>
-static inline void WriteParam(Message* m, const P& p) {
+static inline void WriteParam(base::Pickle* m, const P& p) {
typedef typename SimilarTypeTraits<P>::Type Type;
ParamTraits<Type>::Write(m, static_cast<const Type& >(p));
}
template <class P>
-static inline bool WARN_UNUSED_RESULT
-ReadParam(const Message* m, base::PickleIterator* iter, P* p) {
+static inline bool WARN_UNUSED_RESULT ReadParam(const base::Pickle* m,
+ base::PickleIterator* iter,
+ P* p) {
typedef typename SimilarTypeTraits<P>::Type Type;
return ParamTraits<Type>::Read(m, iter, reinterpret_cast<Type* >(p));
}
@@ -123,10 +122,11 @@ static inline void LogParam(const P& p, std::string* l) {
template <>
struct ParamTraits<bool> {
typedef bool param_type;
- static void Write(Message* m, const param_type& p) {
- m->WriteBool(p);
+ static void GetSize(base::PickleSizer* sizer, const param_type& p) {
+ sizer->AddBool();
}
- static bool Read(const Message* m,
+ static void Write(base::Pickle* m, const param_type& p) { m->WriteBool(p); }
+ static bool Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
return iter->ReadBool(r);
@@ -137,24 +137,31 @@ struct ParamTraits<bool> {
template <>
struct IPC_EXPORT ParamTraits<signed char> {
typedef signed char param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
+ static void GetSize(base::PickleSizer* sizer, const param_type& p);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* r);
static void Log(const param_type& p, std::string* l);
};
template <>
struct IPC_EXPORT ParamTraits<unsigned char> {
typedef unsigned char param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
+ static void GetSize(base::PickleSizer* sizer, const param_type& p);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* r);
static void Log(const param_type& p, std::string* l);
};
template <>
struct IPC_EXPORT ParamTraits<unsigned short> {
typedef unsigned short param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m,
+ static void GetSize(base::PickleSizer* sizer, const param_type& p);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r);
static void Log(const param_type& p, std::string* l);
@@ -163,10 +170,11 @@ struct IPC_EXPORT ParamTraits<unsigned short> {
template <>
struct ParamTraits<int> {
typedef int param_type;
- static void Write(Message* m, const param_type& p) {
- m->WriteInt(p);
+ static void GetSize(base::PickleSizer* sizer, const param_type& p) {
+ sizer->AddInt();
}
- static bool Read(const Message* m,
+ static void Write(base::Pickle* m, const param_type& p) { m->WriteInt(p); }
+ static bool Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
return iter->ReadInt(r);
@@ -177,10 +185,11 @@ struct ParamTraits<int> {
template <>
struct ParamTraits<unsigned int> {
typedef unsigned int param_type;
- static void Write(Message* m, const param_type& p) {
- m->WriteInt(p);
+ static void GetSize(base::PickleSizer* sizer, const param_type& p) {
+ sizer->AddInt();
}
- static bool Read(const Message* m,
+ static void Write(base::Pickle* m, const param_type& p) { m->WriteInt(p); }
+ static bool Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
return iter->ReadInt(reinterpret_cast<int*>(r));
@@ -188,13 +197,29 @@ struct ParamTraits<unsigned int> {
IPC_EXPORT static void Log(const param_type& p, std::string* l);
};
+// long isn't safe to send over IPC because it's 4 bytes on 32 bit builds but
+// 8 bytes on 64 bit builds. So if a 32 bit and 64 bit process have a channel
+// that would cause problem.
+// We need to keep this on for a few configs:
+// 1) Windows because DWORD is typedef'd to it, which is fine because we have
+// 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.
+// 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) || \
+ (defined(OS_ANDROID) && defined(ARCH_CPU_64_BITS))
template <>
struct ParamTraits<long> {
typedef long param_type;
- static void Write(Message* m, const param_type& p) {
- m->WriteLongUsingDangerousNonPortableLessPersistableForm(p);
+ static void GetSize(base::PickleSizer* sizer, const param_type& p) {
+ sizer->AddLong();
+ }
+ static void Write(base::Pickle* m, const param_type& p) {
+ m->WriteLong(p);
}
- static bool Read(const Message* m,
+ static bool Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
return iter->ReadLong(r);
@@ -205,24 +230,31 @@ struct ParamTraits<long> {
template <>
struct ParamTraits<unsigned long> {
typedef unsigned long param_type;
- static void Write(Message* m, const param_type& p) {
- m->WriteLongUsingDangerousNonPortableLessPersistableForm(p);
+ static void GetSize(base::PickleSizer* sizer, const param_type& p) {
+ sizer->AddLong();
}
- static bool Read(const Message* m,
+ static void Write(base::Pickle* m, const param_type& p) {
+ m->WriteLong(p);
+ }
+ static bool Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
return iter->ReadLong(reinterpret_cast<long*>(r));
}
IPC_EXPORT static void Log(const param_type& p, std::string* l);
};
+#endif
template <>
struct ParamTraits<long long> {
typedef long long param_type;
- static void Write(Message* m, const param_type& p) {
+ static void GetSize(base::PickleSizer* sizer, const param_type& p) {
+ sizer->AddInt64();
+ }
+ static void Write(base::Pickle* m, const param_type& p) {
m->WriteInt64(static_cast<int64_t>(p));
}
- static bool Read(const Message* m,
+ static bool Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
return iter->ReadInt64(reinterpret_cast<int64_t*>(r));
@@ -233,10 +265,11 @@ struct ParamTraits<long long> {
template <>
struct ParamTraits<unsigned long long> {
typedef unsigned long long param_type;
- static void Write(Message* m, const param_type& p) {
- m->WriteInt64(p);
+ static void GetSize(base::PickleSizer* sizer, const param_type& p) {
+ sizer->AddInt64();
}
- static bool Read(const Message* m,
+ static void Write(base::Pickle* m, const param_type& p) { m->WriteInt64(p); }
+ static bool Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
return iter->ReadInt64(reinterpret_cast<int64_t*>(r));
@@ -250,10 +283,11 @@ struct ParamTraits<unsigned long long> {
template <>
struct IPC_EXPORT ParamTraits<float> {
typedef float param_type;
- static void Write(Message* m, const param_type& p) {
- m->WriteFloat(p);
+ static void GetSize(base::PickleSizer* sizer, const param_type& p) {
+ sizer->AddFloat();
}
- static bool Read(const Message* m,
+ static void Write(base::Pickle* m, const param_type& p) { m->WriteFloat(p); }
+ static bool Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
return iter->ReadFloat(r);
@@ -264,8 +298,9 @@ struct IPC_EXPORT ParamTraits<float> {
template <>
struct IPC_EXPORT ParamTraits<double> {
typedef double param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m,
+ static void GetSize(base::PickleSizer* sizer, const param_type& p);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r);
static void Log(const param_type& p, std::string* l);
@@ -276,10 +311,11 @@ struct IPC_EXPORT ParamTraits<double> {
template <>
struct ParamTraits<std::string> {
typedef std::string param_type;
- static void Write(Message* m, const param_type& p) {
- m->WriteString(p);
+ static void GetSize(base::PickleSizer* sizer, const param_type& p) {
+ sizer->AddString(p);
}
- static bool Read(const Message* m,
+ static void Write(base::Pickle* m, const param_type& p) { m->WriteString(p); }
+ static bool Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
return iter->ReadString(r);
@@ -290,10 +326,13 @@ struct ParamTraits<std::string> {
template <>
struct ParamTraits<base::string16> {
typedef base::string16 param_type;
- static void Write(Message* m, const param_type& p) {
+ static void GetSize(base::PickleSizer* sizer, const param_type& p) {
+ sizer->AddString16(p);
+ }
+ static void Write(base::Pickle* m, const param_type& p) {
m->WriteString16(p);
}
- static bool Read(const Message* m,
+ static bool Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
return iter->ReadString16(r);
@@ -304,8 +343,9 @@ struct ParamTraits<base::string16> {
template <>
struct IPC_EXPORT ParamTraits<std::vector<char> > {
typedef std::vector<char> param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message*,
+ static void GetSize(base::PickleSizer* sizer, const param_type& p);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle*,
base::PickleIterator* iter,
param_type* r);
static void Log(const param_type& p, std::string* l);
@@ -314,8 +354,9 @@ struct IPC_EXPORT ParamTraits<std::vector<char> > {
template <>
struct IPC_EXPORT ParamTraits<std::vector<unsigned char> > {
typedef std::vector<unsigned char> param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m,
+ static void GetSize(base::PickleSizer* sizer, const param_type& p);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r);
static void Log(const param_type& p, std::string* l);
@@ -324,8 +365,9 @@ struct IPC_EXPORT ParamTraits<std::vector<unsigned char> > {
template <>
struct IPC_EXPORT ParamTraits<std::vector<bool> > {
typedef std::vector<bool> param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m,
+ static void GetSize(base::PickleSizer* sizer, const param_type& p);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r);
static void Log(const param_type& p, std::string* l);
@@ -334,12 +376,17 @@ struct IPC_EXPORT ParamTraits<std::vector<bool> > {
template <class P>
struct ParamTraits<std::vector<P> > {
typedef std::vector<P> param_type;
- static void Write(Message* m, const param_type& p) {
+ static void GetSize(base::PickleSizer* sizer, const param_type& p) {
+ GetParamSize(sizer, static_cast<int>(p.size()));
+ for (size_t i = 0; i < p.size(); i++)
+ GetParamSize(sizer, p[i]);
+ }
+ static void Write(base::Pickle* m, const param_type& p) {
WriteParam(m, static_cast<int>(p.size()));
for (size_t i = 0; i < p.size(); i++)
WriteParam(m, p[i]);
}
- static bool Read(const Message* m,
+ static bool Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
int size;
@@ -368,13 +415,19 @@ struct ParamTraits<std::vector<P> > {
template <class P>
struct ParamTraits<std::set<P> > {
typedef std::set<P> param_type;
- static void Write(Message* m, const param_type& p) {
+ static void GetSize(base::PickleSizer* sizer, const param_type& p) {
+ GetParamSize(sizer, static_cast<int>(p.size()));
+ typename param_type::const_iterator iter;
+ for (iter = p.begin(); iter != p.end(); ++iter)
+ GetParamSize(sizer, *iter);
+ }
+ static void Write(base::Pickle* m, const param_type& p) {
WriteParam(m, static_cast<int>(p.size()));
typename param_type::const_iterator iter;
for (iter = p.begin(); iter != p.end(); ++iter)
WriteParam(m, *iter);
}
- static bool Read(const Message* m,
+ static bool Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
int size;
@@ -396,7 +449,15 @@ struct ParamTraits<std::set<P> > {
template <class K, class V, class C, class A>
struct ParamTraits<std::map<K, V, C, A> > {
typedef std::map<K, V, C, A> param_type;
- static void Write(Message* m, const param_type& p) {
+ static void GetSize(base::PickleSizer* sizer, const param_type& p) {
+ GetParamSize(sizer, static_cast<int>(p.size()));
+ typename param_type::const_iterator iter;
+ for (iter = p.begin(); iter != p.end(); ++iter) {
+ GetParamSize(sizer, iter->first);
+ GetParamSize(sizer, iter->second);
+ }
+ }
+ static void Write(base::Pickle* m, const param_type& p) {
WriteParam(m, static_cast<int>(p.size()));
typename param_type::const_iterator iter;
for (iter = p.begin(); iter != p.end(); ++iter) {
@@ -404,7 +465,7 @@ struct ParamTraits<std::map<K, V, C, A> > {
WriteParam(m, iter->second);
}
}
- static bool Read(const Message* m,
+ static bool Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
int size;
@@ -428,11 +489,15 @@ struct ParamTraits<std::map<K, V, C, A> > {
template <class A, class B>
struct ParamTraits<std::pair<A, B> > {
typedef std::pair<A, B> param_type;
- static void Write(Message* m, const param_type& p) {
+ static void GetSize(base::PickleSizer* sizer, const param_type& p) {
+ GetParamSize(sizer, p.first);
+ GetParamSize(sizer, p.second);
+ }
+ static void Write(base::Pickle* m, const param_type& p) {
WriteParam(m, p.first);
WriteParam(m, p.second);
}
- static bool Read(const Message* m,
+ static bool Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
return ReadParam(m, iter, &r->first) && ReadParam(m, iter, &r->second);
@@ -450,8 +515,10 @@ struct ParamTraits<std::pair<A, B> > {
template <>
struct IPC_EXPORT ParamTraits<BrokerableAttachment::AttachmentId> {
typedef BrokerableAttachment::AttachmentId param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* r);
static void Log(const param_type& p, std::string* l);
};
@@ -460,8 +527,9 @@ struct IPC_EXPORT ParamTraits<BrokerableAttachment::AttachmentId> {
template <>
struct IPC_EXPORT ParamTraits<base::DictionaryValue> {
typedef base::DictionaryValue param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m,
+ static void GetSize(base::PickleSizer* sizer, const param_type& p);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r);
static void Log(const param_type& p, std::string* l);
@@ -486,8 +554,8 @@ struct IPC_EXPORT ParamTraits<base::DictionaryValue> {
template<>
struct IPC_EXPORT ParamTraits<base::FileDescriptor> {
typedef base::FileDescriptor param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m,
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r);
static void Log(const param_type& p, std::string* l);
@@ -498,8 +566,10 @@ struct IPC_EXPORT ParamTraits<base::FileDescriptor> {
template <>
struct IPC_EXPORT ParamTraits<base::SharedMemoryHandle> {
typedef base::SharedMemoryHandle param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* r);
static void Log(const param_type& p, std::string* l);
};
#endif // (defined(OS_MACOSX) && !defined(OS_IOS)) || defined(OS_WIN)
@@ -507,8 +577,9 @@ struct IPC_EXPORT ParamTraits<base::SharedMemoryHandle> {
template <>
struct IPC_EXPORT ParamTraits<base::FilePath> {
typedef base::FilePath param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m,
+ static void GetSize(base::PickleSizer* sizer, const param_type& p);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r);
static void Log(const param_type& p, std::string* l);
@@ -517,8 +588,9 @@ struct IPC_EXPORT ParamTraits<base::FilePath> {
template <>
struct IPC_EXPORT ParamTraits<base::ListValue> {
typedef base::ListValue param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m,
+ static void GetSize(base::PickleSizer* sizer, const param_type& p);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r);
static void Log(const param_type& p, std::string* l);
@@ -527,8 +599,9 @@ struct IPC_EXPORT ParamTraits<base::ListValue> {
template <>
struct IPC_EXPORT ParamTraits<base::NullableString16> {
typedef base::NullableString16 param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m,
+ static void GetSize(base::PickleSizer* sizer, const param_type& p);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r);
static void Log(const param_type& p, std::string* l);
@@ -537,8 +610,9 @@ struct IPC_EXPORT ParamTraits<base::NullableString16> {
template <>
struct IPC_EXPORT ParamTraits<base::File::Info> {
typedef base::File::Info param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m,
+ static void GetSize(base::PickleSizer* sizer, const param_type& p);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r);
static void Log(const param_type& p, std::string* l);
@@ -559,8 +633,9 @@ struct SimilarTypeTraits<HWND> {
template <>
struct IPC_EXPORT ParamTraits<base::Time> {
typedef base::Time param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m,
+ static void GetSize(base::PickleSizer* sizer, const param_type& p);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r);
static void Log(const param_type& p, std::string* l);
@@ -569,8 +644,9 @@ struct IPC_EXPORT ParamTraits<base::Time> {
template <>
struct IPC_EXPORT ParamTraits<base::TimeDelta> {
typedef base::TimeDelta param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m,
+ static void GetSize(base::PickleSizer* sizer, const param_type& p);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r);
static void Log(const param_type& p, std::string* l);
@@ -579,19 +655,20 @@ struct IPC_EXPORT ParamTraits<base::TimeDelta> {
template <>
struct IPC_EXPORT ParamTraits<base::TimeTicks> {
typedef base::TimeTicks param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m,
+ static void GetSize(base::PickleSizer* sizer, const param_type& p);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r);
static void Log(const param_type& p, std::string* l);
};
template <>
-struct ParamTraits<base::Tuple<>> {
- typedef base::Tuple<> param_type;
- static void Write(Message* m, const param_type& p) {
- }
- static bool Read(const Message* m,
+struct ParamTraits<std::tuple<>> {
+ typedef std::tuple<> param_type;
+ static void GetSize(base::PickleSizer* sizer, const param_type& p) {}
+ static void Write(base::Pickle* m, const param_type& p) {}
+ static bool Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
return true;
@@ -601,134 +678,159 @@ struct ParamTraits<base::Tuple<>> {
};
template <class A>
-struct ParamTraits<base::Tuple<A>> {
- typedef base::Tuple<A> param_type;
- static void Write(Message* m, const param_type& p) {
- WriteParam(m, base::get<0>(p));
+struct ParamTraits<std::tuple<A>> {
+ typedef std::tuple<A> param_type;
+ static void GetSize(base::PickleSizer* sizer, const param_type& p) {
+ GetParamSize(sizer, std::get<0>(p));
}
- static bool Read(const Message* m,
+ 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, &base::get<0>(*r));
+ return ReadParam(m, iter, &std::get<0>(*r));
}
static void Log(const param_type& p, std::string* l) {
- LogParam(base::get<0>(p), l);
+ LogParam(std::get<0>(p), l);
}
};
template <class A, class B>
-struct ParamTraits<base::Tuple<A, B>> {
- typedef base::Tuple<A, B> param_type;
- static void Write(Message* m, const param_type& p) {
- WriteParam(m, base::get<0>(p));
- WriteParam(m, base::get<1>(p));
+struct ParamTraits<std::tuple<A, B>> {
+ typedef std::tuple<A, B> 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 bool Read(const Message* m,
+ static bool Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
- return (ReadParam(m, iter, &base::get<0>(*r)) &&
- ReadParam(m, iter, &base::get<1>(*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(base::get<0>(p), l);
+ LogParam(std::get<0>(p), l);
l->append(", ");
- LogParam(base::get<1>(p), l);
+ LogParam(std::get<1>(p), l);
}
};
template <class A, class B, class C>
-struct ParamTraits<base::Tuple<A, B, C>> {
- typedef base::Tuple<A, B, C> param_type;
- static void Write(Message* m, const param_type& p) {
- WriteParam(m, base::get<0>(p));
- WriteParam(m, base::get<1>(p));
- WriteParam(m, base::get<2>(p));
- }
- static bool Read(const Message* m,
+struct ParamTraits<std::tuple<A, B, C>> {
+ typedef std::tuple<A, B, C> 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 bool Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
- return (ReadParam(m, iter, &base::get<0>(*r)) &&
- ReadParam(m, iter, &base::get<1>(*r)) &&
- ReadParam(m, iter, &base::get<2>(*r)));
+ return (ReadParam(m, iter, &std::get<0>(*r)) &&
+ ReadParam(m, iter, &std::get<1>(*r)) &&
+ ReadParam(m, iter, &std::get<2>(*r)));
}
static void Log(const param_type& p, std::string* l) {
- LogParam(base::get<0>(p), l);
+ LogParam(std::get<0>(p), l);
l->append(", ");
- LogParam(base::get<1>(p), l);
+ LogParam(std::get<1>(p), l);
l->append(", ");
- LogParam(base::get<2>(p), l);
+ LogParam(std::get<2>(p), l);
}
};
template <class A, class B, class C, class D>
-struct ParamTraits<base::Tuple<A, B, C, D>> {
- typedef base::Tuple<A, B, C, D> param_type;
- static void Write(Message* m, const param_type& p) {
- WriteParam(m, base::get<0>(p));
- WriteParam(m, base::get<1>(p));
- WriteParam(m, base::get<2>(p));
- WriteParam(m, base::get<3>(p));
- }
- static bool Read(const Message* m,
+struct ParamTraits<std::tuple<A, B, C, D>> {
+ typedef std::tuple<A, B, C, D> 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, &base::get<0>(*r)) &&
- ReadParam(m, iter, &base::get<1>(*r)) &&
- ReadParam(m, iter, &base::get<2>(*r)) &&
- ReadParam(m, iter, &base::get<3>(*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(base::get<0>(p), l);
+ LogParam(std::get<0>(p), l);
l->append(", ");
- LogParam(base::get<1>(p), l);
+ LogParam(std::get<1>(p), l);
l->append(", ");
- LogParam(base::get<2>(p), l);
+ LogParam(std::get<2>(p), l);
l->append(", ");
- LogParam(base::get<3>(p), l);
+ LogParam(std::get<3>(p), l);
}
};
template <class A, class B, class C, class D, class E>
-struct ParamTraits<base::Tuple<A, B, C, D, E>> {
- typedef base::Tuple<A, B, C, D, E> param_type;
- static void Write(Message* m, const param_type& p) {
- WriteParam(m, base::get<0>(p));
- WriteParam(m, base::get<1>(p));
- WriteParam(m, base::get<2>(p));
- WriteParam(m, base::get<3>(p));
- WriteParam(m, base::get<4>(p));
- }
- static bool Read(const Message* m,
+struct ParamTraits<std::tuple<A, B, C, D, E>> {
+ typedef std::tuple<A, B, C, D, E> 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));
+ GetParamSize(sizer, std::get<4>(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));
+ }
+ static bool Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
- return (ReadParam(m, iter, &base::get<0>(*r)) &&
- ReadParam(m, iter, &base::get<1>(*r)) &&
- ReadParam(m, iter, &base::get<2>(*r)) &&
- ReadParam(m, iter, &base::get<3>(*r)) &&
- ReadParam(m, iter, &base::get<4>(*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(base::get<0>(p), l);
+ LogParam(std::get<0>(p), l);
l->append(", ");
- LogParam(base::get<1>(p), l);
+ LogParam(std::get<1>(p), l);
l->append(", ");
- LogParam(base::get<2>(p), l);
+ LogParam(std::get<2>(p), l);
l->append(", ");
- LogParam(base::get<3>(p), l);
+ LogParam(std::get<3>(p), l);
l->append(", ");
- LogParam(base::get<4>(p), l);
+ LogParam(std::get<4>(p), l);
}
};
template<class P>
struct ParamTraits<ScopedVector<P> > {
typedef ScopedVector<P> param_type;
- static void Write(Message* m, const param_type& p) {
+ static void Write(base::Pickle* m, const param_type& p) {
WriteParam(m, static_cast<int>(p.size()));
for (size_t i = 0; i < p.size(); i++)
WriteParam(m, *p[i]);
}
- static bool Read(const Message* m,
+ static bool Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
int size = 0;
@@ -756,12 +858,17 @@ struct ParamTraits<ScopedVector<P> > {
template <class P, size_t stack_capacity>
struct ParamTraits<base::StackVector<P, stack_capacity> > {
typedef base::StackVector<P, stack_capacity> param_type;
- static void Write(Message* m, const param_type& p) {
+ static void GetSize(base::PickleSizer* sizer, const param_type& p) {
+ GetParamSize(sizer, static_cast<int>(p->size()));
+ for (size_t i = 0; i < p->size(); i++)
+ GetParamSize(sizer, p[i]);
+ }
+ static void Write(base::Pickle* m, const param_type& p) {
WriteParam(m, static_cast<int>(p->size()));
for (size_t i = 0; i < p->size(); i++)
WriteParam(m, p[i]);
}
- static bool Read(const Message* m,
+ static bool Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
int size;
@@ -796,7 +903,15 @@ struct ParamTraits<base::SmallMap<NormalMap, kArraySize, EqualKey, MapInit> > {
typedef base::SmallMap<NormalMap, kArraySize, EqualKey, MapInit> param_type;
typedef typename param_type::key_type K;
typedef typename param_type::data_type V;
- static void Write(Message* m, const param_type& p) {
+ static void GetSize(base::PickleSizer* sizer, const param_type& p) {
+ GetParamSize(sizer, static_cast<int>(p.size()));
+ typename param_type::const_iterator iter;
+ for (iter = p.begin(); iter != p.end(); ++iter) {
+ GetParamSize(sizer, iter->first);
+ GetParamSize(sizer, iter->second);
+ }
+ }
+ static void Write(base::Pickle* m, const param_type& p) {
WriteParam(m, static_cast<int>(p.size()));
typename param_type::const_iterator iter;
for (iter = p.begin(); iter != p.end(); ++iter) {
@@ -804,7 +919,7 @@ struct ParamTraits<base::SmallMap<NormalMap, kArraySize, EqualKey, MapInit> > {
WriteParam(m, iter->second);
}
}
- static bool Read(const Message* m,
+ static bool Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
int size;
@@ -828,13 +943,19 @@ struct ParamTraits<base::SmallMap<NormalMap, kArraySize, EqualKey, MapInit> > {
template <class P>
struct ParamTraits<scoped_ptr<P> > {
typedef scoped_ptr<P> param_type;
- static void Write(Message* m, const param_type& p) {
+ static void GetSize(base::PickleSizer* sizer, const param_type& p) {
+ bool valid = !!p;
+ GetParamSize(sizer, valid);
+ if (valid)
+ GetParamSize(sizer, *p);
+ }
+ static void Write(base::Pickle* m, const param_type& p) {
bool valid = !!p;
WriteParam(m, valid);
if (valid)
WriteParam(m, *p);
}
- static bool Read(const Message* m,
+ static bool Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
bool valid = false;
@@ -869,8 +990,8 @@ struct ParamTraits<scoped_ptr<P> > {
template<>
struct IPC_EXPORT ParamTraits<IPC::ChannelHandle> {
typedef ChannelHandle param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m,
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r);
static void Log(const param_type& p, std::string* l);
@@ -879,8 +1000,9 @@ struct IPC_EXPORT ParamTraits<IPC::ChannelHandle> {
template <>
struct IPC_EXPORT ParamTraits<LogData> {
typedef LogData param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m,
+ static void GetSize(base::PickleSizer* sizer, const param_type& p);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r);
static void Log(const param_type& p, std::string* l);
@@ -888,8 +1010,8 @@ struct IPC_EXPORT ParamTraits<LogData> {
template <>
struct IPC_EXPORT ParamTraits<Message> {
- static void Write(Message* m, const Message& p);
- static bool Read(const Message* m,
+ static void Write(base::Pickle* m, const Message& p);
+ static bool Read(const base::Pickle* m,
base::PickleIterator* iter,
Message* r);
static void Log(const Message& p, std::string* l);
@@ -901,8 +1023,9 @@ struct IPC_EXPORT ParamTraits<Message> {
template <>
struct IPC_EXPORT ParamTraits<HANDLE> {
typedef HANDLE param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m,
+ static void GetSize(base::PickleSizer* sizer, const param_type& p);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r);
static void Log(const param_type& p, std::string* l);
@@ -911,8 +1034,9 @@ struct IPC_EXPORT ParamTraits<HANDLE> {
template <>
struct IPC_EXPORT ParamTraits<LOGFONT> {
typedef LOGFONT param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m,
+ static void GetSize(base::PickleSizer* sizer, const param_type& p);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r);
static void Log(const param_type& p, std::string* l);
@@ -921,8 +1045,9 @@ struct IPC_EXPORT ParamTraits<LOGFONT> {
template <>
struct IPC_EXPORT ParamTraits<MSG> {
typedef MSG param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m,
+ static void GetSize(base::PickleSizer* sizer, const param_type& p);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r);
static void Log(const param_type& p, std::string* l);
@@ -932,17 +1057,6 @@ struct IPC_EXPORT ParamTraits<MSG> {
//-----------------------------------------------------------------------------
// Generic message subclasses
-// Used for asynchronous messages.
-template <class ParamType>
-class MessageSchema {
- public:
- typedef ParamType Param;
- typedef typename base::TupleTypes<ParamType>::ParamTuple RefParam;
-
- static void Write(Message* msg, const RefParam& p) IPC_MSG_NOINLINE;
- static bool Read(const Message* msg, Param* p) IPC_MSG_NOINLINE;
-};
-
// defined in ipc_logging.cc
IPC_EXPORT void GenerateLogData(const std::string& channel,
const Message& message,
@@ -989,79 +1103,6 @@ inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
inline void ConnectMessageAndReply(const Message* msg, Message* reply) {}
#endif
-// This class assumes that its template argument is a RefTuple (a Tuple with
-// reference elements). This would go into ipc_message_utils_impl.h, but it is
-// also used by chrome_frame.
-template <class RefTuple>
-class ParamDeserializer : public MessageReplyDeserializer {
- public:
- explicit ParamDeserializer(const RefTuple& out) : out_(out) { }
-
- bool SerializeOutputParameters(const IPC::Message& msg,
- base::PickleIterator iter) override {
- return ReadParam(&msg, &iter, &out_);
- }
-
- RefTuple out_;
-};
-
-// Used for synchronous messages.
-template <class SendParamType, class ReplyParamType>
-class SyncMessageSchema {
- public:
- typedef SendParamType SendParam;
- typedef typename base::TupleTypes<SendParam>::ParamTuple RefSendParam;
- typedef ReplyParamType ReplyParam;
-
- static void Write(Message* msg, const RefSendParam& send) IPC_MSG_NOINLINE;
- static bool ReadSendParam(const Message* msg, SendParam* p) IPC_MSG_NOINLINE;
- static bool ReadReplyParam(
- const Message* msg,
- typename base::TupleTypes<ReplyParam>::ValueTuple* p) IPC_MSG_NOINLINE;
-
- template<class T, class S, class Method>
- static bool DispatchWithSendParams(bool ok, const SendParam& send_params,
- const Message* msg, T* obj, S* sender,
- Method func) {
- Message* reply = SyncMessage::GenerateReply(msg);
- if (ok) {
- typename base::TupleTypes<ReplyParam>::ValueTuple reply_params;
- base::DispatchToMethod(obj, func, send_params, &reply_params);
- WriteParam(reply, reply_params);
- LogReplyParamsToMessage(reply_params, msg);
- } else {
- NOTREACHED() << "Error deserializing message " << msg->type();
- reply->set_reply_error();
- }
- sender->Send(reply);
- return ok;
- }
-
- template<class T, class Method>
- static bool DispatchDelayReplyWithSendParams(bool ok,
- const SendParam& send_params,
- const Message* msg, T* obj,
- Method func) {
- Message* reply = SyncMessage::GenerateReply(msg);
- if (ok) {
- base::Tuple<Message&> t = base::MakeRefTuple(*reply);
- ConnectMessageAndReply(msg, reply);
- base::DispatchToMethod(obj, func, send_params, &t);
- } else {
- NOTREACHED() << "Error deserializing message " << msg->type();
- reply->set_reply_error();
- obj->Send(reply);
- }
- return ok;
- }
-
- template <typename... Ts>
- static void WriteReplyParams(Message* reply, Ts... args) {
- ReplyParam p(args...);
- WriteParam(reply, p);
- }
-};
-
} // namespace IPC
#endif // IPC_IPC_MESSAGE_UTILS_H_
diff --git a/chromium/ipc/ipc_message_utils_impl.h b/chromium/ipc/ipc_message_utils_impl.h
deleted file mode 100644
index 485dca578e9..00000000000
--- a/chromium/ipc/ipc_message_utils_impl.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (c) 2012 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.
-//
-// This file contains templates forward declared (but not defined) in
-// ipc_message_utils.h so that they are only instantiated in certain files,
-// notably a few IPC unit tests.
-
-#ifndef IPC_IPC_MESSAGE_UTILS_IMPL_H_
-#define IPC_IPC_MESSAGE_UTILS_IMPL_H_
-
-namespace IPC {
-
-template <class ParamType>
-void MessageSchema<ParamType>::Write(Message* msg, const RefParam& p) {
- WriteParam(msg, p);
-}
-
-template <class ParamType>
-bool MessageSchema<ParamType>::Read(const Message* msg, Param* p) {
- base::PickleIterator iter(*msg);
- if (ReadParam(msg, &iter, p))
- return true;
- NOTREACHED() << "Error deserializing message " << msg->type();
- return false;
-}
-
-template <class SendParamType, class ReplyParamType>
-void SyncMessageSchema<SendParamType, ReplyParamType>::Write(
- Message* msg,
- const RefSendParam& send) {
- WriteParam(msg, send);
-}
-
-template <class SendParamType, class ReplyParamType>
-bool SyncMessageSchema<SendParamType, ReplyParamType>::ReadSendParam(
- const Message* msg, SendParam* p) {
- base::PickleIterator iter = SyncMessage::GetDataIterator(msg);
- return ReadParam(msg, &iter, p);
-}
-
-template <class SendParamType, class ReplyParamType>
-bool SyncMessageSchema<SendParamType, ReplyParamType>::ReadReplyParam(
- const Message* msg, typename base::TupleTypes<ReplyParam>::ValueTuple* p) {
- base::PickleIterator iter = SyncMessage::GetDataIterator(msg);
- return ReadParam(msg, &iter, p);
-}
-
-} // namespace IPC
-
-#endif // IPC_IPC_MESSAGE_UTILS_IMPL_H_
diff --git a/chromium/ipc/ipc_message_utils_unittest.cc b/chromium/ipc/ipc_message_utils_unittest.cc
index f3aa31a5160..659047d2061 100644
--- a/chromium/ipc/ipc_message_utils_unittest.cc
+++ b/chromium/ipc/ipc_message_utils_unittest.cc
@@ -8,6 +8,7 @@
#include <stdint.h>
#include "base/files/file_path.h"
+#include "base/json/json_reader.h"
#include "ipc/ipc_message.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -90,5 +91,47 @@ TEST(IPCMessageUtilsTest, StackVector) {
EXPECT_EQ(stack_vector[i], output[i]);
}
+// Tests that PickleSizer and Pickle agree on the size of a complex base::Value.
+TEST(IPCMessageUtilsTest, ValueSize) {
+ scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue);
+ value->SetWithoutPathExpansion("foo", new base::FundamentalValue(42));
+ value->SetWithoutPathExpansion("bar", new base::FundamentalValue(3.14));
+ value->SetWithoutPathExpansion("baz", new base::StringValue("hello"));
+ value->SetWithoutPathExpansion("qux", base::Value::CreateNullValue());
+
+ scoped_ptr<base::DictionaryValue> nested_dict(new base::DictionaryValue);
+ nested_dict->SetWithoutPathExpansion("foobar", new base::FundamentalValue(5));
+ value->SetWithoutPathExpansion("nested", std::move(nested_dict));
+
+ scoped_ptr<base::ListValue> list_value(new base::ListValue);
+ list_value->Append(new base::StringValue("im a string"));
+ list_value->Append(new base::StringValue("im another string"));
+ value->SetWithoutPathExpansion("awesome-list", std::move(list_value));
+
+ base::Pickle pickle;
+ IPC::WriteParam(&pickle, *value);
+
+ base::PickleSizer sizer;
+ IPC::GetParamSize(&sizer, *value);
+
+ EXPECT_EQ(sizer.payload_size(), pickle.payload_size());
+}
+
+TEST(IPCMessageUtilsTest, JsonValueSize) {
+ const char kJson[] = "[ { \"foo\": \"bar\", \"baz\": 1234.0 } ]";
+ std::unique_ptr<base::Value> json_value = base::JSONReader::Read(kJson);
+ EXPECT_NE(nullptr, json_value);
+ base::ListValue value;
+ value.Append(std::move(json_value));
+
+ base::Pickle pickle;
+ IPC::WriteParam(&pickle, value);
+
+ base::PickleSizer sizer;
+ IPC::GetParamSize(&sizer, value);
+
+ EXPECT_EQ(sizer.payload_size(), pickle.payload_size());
+}
+
} // namespace
} // namespace IPC
diff --git a/chromium/ipc/ipc_perftest_support.cc b/chromium/ipc/ipc_perftest_support.cc
index 1ecc7c740e3..5cd2b1db82a 100644
--- a/chromium/ipc/ipc_perftest_support.cc
+++ b/chromium/ipc/ipc_perftest_support.cc
@@ -227,6 +227,9 @@ class PerformanceChannelListener : public Listener {
scoped_ptr<base::PerfTimeLogger> perf_logger_;
};
+IPCChannelPerfTestBase::IPCChannelPerfTestBase() = default;
+IPCChannelPerfTestBase::~IPCChannelPerfTestBase() = default;
+
std::vector<PingPongTestParams>
IPCChannelPerfTestBase::GetDefaultTestParams() {
// Test several sizes. We use 12^N for message size, and limit the message
@@ -281,14 +284,14 @@ void IPCChannelPerfTestBase::RunTestChannelPingPong(
void IPCChannelPerfTestBase::RunTestChannelProxyPingPong(
const std::vector<PingPongTestParams>& params) {
+ io_thread_.reset(new base::TestIOThread(base::TestIOThread::kAutoStart));
InitWithCustomMessageLoop("PerformanceClient",
make_scoped_ptr(new base::MessageLoop()));
- base::TestIOThread io_thread(base::TestIOThread::kAutoStart);
// Set up IPC channel and start client.
PerformanceChannelListener listener("ChannelProxy");
- CreateChannelProxy(&listener, io_thread.task_runner());
+ CreateChannelProxy(&listener, io_thread_->task_runner());
listener.Init(channel_proxy());
ASSERT_TRUE(StartClient());
@@ -318,6 +321,8 @@ void IPCChannelPerfTestBase::RunTestChannelProxyPingPong(
EXPECT_TRUE(WaitForClientShutdown());
DestroyChannelProxy();
+
+ io_thread_.reset();
}
diff --git a/chromium/ipc/ipc_perftest_support.h b/chromium/ipc/ipc_perftest_support.h
index 80c58d127b9..82eb1eefbf0 100644
--- a/chromium/ipc/ipc_perftest_support.h
+++ b/chromium/ipc/ipc_perftest_support.h
@@ -10,6 +10,8 @@
#include <vector>
#include "base/macros.h"
+#include "base/test/test_io_thread.h"
+#include "base/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "ipc/ipc_test_base.h"
@@ -34,12 +36,24 @@ class PingPongTestParams {
class IPCChannelPerfTestBase : public IPCTestBase {
public:
+ IPCChannelPerfTestBase();
+ ~IPCChannelPerfTestBase() override;
+
static std::vector<PingPongTestParams> GetDefaultTestParams();
void RunTestChannelPingPong(
const std::vector<PingPongTestParams>& params_list);
void RunTestChannelProxyPingPong(
const std::vector<PingPongTestParams>& params_list);
+
+ scoped_refptr<base::TaskRunner> io_task_runner() {
+ if (io_thread_)
+ return io_thread_->task_runner();
+ return base::ThreadTaskRunnerHandle::Get();
+ }
+
+ private:
+ scoped_ptr<base::TestIOThread> io_thread_;
};
class PingPongTestClient {
diff --git a/chromium/ipc/ipc_platform_file.cc b/chromium/ipc/ipc_platform_file.cc
index 97c176f3d7b..dbcfddcc779 100644
--- a/chromium/ipc/ipc_platform_file.cc
+++ b/chromium/ipc/ipc_platform_file.cc
@@ -11,24 +11,23 @@
namespace IPC {
-PlatformFileForTransit GetFileHandleForProcess(base::PlatformFile handle,
- base::ProcessHandle process,
- bool close_source_handle) {
- IPC::PlatformFileForTransit out_handle;
+PlatformFileForTransit GetPlatformFileForTransit(base::PlatformFile handle,
+ bool close_source_handle) {
#if defined(OS_WIN)
+ HANDLE raw_handle = INVALID_HANDLE_VALUE;
DWORD options = DUPLICATE_SAME_ACCESS;
if (close_source_handle)
options |= DUPLICATE_CLOSE_SOURCE;
if (handle == INVALID_HANDLE_VALUE ||
- !::DuplicateHandle(::GetCurrentProcess(),
- handle,
- process,
- &out_handle,
- 0,
- FALSE,
- options)) {
- out_handle = IPC::InvalidPlatformFileForTransit();
+ !::DuplicateHandle(::GetCurrentProcess(), handle, ::GetCurrentProcess(),
+ &raw_handle, 0, FALSE, options)) {
+ return IPC::InvalidPlatformFileForTransit();
}
+
+ IPC::PlatformFileForTransit out_handle = IPC::PlatformFileForTransit(
+ raw_handle, base::GetCurrentProcId());
+ out_handle.SetOwnershipPassesToIPC(true);
+ return out_handle;
#elif defined(OS_POSIX)
// If asked to close the source, we can simply re-use the source fd instead of
// dup()ing and close()ing.
@@ -39,16 +38,14 @@ PlatformFileForTransit GetFileHandleForProcess(base::PlatformFile handle,
// close the source handle before the message is sent, creating a race
// condition.
int fd = close_source_handle ? handle : ::dup(handle);
- out_handle = base::FileDescriptor(fd, true);
+ return base::FileDescriptor(fd, true);
#else
#error Not implemented.
#endif
- return out_handle;
}
-PlatformFileForTransit TakeFileHandleForProcess(base::File file,
- base::ProcessHandle process) {
- return GetFileHandleForProcess(file.TakePlatformFile(), process, true);
+PlatformFileForTransit TakePlatformFileForTransit(base::File file) {
+ return GetPlatformFileForTransit(file.TakePlatformFile(), true);
}
} // namespace IPC
diff --git a/chromium/ipc/ipc_platform_file.h b/chromium/ipc/ipc_platform_file.h
index fb4d0e423de..15807f60b75 100644
--- a/chromium/ipc/ipc_platform_file.h
+++ b/chromium/ipc/ipc_platform_file.h
@@ -14,17 +14,24 @@
#include "base/file_descriptor_posix.h"
#endif
+#if defined(OS_WIN)
+#include "base/memory/shared_memory_handle.h"
+#endif
+
namespace IPC {
#if defined(OS_WIN)
-typedef base::PlatformFile PlatformFileForTransit;
+// The semantics for IPC transfer of a SharedMemoryHandle are exactly the same
+// as for a PlatformFileForTransit. The object wraps a HANDLE, and has some
+// metadata that indicates the process to which the HANDLE belongs.
+using PlatformFileForTransit = base::SharedMemoryHandle;
#elif defined(OS_POSIX)
typedef base::FileDescriptor PlatformFileForTransit;
#endif
inline PlatformFileForTransit InvalidPlatformFileForTransit() {
#if defined(OS_WIN)
- return INVALID_HANDLE_VALUE;
+ return PlatformFileForTransit();
#elif defined(OS_POSIX)
return base::FileDescriptor();
#endif
@@ -33,7 +40,7 @@ inline PlatformFileForTransit InvalidPlatformFileForTransit() {
inline base::PlatformFile PlatformFileForTransitToPlatformFile(
const PlatformFileForTransit& transit) {
#if defined(OS_WIN)
- return transit;
+ return transit.GetHandle();
#elif defined(OS_POSIX)
return transit.fd;
#endif
@@ -42,23 +49,22 @@ inline base::PlatformFile PlatformFileForTransitToPlatformFile(
inline base::File PlatformFileForTransitToFile(
const PlatformFileForTransit& transit) {
#if defined(OS_WIN)
- return base::File(transit);
+ return base::File(transit.GetHandle());
#elif defined(OS_POSIX)
return base::File(transit.fd);
#endif
}
-// Returns a file handle equivalent to |file| that can be used in |process|.
-IPC_EXPORT PlatformFileForTransit GetFileHandleForProcess(
+// Creates a new handle that can be passed through IPC. The result must be
+// passed to the IPC layer as part of a message, or else it will leak.
+IPC_EXPORT PlatformFileForTransit GetPlatformFileForTransit(
base::PlatformFile file,
- base::ProcessHandle process,
bool close_source_handle);
-// Returns a file handle equivalent to |file| that can be used in |process|.
+// Creates a new handle that can be passed through IPC. The result must be
+// passed to the IPC layer as part of a message, or else it will leak.
// Note that this function takes ownership of |file|.
-IPC_EXPORT PlatformFileForTransit TakeFileHandleForProcess(
- base::File file,
- base::ProcessHandle process);
+IPC_EXPORT PlatformFileForTransit TakePlatformFileForTransit(base::File file);
} // namespace IPC
diff --git a/chromium/ipc/ipc_send_fds_test.cc b/chromium/ipc/ipc_send_fds_test.cc
index 81f589412d6..264aa855f91 100644
--- a/chromium/ipc/ipc_send_fds_test.cc
+++ b/chromium/ipc/ipc_send_fds_test.cc
@@ -193,6 +193,8 @@ MULTIPROCESS_IPC_TEST_CLIENT_MAIN(SendFdsSandboxedClient) {
// Enable the sandbox.
char* error_buff = NULL;
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
int error = sandbox_init(kSBXProfilePureComputation, SANDBOX_NAMED,
&error_buff);
bool success = (error == 0 && error_buff == NULL);
@@ -200,6 +202,7 @@ MULTIPROCESS_IPC_TEST_CLIENT_MAIN(SendFdsSandboxedClient) {
return -1;
sandbox_free_error(error_buff);
+#pragma clang diagnostic pop
// Make sure sandbox is really enabled.
if (open(kDevZeroPath, O_RDONLY) != -1) {
diff --git a/chromium/ipc/ipc_sync_channel.cc b/chromium/ipc/ipc_sync_channel.cc
index d1942112d9a..48d9328fe1b 100644
--- a/chromium/ipc/ipc_sync_channel.cc
+++ b/chromium/ipc/ipc_sync_channel.cc
@@ -80,7 +80,7 @@ class SyncChannel::ReceivedSyncMsgQueue :
if (!was_task_pending) {
listener_task_runner_->PostTask(
FROM_HERE, base::Bind(&ReceivedSyncMsgQueue::DispatchMessagesTask,
- this, scoped_refptr<SyncContext>(context)));
+ this, base::RetainedRef(context)));
}
}
@@ -317,7 +317,13 @@ bool SyncChannel::SyncContext::TryToUnblockListener(const Message* msg) {
} else {
DVLOG(1) << "Received error reply";
}
- deserializers_.back().done_event->Signal();
+
+ base::WaitableEvent* done_event = deserializers_.back().done_event;
+ TRACE_EVENT_FLOW_BEGIN0(
+ TRACE_DISABLED_BY_DEFAULT("ipc.flow"),
+ "SyncChannel::SyncContext::TryToUnblockListener", done_event);
+
+ done_event->Signal();
return true;
}
@@ -369,24 +375,16 @@ void SyncChannel::SyncContext::OnChannelClosed() {
Context::OnChannelClosed();
}
-void SyncChannel::SyncContext::OnSendTimeout(int message_id) {
- base::AutoLock auto_lock(deserializers_lock_);
- PendingSyncMessageQueue::iterator iter;
- DVLOG(1) << "Send timeout";
- for (iter = deserializers_.begin(); iter != deserializers_.end(); iter++) {
- if (iter->id == message_id) {
- iter->done_event->Signal();
- break;
- }
- }
-}
-
void SyncChannel::SyncContext::CancelPendingSends() {
base::AutoLock auto_lock(deserializers_lock_);
PendingSyncMessageQueue::iterator iter;
DVLOG(1) << "Canceling pending sends";
- for (iter = deserializers_.begin(); iter != deserializers_.end(); iter++)
+ for (iter = deserializers_.begin(); iter != deserializers_.end(); iter++) {
+ TRACE_EVENT_FLOW_BEGIN0(TRACE_DISABLED_BY_DEFAULT("ipc.flow"),
+ "SyncChannel::SyncContext::CancelPendingSends",
+ iter->done_event);
iter->done_event->Signal();
+ }
}
void SyncChannel::SyncContext::OnWaitableEventSignaled(WaitableEvent* event) {
@@ -503,6 +501,9 @@ bool SyncChannel::Send(Message* message) {
// *this* might get deleted, so only call static functions at this point.
WaitForReply(context.get(), pump_messages_event);
+ TRACE_EVENT_FLOW_END0(TRACE_DISABLED_BY_DEFAULT("ipc.flow"),
+ "SyncChannel::Send", context->GetSendDoneEvent());
+
return context->Pop();
}
diff --git a/chromium/ipc/ipc_sync_channel.h b/chromium/ipc/ipc_sync_channel.h
index 240a28efc98..eb2a272330c 100644
--- a/chromium/ipc/ipc_sync_channel.h
+++ b/chromium/ipc/ipc_sync_channel.h
@@ -156,10 +156,6 @@ class IPC_EXPORT SyncChannel : public ChannelProxy {
// returned. Otherwise the function returns false.
bool TryToUnblockListener(const Message* msg);
- // Called on the IPC thread when a sync send that runs a nested message loop
- // times out.
- void OnSendTimeout(int message_id);
-
base::WaitableEvent* shutdown_event() { return shutdown_event_; }
ReceivedSyncMsgQueue* received_sync_msgs() {
diff --git a/chromium/ipc/ipc_sync_channel_unittest.cc b/chromium/ipc/ipc_sync_channel_unittest.cc
index 21ebafb638c..e3a71927a9b 100644
--- a/chromium/ipc/ipc_sync_channel_unittest.cc
+++ b/chromium/ipc/ipc_sync_channel_unittest.cc
@@ -39,16 +39,18 @@ namespace {
class Worker : public Listener, public Sender {
public:
// Will create a channel without a name.
- Worker(Channel::Mode mode, const std::string& thread_name)
+ Worker(Channel::Mode mode,
+ const std::string& thread_name,
+ const std::string& channel_name)
: done_(new WaitableEvent(false, false)),
channel_created_(new WaitableEvent(false, false)),
+ channel_name_(channel_name),
mode_(mode),
ipc_thread_((thread_name + "_ipc").c_str()),
listener_thread_((thread_name + "_listener").c_str()),
overrided_thread_(NULL),
shutdown_event_(true, false),
- is_shutdown_(false) {
- }
+ is_shutdown_(false) {}
// Will create a named channel and use this name for the threads' name.
Worker(const std::string& channel_name, Channel::Mode mode)
@@ -276,9 +278,9 @@ class IPCSyncChannelTest : public testing::Test {
class SimpleServer : public Worker {
public:
- explicit SimpleServer(bool pump_during_send)
- : Worker(Channel::MODE_SERVER, "simpler_server"),
- pump_during_send_(pump_during_send) { }
+ SimpleServer(bool pump_during_send, const std::string& channel_name)
+ : Worker(Channel::MODE_SERVER, "simpler_server", channel_name),
+ pump_during_send_(pump_during_send) {}
void Run() override {
SendAnswerToLife(pump_during_send_, true);
Done();
@@ -289,7 +291,8 @@ class SimpleServer : public Worker {
class SimpleClient : public Worker {
public:
- SimpleClient() : Worker(Channel::MODE_CLIENT, "simple_client") { }
+ explicit SimpleClient(const std::string& channel_name)
+ : Worker(Channel::MODE_CLIENT, "simple_client", channel_name) {}
void OnAnswer(int* answer) override {
*answer = 42;
@@ -299,8 +302,8 @@ class SimpleClient : public Worker {
void Simple(bool pump_during_send) {
std::vector<Worker*> workers;
- workers.push_back(new SimpleServer(pump_during_send));
- workers.push_back(new SimpleClient());
+ workers.push_back(new SimpleServer(pump_during_send, "Simple"));
+ workers.push_back(new SimpleClient("Simple"));
RunTest(workers);
}
@@ -322,9 +325,9 @@ TEST_F(IPCSyncChannelTest, MAYBE_Simple) {
// ChannelProxy::Init separately) process.
class TwoStepServer : public Worker {
public:
- explicit TwoStepServer(bool create_pipe_now)
- : Worker(Channel::MODE_SERVER, "simpler_server"),
- create_pipe_now_(create_pipe_now) { }
+ TwoStepServer(bool create_pipe_now, const std::string& channel_name)
+ : Worker(Channel::MODE_SERVER, "simpler_server", channel_name),
+ create_pipe_now_(create_pipe_now) {}
void Run() override {
SendAnswerToLife(false, true);
@@ -345,9 +348,9 @@ class TwoStepServer : public Worker {
class TwoStepClient : public Worker {
public:
- TwoStepClient(bool create_pipe_now)
- : Worker(Channel::MODE_CLIENT, "simple_client"),
- create_pipe_now_(create_pipe_now) { }
+ TwoStepClient(bool create_pipe_now, const std::string& channel_name)
+ : Worker(Channel::MODE_CLIENT, "simple_client", channel_name),
+ create_pipe_now_(create_pipe_now) {}
void OnAnswer(int* answer) override {
*answer = 42;
@@ -368,8 +371,8 @@ class TwoStepClient : public Worker {
void TwoStep(bool create_server_pipe_now, bool create_client_pipe_now) {
std::vector<Worker*> workers;
- workers.push_back(new TwoStepServer(create_server_pipe_now));
- workers.push_back(new TwoStepClient(create_client_pipe_now));
+ workers.push_back(new TwoStepServer(create_server_pipe_now, "TwoStep"));
+ workers.push_back(new TwoStepClient(create_client_pipe_now, "TwoStep"));
RunTest(workers);
}
@@ -386,7 +389,8 @@ TEST_F(IPCSyncChannelTest, TwoStepInitialization) {
class DelayClient : public Worker {
public:
- DelayClient() : Worker(Channel::MODE_CLIENT, "delay_client") { }
+ explicit DelayClient(const std::string& channel_name)
+ : Worker(Channel::MODE_CLIENT, "delay_client", channel_name) {}
void OnAnswerDelay(Message* reply_msg) override {
SyncChannelTestMsg_AnswerToLife::WriteReplyParams(reply_msg, 42);
@@ -397,8 +401,8 @@ class DelayClient : public Worker {
void DelayReply(bool pump_during_send) {
std::vector<Worker*> workers;
- workers.push_back(new SimpleServer(pump_during_send));
- workers.push_back(new DelayClient());
+ workers.push_back(new SimpleServer(pump_during_send, "DelayReply"));
+ workers.push_back(new DelayClient("DelayReply"));
RunTest(workers);
}
@@ -412,10 +416,12 @@ TEST_F(IPCSyncChannelTest, DelayReply) {
class NoHangServer : public Worker {
public:
- NoHangServer(WaitableEvent* got_first_reply, bool pump_during_send)
- : Worker(Channel::MODE_SERVER, "no_hang_server"),
+ NoHangServer(WaitableEvent* got_first_reply,
+ bool pump_during_send,
+ const std::string& channel_name)
+ : Worker(Channel::MODE_SERVER, "no_hang_server", channel_name),
got_first_reply_(got_first_reply),
- pump_during_send_(pump_during_send) { }
+ pump_during_send_(pump_during_send) {}
void Run() override {
SendAnswerToLife(pump_during_send_, true);
got_first_reply_->Signal();
@@ -430,9 +436,9 @@ class NoHangServer : public Worker {
class NoHangClient : public Worker {
public:
- explicit NoHangClient(WaitableEvent* got_first_reply)
- : Worker(Channel::MODE_CLIENT, "no_hang_client"),
- got_first_reply_(got_first_reply) { }
+ NoHangClient(WaitableEvent* got_first_reply, const std::string& channel_name)
+ : Worker(Channel::MODE_CLIENT, "no_hang_client", channel_name),
+ got_first_reply_(got_first_reply) {}
void OnAnswerDelay(Message* reply_msg) override {
// Use the DELAY_REPLY macro so that we can force the reply to be sent
@@ -450,8 +456,9 @@ class NoHangClient : public Worker {
void NoHang(bool pump_during_send) {
WaitableEvent got_first_reply(false, false);
std::vector<Worker*> workers;
- workers.push_back(new NoHangServer(&got_first_reply, pump_during_send));
- workers.push_back(new NoHangClient(&got_first_reply));
+ workers.push_back(
+ new NoHangServer(&got_first_reply, pump_during_send, "NoHang"));
+ workers.push_back(new NoHangClient(&got_first_reply, "NoHang"));
RunTest(workers);
}
@@ -465,10 +472,12 @@ TEST_F(IPCSyncChannelTest, NoHang) {
class UnblockServer : public Worker {
public:
- UnblockServer(bool pump_during_send, bool delete_during_send)
- : Worker(Channel::MODE_SERVER, "unblock_server"),
- pump_during_send_(pump_during_send),
- delete_during_send_(delete_during_send) { }
+ UnblockServer(bool pump_during_send,
+ bool delete_during_send,
+ const std::string& channel_name)
+ : Worker(Channel::MODE_SERVER, "unblock_server", channel_name),
+ pump_during_send_(pump_during_send),
+ delete_during_send_(delete_during_send) {}
void Run() override {
if (delete_during_send_) {
// Use custom code since race conditions mean the answer may or may not be
@@ -497,9 +506,9 @@ class UnblockServer : public Worker {
class UnblockClient : public Worker {
public:
- explicit UnblockClient(bool pump_during_send)
- : Worker(Channel::MODE_CLIENT, "unblock_client"),
- pump_during_send_(pump_during_send) { }
+ UnblockClient(bool pump_during_send, const std::string& channel_name)
+ : Worker(Channel::MODE_CLIENT, "unblock_client", channel_name),
+ pump_during_send_(pump_during_send) {}
void OnAnswer(int* answer) override {
SendDouble(pump_during_send_, true);
@@ -512,8 +521,9 @@ class UnblockClient : public Worker {
void Unblock(bool server_pump, bool client_pump, bool delete_during_send) {
std::vector<Worker*> workers;
- workers.push_back(new UnblockServer(server_pump, delete_during_send));
- workers.push_back(new UnblockClient(client_pump));
+ workers.push_back(
+ new UnblockServer(server_pump, delete_during_send, "Unblock"));
+ workers.push_back(new UnblockClient(client_pump, "Unblock"));
RunTest(workers);
}
@@ -544,10 +554,14 @@ TEST_F(IPCSyncChannelTest, MAYBE_ChannelDeleteDuringSend) {
class RecursiveServer : public Worker {
public:
- RecursiveServer(bool expected_send_result, bool pump_first, bool pump_second)
- : Worker(Channel::MODE_SERVER, "recursive_server"),
+ RecursiveServer(bool expected_send_result,
+ bool pump_first,
+ bool pump_second,
+ const std::string& channel_name)
+ : Worker(Channel::MODE_SERVER, "recursive_server", channel_name),
expected_send_result_(expected_send_result),
- pump_first_(pump_first), pump_second_(pump_second) {}
+ pump_first_(pump_first),
+ pump_second_(pump_second) {}
void Run() override {
SendDouble(pump_first_, expected_send_result_);
Done();
@@ -563,9 +577,12 @@ class RecursiveServer : public Worker {
class RecursiveClient : public Worker {
public:
- RecursiveClient(bool pump_during_send, bool close_channel)
- : Worker(Channel::MODE_CLIENT, "recursive_client"),
- pump_during_send_(pump_during_send), close_channel_(close_channel) {}
+ RecursiveClient(bool pump_during_send,
+ bool close_channel,
+ const std::string& channel_name)
+ : Worker(Channel::MODE_CLIENT, "recursive_client", channel_name),
+ pump_during_send_(pump_during_send),
+ close_channel_(close_channel) {}
void OnDoubleDelay(int in, Message* reply_msg) override {
SendDouble(pump_during_send_, !close_channel_);
@@ -594,9 +611,9 @@ class RecursiveClient : public Worker {
void Recursive(
bool server_pump_first, bool server_pump_second, bool client_pump) {
std::vector<Worker*> workers;
- workers.push_back(
- new RecursiveServer(true, server_pump_first, server_pump_second));
- workers.push_back(new RecursiveClient(client_pump, false));
+ workers.push_back(new RecursiveServer(true, server_pump_first,
+ server_pump_second, "Recursive"));
+ workers.push_back(new RecursiveClient(client_pump, false, "Recursive"));
RunTest(workers);
}
@@ -617,9 +634,9 @@ TEST_F(IPCSyncChannelTest, Recursive) {
void RecursiveNoHang(
bool server_pump_first, bool server_pump_second, bool client_pump) {
std::vector<Worker*> workers;
- workers.push_back(
- new RecursiveServer(false, server_pump_first, server_pump_second));
- workers.push_back(new RecursiveClient(client_pump, true));
+ workers.push_back(new RecursiveServer(false, server_pump_first,
+ server_pump_second, "RecursiveNoHang"));
+ workers.push_back(new RecursiveClient(client_pump, true, "RecursiveNoHang"));
RunTest(workers);
}
@@ -860,8 +877,8 @@ TEST_F(IPCSyncChannelTest, QueuedReply) {
class ChattyClient : public Worker {
public:
- ChattyClient() :
- Worker(Channel::MODE_CLIENT, "chatty_client") { }
+ explicit ChattyClient(const std::string& channel_name)
+ : Worker(Channel::MODE_CLIENT, "chatty_client", channel_name) {}
void OnAnswer(int* answer) override {
// The PostMessage limit is 10k. Send 20% more than that.
@@ -878,8 +895,8 @@ class ChattyClient : public Worker {
void ChattyServer(bool pump_during_send) {
std::vector<Worker*> workers;
- workers.push_back(new UnblockServer(pump_during_send, false));
- workers.push_back(new ChattyClient());
+ workers.push_back(new UnblockServer(pump_during_send, false, "ChattyServer"));
+ workers.push_back(new ChattyClient("ChattyServer"));
RunTest(workers);
}
@@ -913,8 +930,8 @@ void TimeoutCallback() {
class DoneEventRaceServer : public Worker {
public:
- DoneEventRaceServer()
- : Worker(Channel::MODE_SERVER, "done_event_race_server") { }
+ explicit DoneEventRaceServer(const std::string& channel_name)
+ : Worker(Channel::MODE_SERVER, "done_event_race_server", channel_name) {}
void Run() override {
base::ThreadTaskRunnerHandle::Get()->PostTask(
@@ -942,8 +959,8 @@ class DoneEventRaceServer : public Worker {
// reply comes back OnObjectSignaled will be called for the first message.
TEST_F(IPCSyncChannelTest, MAYBE_DoneEventRace) {
std::vector<Worker*> workers;
- workers.push_back(new DoneEventRaceServer());
- workers.push_back(new SimpleClient());
+ workers.push_back(new DoneEventRaceServer("DoneEventRace"));
+ workers.push_back(new SimpleClient("DoneEventRace"));
RunTest(workers);
}
@@ -984,8 +1001,10 @@ class TestSyncMessageFilter : public SyncMessageFilter {
class SyncMessageFilterServer : public Worker {
public:
- SyncMessageFilterServer()
- : Worker(Channel::MODE_SERVER, "sync_message_filter_server"),
+ explicit SyncMessageFilterServer(const std::string& channel_name)
+ : Worker(Channel::MODE_SERVER,
+ "sync_message_filter_server",
+ channel_name),
thread_("helper_thread") {
base::Thread::Options options;
options.message_loop_type = base::MessageLoop::TYPE_DEFAULT;
@@ -1006,10 +1025,9 @@ class SyncMessageFilterServer : public Worker {
// channel does not crash after the channel has been closed.
class ServerSendAfterClose : public Worker {
public:
- ServerSendAfterClose()
- : Worker(Channel::MODE_SERVER, "simpler_server"),
- send_result_(true) {
- }
+ explicit ServerSendAfterClose(const std::string& channel_name)
+ : Worker(Channel::MODE_SERVER, "simpler_server", channel_name),
+ send_result_(true) {}
bool SendDummy() {
ListenerThread()->task_runner()->PostTask(
@@ -1040,14 +1058,14 @@ class ServerSendAfterClose : public Worker {
// Tests basic synchronous call
TEST_F(IPCSyncChannelTest, SyncMessageFilter) {
std::vector<Worker*> workers;
- workers.push_back(new SyncMessageFilterServer());
- workers.push_back(new SimpleClient());
+ workers.push_back(new SyncMessageFilterServer("SyncMessageFilter"));
+ workers.push_back(new SimpleClient("SyncMessageFilter"));
RunTest(workers);
}
// Test the case when the channel is closed and a Send is attempted after that.
TEST_F(IPCSyncChannelTest, SendAfterClose) {
- ServerSendAfterClose server;
+ ServerSendAfterClose server("SendAfterClose");
server.Start();
server.done_event()->Wait();
diff --git a/chromium/ipc/ipc_sync_message_filter.cc b/chromium/ipc/ipc_sync_message_filter.cc
index 1a6f6d9255a..73e905833ed 100644
--- a/chromium/ipc/ipc_sync_message_filter.cc
+++ b/chromium/ipc/ipc_sync_message_filter.cc
@@ -59,7 +59,10 @@ bool SyncMessageFilter::Send(Message* message) {
}
base::WaitableEvent* events[2] = { shutdown_event_, &done_event };
- base::WaitableEvent::WaitMany(events, 2);
+ if (base::WaitableEvent::WaitMany(events, 2) == 1) {
+ TRACE_EVENT_FLOW_END0(TRACE_DISABLED_BY_DEFAULT("ipc.flow"),
+ "SyncMessageFilter::Send", &done_event);
+ }
{
base::AutoLock auto_lock(lock_);
@@ -103,6 +106,9 @@ bool SyncMessageFilter::OnMessageReceived(const Message& message) {
(*iter)->send_result =
(*iter)->deserializer->SerializeOutputParameters(message);
}
+ TRACE_EVENT_FLOW_BEGIN0(TRACE_DISABLED_BY_DEFAULT("ipc.flow"),
+ "SyncMessageFilter::OnMessageReceived",
+ (*iter)->done_event);
(*iter)->done_event->Signal();
return true;
}
@@ -142,6 +148,9 @@ void SyncMessageFilter::SignalAllEvents() {
lock_.AssertAcquired();
for (PendingSyncMessages::iterator iter = pending_sync_messages_.begin();
iter != pending_sync_messages_.end(); ++iter) {
+ TRACE_EVENT_FLOW_BEGIN0(TRACE_DISABLED_BY_DEFAULT("ipc.flow"),
+ "SyncMessageFilter::SignalAllEvents",
+ (*iter)->done_event);
(*iter)->done_event->Signal();
}
}
diff --git a/chromium/ipc/ipc_test_base.h b/chromium/ipc/ipc_test_base.h
index 360188f6a5b..0646363805b 100644
--- a/chromium/ipc/ipc_test_base.h
+++ b/chromium/ipc/ipc_test_base.h
@@ -48,8 +48,9 @@ class IPCTestBase : public base::MultiProcessTest {
// message loop on the main thread. As IPCTestBase creates IO message loop by
// default, such tests need to provide a custom message loop for the main
// thread.
- void InitWithCustomMessageLoop(const std::string& test_client_name,
- scoped_ptr<base::MessageLoop> message_loop);
+ virtual void InitWithCustomMessageLoop(
+ const std::string& test_client_name,
+ scoped_ptr<base::MessageLoop> message_loop);
// Creates a channel with the given listener and connects to the channel
// (returning true if successful), respectively. Use these to use a channel
@@ -80,7 +81,7 @@ class IPCTestBase : public base::MultiProcessTest {
// Starts the client process, returning true if successful; this should be
// done after connecting to the channel.
- bool StartClient();
+ virtual bool StartClient();
#if defined(OS_POSIX)
// A StartClient() variant that allows caller to pass the FD of IPC pipe
@@ -91,7 +92,7 @@ class IPCTestBase : public base::MultiProcessTest {
// this does not initiate client shutdown; that must be done by the test
// (somehow). This must be called before the end of the test whenever
// StartClient() was called successfully.
- bool WaitForClientShutdown();
+ virtual bool WaitForClientShutdown();
IPC::ChannelHandle GetTestChannelHandle();
@@ -104,6 +105,10 @@ class IPCTestBase : public base::MultiProcessTest {
IPC::Channel* channel() { return channel_.get(); }
IPC::ChannelProxy* channel_proxy() { return channel_proxy_.get(); }
+ void set_channel_proxy(std::unique_ptr<IPC::ChannelProxy> proxy) {
+ DCHECK(!channel_proxy_);
+ channel_proxy_.swap(proxy);
+ }
const base::Process& client_process() const { return client_process_; }
scoped_refptr<base::SequencedTaskRunner> task_runner();
diff --git a/chromium/ipc/ipc_test_sink.h b/chromium/ipc/ipc_test_sink.h
index ab8531d5ea8..3e70704348e 100644
--- a/chromium/ipc/ipc_test_sink.h
+++ b/chromium/ipc/ipc_test_sink.h
@@ -59,17 +59,22 @@ class Message;
//
// class MyListener : public IPC::Listener {
// public:
+// MyListener(const base::Closure& closure)
+// : message_received_closure_(closure) {}
// virtual bool OnMessageReceived(const IPC::Message& msg) {
// <do something with the message>
-// MessageLoop::current()->QuitWhenIdle();
+// message_received_closure_.Run();
// return false; // to store the message in the sink, or true to drop it
// }
+// private:
+// base::Closure message_received_closure_;
// };
//
-// MyListener listener;
+// base::RunLoop run_loop;
+// MyListener listener(run_loop.QuitClosure());
// test_sink.AddFilter(&listener);
// StartSomeAsynchronousProcess(&test_sink);
-// MessageLoop::current()->Run();
+// run_loop.Run();
// <inspect the results>
// ...
//
diff --git a/chromium/ipc/ipc_tests_apk.isolate b/chromium/ipc/ipc_tests_apk.isolate
index 0c0cf1c5ca7..50047a43362 100644
--- a/chromium/ipc/ipc_tests_apk.isolate
+++ b/chromium/ipc/ipc_tests_apk.isolate
@@ -8,6 +8,7 @@
'variables': {
'command': [
'<(PRODUCT_DIR)/bin/run_ipc_tests',
+ '--logcat-output-dir', '${ISOLATED_OUTDIR}/logcats',
],
'files': [
'<(PRODUCT_DIR)/bin/run_ipc_tests',
diff --git a/chromium/ipc/mach_port_attachment_mac.cc b/chromium/ipc/mach_port_attachment_mac.cc
index 65baa3480ed..47fd4e98ba4 100644
--- a/chromium/ipc/mach_port_attachment_mac.cc
+++ b/chromium/ipc/mach_port_attachment_mac.cc
@@ -20,6 +20,9 @@ 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/chromium/ipc/mach_port_attachment_mac.h b/chromium/ipc/mach_port_attachment_mac.h
index 244014ed724..658cff428f9 100644
--- a/chromium/ipc/mach_port_attachment_mac.h
+++ b/chromium/ipc/mach_port_attachment_mac.h
@@ -51,6 +51,13 @@ 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/chromium/ipc/mach_port_mac.cc b/chromium/ipc/mach_port_mac.cc
index 51a5bd7abfc..9375d728eab 100644
--- a/chromium/ipc/mach_port_mac.cc
+++ b/chromium/ipc/mach_port_mac.cc
@@ -12,7 +12,7 @@
namespace IPC {
// static
-void ParamTraits<MachPortMac>::Write(Message* m, const param_type& p) {
+void ParamTraits<MachPortMac>::Write(base::Pickle* m, const param_type& p) {
if (!m->WriteAttachment(
new IPC::internal::MachPortAttachmentMac(p.get_mach_port()))) {
NOTREACHED();
@@ -20,16 +20,18 @@ void ParamTraits<MachPortMac>::Write(Message* m, const param_type& p) {
}
// static
-bool ParamTraits<MachPortMac>::Read(const Message* m,
+bool ParamTraits<MachPortMac>::Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
- scoped_refptr<MessageAttachment> attachment;
- if (!m->ReadAttachment(iter, &attachment))
+ scoped_refptr<base::Pickle::Attachment> base_attachment;
+ if (!m->ReadAttachment(iter, &base_attachment))
return false;
+ MessageAttachment* attachment =
+ static_cast<MessageAttachment*>(base_attachment.get());
if (attachment->GetType() != MessageAttachment::TYPE_BROKERABLE_ATTACHMENT)
return false;
BrokerableAttachment* brokerable_attachment =
- static_cast<BrokerableAttachment*>(attachment.get());
+ static_cast<BrokerableAttachment*>(attachment);
if (brokerable_attachment->GetBrokerableType() !=
BrokerableAttachment::MACH_PORT) {
return false;
diff --git a/chromium/ipc/mach_port_mac.h b/chromium/ipc/mach_port_mac.h
index 5c420c0fed3..b95a37b47d0 100644
--- a/chromium/ipc/mach_port_mac.h
+++ b/chromium/ipc/mach_port_mac.h
@@ -71,8 +71,10 @@ class IPC_EXPORT MachPortMac {
template <>
struct IPC_EXPORT ParamTraits<MachPortMac> {
typedef MachPortMac param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, base::PickleIterator* iter, param_type* p);
+ 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);
};
diff --git a/chromium/ipc/message_router.cc b/chromium/ipc/message_router.cc
new file mode 100644
index 00000000000..aaf4a1f7d8d
--- /dev/null
+++ b/chromium/ipc/message_router.cc
@@ -0,0 +1,55 @@
+// Copyright (c) 2011 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/message_router.h"
+
+#include "ipc/ipc_message.h"
+
+namespace IPC {
+
+MessageRouter::MessageRouter() {}
+
+MessageRouter::~MessageRouter() {}
+
+bool MessageRouter::OnControlMessageReceived(const IPC::Message& msg) {
+ NOTREACHED()
+ << "should override in subclass if you care about control messages";
+ return false;
+}
+
+bool MessageRouter::Send(IPC::Message* msg) {
+ NOTREACHED()
+ << "should override in subclass if you care about sending messages";
+ return false;
+}
+
+bool MessageRouter::AddRoute(int32_t routing_id, IPC::Listener* listener) {
+ if (routes_.Lookup(routing_id)) {
+ DLOG(ERROR) << "duplicate routing ID";
+ return false;
+ }
+ routes_.AddWithID(listener, routing_id);
+ return true;
+}
+
+void MessageRouter::RemoveRoute(int32_t routing_id) {
+ routes_.Remove(routing_id);
+}
+
+bool MessageRouter::OnMessageReceived(const IPC::Message& msg) {
+ if (msg.routing_id() == MSG_ROUTING_CONTROL)
+ return OnControlMessageReceived(msg);
+
+ return RouteMessage(msg);
+}
+
+bool MessageRouter::RouteMessage(const IPC::Message& msg) {
+ IPC::Listener* listener = routes_.Lookup(msg.routing_id());
+ if (!listener)
+ return false;
+
+ return listener->OnMessageReceived(msg);
+}
+
+} // namespace IPC
diff --git a/chromium/ipc/message_router.h b/chromium/ipc/message_router.h
new file mode 100644
index 00000000000..db4bc271fc9
--- /dev/null
+++ b/chromium/ipc/message_router.h
@@ -0,0 +1,71 @@
+// Copyright (c) 2012 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_MESSAGE_ROUTER_H_
+#define IPC_MESSAGE_ROUTER_H_
+
+#include <stdint.h>
+
+#include "base/id_map.h"
+#include "base/macros.h"
+#include "ipc/ipc_export.h"
+#include "ipc/ipc_listener.h"
+#include "ipc/ipc_sender.h"
+
+// The MessageRouter handles all incoming messages sent to it by routing them
+// to the correct listener. Routing is based on the Message's routing ID.
+// Since routing IDs are typically assigned asynchronously by the browser
+// process, the MessageRouter has the notion of pending IDs for listeners that
+// have not yet been assigned a routing ID.
+//
+// When a message arrives, the routing ID is used to index the set of routes to
+// find a listener. If a listener is found, then the message is passed to it.
+// Otherwise, the message is ignored if its routing ID is not equal to
+// MSG_ROUTING_CONTROL.
+//
+// The MessageRouter supports the IPC::Sender interface for outgoing messages,
+// but does not define a meaningful implementation of it. The subclass of
+// MessageRouter is intended to provide that if appropriate.
+//
+// The MessageRouter can be used as a concrete class provided its Send method
+// is not called and it does not receive any control messages.
+
+namespace IPC {
+
+class IPC_EXPORT MessageRouter : public Listener, public Sender {
+ public:
+ MessageRouter();
+ ~MessageRouter() override;
+
+ // Implemented by subclasses to handle control messages
+ virtual bool OnControlMessageReceived(const Message& msg);
+
+ // Listener implementation:
+ bool OnMessageReceived(const Message& msg) override;
+
+ // Like OnMessageReceived, except it only handles routed messages. Returns
+ // true if the message was dispatched, or false if there was no listener for
+ // that route id.
+ virtual bool RouteMessage(const Message& msg);
+
+ // Sender implementation:
+ bool Send(Message* msg) override;
+
+ // Called to add a listener for a particular message routing ID.
+ // Returns true if succeeded.
+ bool AddRoute(int32_t routing_id, Listener* listener);
+
+ // Called to remove a listener for a particular message routing ID.
+ void RemoveRoute(int32_t routing_id);
+
+ private:
+ // A list of all listeners with assigned routing IDs.
+ IDMap<Listener> routes_;
+
+ DISALLOW_COPY_AND_ASSIGN(MessageRouter);
+};
+
+} // namespace IPC
+
+#endif // IPC_MESSAGE_ROUTER_H_
diff --git a/chromium/ipc/mojo/BUILD.gn b/chromium/ipc/mojo/BUILD.gn
index 29e3a957420..22f063aaf83 100644
--- a/chromium/ipc/mojo/BUILD.gn
+++ b/chromium/ipc/mojo/BUILD.gn
@@ -5,17 +5,14 @@
import("//mojo/public/tools/bindings/mojom.gni")
import("//testing/test.gni")
-mojom("client_channel") {
+mojom("mojom") {
sources = [
- "client_channel.mojom",
+ "ipc.mojom",
]
}
component("mojo") {
sources = [
- "async_handle_waiter.cc",
- "async_handle_waiter.h",
- "client_channel.mojom",
"ipc_channel_mojo.cc",
"ipc_channel_mojo.h",
"ipc_message_pipe_reader.cc",
@@ -35,35 +32,33 @@ component("mojo") {
defines = [ "IPC_MOJO_IMPLEMENTATION" ]
deps = [
- ":client_channel",
+ ":mojom",
"//base",
"//base/third_party/dynamic_annotations",
"//ipc",
- "//mojo/environment:chromium",
- "//mojo/public/c/environment:environment",
+ "//mojo/edk/system",
"//mojo/public/cpp/bindings",
- "//third_party/mojo/src/mojo/edk/system",
]
}
test("ipc_mojo_unittests") {
sources = [
- "async_handle_waiter_unittest.cc",
"ipc_channel_mojo_unittest.cc",
"ipc_mojo_bootstrap_unittest.cc",
"run_all_unittests.cc",
]
deps = [
+ ":mojo",
+ ":mojom",
"//base",
"//base/test:test_support",
"//base/third_party/dynamic_annotations",
"//ipc",
"//ipc:test_support",
- "//ipc/mojo",
- "//mojo/environment:chromium",
+ "//mojo/edk/system",
+ "//mojo/edk/test:test_support",
"//testing/gtest",
- "//third_party/mojo/src/mojo/edk/system",
"//url",
]
}
@@ -71,18 +66,24 @@ test("ipc_mojo_unittests") {
test("ipc_mojo_perftests") {
sources = [
"ipc_mojo_perftest.cc",
+ "run_all_perftests.cc",
]
deps = [
+ ":mojo",
+ ":mojom",
"//base",
"//base/test:test_support",
- "//base/test:test_support_perf",
"//base/third_party/dynamic_annotations",
"//ipc",
"//ipc:test_support",
- "//ipc/mojo",
- "//mojo/environment:chromium",
- "//third_party/mojo/src/mojo/edk/system",
+ "//mojo/edk/system",
+ "//mojo/edk/test:test_support",
+ "//mojo/edk/test:test_support_impl",
"//url",
]
+
+ if (is_linux && !is_component_build) {
+ public_configs = [ "//build/config/gcc:rpath_for_built_shared_libraries" ]
+ }
}
diff --git a/chromium/ipc/mojo/DEPS b/chromium/ipc/mojo/DEPS
index 59e80a9bf82..00f925a060d 100644
--- a/chromium/ipc/mojo/DEPS
+++ b/chromium/ipc/mojo/DEPS
@@ -1,5 +1,5 @@
include_rules = [
"+mojo/edk/embedder",
+ "+mojo/edk/test",
"+mojo/public",
- "+third_party/mojo/src/mojo/edk/embedder",
]
diff --git a/chromium/ipc/mojo/async_handle_waiter.cc b/chromium/ipc/mojo/async_handle_waiter.cc
deleted file mode 100644
index 4e07480f6cf..00000000000
--- a/chromium/ipc/mojo/async_handle_waiter.cc
+++ /dev/null
@@ -1,171 +0,0 @@
-// Copyright 2015 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/mojo/async_handle_waiter.h"
-
-#include "base/atomic_ref_count.h"
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/location.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "third_party/mojo/src/mojo/edk/embedder/embedder.h"
-
-namespace IPC {
-namespace internal {
-
-class AsyncHandleWaiterContextTraits {
- public:
- static void Destruct(const AsyncHandleWaiter::Context* context);
-};
-
-// The thread-safe part of |AsyncHandleWaiter|.
-// As |AsyncWait()| invokes the given callback from an arbitrary thread,
-// |HandleIsReady()| and the bound |this| have to be thread-safe.
-class AsyncHandleWaiter::Context
- : public base::RefCountedThreadSafe<AsyncHandleWaiter::Context,
- AsyncHandleWaiterContextTraits>,
- public base::MessageLoopForIO::IOObserver {
- public:
- Context(base::WeakPtr<AsyncHandleWaiter> waiter)
- : io_runner_(base::MessageLoopForIO::current()->task_runner()),
- waiter_(waiter),
- last_result_(MOJO_RESULT_INTERNAL),
- io_loop_level_(0),
- should_invoke_callback_(false) {
- base::MessageLoopForIO::current()->AddIOObserver(this);
- }
-
- void HandleIsReady(MojoResult result) {
- last_result_ = result;
-
- // If the signaling happens in the IO handler, use |IOObserver| callback
- // to invoke the callback.
- if (IsCalledFromIOHandler()) {
- should_invoke_callback_ = true;
- return;
- }
-
- io_runner_->PostTask(FROM_HERE,
- base::Bind(&Context::InvokeWaiterCallback, this));
- }
-
- private:
- friend void base::DeletePointer<const Context>(const Context* self);
- friend class AsyncHandleWaiterContextTraits;
- friend class base::RefCountedThreadSafe<Context>;
-
- ~Context() override {
- DCHECK(base::MessageLoopForIO::current()->task_runner() == io_runner_);
- base::MessageLoopForIO::current()->RemoveIOObserver(this);
- }
-
- bool IsCalledFromIOHandler() const {
- base::MessageLoop* loop = base::MessageLoop::current();
- if (!loop)
- return false;
- if (loop->task_runner() != io_runner_)
- return false;
- return io_loop_level_ > 0;
- }
-
- // Called from |io_runner_| thus safe to touch |waiter_|.
- void InvokeWaiterCallback() {
- MojoResult result = last_result_;
- last_result_ = MOJO_RESULT_INTERNAL;
- if (waiter_)
- waiter_->InvokeCallback(result);
- }
-
- // IOObserver implementation:
-
- void WillProcessIOEvent() override {
- DCHECK(io_loop_level_ != 0 || !should_invoke_callback_);
- DCHECK_GE(io_loop_level_, 0);
- io_loop_level_++;
- }
-
- void DidProcessIOEvent() override {
- // This object could have been constructed in another's class's
- // DidProcessIOEvent.
- if (io_loop_level_== 0)
- return;
-
- DCHECK_GE(io_loop_level_, 1);
-
- // Leaving a nested loop.
- if (io_loop_level_ > 1) {
- io_loop_level_--;
- return;
- }
-
- // The zero |waiter_| indicates that |this| have lost the owner and can be
- // under destruction. So we cannot wrap it with a |scoped_refptr| anymore.
- if (!waiter_) {
- should_invoke_callback_ = false;
- io_loop_level_--;
- return;
- }
-
- // We have to protect |this| because |AsyncHandleWaiter| can be
- // deleted during the callback.
- scoped_refptr<Context> protect(this);
- while (should_invoke_callback_) {
- should_invoke_callback_ = false;
- InvokeWaiterCallback();
- }
-
- io_loop_level_--;
- }
-
- // Only |io_runner_| is accessed from arbitrary threads. Others are touched
- // only from the IO thread.
- const scoped_refptr<base::TaskRunner> io_runner_;
-
- const base::WeakPtr<AsyncHandleWaiter> waiter_;
- MojoResult last_result_;
- int io_loop_level_;
- bool should_invoke_callback_;
-
- DISALLOW_COPY_AND_ASSIGN(Context);
-};
-
-AsyncHandleWaiter::AsyncHandleWaiter(base::Callback<void(MojoResult)> callback)
- : callback_(callback),
- weak_factory_(this) {
- context_ = new Context(weak_factory_.GetWeakPtr());
-}
-
-AsyncHandleWaiter::~AsyncHandleWaiter() {
-}
-
-MojoResult AsyncHandleWaiter::Wait(MojoHandle handle,
- MojoHandleSignals signals) {
- return mojo::embedder::AsyncWait(
- handle, signals, base::Bind(&Context::HandleIsReady, context_));
-}
-
-void AsyncHandleWaiter::InvokeCallback(MojoResult result) {
- callback_.Run(result);
-}
-
-base::MessageLoopForIO::IOObserver* AsyncHandleWaiter::GetIOObserverForTest() {
- return context_.get();
-}
-
-base::Callback<void(MojoResult)> AsyncHandleWaiter::GetWaitCallbackForTest() {
- return base::Bind(&Context::HandleIsReady, context_);
-}
-
-// static
-void AsyncHandleWaiterContextTraits::Destruct(
- const AsyncHandleWaiter::Context* context) {
- context->io_runner_->PostTask(
- FROM_HERE,
- base::Bind(&base::DeletePointer<const AsyncHandleWaiter::Context>,
- base::Unretained(context)));
-}
-
-} // namespace internal
-} // namespace IPC
diff --git a/chromium/ipc/mojo/async_handle_waiter.h b/chromium/ipc/mojo/async_handle_waiter.h
deleted file mode 100644
index e82c27ae29c..00000000000
--- a/chromium/ipc/mojo/async_handle_waiter.h
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2015 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_MOJO_ASYNC_HANDLE_WAITER_H_
-#define IPC_MOJO_ASYNC_HANDLE_WAITER_H_
-
-#include "base/callback.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
-#include "base/message_loop/message_loop.h"
-#include "ipc/ipc_export.h"
-#include "mojo/public/c/system/types.h"
-
-namespace IPC {
-namespace internal {
-
-// |AsyncHandleWaiter| waits on a mojo handle asynchronously and
-// invokes the given |callback| through |runner| when it is signaled.
-// * To start waiting, the client must call |AsyncHandleWaiter::Wait()|.
-// The client can call |Wait()| again once it is signaled and
-// the |callback| is invoked.
-// * To cancel waiting, delete the instance.
-//
-// |AsyncHandleWaiter| must be created, used and deleted only from the IO
-// |thread.
-class IPC_MOJO_EXPORT AsyncHandleWaiter {
- public:
- class Context;
-
- explicit AsyncHandleWaiter(base::Callback<void(MojoResult)> callback);
- ~AsyncHandleWaiter();
-
- MojoResult Wait(MojoHandle handle, MojoHandleSignals signals);
-
- base::MessageLoopForIO::IOObserver* GetIOObserverForTest();
- base::Callback<void(MojoResult)> GetWaitCallbackForTest();
-
- private:
- void InvokeCallback(MojoResult result);
-
- scoped_refptr<Context> context_;
- base::Callback<void(MojoResult)> callback_;
- base::WeakPtrFactory<AsyncHandleWaiter> weak_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(AsyncHandleWaiter);
-};
-
-} // namespace internal
-} // namespace IPC
-
-#endif // IPC_MOJO_ASYNC_HANDLE_WAITER_H_
diff --git a/chromium/ipc/mojo/async_handle_waiter_unittest.cc b/chromium/ipc/mojo/async_handle_waiter_unittest.cc
deleted file mode 100644
index e17b4fd3b09..00000000000
--- a/chromium/ipc/mojo/async_handle_waiter_unittest.cc
+++ /dev/null
@@ -1,260 +0,0 @@
-// Copyright 2015 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/mojo/async_handle_waiter.h"
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include "base/bind.h"
-#include "base/location.h"
-#include "base/run_loop.h"
-#include "base/single_thread_task_runner.h"
-#include "base/threading/thread.h"
-#include "mojo/public/cpp/system/message_pipe.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace IPC {
-namespace internal {
-namespace {
-
-void ReadOneByteOfX(MojoHandle pipe) {
- uint32_t size = 1;
- char buffer = ' ';
- MojoResult rv = MojoReadMessage(pipe, &buffer, &size, nullptr, nullptr,
- MOJO_READ_MESSAGE_FLAG_NONE);
- CHECK_EQ(rv, MOJO_RESULT_OK);
- CHECK_EQ(size, 1U);
- CHECK_EQ(buffer, 'X');
-}
-
-class AsyncHandleWaiterTest : public testing::Test {
- public:
- AsyncHandleWaiterTest() : worker_("test_worker") {
- worker_.StartWithOptions(
- base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
- }
-
- void SetUp() override {
- message_loop_.reset(new base::MessageLoopForIO());
- ResetSignaledStates();
- mojo::CreateMessagePipe(nullptr, &pipe_to_write_, &pipe_to_read_);
- target_.reset(new AsyncHandleWaiter(base::Bind(
- &AsyncHandleWaiterTest::HandleIsReady, base::Unretained(this))));
- }
-
- protected:
- MojoResult Start() {
- return target_->Wait(pipe_to_read_.get().value(),
- MOJO_HANDLE_SIGNAL_READABLE);
- }
-
- void ResetSignaledStates() {
- signaled_result_ = MOJO_RESULT_UNKNOWN;
- run_loop_.reset(new base::RunLoop());
- }
-
- void WriteToPipe() {
- MojoResult rv = MojoWriteMessage(pipe_to_write_.get().value(), "X", 1,
- nullptr, 0, MOJO_WRITE_MESSAGE_FLAG_NONE);
- CHECK_EQ(rv, MOJO_RESULT_OK);
- }
-
- void WriteToPipeFromWorker() {
- worker_.task_runner()->PostTask(
- FROM_HERE, base::Bind(&AsyncHandleWaiterTest::WriteToPipe,
- base::Unretained(this)));
- }
-
- void WaitAndAssertSignaledAndMessageIsArrived() {
- run_loop_->Run();
- EXPECT_EQ(MOJO_RESULT_OK, signaled_result_);
-
- ReadOneByteOfX(pipe_to_read_.get().value());
- }
-
- void WaitAndAssertNotSignaled() {
- run_loop_->RunUntilIdle();
- EXPECT_EQ(MOJO_RESULT_OK, MojoWait(pipe_to_read_.get().value(),
- MOJO_HANDLE_SIGNAL_READABLE, 0,
- nullptr));
- EXPECT_EQ(MOJO_RESULT_UNKNOWN, signaled_result_);
- }
-
- void HandleIsReady(MojoResult result) {
- CHECK_EQ(base::MessageLoop::current(), message_loop_.get());
- CHECK_EQ(signaled_result_, MOJO_RESULT_UNKNOWN);
- signaled_result_ = result;
- run_loop_->Quit();
- }
-
- base::Thread worker_;
- scoped_ptr<base::MessageLoop> message_loop_;
- scoped_ptr<base::RunLoop> run_loop_;
- mojo::ScopedMessagePipeHandle pipe_to_write_;
- mojo::ScopedMessagePipeHandle pipe_to_read_;
-
- scoped_ptr<AsyncHandleWaiter> target_;
- MojoResult signaled_result_;
-};
-
-TEST_F(AsyncHandleWaiterTest, SignalFromSameThread) {
- EXPECT_EQ(MOJO_RESULT_OK, Start());
- WriteToPipe();
- WaitAndAssertSignaledAndMessageIsArrived();
-
- // Ensures that the waiter is reusable.
- ResetSignaledStates();
-
- EXPECT_EQ(MOJO_RESULT_OK, Start());
- WriteToPipe();
- WaitAndAssertSignaledAndMessageIsArrived();
-}
-
-TEST_F(AsyncHandleWaiterTest, SignalFromDifferentThread) {
- EXPECT_EQ(MOJO_RESULT_OK, Start());
- WriteToPipeFromWorker();
- WaitAndAssertSignaledAndMessageIsArrived();
-
- // Ensures that the waiter is reusable.
- ResetSignaledStates();
-
- EXPECT_EQ(MOJO_RESULT_OK, Start());
- WriteToPipeFromWorker();
- WaitAndAssertSignaledAndMessageIsArrived();
-}
-
-TEST_F(AsyncHandleWaiterTest, DeleteWaiterBeforeWrite) {
- EXPECT_EQ(MOJO_RESULT_OK, Start());
-
- target_.reset();
-
- WriteToPipe();
- WaitAndAssertNotSignaled();
-}
-
-TEST_F(AsyncHandleWaiterTest, DeleteWaiterBeforeSignal) {
- EXPECT_EQ(MOJO_RESULT_OK, Start());
- WriteToPipe();
-
- target_.reset();
-
- WaitAndAssertNotSignaled();
-}
-
-class HandlerThatReenters {
- public:
- HandlerThatReenters(base::RunLoop* loop, MojoHandle handle)
- : target_(nullptr), handle_(handle), loop_(loop), step_(0) {}
-
- void set_target(AsyncHandleWaiter* target) { target_ = target; }
-
- void HandleIsReady(MojoResult result) {
- switch (step_) {
- case 0:
- RestartAndClose(result);
- break;
- case 1:
- HandleClosingSignal(result);
- break;
- default:
- NOTREACHED();
- break;
- }
- }
-
- void RestartAndClose(MojoResult result) {
- CHECK_EQ(step_, 0);
- CHECK_EQ(result, MOJO_RESULT_OK);
- step_ = 1;
-
- ReadOneByteOfX(handle_);
- target_->Wait(handle_, MOJO_HANDLE_SIGNAL_READABLE);
-
- // This signals the |AsyncHandleWaiter|.
- MojoResult rv = MojoClose(handle_);
- CHECK_EQ(rv, MOJO_RESULT_OK);
- }
-
- void HandleClosingSignal(MojoResult result) {
- CHECK_EQ(step_, 1);
- CHECK_EQ(result, MOJO_RESULT_CANCELLED);
- step_ = 2;
- loop_->Quit();
- }
-
- bool IsClosingHandled() const { return step_ == 2; }
-
- AsyncHandleWaiter* target_;
- MojoHandle handle_;
- base::RunLoop* loop_;
- int step_;
-};
-
-TEST_F(AsyncHandleWaiterTest, RestartWaitingWhileSignaled) {
- HandlerThatReenters handler(run_loop_.get(), pipe_to_read_.get().value());
- target_.reset(new AsyncHandleWaiter(base::Bind(
- &HandlerThatReenters::HandleIsReady, base::Unretained(&handler))));
- handler.set_target(target_.get());
-
- EXPECT_EQ(MOJO_RESULT_OK, Start());
- WriteToPipe();
- run_loop_->Run();
-
- EXPECT_TRUE(handler.IsClosingHandled());
-
- // |HandlerThatReenters::RestartAndClose| already closed it.
- ::ignore_result(pipe_to_read_.release());
-}
-
-class AsyncHandleWaiterIOObserverTest : public testing::Test {
- public:
- void SetUp() override {
- message_loop_.reset(new base::MessageLoopForIO());
- target_.reset(new AsyncHandleWaiter(
- base::Bind(&AsyncHandleWaiterIOObserverTest::HandleIsReady,
- base::Unretained(this))));
- invocation_count_ = 0;
- }
-
- void HandleIsReady(MojoResult result) { invocation_count_++; }
-
- scoped_ptr<base::MessageLoop> message_loop_;
- scoped_ptr<AsyncHandleWaiter> target_;
- size_t invocation_count_;
-};
-
-TEST_F(AsyncHandleWaiterIOObserverTest, OutsideIOEvnet) {
- target_->GetWaitCallbackForTest().Run(MOJO_RESULT_OK);
- EXPECT_EQ(0U, invocation_count_);
- message_loop_->RunUntilIdle();
- EXPECT_EQ(1U, invocation_count_);
-}
-
-TEST_F(AsyncHandleWaiterIOObserverTest, InsideIOEvnet) {
- target_->GetIOObserverForTest()->WillProcessIOEvent();
- target_->GetWaitCallbackForTest().Run(MOJO_RESULT_OK);
- EXPECT_EQ(0U, invocation_count_);
- target_->GetIOObserverForTest()->DidProcessIOEvent();
- EXPECT_EQ(1U, invocation_count_);
-}
-
-TEST_F(AsyncHandleWaiterIOObserverTest, Reenter) {
- target_->GetIOObserverForTest()->WillProcessIOEvent();
- target_->GetWaitCallbackForTest().Run(MOJO_RESULT_OK);
- EXPECT_EQ(0U, invocation_count_);
-
- // As if some other io handler start nested loop.
- target_->GetIOObserverForTest()->WillProcessIOEvent();
- target_->GetWaitCallbackForTest().Run(MOJO_RESULT_OK);
- target_->GetIOObserverForTest()->DidProcessIOEvent();
- EXPECT_EQ(0U, invocation_count_);
-
- target_->GetIOObserverForTest()->DidProcessIOEvent();
- EXPECT_EQ(1U, invocation_count_);
-}
-
-} // namespace
-} // namespace internal
-} // namespace IPC
diff --git a/chromium/ipc/mojo/client_channel.mojom b/chromium/ipc/mojo/client_channel.mojom
deleted file mode 100644
index fd909d4ada6..00000000000
--- a/chromium/ipc/mojo/client_channel.mojom
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright 2014 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.
-
-module IPC;
-
-interface ClientChannel {
- Init(handle<message_pipe> pipe, int32 peer_pid) => (int32 pid);
-};
diff --git a/chromium/ipc/mojo/ipc.mojom b/chromium/ipc/mojo/ipc.mojom
new file mode 100644
index 00000000000..d15a23c3e95
--- /dev/null
+++ b/chromium/ipc/mojo/ipc.mojom
@@ -0,0 +1,31 @@
+// Copyright 2016 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.
+
+module IPC.mojom;
+
+struct SerializedHandle {
+ handle the_handle;
+
+ enum Type {
+ MOJO_HANDLE,
+ WIN_HANDLE,
+ MACH_PORT,
+ };
+
+ Type type;
+};
+
+interface Channel {
+ Receive(array<uint8> data, array<SerializedHandle>? handles);
+};
+
+// An interface for connecting a pair of Channel interfaces representing a
+// bidirectional IPC channel.
+interface Bootstrap {
+ // Initializes a Chrome IPC channel over |to_client_channel| and
+ // |to_server_channel|. Each side also sends its PID to the other side.
+ Init(associated Channel& to_client_channel,
+ associated Channel to_server_channel,
+ int32 pid) => (int32 pid);
+};
diff --git a/chromium/ipc/mojo/ipc_channel_mojo.cc b/chromium/ipc/mojo/ipc_channel_mojo.cc
index 404c814516e..e7d0a9a33cf 100644
--- a/chromium/ipc/mojo/ipc_channel_mojo.cc
+++ b/chromium/ipc/mojo/ipc_channel_mojo.cc
@@ -20,177 +20,67 @@
#include "ipc/ipc_logging.h"
#include "ipc/ipc_message_attachment_set.h"
#include "ipc/ipc_message_macros.h"
-#include "ipc/mojo/client_channel.mojom.h"
#include "ipc/mojo/ipc_mojo_bootstrap.h"
#include "ipc/mojo/ipc_mojo_handle_attachment.h"
+#include "mojo/edk/embedder/embedder.h"
#include "mojo/public/cpp/bindings/binding.h"
-#include "third_party/mojo/src/mojo/edk/embedder/embedder.h"
#if defined(OS_POSIX) && !defined(OS_NACL)
#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 {
-// TODO(jam): do more tests on using channel on same thread if it supports it (
-// i.e. with use-new-edk and Windows). Also see message_pipe_dispatcher.cc
-bool g_use_channel_on_io_thread_only = true;
-
class MojoChannelFactory : public ChannelFactory {
public:
- MojoChannelFactory(scoped_refptr<base::TaskRunner> io_runner,
- ChannelHandle channel_handle,
- Channel::Mode mode)
- : io_runner_(io_runner), channel_handle_(channel_handle), mode_(mode) {}
+ MojoChannelFactory(mojo::ScopedMessagePipeHandle handle, Channel::Mode mode)
+ : handle_(std::move(handle)), mode_(mode) {}
- std::string GetName() const override {
- return channel_handle_.name;
- }
+ std::string GetName() const override { return ""; }
scoped_ptr<Channel> BuildChannel(Listener* listener) override {
- return ChannelMojo::Create(io_runner_, channel_handle_, mode_, listener);
- }
-
- private:
- scoped_refptr<base::TaskRunner> io_runner_;
- ChannelHandle channel_handle_;
- Channel::Mode mode_;
-};
-
-//------------------------------------------------------------------------------
-
-class ClientChannelMojo : public ChannelMojo, public ClientChannel {
- public:
- ClientChannelMojo(scoped_refptr<base::TaskRunner> io_runner,
- const ChannelHandle& handle,
- Listener* listener)
- : ChannelMojo(io_runner, handle, Channel::MODE_CLIENT, listener),
- binding_(this),
- weak_factory_(this) {
- }
- ~ClientChannelMojo() override {}
-
- // MojoBootstrap::Delegate implementation
- void OnPipeAvailable(mojo::embedder::ScopedPlatformHandle handle,
- int32_t peer_pid) override {
- if (base::CommandLine::ForCurrentProcess()->HasSwitch("use-new-edk")) {
- InitMessageReader(
- mojo::embedder::CreateChannel(
- std::move(handle),
- base::Callback<void(mojo::embedder::ChannelInfo*)>(),
- scoped_refptr<base::TaskRunner>()),
- peer_pid);
- return;
- }
- CreateMessagingPipe(
- std::move(handle),
- base::Bind(&ClientChannelMojo::BindPipe, weak_factory_.GetWeakPtr()));
- }
-
- // ClientChannel implementation
- void Init(
- mojo::ScopedMessagePipeHandle pipe,
- int32_t peer_pid,
- const mojo::Callback<void(int32_t)>& callback) override {
- InitMessageReader(std::move(pipe), static_cast<base::ProcessId>(peer_pid));
- callback.Run(GetSelfPID());
+ return ChannelMojo::Create(std::move(handle_), mode_, listener);
}
private:
- void BindPipe(mojo::ScopedMessagePipeHandle handle) {
- binding_.Bind(std::move(handle));
- }
- void OnConnectionError() {
- listener()->OnChannelError();
- }
-
- mojo::Binding<ClientChannel> binding_;
- base::WeakPtrFactory<ClientChannelMojo> weak_factory_;
+ mojo::ScopedMessagePipeHandle handle_;
+ const Channel::Mode mode_;
- DISALLOW_COPY_AND_ASSIGN(ClientChannelMojo);
+ DISALLOW_COPY_AND_ASSIGN(MojoChannelFactory);
};
-//------------------------------------------------------------------------------
-
-class ServerChannelMojo : public ChannelMojo {
- public:
- ServerChannelMojo(scoped_refptr<base::TaskRunner> io_runner,
- const ChannelHandle& handle,
- Listener* listener)
- : ChannelMojo(io_runner, handle, Channel::MODE_SERVER, listener),
- weak_factory_(this) {
- }
- ~ServerChannelMojo() override {
- Close();
- }
-
- // MojoBootstrap::Delegate implementation
- void OnPipeAvailable(mojo::embedder::ScopedPlatformHandle handle,
- int32_t peer_pid) override {
- if (base::CommandLine::ForCurrentProcess()->HasSwitch("use-new-edk")) {
- message_pipe_ = mojo::embedder::CreateChannel(
- std::move(handle),
- base::Callback<void(mojo::embedder::ChannelInfo*)>(),
- scoped_refptr<base::TaskRunner>());
- if (!message_pipe_.is_valid()) {
- LOG(WARNING) << "mojo::CreateMessagePipe failed: ";
- listener()->OnChannelError();
- return;
- }
- InitMessageReader(std::move(message_pipe_), peer_pid);
- return;
- }
-
- mojo::ScopedMessagePipeHandle peer;
- MojoResult create_result =
- mojo::CreateMessagePipe(nullptr, &message_pipe_, &peer);
- if (create_result != MOJO_RESULT_OK) {
- LOG(WARNING) << "mojo::CreateMessagePipe failed: " << create_result;
- listener()->OnChannelError();
- return;
- }
- CreateMessagingPipe(
- std::move(handle),
- base::Bind(&ServerChannelMojo::InitClientChannel,
- weak_factory_.GetWeakPtr(), base::Passed(&peer)));
- }
- // Channel override
- void Close() override {
- client_channel_.reset();
- message_pipe_.reset();
- ChannelMojo::Close();
- }
-
- private:
- void InitClientChannel(mojo::ScopedMessagePipeHandle peer_handle,
- mojo::ScopedMessagePipeHandle handle) {
- client_channel_.Bind(
- mojo::InterfacePtrInfo<ClientChannel>(std::move(handle), 0u));
- client_channel_.set_connection_error_handler(base::Bind(
- &ServerChannelMojo::OnConnectionError, base::Unretained(this)));
- client_channel_->Init(
- std::move(peer_handle), static_cast<int32_t>(GetSelfPID()),
- base::Bind(&ServerChannelMojo::ClientChannelWasInitialized,
- base::Unretained(this)));
- }
-
- void OnConnectionError() {
- listener()->OnChannelError();
- }
-
- // ClientChannelClient implementation
- void ClientChannelWasInitialized(int32_t peer_pid) {
- InitMessageReader(std::move(message_pipe_), peer_pid);
- }
-
- mojo::InterfacePtr<ClientChannel> client_channel_;
- mojo::ScopedMessagePipeHandle message_pipe_;
- base::WeakPtrFactory<ServerChannelMojo> weak_factory_;
+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;
+}
- DISALLOW_COPY_AND_ASSIGN(ServerChannelMojo);
-};
+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)
@@ -201,241 +91,254 @@ base::ScopedFD TakeOrDupFile(internal::PlatformFileAttachment* attachment) {
#endif
-} // namespace
-
-//------------------------------------------------------------------------------
+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;
+ }
-ChannelMojo::ChannelInfoDeleter::ChannelInfoDeleter(
- scoped_refptr<base::TaskRunner> io_runner)
- : io_runner(io_runner) {
+ 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)
}
-ChannelMojo::ChannelInfoDeleter::~ChannelInfoDeleter() {
+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;
}
-void ChannelMojo::ChannelInfoDeleter::operator()(
- mojo::embedder::ChannelInfo* ptr) const {
- if (base::ThreadTaskRunnerHandle::Get() == io_runner) {
- mojo::embedder::DestroyChannelOnIOThread(ptr);
- } else {
- io_runner->PostTask(
- FROM_HERE, base::Bind(&mojo::embedder::DestroyChannelOnIOThread, ptr));
+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
-// static
-bool ChannelMojo::ShouldBeUsed() {
- // TODO(rockot): Investigate performance bottlenecks and hopefully reenable
- // this at some point. http://crbug.com/500019
- return false;
-}
+//------------------------------------------------------------------------------
// static
scoped_ptr<ChannelMojo> ChannelMojo::Create(
- scoped_refptr<base::TaskRunner> io_runner,
- const ChannelHandle& channel_handle,
+ mojo::ScopedMessagePipeHandle handle,
Mode mode,
Listener* listener) {
- switch (mode) {
- case Channel::MODE_CLIENT:
- return make_scoped_ptr(
- new ClientChannelMojo(io_runner, channel_handle, listener));
- case Channel::MODE_SERVER:
- return make_scoped_ptr(
- new ServerChannelMojo(io_runner, channel_handle, listener));
- default:
- NOTREACHED();
- return nullptr;
- }
+ return make_scoped_ptr(new ChannelMojo(std::move(handle), mode, listener));
}
// static
scoped_ptr<ChannelFactory> ChannelMojo::CreateServerFactory(
- scoped_refptr<base::TaskRunner> io_runner,
- const ChannelHandle& channel_handle) {
+ mojo::ScopedMessagePipeHandle handle) {
return make_scoped_ptr(
- new MojoChannelFactory(io_runner, channel_handle, Channel::MODE_SERVER));
+ new MojoChannelFactory(std::move(handle), Channel::MODE_SERVER));
}
// static
scoped_ptr<ChannelFactory> ChannelMojo::CreateClientFactory(
- scoped_refptr<base::TaskRunner> io_runner,
- const ChannelHandle& channel_handle) {
+ mojo::ScopedMessagePipeHandle handle) {
return make_scoped_ptr(
- new MojoChannelFactory(io_runner, channel_handle, Channel::MODE_CLIENT));
+ new MojoChannelFactory(std::move(handle), Channel::MODE_CLIENT));
}
-ChannelMojo::ChannelMojo(scoped_refptr<base::TaskRunner> io_runner,
- const ChannelHandle& handle,
+ChannelMojo::ChannelMojo(mojo::ScopedMessagePipeHandle handle,
Mode mode,
Listener* listener)
- : listener_(listener),
- peer_pid_(base::kNullProcessId),
- io_runner_(io_runner),
- channel_info_(nullptr, ChannelInfoDeleter(nullptr)),
+ : pipe_(handle.get()),
+ listener_(listener),
waiting_connect_(true),
weak_factory_(this) {
// Create MojoBootstrap after all members are set as it touches
// ChannelMojo from a different thread.
- bootstrap_ = MojoBootstrap::Create(handle, mode, this);
- if (!g_use_channel_on_io_thread_only ||
- io_runner == base::MessageLoop::current()->task_runner()) {
- InitOnIOThread();
- } else {
- io_runner->PostTask(FROM_HERE, base::Bind(&ChannelMojo::InitOnIOThread,
- base::Unretained(this)));
- }
+ bootstrap_ = MojoBootstrap::Create(std::move(handle), mode, this);
}
ChannelMojo::~ChannelMojo() {
Close();
}
-void ChannelMojo::InitOnIOThread() {
- ipc_support_.reset(
- new ScopedIPCSupport(base::MessageLoop::current()->task_runner()));
-}
-
-void ChannelMojo::CreateMessagingPipe(
- mojo::embedder::ScopedPlatformHandle handle,
- const CreateMessagingPipeCallback& callback) {
- auto return_callback = base::Bind(&ChannelMojo::OnMessagingPipeCreated,
- weak_factory_.GetWeakPtr(), callback);
- if (!g_use_channel_on_io_thread_only ||
- base::ThreadTaskRunnerHandle::Get() == io_runner_) {
- CreateMessagingPipeOnIOThread(std::move(handle),
- base::ThreadTaskRunnerHandle::Get(),
- return_callback);
- } else {
- io_runner_->PostTask(
- FROM_HERE,
- base::Bind(&ChannelMojo::CreateMessagingPipeOnIOThread,
- base::Passed(&handle), base::ThreadTaskRunnerHandle::Get(),
- return_callback));
- }
-}
-
-// static
-void ChannelMojo::CreateMessagingPipeOnIOThread(
- mojo::embedder::ScopedPlatformHandle handle,
- scoped_refptr<base::TaskRunner> callback_runner,
- const CreateMessagingPipeOnIOThreadCallback& callback) {
- mojo::embedder::ChannelInfo* channel_info;
- mojo::ScopedMessagePipeHandle pipe =
- mojo::embedder::CreateChannelOnIOThread(std::move(handle), &channel_info);
- if (base::ThreadTaskRunnerHandle::Get() == callback_runner) {
- callback.Run(std::move(pipe), channel_info);
- } else {
- callback_runner->PostTask(
- FROM_HERE, base::Bind(callback, base::Passed(&pipe), channel_info));
- }
-}
-
-void ChannelMojo::OnMessagingPipeCreated(
- const CreateMessagingPipeCallback& callback,
- mojo::ScopedMessagePipeHandle handle,
- mojo::embedder::ChannelInfo* channel_info) {
- DCHECK(!channel_info_.get());
- channel_info_ = scoped_ptr<mojo::embedder::ChannelInfo, ChannelInfoDeleter>(
- channel_info, ChannelInfoDeleter(io_runner_));
- callback.Run(std::move(handle));
-}
-
bool ChannelMojo::Connect() {
+ WillConnect();
+ base::AutoLock lock(lock_);
+ DCHECK(!task_runner_);
+ task_runner_ = base::ThreadTaskRunnerHandle::Get();
DCHECK(!message_reader_);
- return bootstrap_->Connect();
+ bootstrap_->Connect();
+ return true;
}
void ChannelMojo::Close() {
- scoped_ptr<internal::MessagePipeReader, ReaderDeleter> to_be_deleted;
-
+ scoped_ptr<internal::MessagePipeReader, ReaderDeleter> reader;
{
- // |message_reader_| has to be cleared inside the lock,
- // but the instance has to be deleted outside.
- base::AutoLock l(lock_);
- to_be_deleted = std::move(message_reader_);
+ base::AutoLock lock(lock_);
+ if (!message_reader_)
+ return;
+ // The reader's destructor may re-enter Close, so we swap it out first to
+ // avoid deadlock when freeing it below.
+ std::swap(message_reader_, reader);
+
// We might Close() before we Connect().
waiting_connect_ = false;
}
- channel_info_.reset();
- ipc_support_.reset();
- to_be_deleted.reset();
+ reader.reset();
+}
+
+// MojoBootstrap::Delegate implementation
+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);
}
void ChannelMojo::OnBootstrapError() {
listener_->OnChannelError();
}
-namespace {
-
-// ClosingDeleter calls |CloseWithErrorIfPending| before deleting the
-// |MessagePipeReader|.
-struct ClosingDeleter {
- typedef std::default_delete<internal::MessagePipeReader> DefaultType;
-
- void operator()(internal::MessagePipeReader* ptr) const {
- ptr->CloseWithErrorIfPending();
- delete ptr;
- }
-};
-
-} // namespace
-
-void ChannelMojo::InitMessageReader(mojo::ScopedMessagePipeHandle pipe,
- int32_t peer_pid) {
- scoped_ptr<internal::MessagePipeReader, ClosingDeleter> reader(
- new internal::MessagePipeReader(std::move(pipe), this));
+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(pipe_, std::move(sender_ptr),
+ std::move(receiver), peer_pid, this));
+ bool connected = true;
{
- base::AutoLock l(lock_);
+ base::AutoLock lock(lock_);
for (size_t i = 0; i < pending_messages_.size(); ++i) {
- bool sent = reader->Send(make_scoped_ptr(pending_messages_[i]));
- pending_messages_[i] = nullptr;
- if (!sent) {
- // OnChannelError() is notified through ClosingDeleter.
+ if (!reader->Send(std::move(pending_messages_[i]))) {
+ LOG(ERROR) << "Failed to flush pending messages";
pending_messages_.clear();
- LOG(ERROR) << "Failed to flush pending messages";
- return;
+ connected = false;
+ break;
}
}
- // We set |message_reader_| here and won't get any |pending_messages_|
- // hereafter. Although we might have some if there is an error, we don't
- // care. They cannot be sent anyway.
- message_reader_.reset(reader.release());
- pending_messages_.clear();
- waiting_connect_ = false;
+ if (connected) {
+ // We set |message_reader_| here and won't get any |pending_messages_|
+ // hereafter. Although we might have some if there is an error, we don't
+ // care. They cannot be sent anyway.
+ message_reader_ = std::move(reader);
+ pending_messages_.clear();
+ waiting_connect_ = false;
+ }
}
- set_peer_pid(peer_pid);
- listener_->OnChannelConnected(static_cast<int32_t>(GetPeerPID()));
- if (message_reader_)
- message_reader_->ReadMessagesThenWait();
-}
-
-void ChannelMojo::OnPipeClosed(internal::MessagePipeReader* reader) {
- Close();
+ if (connected)
+ listener_->OnChannelConnected(static_cast<int32_t>(GetPeerPID()));
+ else
+ OnPipeError();
}
-void ChannelMojo::OnPipeError(internal::MessagePipeReader* reader) {
- listener_->OnChannelError();
+void ChannelMojo::OnPipeError() {
+ DCHECK(task_runner_);
+ if (task_runner_->RunsTasksOnCurrentThread()) {
+ listener_->OnChannelError();
+ } else {
+ task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&ChannelMojo::OnPipeError, weak_factory_.GetWeakPtr()));
+ }
}
-
-// Warning: Keep the implementation thread-safe.
bool ChannelMojo::Send(Message* message) {
- base::AutoLock l(lock_);
+ base::AutoLock lock(lock_);
if (!message_reader_) {
- pending_messages_.push_back(message);
+ pending_messages_.push_back(make_scoped_ptr(message));
// Counts as OK before the connection is established, but it's an
// error otherwise.
return waiting_connect_;
}
- return message_reader_->Send(make_scoped_ptr(message));
+ if (!message_reader_->Send(make_scoped_ptr(message))) {
+ OnPipeError();
+ return false;
+ }
+
+ return true;
}
bool ChannelMojo::IsSendThreadSafe() const {
@@ -443,17 +346,25 @@ bool ChannelMojo::IsSendThreadSafe() const {
}
base::ProcessId ChannelMojo::GetPeerPID() const {
- return peer_pid_;
+ base::AutoLock lock(lock_);
+ if (!message_reader_)
+ return base::kNullProcessId;
+
+ return message_reader_->GetPeerPid();
}
base::ProcessId ChannelMojo::GetSelfPID() const {
return bootstrap_->GetSelfPID();
}
-void ChannelMojo::OnMessageReceived(Message& message) {
+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);
@@ -461,92 +372,64 @@ void ChannelMojo::OnMessageReceived(Message& message) {
#if defined(OS_POSIX) && !defined(OS_NACL)
int ChannelMojo::GetClientFileDescriptor() const {
- return bootstrap_->GetClientFileDescriptor();
+ return -1;
}
base::ScopedFD ChannelMojo::TakeClientFileDescriptor() {
- return bootstrap_->TakeClientFileDescriptor();
+ return base::ScopedFD(GetClientFileDescriptor());
}
#endif // defined(OS_POSIX) && !defined(OS_NACL)
// static
MojoResult ChannelMojo::ReadFromMessageAttachmentSet(
Message* message,
- std::vector<MojoHandle>* handles) {
- // We dup() the handles in IPC::Message to transmit.
- // IPC::MessageAttachmentSet has intricate lifecycle semantics
- // of FDs, so just to dup()-and-own them is the safest option.
+ mojo::Array<mojom::SerializedHandlePtr>* handles) {
if (message->HasAttachments()) {
MessageAttachmentSet* set = message->attachment_set();
for (unsigned i = 0; i < set->num_non_brokerable_attachments(); ++i) {
- scoped_refptr<MessageAttachment> attachment =
- set->GetNonBrokerableAttachmentAt(i);
- switch (attachment->GetType()) {
- case MessageAttachment::TYPE_PLATFORM_FILE:
-#if defined(OS_POSIX) && !defined(OS_NACL)
- {
- base::ScopedFD file =
- TakeOrDupFile(static_cast<IPC::internal::PlatformFileAttachment*>(
- attachment.get()));
- if (!file.is_valid()) {
- DPLOG(WARNING) << "Failed to dup FD to transmit.";
- set->CommitAllDescriptors();
- return MOJO_RESULT_UNKNOWN;
- }
-
- MojoHandle wrapped_handle;
- MojoResult wrap_result = mojo::embedder::CreatePlatformHandleWrapper(
- mojo::embedder::ScopedPlatformHandle(
- mojo::embedder::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(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(handle.release().value());
- } break;
- case MessageAttachment::TYPE_BROKERABLE_ATTACHMENT:
- // Brokerable attachments are handled by the AttachmentBroker so
- // there's no need to do anything here.
- NOTREACHED();
- break;
+ MojoResult result = WrapAttachment(
+ set->GetNonBrokerableAttachmentAt(i).get(), handles);
+ if (result != MOJO_RESULT_OK) {
+ set->CommitAllDescriptors();
+ return result;
+ }
+ }
+ for (unsigned i = 0; i < set->num_brokerable_attachments(); ++i) {
+ MojoResult result =
+ WrapAttachment(set->GetBrokerableAttachmentAt(i).get(), handles);
+ if (result != MOJO_RESULT_OK) {
+ set->CommitAllDescriptors();
+ return result;
}
}
-
set->CommitAllDescriptors();
}
-
return MOJO_RESULT_OK;
}
// static
MojoResult ChannelMojo::WriteToMessageAttachmentSet(
- const std::vector<MojoHandle>& handle_buffer,
+ mojo::Array<mojom::SerializedHandlePtr> handle_buffer,
Message* message) {
for (size_t i = 0; i < handle_buffer.size(); ++i) {
+ scoped_refptr<MessageAttachment> unwrapped_attachment;
+ MojoResult unwrap_result = UnwrapAttachment(std::move(handle_buffer[i]),
+ &unwrapped_attachment);
+ if (unwrap_result != MOJO_RESULT_OK) {
+ LOG(WARNING) << "Pipe failed to unwrap handles. Closing: "
+ << unwrap_result;
+ return unwrap_result;
+ }
+ DCHECK(unwrapped_attachment);
+
bool ok = message->attachment_set()->AddAttachment(
- new IPC::internal::MojoHandleAttachment(
- mojo::MakeScopedHandle(mojo::Handle(handle_buffer[i]))));
+ std::move(unwrapped_attachment));
DCHECK(ok);
if (!ok) {
LOG(ERROR) << "Failed to add new Mojo handle.";
return MOJO_RESULT_UNKNOWN;
}
}
-
return MOJO_RESULT_OK;
}
diff --git a/chromium/ipc/mojo/ipc_channel_mojo.h b/chromium/ipc/mojo/ipc_channel_mojo.h
index a5ddf1e4077..5968d84ec9b 100644
--- a/chromium/ipc/mojo/ipc_channel_mojo.h
+++ b/chromium/ipc/mojo/ipc_channel_mojo.h
@@ -10,43 +10,29 @@
#include <vector>
#include "base/macros.h"
+#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/scoped_vector.h"
#include "base/memory/weak_ptr.h"
#include "base/synchronization/lock.h"
+#include "base/task_runner.h"
#include "build/build_config.h"
#include "ipc/ipc_channel.h"
#include "ipc/ipc_channel_factory.h"
#include "ipc/ipc_export.h"
#include "ipc/mojo/ipc_message_pipe_reader.h"
#include "ipc/mojo/ipc_mojo_bootstrap.h"
-#include "ipc/mojo/scoped_ipc_support.h"
+#include "mojo/edk/embedder/scoped_platform_handle.h"
#include "mojo/public/cpp/system/core.h"
-#include "third_party/mojo/src/mojo/edk/embedder/channel_info_forward.h"
namespace IPC {
-// Mojo-based IPC::Channel implementation over a platform handle.
+// Mojo-based IPC::Channel implementation over a Mojo message pipe.
//
-// ChannelMojo builds Mojo MessagePipe using underlying pipe given by
-// "bootstrap" IPC::Channel which creates and owns platform pipe like
-// named socket. The bootstrap Channel is used only for establishing
-// the underlying connection. ChannelMojo takes its handle over once
-// the it is made and puts MessagePipe on it.
+// ChannelMojo builds a Mojo MessagePipe using the provided message pipe
+// |handle| and builds an associated interface for each direction on the
+// channel.
//
-// ChannelMojo has a couple of MessagePipes:
-//
-// * The first MessagePipe, which is built on top of bootstrap handle,
-// is the "control" pipe. It is used to communicate out-of-band
-// control messages that aren't visible from IPC::Listener.
-//
-// * The second MessagePipe, which is created by the server channel
-// and sent to client Channel over the control pipe, is used
-// to send IPC::Messages as an IPC::Sender.
-//
-// TODO(morrita): Extract handle creation part of IPC::Channel into
-// separate class to clarify what ChannelMojo relies
-// on.
// TODO(morrita): Add APIs to create extra MessagePipes to let
// Mojo-based objects talk over this Channel.
//
@@ -55,32 +41,19 @@ class IPC_MOJO_EXPORT ChannelMojo
public MojoBootstrap::Delegate,
public NON_EXPORTED_BASE(internal::MessagePipeReader::Delegate) {
public:
- using CreateMessagingPipeCallback =
- base::Callback<void(mojo::ScopedMessagePipeHandle)>;
- using CreateMessagingPipeOnIOThreadCallback =
- base::Callback<void(mojo::ScopedMessagePipeHandle,
- mojo::embedder::ChannelInfo*)>;
-
- // True if ChannelMojo should be used regardless of the flag.
- static bool ShouldBeUsed();
-
- // Create ChannelMojo. A bootstrap channel is created as well.
- static scoped_ptr<ChannelMojo> Create(
- scoped_refptr<base::TaskRunner> io_runner,
- const ChannelHandle& channel_handle,
- Mode mode,
- Listener* listener);
+ // Creates a ChannelMojo.
+ static scoped_ptr<ChannelMojo> Create(mojo::ScopedMessagePipeHandle handle,
+ Mode mode,
+ Listener* listener);
// Create a factory object for ChannelMojo.
// The factory is used to create Mojo-based ChannelProxy family.
// |host| must not be null.
static scoped_ptr<ChannelFactory> CreateServerFactory(
- scoped_refptr<base::TaskRunner> io_runner,
- const ChannelHandle& channel_handle);
+ mojo::ScopedMessagePipeHandle handle);
static scoped_ptr<ChannelFactory> CreateClientFactory(
- scoped_refptr<base::TaskRunner> io_runner,
- const ChannelHandle& channel_handle);
+ mojo::ScopedMessagePipeHandle handle);
~ChannelMojo() override;
@@ -100,77 +73,49 @@ class IPC_MOJO_EXPORT ChannelMojo
// These access protected API of IPC::Message, which has ChannelMojo
// as a friend class.
static MojoResult WriteToMessageAttachmentSet(
- const std::vector<MojoHandle>& handle_buffer,
+ mojo::Array<mojom::SerializedHandlePtr> handle_buffer,
Message* message);
static MojoResult ReadFromMessageAttachmentSet(
Message* message,
- std::vector<MojoHandle>* handles);
+ mojo::Array<mojom::SerializedHandlePtr>* handles);
// MojoBootstrapDelegate implementation
+ void OnPipesAvailable(mojom::ChannelAssociatedPtrInfo send_channel,
+ mojom::ChannelAssociatedRequest receive_channel,
+ int32_t peer_pid) override;
void OnBootstrapError() override;
// MessagePipeReader::Delegate
- void OnMessageReceived(Message& message) override;
- void OnPipeClosed(internal::MessagePipeReader* reader) override;
- void OnPipeError(internal::MessagePipeReader* reader) override;
+ void OnMessageReceived(const Message& message) override;
+ void OnPipeError() override;
- protected:
- ChannelMojo(scoped_refptr<base::TaskRunner> io_runner,
- const ChannelHandle& channel_handle,
+ private:
+ ChannelMojo(mojo::ScopedMessagePipeHandle handle,
Mode mode,
Listener* listener);
- void CreateMessagingPipe(mojo::embedder::ScopedPlatformHandle handle,
- const CreateMessagingPipeCallback& callback);
- void InitMessageReader(mojo::ScopedMessagePipeHandle pipe, int32_t peer_pid);
-
- Listener* listener() const { return listener_; }
- void set_peer_pid(base::ProcessId pid) { peer_pid_ = pid; }
-
- private:
- struct ChannelInfoDeleter {
- explicit ChannelInfoDeleter(scoped_refptr<base::TaskRunner> io_runner);
- ~ChannelInfoDeleter();
-
- void operator()(mojo::embedder::ChannelInfo* ptr) const;
-
- scoped_refptr<base::TaskRunner> io_runner;
- };
+ void InitMessageReader(mojom::ChannelAssociatedPtrInfo sender,
+ mojom::ChannelAssociatedRequest receiver,
+ base::ProcessId peer_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;
- void InitOnIOThread();
-
- static void CreateMessagingPipeOnIOThread(
- mojo::embedder::ScopedPlatformHandle handle,
- scoped_refptr<base::TaskRunner> callback_runner,
- const CreateMessagingPipeOnIOThreadCallback& callback);
- void OnMessagingPipeCreated(const CreateMessagingPipeCallback& callback,
- mojo::ScopedMessagePipeHandle handle,
- mojo::embedder::ChannelInfo* channel_info);
+ // A TaskRunner which runs tasks on the ChannelMojo's owning thread.
+ scoped_refptr<base::TaskRunner> task_runner_;
+ const mojo::MessagePipeHandle pipe_;
scoped_ptr<MojoBootstrap> bootstrap_;
Listener* listener_;
- base::ProcessId peer_pid_;
- scoped_refptr<base::TaskRunner> io_runner_;
- scoped_ptr<mojo::embedder::ChannelInfo,
- ChannelInfoDeleter> channel_info_;
-
- // Guards |message_reader_|, |waiting_connect_| and |pending_messages_|
- //
- // * The contents of |pending_messages_| can be modified from any thread.
- // * |message_reader_| is modified only from the IO thread,
- // but they can be referenced from other threads.
- base::Lock lock_;
+
+ // Guards access to the fields below.
+ mutable base::Lock lock_;
scoped_ptr<internal::MessagePipeReader, ReaderDeleter> message_reader_;
- ScopedVector<Message> pending_messages_;
+ std::vector<scoped_ptr<Message>> pending_messages_;
bool waiting_connect_;
- scoped_ptr<ScopedIPCSupport> ipc_support_;
-
base::WeakPtrFactory<ChannelMojo> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(ChannelMojo);
diff --git a/chromium/ipc/mojo/ipc_channel_mojo_unittest.cc b/chromium/ipc/mojo/ipc_channel_mojo_unittest.cc
index b4f4154c67c..615e72d5945 100644
--- a/chromium/ipc/mojo/ipc_channel_mojo_unittest.cc
+++ b/chromium/ipc/mojo/ipc_channel_mojo_unittest.cc
@@ -15,6 +15,7 @@
#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"
@@ -22,22 +23,45 @@
#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 "ipc/mojo/scoped_ipc_support.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 {}
@@ -59,8 +83,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));
}
@@ -71,13 +95,12 @@ class ListenerThatExpectsOK : public IPC::Listener {
class ChannelClient {
public:
- 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 Init(mojo::ScopedMessagePipeHandle handle) {
+ handle_ = std::move(handle);
}
-
- void Connect() {
+ void Connect(IPC::Listener* listener) {
+ channel_ = IPC::ChannelMojo::Create(std::move(handle_),
+ IPC::Channel::MODE_CLIENT, listener);
CHECK(channel_->Connect());
}
@@ -94,48 +117,46 @@ class ChannelClient {
private:
base::MessageLoopForIO main_message_loop_;
+ mojo::ScopedMessagePipeHandle handle_;
scoped_ptr<IPC::ChannelMojo> channel_;
};
-class IPCChannelMojoTestBase : public IPCTestBase {
+class IPCChannelMojoTest : public testing::Test {
public:
- void InitWithMojo(const std::string& test_client_name) {
- Init(test_client_name);
- }
+ IPCChannelMojoTest() : io_thread_(base::TestIOThread::Mode::kAutoStart) {}
- 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();
+ void TearDown() override { base::RunLoop().RunUntilIdle(); }
- IPCTestBase::TearDown();
+ void InitWithMojo(const std::string& test_client_name) {
+ handle_ = helper_.StartChild(test_client_name);
}
-};
-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);
+ void CreateChannel(IPC::Listener* listener) {
+ channel_ = IPC::ChannelMojo::Create(std::move(handle_),
+ IPC::Channel::MODE_SERVER, listener);
}
- bool DidStartClient() override {
- bool ok = IPCTestBase::DidStartClient();
- DCHECK(ok);
- return ok;
- }
-};
+ bool ConnectChannel() { return channel_->Connect(); }
+ void DestroyChannel() { channel_.reset(); }
+
+ bool WaitForClientShutdown() { return helper_.WaitForChildTestShutdown(); }
+
+ IPC::Sender* sender() { return channel(); }
+ IPC::Channel* channel() { return channel_.get(); }
+
+ private:
+ base::MessageLoop message_loop_;
+ base::TestIOThread io_thread_;
+ mojo::edk::test::MultiprocessTestHelper helper_;
+ mojo::ScopedMessagePipeHandle handle_;
+ scoped_ptr<IPC::Channel> channel_;
+};
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);
@@ -163,15 +184,12 @@ 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());
- this->channel()->Close();
+ channel()->Close();
EXPECT_TRUE(WaitForClientShutdown());
EXPECT_TRUE(listener.is_connected_called());
@@ -181,28 +199,22 @@ TEST_F(IPCChannelMojoTest, MAYBE_ConnectedFromClient) {
}
// A long running process that connects to us
-MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoTestClient) {
+DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(IPCChannelMojoTestClient, ChannelClient) {
TestChannelListenerWithExtraExpectations listener;
- ChannelClient client(&listener, "IPCChannelMojoTestClient");
- client.Connect();
- listener.Init(client.channel());
+ Connect(&listener);
+ listener.Init(channel());
- IPC::TestChannelListener::SendOneMessage(
- client.channel(), "hello from child");
+ IPC::TestChannelListener::SendOneMessage(channel(), "hello from child");
base::MessageLoop::current()->Run();
EXPECT_TRUE(listener.is_connected_called());
EXPECT_TRUE(listener.HasSentAll());
- client.Close();
-
- return 0;
+ Close();
}
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();
@@ -221,30 +233,11 @@ 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();
@@ -252,16 +245,14 @@ class ListenerThatQuits : public IPC::Listener {
};
// A long running process that connects to us.
-MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoErraticTestClient) {
+DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(IPCChannelMojoErraticTestClient,
+ ChannelClient) {
ListenerThatQuits listener;
- ChannelClient client(&listener, "IPCChannelMojoErraticTestClient");
- client.Connect();
+ Connect(&listener);
base::MessageLoop::current()->Run();
- client.Close();
-
- return 0;
+ Close();
}
// Times out on Android; see http://crbug.com/502290
@@ -270,7 +261,7 @@ MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoErraticTestClient) {
#else
#define MAYBE_SendFailWithPendingMessages SendFailWithPendingMessages
#endif
-TEST_F(IPCChannelMojoErrorTest, MAYBE_SendFailWithPendingMessages) {
+TEST_F(IPCChannelMojoTest, MAYBE_SendFailWithPendingMessages) {
InitWithMojo("IPCChannelMojoErraticTestClient");
// Set up IPC channel and start client.
@@ -283,14 +274,13 @@ TEST_F(IPCChannelMojoErrorTest, 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();
- this->channel()->Close();
+ channel()->Close();
EXPECT_TRUE(WaitForClientShutdown());
EXPECT_TRUE(listener.has_error());
@@ -336,6 +326,9 @@ 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));
@@ -378,9 +371,10 @@ class HandleSendingHelper {
static void ReadReceivedFile(const IPC::Message& message,
base::PickleIterator* iter) {
base::ScopedFD fd;
- scoped_refptr<IPC::MessageAttachment> attachment;
+ scoped_refptr<base::Pickle::Attachment> attachment;
EXPECT_TRUE(message.ReadAttachment(iter, &attachment));
- base::File file(attachment->TakePlatformFile());
+ base::File file(static_cast<IPC::MessageAttachment*>(attachment.get())
+ ->TakePlatformFile());
std::string content(GetSendingFileContent().size(), ' ');
file.Read(0, &content[0], content.size());
EXPECT_EQ(content, GetSendingFileContent());
@@ -422,34 +416,33 @@ 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();
- this->channel()->Close();
+ channel()->Close();
EXPECT_TRUE(WaitForClientShutdown());
DestroyChannel();
}
-MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoTestSendMessagePipeClient) {
+DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(IPCChannelMojoTestSendMessagePipeClient,
+ ChannelClient) {
ListenerThatExpectsMessagePipe listener;
- ChannelClient client(&listener, "IPCChannelMojoTestSendMessagePipeClient");
- client.Connect();
- listener.set_sender(client.channel());
+ Connect(&listener);
+ listener.set_sender(channel());
base::MessageLoop::current()->Run();
- client.Close();
-
- return 0;
+ Close();
}
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));
@@ -494,18 +487,19 @@ class ListenerThatExpectsMessagePipeUsingParamTrait : public IPC::Listener {
bool receiving_valid_;
};
-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());
+class ParamTraitMessagePipeClient : public ChannelClient {
+ public:
+ void RunTest(bool receiving_valid_handle) {
+ ListenerThatExpectsMessagePipeUsingParamTrait listener(
+ receiving_valid_handle);
+ Connect(&listener);
+ listener.set_sender(channel());
- base::MessageLoop::current()->Run();
+ base::MessageLoop::current()->Run();
- client.Close();
-}
+ Close();
+ }
+};
// Times out on Android; see http://crbug.com/502290
#if defined(OS_ANDROID)
@@ -519,7 +513,6 @@ TEST_F(IPCChannelMojoTest, MAYBE_ParamTraitValidMessagePipe) {
ListenerThatExpectsOK listener;
CreateChannel(&listener);
ASSERT_TRUE(ConnectChannel());
- ASSERT_TRUE(StartClient());
TestingMessagePipe pipe;
@@ -528,17 +521,17 @@ TEST_F(IPCChannelMojoTest, MAYBE_ParamTraitValidMessagePipe) {
pipe.peer.release());
WriteOK(pipe.self.get());
- this->channel()->Send(message.release());
+ channel()->Send(message.release());
base::MessageLoop::current()->Run();
- this->channel()->Close();
+ channel()->Close();
EXPECT_TRUE(WaitForClientShutdown());
DestroyChannel();
}
-MULTIPROCESS_IPC_TEST_CLIENT_MAIN(ParamTraitValidMessagePipeClient) {
- ParamTraitMessagePipeClient(true, "ParamTraitValidMessagePipeClient");
- return 0;
+DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(ParamTraitValidMessagePipeClient,
+ ParamTraitMessagePipeClient) {
+ RunTest(true);
}
// Times out on Android; see http://crbug.com/502290
@@ -553,37 +546,41 @@ 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);
- this->channel()->Send(message.release());
+ channel()->Send(message.release());
base::MessageLoop::current()->Run();
- this->channel()->Close();
+ channel()->Close();
EXPECT_TRUE(WaitForClientShutdown());
DestroyChannel();
}
-MULTIPROCESS_IPC_TEST_CLIENT_MAIN(ParamTraitInvalidMessagePipeClient) {
- ParamTraitMessagePipeClient(false, "ParamTraitInvalidMessagePipeClient");
- return 0;
+DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(ParamTraitInvalidMessagePipeClient,
+ ParamTraitMessagePipeClient) {
+ RunTest(false);
}
-TEST_F(IPCChannelMojoTest, SendFailAfterClose) {
+// Times out on Android. crbug.com/593790
+#if defined(OS_ANDROID)
+#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();
- this->channel()->Close();
- ASSERT_FALSE(this->channel()->Send(new IPC::Message()));
+ channel()->Close();
+ ASSERT_FALSE(channel()->Send(new IPC::Message()));
EXPECT_TRUE(WaitForClientShutdown());
DestroyChannel();
@@ -591,12 +588,9 @@ 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_);
@@ -609,80 +603,21 @@ class ListenerSendingOneOk : public IPC::Listener {
IPC::Sender* sender_;
};
-MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoTestSendOkClient) {
+DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(IPCChannelMojoTestSendOkClient,
+ ChannelClient) {
ListenerSendingOneOk listener;
- ChannelClient client(&listener, "IPCChannelMojoTestSendOkClient");
- client.Connect();
- listener.set_sender(client.channel());
+ Connect(&listener);
+ listener.set_sender(channel());
base::MessageLoop::current()->Run();
- client.Close();
-
- return 0;
+ Close();
}
-#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;
- }
-};
-
-TEST_F(IPCChannelMojoDeadHandleTest, 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();
-
- 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 {}
@@ -694,9 +629,7 @@ class ListenerThatExpectsFile : public IPC::Listener {
return true;
}
- void OnChannelError() override {
- NOTREACHED();
- }
+ void OnChannelError() override { NOTREACHED(); }
void set_sender(IPC::Sender* sender) { sender_ = sender; }
@@ -716,7 +649,6 @@ 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 |
@@ -724,24 +656,21 @@ TEST_F(IPCChannelMojoTest, MAYBE_SendPlatformHandle) {
HandleSendingHelper::WriteFileThenSend(channel(), file);
base::MessageLoop::current()->Run();
- this->channel()->Close();
+ channel()->Close();
EXPECT_TRUE(WaitForClientShutdown());
DestroyChannel();
}
-MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoTestSendPlatformHandleClient) {
+DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(IPCChannelMojoTestSendPlatformHandleClient,
+ ChannelClient) {
ListenerThatExpectsFile listener;
- ChannelClient client(
- &listener, "IPCChannelMojoTestSendPlatformHandleClient");
- client.Connect();
- listener.set_sender(client.channel());
+ Connect(&listener);
+ listener.set_sender(channel());
base::MessageLoop::current()->Run();
- client.Close();
-
- return 0;
+ Close();
}
class ListenerThatExpectsFileAndPipe : public IPC::Listener {
@@ -779,7 +708,6 @@ 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 |
@@ -788,25 +716,22 @@ TEST_F(IPCChannelMojoTest, MAYBE_SendPlatformHandleAndPipe) {
HandleSendingHelper::WriteFileAndPipeThenSend(channel(), file, &pipe);
base::MessageLoop::current()->Run();
- this->channel()->Close();
+ channel()->Close();
EXPECT_TRUE(WaitForClientShutdown());
DestroyChannel();
}
-MULTIPROCESS_IPC_TEST_CLIENT_MAIN(
- IPCChannelMojoTestSendPlatformHandleAndPipeClient) {
+DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(
+ IPCChannelMojoTestSendPlatformHandleAndPipeClient,
+ ChannelClient) {
ListenerThatExpectsFileAndPipe listener;
- ChannelClient client(&listener,
- "IPCChannelMojoTestSendPlatformHandleAndPipeClient");
- client.Connect();
- listener.set_sender(client.channel());
+ Connect(&listener);
+ listener.set_sender(channel());
base::MessageLoop::current()->Run();
- client.Close();
-
- return 0;
+ Close();
}
#endif
@@ -834,7 +759,6 @@ TEST_F(IPCChannelMojoTest, VerifyGlobalPid) {
ListenerThatVerifiesPeerPid listener;
CreateChannel(&listener);
ASSERT_TRUE(ConnectChannel());
- ASSERT_TRUE(StartClient());
base::MessageLoop::current()->Run();
channel()->Close();
@@ -843,20 +767,17 @@ TEST_F(IPCChannelMojoTest, VerifyGlobalPid) {
DestroyChannel();
}
-MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoTestVerifyGlobalPidClient) {
+DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(IPCChannelMojoTestVerifyGlobalPidClient,
+ ChannelClient) {
IPC::Channel::SetGlobalPid(kMagicChildId);
ListenerThatQuits listener;
- ChannelClient client(&listener,
- "IPCChannelMojoTestVerifyGlobalPidClient");
- client.Connect();
+ Connect(&listener);
base::MessageLoop::current()->Run();
- client.Close();
-
- return 0;
+ Close();
}
-#endif // OS_LINUX
+#endif // OS_LINUX
} // namespace
diff --git a/chromium/ipc/mojo/ipc_message_pipe_reader.cc b/chromium/ipc/mojo/ipc_message_pipe_reader.cc
index 19d9e303a6d..b657bfdc168 100644
--- a/chromium/ipc/mojo/ipc_message_pipe_reader.cc
+++ b/chromium/ipc/mojo/ipc_message_pipe_reader.cc
@@ -5,66 +5,82 @@
#include "ipc/mojo/ipc_message_pipe_reader.h"
#include <stdint.h>
+
#include <utility>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/location.h"
#include "base/logging.h"
+#include "base/macros.h"
#include "base/single_thread_task_runner.h"
#include "base/thread_task_runner_handle.h"
-#include "ipc/mojo/async_handle_waiter.h"
#include "ipc/mojo/ipc_channel_mojo.h"
+#include "mojo/public/cpp/bindings/message.h"
namespace IPC {
namespace internal {
-MessagePipeReader::MessagePipeReader(mojo::ScopedMessagePipeHandle handle,
- MessagePipeReader::Delegate* delegate)
- : pipe_(std::move(handle)),
- handle_copy_(pipe_.get().value()),
- delegate_(delegate),
- async_waiter_(new AsyncHandleWaiter(
- base::Bind(&MessagePipeReader::PipeIsReady, base::Unretained(this)))),
- pending_send_error_(MOJO_RESULT_OK) {}
+namespace {
-MessagePipeReader::~MessagePipeReader() {
- DCHECK(thread_checker_.CalledOnValidThread());
- // The pipe should be closed before deletion.
- CHECK(!IsValid());
-}
+// Used by Send() to capture a serialized Channel::Receive message.
+class MessageSerializer : public mojo::MessageReceiverWithResponder {
+ public:
+ MessageSerializer() {}
+ ~MessageSerializer() override {}
-void MessagePipeReader::Close() {
- DCHECK(thread_checker_.CalledOnValidThread());
- async_waiter_.reset();
- pipe_.reset();
- OnPipeClosed();
-}
+ mojo::Message* message() { return &message_; }
-void MessagePipeReader::CloseWithError(MojoResult error) {
- DCHECK(thread_checker_.CalledOnValidThread());
- OnPipeError(error);
- Close();
+ private:
+ // mojo::MessageReceiverWithResponder
+ bool Accept(mojo::Message* message) override {
+ message->MoveTo(&message_);
+ return true;
+ }
+
+ bool AcceptWithResponder(mojo::Message* message,
+ mojo::MessageReceiver* responder) override {
+ NOTREACHED();
+ return false;
+ }
+
+ mojo::Message message_;
+
+ DISALLOW_COPY_AND_ASSIGN(MessageSerializer);
+};
+
+} // namespace
+
+MessagePipeReader::MessagePipeReader(
+ mojo::MessagePipeHandle pipe,
+ 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_interface_id_(sender_.interface_id()),
+ sender_pipe_(pipe) {
+ sender_.set_connection_error_handler(
+ base::Bind(&MessagePipeReader::OnPipeError, base::Unretained(this),
+ MOJO_RESULT_FAILED_PRECONDITION));
+ binding_.set_connection_error_handler(
+ base::Bind(&MessagePipeReader::OnPipeError, base::Unretained(this),
+ MOJO_RESULT_FAILED_PRECONDITION));
}
-void MessagePipeReader::CloseWithErrorIfPending() {
+MessagePipeReader::~MessagePipeReader() {
DCHECK(thread_checker_.CalledOnValidThread());
- MojoResult pending_error = base::subtle::NoBarrier_Load(&pending_send_error_);
- if (pending_error == MOJO_RESULT_OK)
- return;
- // NOTE: This races with Send(), and therefore the value of
- // pending_send_error() can change.
- CloseWithError(pending_error);
- return;
+ // The pipe should be closed before deletion.
}
-void MessagePipeReader::CloseWithErrorLater(MojoResult error) {
- DCHECK_NE(error, MOJO_RESULT_OK);
- // NOTE: No assumptions about the value of |pending_send_error_| or whether or
- // not the error has been signaled can be made. If Send() is called
- // immediately before Close() and errors, it's possible for the error to not
- // be signaled.
- base::subtle::NoBarrier_Store(&pending_send_error_, error);
+void MessagePipeReader::Close() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ sender_.reset();
+ if (binding_.is_bound())
+ binding_.Close();
}
bool MessagePipeReader::Send(scoped_ptr<Message> message) {
@@ -72,165 +88,68 @@ bool MessagePipeReader::Send(scoped_ptr<Message> message) {
"MessagePipeReader::Send",
message->flags(),
TRACE_EVENT_FLAG_FLOW_OUT);
- std::vector<MojoHandle> handles;
+ mojo::Array<mojom::SerializedHandlePtr> handles(nullptr);
MojoResult result = MOJO_RESULT_OK;
result = ChannelMojo::ReadFromMessageAttachmentSet(message.get(), &handles);
- if (result == MOJO_RESULT_OK) {
- result = MojoWriteMessage(handle(),
- message->data(),
- static_cast<uint32_t>(message->size()),
- handles.empty() ? nullptr : &handles[0],
- static_cast<uint32_t>(handles.size()),
- MOJO_WRITE_MESSAGE_FLAG_NONE);
- }
-
- if (result != MOJO_RESULT_OK) {
- std::for_each(handles.begin(), handles.end(), &MojoClose);
- // We cannot call CloseWithError() here as Send() is protected by
- // ChannelMojo's lock and CloseWithError() could re-enter ChannelMojo. We
- // cannot call CloseWithError() also because Send() can be called from
- // non-UI thread while OnPipeError() expects to be called on IO thread.
- CloseWithErrorLater(result);
+ if (result != MOJO_RESULT_OK)
return false;
- }
- return true;
+ mojo::Array<uint8_t> data(message->size());
+ std::copy(reinterpret_cast<const uint8_t*>(message->data()),
+ reinterpret_cast<const uint8_t*>(message->data()) + message->size(),
+ &data[0]);
+
+ MessageSerializer serializer;
+ mojom::ChannelProxy proxy(&serializer);
+ proxy.Receive(std::move(data), std::move(handles));
+ mojo::Message* mojo_message = serializer.message();
+
+ size_t num_handles = mojo_message->handles()->size();
+ DCHECK_LE(num_handles, std::numeric_limits<uint32_t>::max());
+
+ mojo_message->set_interface_id(sender_interface_id_);
+ result = mojo::WriteMessageRaw(
+ sender_pipe_, mojo_message->data(), mojo_message->data_num_bytes(),
+ reinterpret_cast<const MojoHandle*>(mojo_message->handles()->data()),
+ static_cast<uint32_t>(num_handles), MOJO_WRITE_MESSAGE_FLAG_NONE);
+
+ // If the write was successful, the handles have been transferred and they
+ // should not be closed when the message is destroyed.
+ if (result == MOJO_RESULT_OK)
+ mojo_message->mutable_handles()->clear();
+
+ DVLOG(4) << "Send " << message->type() << ": " << message->size();
+ return result == MOJO_RESULT_OK;
}
-void MessagePipeReader::OnMessageReceived() {
- Message message(data_buffer().empty() ? "" : &data_buffer()[0],
- static_cast<uint32_t>(data_buffer().size()));
+void MessagePipeReader::Receive(
+ mojo::Array<uint8_t> data,
+ mojo::Array<mojom::SerializedHandlePtr> handles) {
+ Message message(
+ data.size() == 0 ? "" : reinterpret_cast<const char*>(&data[0]),
+ static_cast<uint32_t>(data.size()));
+ message.set_sender_pid(peer_pid_);
- std::vector<MojoHandle> handle_buffer;
- TakeHandleBuffer(&handle_buffer);
+ DVLOG(4) << "Receive " << message.type() << ": " << message.size();
MojoResult write_result =
- ChannelMojo::WriteToMessageAttachmentSet(handle_buffer, &message);
+ ChannelMojo::WriteToMessageAttachmentSet(std::move(handles), &message);
if (write_result != MOJO_RESULT_OK) {
- CloseWithError(write_result);
+ OnPipeError(write_result);
return;
}
TRACE_EVENT_WITH_FLOW0(TRACE_DISABLED_BY_DEFAULT("ipc.flow"),
- "MessagePipeReader::OnMessageReceived",
+ "MessagePipeReader::Receive",
message.flags(),
TRACE_EVENT_FLAG_FLOW_IN);
delegate_->OnMessageReceived(message);
}
-void MessagePipeReader::OnPipeClosed() {
- DCHECK(thread_checker_.CalledOnValidThread());
- if (!delegate_)
- return;
- delegate_->OnPipeClosed(this);
- delegate_ = nullptr;
-}
-
void MessagePipeReader::OnPipeError(MojoResult error) {
DCHECK(thread_checker_.CalledOnValidThread());
- if (!delegate_)
- return;
- delegate_->OnPipeError(this);
-}
-
-MojoResult MessagePipeReader::ReadMessageBytes() {
- DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(handle_buffer_.empty());
-
- uint32_t num_bytes = static_cast<uint32_t>(data_buffer_.size());
- uint32_t num_handles = 0;
- MojoResult result = MojoReadMessage(pipe_.get().value(),
- num_bytes ? &data_buffer_[0] : nullptr,
- &num_bytes,
- nullptr,
- &num_handles,
- MOJO_READ_MESSAGE_FLAG_NONE);
- data_buffer_.resize(num_bytes);
- handle_buffer_.resize(num_handles);
- if (result == MOJO_RESULT_RESOURCE_EXHAUSTED) {
- // MOJO_RESULT_RESOURCE_EXHAUSTED was asking the caller that
- // it needs more bufer. So we re-read it with resized buffers.
- result = MojoReadMessage(pipe_.get().value(),
- num_bytes ? &data_buffer_[0] : nullptr,
- &num_bytes,
- num_handles ? &handle_buffer_[0] : nullptr,
- &num_handles,
- MOJO_READ_MESSAGE_FLAG_NONE);
- }
-
- DCHECK(0 == num_bytes || data_buffer_.size() == num_bytes);
- DCHECK(0 == num_handles || handle_buffer_.size() == num_handles);
- return result;
-}
-
-void MessagePipeReader::ReadAvailableMessages() {
- DCHECK(thread_checker_.CalledOnValidThread());
- while (pipe_.is_valid()) {
- MojoResult read_result = ReadMessageBytes();
- if (read_result == MOJO_RESULT_SHOULD_WAIT)
- break;
- if (read_result != MOJO_RESULT_OK) {
- DLOG(WARNING)
- << "Pipe got error from ReadMessage(). Closing: " << read_result;
- OnPipeError(read_result);
- Close();
- break;
- }
-
- OnMessageReceived();
- }
-
-}
-
-void MessagePipeReader::ReadMessagesThenWait() {
- DCHECK(thread_checker_.CalledOnValidThread());
- while (true) {
- ReadAvailableMessages();
- if (!pipe_.is_valid())
- break;
- // |Wait()| is safe to call only after all messages are read.
- // If can fail with |MOJO_RESULT_ALREADY_EXISTS| otherwise.
- // Also, we don't use MOJO_HANDLE_SIGNAL_WRITABLE here, expecting buffer in
- // MessagePipe.
- MojoResult result =
- async_waiter_->Wait(pipe_.get().value(), MOJO_HANDLE_SIGNAL_READABLE);
- // If the result is |MOJO_RESULT_ALREADY_EXISTS|, there could be messages
- // that have been arrived after the last |ReadAvailableMessages()|.
- // We have to consume then and retry in that case.
- if (result != MOJO_RESULT_ALREADY_EXISTS) {
- if (result != MOJO_RESULT_OK) {
- LOG(ERROR) << "Failed to wait on the pipe. Result is " << result;
- OnPipeError(result);
- Close();
- }
-
- break;
- }
- }
-}
-
-void MessagePipeReader::PipeIsReady(MojoResult wait_result) {
- DCHECK(thread_checker_.CalledOnValidThread());
- CloseWithErrorIfPending();
- if (!IsValid()) {
- // There was a pending error and it closed the pipe.
- // We cannot do the work anymore.
- return;
- }
-
- if (wait_result != MOJO_RESULT_OK) {
- if (wait_result != MOJO_RESULT_ABORTED) {
- // FAILED_PRECONDITION happens every time the peer is dead so
- // it isn't worth polluting the log message.
- LOG_IF(WARNING, wait_result != MOJO_RESULT_FAILED_PRECONDITION)
- << "Pipe got error from the waiter. Closing: " << wait_result;
- OnPipeError(wait_result);
- }
-
- Close();
- return;
- }
-
- ReadMessagesThenWait();
+ if (delegate_)
+ delegate_->OnPipeError();
+ Close();
}
void MessagePipeReader::DelayedDeleter::operator()(
diff --git a/chromium/ipc/mojo/ipc_message_pipe_reader.h b/chromium/ipc/mojo/ipc_message_pipe_reader.h
index 375812305ca..d2ba9dea45d 100644
--- a/chromium/ipc/mojo/ipc_message_pipe_reader.h
+++ b/chromium/ipc/mojo/ipc_message_pipe_reader.h
@@ -16,8 +16,10 @@
#include "base/memory/scoped_ptr.h"
#include "base/threading/thread_checker.h"
#include "ipc/ipc_message.h"
-#include "mojo/public/c/environment/async_waiter.h"
+#include "ipc/mojo/ipc.mojom.h"
+#include "mojo/public/cpp/bindings/associated_binding.h"
#include "mojo/public/cpp/system/core.h"
+#include "mojo/public/cpp/system/message_pipe.h"
namespace IPC {
namespace internal {
@@ -40,13 +42,12 @@ class AsyncHandleWaiter;
// be called on any thread. All |Delegate| functions will be called on the IO
// thread.
//
-class MessagePipeReader {
+class MessagePipeReader : public mojom::Channel {
public:
class Delegate {
public:
- virtual void OnMessageReceived(Message& message) = 0;
- virtual void OnPipeClosed(MessagePipeReader* reader) = 0;
- virtual void OnPipeError(MessagePipeReader* reader) = 0;
+ virtual void OnMessageReceived(const Message& message) = 0;
+ virtual void OnPipeError() = 0;
};
// Delay the object deletion using the current message loop.
@@ -64,61 +65,55 @@ class MessagePipeReader {
void operator()(MessagePipeReader* ptr) const;
};
- // Both parameters must be non-null.
- // Build a reader that reads messages from |handle| and lets |delegate| know.
- // Note that MessagePipeReader doesn't delete |delete|.
- MessagePipeReader(mojo::ScopedMessagePipeHandle handle, Delegate* delegate);
- virtual ~MessagePipeReader();
-
- MojoHandle handle() const { return handle_copy_; }
-
- // Returns received bytes.
- const std::vector<char>& data_buffer() const {
- return data_buffer_;
- }
-
- // Delegate received handles ownership. The subclass should take the
- // ownership over in its OnMessageReceived(). They will leak otherwise.
- void TakeHandleBuffer(std::vector<MojoHandle>* handle_buffer) {
- handle_buffer_.swap(*handle_buffer);
- }
+ // Builds a reader that reads messages from |receive_handle| and lets
+ // |delegate| know.
+ //
+ // |pipe| is the message pipe handle corresponding to the channel's master
+ // interface. This is the message pipe underlying both |sender| and
+ // |receiver|.
+ //
+ // Both |sender| and |receiver| must be non-null.
+ //
+ // Note that MessagePipeReader doesn't delete |delegate|.
+ MessagePipeReader(mojo::MessagePipeHandle pipe,
+ mojom::ChannelAssociatedPtr sender,
+ mojo::AssociatedInterfaceRequest<mojom::Channel> receiver,
+ base::ProcessId peer_pid,
+ Delegate* delegate);
+ ~MessagePipeReader() override;
// Close and destroy the MessagePipe.
void Close();
- // Close the mesage pipe with notifying the client with the error.
- void CloseWithError(MojoResult error);
- void CloseWithErrorLater(MojoResult error);
- void CloseWithErrorIfPending();
// Return true if the MessagePipe is alive.
- bool IsValid() { return pipe_.is_valid(); }
+ bool IsValid() { return sender_; }
+ // Sends an IPC::Message to the other end of the pipe. Safe to call from any
+ // thread.
bool Send(scoped_ptr<Message> message);
- void ReadMessagesThenWait();
- private:
- void OnMessageReceived();
+ base::ProcessId GetPeerPid() const { return peer_pid_; }
+
+ protected:
void OnPipeClosed();
void OnPipeError(MojoResult error);
- MojoResult ReadMessageBytes();
- void PipeIsReady(MojoResult wait_result);
- void ReadAvailableMessages();
-
- std::vector<char> data_buffer_;
- std::vector<MojoHandle> handle_buffer_;
- mojo::ScopedMessagePipeHandle pipe_;
- // Constant copy of the message pipe handle. For use by Send(), which can run
- // concurrently on non-IO threads.
- // TODO(amistry): This isn't quite right because handles can be re-used and
- // using this can run into the ABA problem. Currently, this is highly unlikely
- // because Mojo internally uses an increasing uint32_t as handle values, but
- // this could change. See crbug.com/524894.
- const MojoHandle handle_copy_;
- // |delegate_| and |async_waiter_| are null once the message pipe is closed.
+ private:
+ // mojom::Channel:
+ void Receive(mojo::Array<uint8_t> data,
+ mojo::Array<mojom::SerializedHandlePtr> handles) override;
+
+ // |delegate_| is null once the message pipe is closed.
Delegate* delegate_;
- scoped_ptr<AsyncHandleWaiter> async_waiter_;
- base::subtle::Atomic32 pending_send_error_;
+ base::ProcessId peer_pid_;
+ mojom::ChannelAssociatedPtr sender_;
+ mojo::AssociatedBinding<mojom::Channel> binding_;
+
+ // Raw message pipe handle and interface ID we use to send legacy IPC messages
+ // over the associated pipe.
+ const uint32_t sender_interface_id_;
+ const mojo::MessagePipeHandle sender_pipe_;
+
base::ThreadChecker thread_checker_;
DISALLOW_COPY_AND_ASSIGN(MessagePipeReader);
diff --git a/chromium/ipc/mojo/ipc_mojo.gyp b/chromium/ipc/mojo/ipc_mojo.gyp
index 313ecb2c99c..75c85d9824a 100644
--- a/chromium/ipc/mojo/ipc_mojo.gyp
+++ b/chromium/ipc/mojo/ipc_mojo.gyp
@@ -17,19 +17,15 @@
'defines': [
'IPC_MOJO_IMPLEMENTATION',
],
- 'includes': [ '../../third_party/mojo/mojom_bindings_generator.gypi' ],
+ 'includes': [ '../../mojo/mojom_bindings_generator.gypi' ],
'dependencies': [
'../ipc.gyp:ipc',
'../../base/base.gyp:base',
'../../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
- '../../mojo/mojo_base.gyp:mojo_environment_chromium',
- '../../third_party/mojo/mojo_edk.gyp:mojo_system_impl',
- '../../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings',
+ '../../mojo/mojo_edk.gyp:mojo_system_impl',
+ '../../mojo/mojo_public.gyp:mojo_cpp_bindings',
],
'sources': [
- 'client_channel.mojom',
- 'async_handle_waiter.cc',
- 'async_handle_waiter.h',
'ipc_channel_mojo.cc',
'ipc_channel_mojo.h',
'ipc_mojo_bootstrap.cc',
@@ -42,6 +38,7 @@
'ipc_mojo_param_traits.h',
'ipc_message_pipe_reader.cc',
'ipc_message_pipe_reader.h',
+ 'ipc.mojom',
'scoped_ipc_support.cc',
'scoped_ipc_support.h',
],
@@ -62,19 +59,19 @@
'../../base/base.gyp:base',
'../../base/base.gyp:base_i18n',
'../../base/base.gyp:test_support_base',
- '../../mojo/mojo_base.gyp:mojo_environment_chromium',
+ '../../mojo/mojo_edk.gyp:mojo_common_test_support',
+ '../../mojo/mojo_edk.gyp:mojo_system_impl',
+ '../../mojo/mojo_public.gyp:mojo_cpp_bindings',
'../../testing/gtest.gyp:gtest',
- '../../third_party/mojo/mojo_edk.gyp:mojo_system_impl',
- '../../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings',
'ipc_mojo',
],
'include_dirs': [
'..'
],
'sources': [
- 'async_handle_waiter_unittest.cc',
'run_all_unittests.cc',
- 'ipc_channel_mojo_unittest.cc',
+
+ "ipc_channel_mojo_unittest.cc",
'ipc_mojo_bootstrap_unittest.cc',
],
'conditions': [
@@ -90,10 +87,10 @@
'../../base/base.gyp:base_i18n',
'../../base/base.gyp:test_support_base',
'../../base/base.gyp:test_support_perf',
- '../../mojo/mojo_base.gyp:mojo_environment_chromium',
+ '../../mojo/mojo_edk.gyp:mojo_common_test_support',
+ '../../mojo/mojo_edk.gyp:mojo_system_impl',
+ '../../mojo/mojo_public.gyp:mojo_cpp_bindings',
'../../testing/gtest.gyp:gtest',
- '../../third_party/mojo/mojo_edk.gyp:mojo_system_impl',
- '../../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings',
'ipc_mojo',
],
'include_dirs': [
diff --git a/chromium/ipc/mojo/ipc_mojo_bootstrap.cc b/chromium/ipc/mojo/ipc_mojo_bootstrap.cc
index d2966756605..a80b4610301 100644
--- a/chromium/ipc/mojo/ipc_mojo_bootstrap.cc
+++ b/chromium/ipc/mojo/ipc_mojo_bootstrap.cc
@@ -13,7 +13,9 @@
#include "build/build_config.h"
#include "ipc/ipc_message_utils.h"
#include "ipc/ipc_platform_file.h"
-#include "third_party/mojo/src/mojo/edk/embedder/platform_channel_pair.h"
+#include "mojo/edk/embedder/embedder.h"
+#include "mojo/edk/embedder/platform_channel_pair.h"
+#include "mojo/public/cpp/bindings/binding.h"
namespace IPC {
@@ -26,127 +28,96 @@ class MojoServerBootstrap : public MojoBootstrap {
MojoServerBootstrap();
private:
- void SendClientPipe(int32_t peer_pid);
+ // MojoBootstrap implementation.
+ void Connect() override;
- // Listener implementations
- bool OnMessageReceived(const Message& message) override;
- void OnChannelConnected(int32_t peer_pid) override;
+ void OnInitDone(int32_t peer_pid);
- mojo::embedder::ScopedPlatformHandle server_pipe_;
- bool connected_;
- int32_t peer_pid_;
+ mojom::BootstrapPtr bootstrap_;
+ IPC::mojom::ChannelAssociatedPtrInfo send_channel_;
+ IPC::mojom::ChannelAssociatedRequest receive_channel_request_;
DISALLOW_COPY_AND_ASSIGN(MojoServerBootstrap);
};
-MojoServerBootstrap::MojoServerBootstrap() : connected_(false), peer_pid_(0) {
-}
+MojoServerBootstrap::MojoServerBootstrap() = default;
-void MojoServerBootstrap::SendClientPipe(int32_t peer_pid) {
+void MojoServerBootstrap::Connect() {
DCHECK_EQ(state(), STATE_INITIALIZED);
- DCHECK(connected_);
-
- mojo::embedder::PlatformChannelPair channel_pair;
- server_pipe_ = channel_pair.PassServerHandle();
-
- base::Process peer_process =
-#if defined(OS_WIN)
- base::Process::OpenWithAccess(peer_pid, PROCESS_DUP_HANDLE);
-#else
- base::Process::Open(peer_pid);
-#endif
- PlatformFileForTransit client_pipe = GetFileHandleForProcess(
-#if defined(OS_POSIX)
- channel_pair.PassClientHandle().release().fd,
-#else
- channel_pair.PassClientHandle().release().handle,
-#endif
- peer_process.Handle(), true);
- if (client_pipe == IPC::InvalidPlatformFileForTransit()) {
-#if !defined(OS_WIN)
- // GetFileHandleForProcess() only fails on Windows.
- NOTREACHED();
-#endif
- LOG(WARNING) << "Failed to translate file handle for client process.";
- Fail();
- return;
- }
- scoped_ptr<Message> message(new Message());
- ParamTraits<PlatformFileForTransit>::Write(message.get(), client_pipe);
- Send(message.release());
+ bootstrap_.Bind(mojom::BootstrapPtrInfo(TakeHandle(), 0));
+ bootstrap_.set_connection_error_handler(
+ base::Bind(&MojoServerBootstrap::Fail, base::Unretained(this)));
- set_state(STATE_WAITING_ACK);
-}
+ IPC::mojom::ChannelAssociatedRequest send_channel_request;
+ IPC::mojom::ChannelAssociatedPtrInfo receive_channel;
-void MojoServerBootstrap::OnChannelConnected(int32_t peer_pid) {
- DCHECK_EQ(state(), STATE_INITIALIZED);
- connected_ = true;
- peer_pid_ = peer_pid;
- SendClientPipe(peer_pid);
+ bootstrap_.associated_group()->CreateAssociatedInterface(
+ mojo::AssociatedGroup::WILL_PASS_REQUEST, &send_channel_,
+ &send_channel_request);
+ bootstrap_.associated_group()->CreateAssociatedInterface(
+ mojo::AssociatedGroup::WILL_PASS_PTR, &receive_channel,
+ &receive_channel_request_);
+
+ bootstrap_->Init(
+ std::move(send_channel_request), std::move(receive_channel),
+ GetSelfPID(),
+ base::Bind(&MojoServerBootstrap::OnInitDone, base::Unretained(this)));
+
+ set_state(STATE_WAITING_ACK);
}
-bool MojoServerBootstrap::OnMessageReceived(const Message&) {
+void MojoServerBootstrap::OnInitDone(int32_t peer_pid) {
if (state() != STATE_WAITING_ACK) {
set_state(STATE_ERROR);
LOG(ERROR) << "Got inconsistent message from client.";
- return false;
+ return;
}
set_state(STATE_READY);
- CHECK(server_pipe_.is_valid());
- delegate()->OnPipeAvailable(
- mojo::embedder::ScopedPlatformHandle(server_pipe_.release()), peer_pid_);
-
- return true;
+ bootstrap_.set_connection_error_handler(mojo::Closure());
+ delegate()->OnPipesAvailable(std::move(send_channel_),
+ std::move(receive_channel_request_), peer_pid);
}
// MojoBootstrap for client processes. You should create the instance
// using MojoBootstrap::Create().
-class MojoClientBootstrap : public MojoBootstrap {
+class MojoClientBootstrap : public MojoBootstrap, public mojom::Bootstrap {
public:
MojoClientBootstrap();
private:
- // Listener implementations
- bool OnMessageReceived(const Message& message) override;
- void OnChannelConnected(int32_t peer_pid) override;
+ // MojoBootstrap implementation.
+ void Connect() override;
- int32_t peer_pid_;
+ // mojom::Bootstrap implementation.
+ void Init(mojom::ChannelAssociatedRequest receive_channel,
+ mojom::ChannelAssociatedPtrInfo send_channel,
+ int32_t peer_pid,
+ const mojo::Callback<void(int32_t)>& callback) override;
+
+ mojo::Binding<mojom::Bootstrap> binding_;
DISALLOW_COPY_AND_ASSIGN(MojoClientBootstrap);
};
-MojoClientBootstrap::MojoClientBootstrap() : peer_pid_(0) {
-}
-
-bool MojoClientBootstrap::OnMessageReceived(const Message& message) {
- if (state() != STATE_INITIALIZED) {
- set_state(STATE_ERROR);
- LOG(ERROR) << "Got inconsistent message from server.";
- return false;
- }
+MojoClientBootstrap::MojoClientBootstrap() : binding_(this) {}
- PlatformFileForTransit pipe;
- base::PickleIterator iter(message);
- if (!ParamTraits<PlatformFileForTransit>::Read(&message, &iter, &pipe)) {
- LOG(WARNING) << "Failed to read a file handle from bootstrap channel.";
- message.set_dispatch_error();
- return false;
- }
-
- // Sends ACK back.
- Send(new Message());
- set_state(STATE_READY);
- delegate()->OnPipeAvailable(
- mojo::embedder::ScopedPlatformHandle(mojo::embedder::PlatformHandle(
- PlatformFileForTransitToPlatformFile(pipe))), peer_pid_);
-
- return true;
+void MojoClientBootstrap::Connect() {
+ binding_.Bind(TakeHandle());
+ binding_.set_connection_error_handler(
+ base::Bind(&MojoClientBootstrap::Fail, base::Unretained(this)));
}
-void MojoClientBootstrap::OnChannelConnected(int32_t peer_pid) {
- peer_pid_ = peer_pid;
+void MojoClientBootstrap::Init(mojom::ChannelAssociatedRequest receive_channel,
+ mojom::ChannelAssociatedPtrInfo send_channel,
+ int32_t peer_pid,
+ const mojo::Callback<void(int32_t)>& callback) {
+ callback.Run(GetSelfPID());
+ set_state(STATE_READY);
+ binding_.set_connection_error_handler(mojo::Closure());
+ delegate()->OnPipesAvailable(std::move(send_channel),
+ std::move(receive_channel), peer_pid);
}
} // namespace
@@ -154,49 +125,37 @@ void MojoClientBootstrap::OnChannelConnected(int32_t peer_pid) {
// MojoBootstrap
// static
-scoped_ptr<MojoBootstrap> MojoBootstrap::Create(ChannelHandle handle,
- Channel::Mode mode,
- Delegate* delegate) {
+scoped_ptr<MojoBootstrap> MojoBootstrap::Create(
+ mojo::ScopedMessagePipeHandle handle,
+ 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());
- scoped_ptr<Channel> bootstrap_channel =
- Channel::Create(handle, mode, self.get());
- self->Init(std::move(bootstrap_channel), delegate);
+ self->Init(std::move(handle), delegate);
return self;
}
MojoBootstrap::MojoBootstrap() : delegate_(NULL), state_(STATE_INITIALIZED) {
}
-MojoBootstrap::~MojoBootstrap() {
-}
+MojoBootstrap::~MojoBootstrap() {}
-void MojoBootstrap::Init(scoped_ptr<Channel> channel, Delegate* delegate) {
- channel_ = std::move(channel);
+void MojoBootstrap::Init(mojo::ScopedMessagePipeHandle handle,
+ Delegate* delegate) {
+ handle_ = std::move(handle);
delegate_ = delegate;
}
-bool MojoBootstrap::Connect() {
- return channel_->Connect();
-}
-
base::ProcessId MojoBootstrap::GetSelfPID() const {
- return channel_->GetSelfPID();
-}
-
-void MojoBootstrap::OnBadMessageReceived(const Message& message) {
- Fail();
-}
-
-void MojoBootstrap::OnChannelError() {
- if (state_ == STATE_READY || state_ == STATE_ERROR)
- return;
- DLOG(WARNING) << "Detected error on Mojo bootstrap channel.";
- Fail();
+#if defined(OS_LINUX)
+ if (int global_pid = Channel::GetGlobalPid())
+ return global_pid;
+#endif // OS_LINUX
+ return base::GetCurrentProcId();
}
void MojoBootstrap::Fail() {
@@ -208,18 +167,8 @@ bool MojoBootstrap::HasFailed() const {
return state() == STATE_ERROR;
}
-bool MojoBootstrap::Send(Message* message) {
- return channel_->Send(message);
-}
-
-#if defined(OS_POSIX) && !defined(OS_NACL)
-int MojoBootstrap::GetClientFileDescriptor() const {
- return channel_->GetClientFileDescriptor();
-}
-
-base::ScopedFD MojoBootstrap::TakeClientFileDescriptor() {
- return channel_->TakeClientFileDescriptor();
+mojo::ScopedMessagePipeHandle MojoBootstrap::TakeHandle() {
+ return std::move(handle_);
}
-#endif // defined(OS_POSIX) && !defined(OS_NACL)
} // namespace IPC
diff --git a/chromium/ipc/mojo/ipc_mojo_bootstrap.h b/chromium/ipc/mojo/ipc_mojo_bootstrap.h
index 4b5ccfb71e9..23e0e9193b7 100644
--- a/chromium/ipc/mojo/ipc_mojo_bootstrap.h
+++ b/chromium/ipc/mojo/ipc_mojo_bootstrap.h
@@ -13,50 +13,46 @@
#include "build/build_config.h"
#include "ipc/ipc_channel.h"
#include "ipc/ipc_listener.h"
-#include "third_party/mojo/src/mojo/edk/embedder/scoped_platform_handle.h"
+#include "ipc/mojo/ipc.mojom.h"
+#include "mojo/edk/embedder/scoped_platform_handle.h"
+#include "mojo/public/cpp/system/message_pipe.h"
namespace IPC {
-// MojoBootstrap establishes a bootstrap pipe between two processes in
-// Chrome. It creates a native IPC::Channel first, then sends one
-// side of a newly created pipe to peer process. The pipe is intended
-// to be wrapped by Mojo MessagePipe.
+// MojoBootstrap establishes a pair of associated interfaces between two
+// processes in Chrome.
//
-// Clients should implement MojoBootstrapDelegate to get the pipe
+// Clients should implement MojoBootstrap::Delegate to get the associated pipes
// from MojoBootstrap object.
//
// This lives on IO thread other than Create(), which can be called from
// UI thread as Channel::Create() can be.
-class IPC_MOJO_EXPORT MojoBootstrap : public Listener {
+class IPC_MOJO_EXPORT MojoBootstrap {
public:
class Delegate {
public:
- virtual void OnPipeAvailable(mojo::embedder::ScopedPlatformHandle handle,
- int32_t peer_pid) = 0;
+ virtual void OnPipesAvailable(
+ mojom::ChannelAssociatedPtrInfo send_channel,
+ mojom::ChannelAssociatedRequest receive_channel,
+ int32_t peer_pid) = 0;
virtual void OnBootstrapError() = 0;
};
- // Create the MojoBootstrap instance.
- // Instead of creating IPC::Channel, passs its ChannelHandle as |handle|,
- // mode as |mode|. The result is notified to passed |delegate|.
- static scoped_ptr<MojoBootstrap> Create(ChannelHandle handle,
+ // 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,
Channel::Mode mode,
Delegate* delegate);
MojoBootstrap();
- ~MojoBootstrap() override;
+ virtual ~MojoBootstrap();
- // Start the handshake over the underlying platform channel.
- bool Connect();
+ // Start the handshake over the underlying message pipe.
+ virtual void Connect() = 0;
- // GetSelfPID returns the PID associated with |channel_|.
+ // GetSelfPID returns our PID.
base::ProcessId GetSelfPID() const;
-#if defined(OS_POSIX) && !defined(OS_NACL)
- int GetClientFileDescriptor() const;
- base::ScopedFD TakeClientFileDescriptor();
-#endif // defined(OS_POSIX) && !defined(OS_NACL)
-
protected:
// On MojoServerBootstrap: INITIALIZED -> WAITING_ACK -> READY
// On MojoClientBootstrap: INITIALIZED -> READY
@@ -64,21 +60,18 @@ class IPC_MOJO_EXPORT MojoBootstrap : public Listener {
enum State { STATE_INITIALIZED, STATE_WAITING_ACK, STATE_READY, STATE_ERROR };
Delegate* delegate() const { return delegate_; }
- bool Send(Message* message);
void Fail();
bool HasFailed() const;
State state() const { return state_; }
void set_state(State state) { state_ = state; }
- private:
- void Init(scoped_ptr<Channel> channel, Delegate* delegate);
+ mojo::ScopedMessagePipeHandle TakeHandle();
- // Listener implementations
- void OnBadMessageReceived(const Message& message) override;
- void OnChannelError() override;
+ private:
+ void Init(mojo::ScopedMessagePipeHandle, Delegate* delegate);
- scoped_ptr<Channel> channel_;
+ mojo::ScopedMessagePipeHandle handle_;
Delegate* delegate_;
State state_;
diff --git a/chromium/ipc/mojo/ipc_mojo_bootstrap_unittest.cc b/chromium/ipc/mojo/ipc_mojo_bootstrap_unittest.cc
index 60046d16c52..d702a6ae7b8 100644
--- a/chromium/ipc/mojo/ipc_mojo_bootstrap_unittest.cc
+++ b/chromium/ipc/mojo/ipc_mojo_bootstrap_unittest.cc
@@ -9,8 +9,14 @@
#include "base/base_paths.h"
#include "base/files/file.h"
#include "base/message_loop/message_loop.h"
+#include "base/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "ipc/ipc_test_base.h"
+#include "ipc/mojo/ipc.mojom.h"
+#include "mojo/edk/embedder/embedder.h"
+#include "mojo/edk/test/mojo_test_base.h"
+#include "mojo/edk/test/multiprocess_test_helper.h"
+#include "mojo/edk/test/scoped_ipc_support.h"
#if defined(OS_POSIX)
#include "base/file_descriptor_posix.h"
@@ -18,33 +24,38 @@
namespace {
-class IPCMojoBootstrapTest : public IPCTestBase {
+class IPCMojoBootstrapTest : public testing::Test {
protected:
+ mojo::edk::test::MultiprocessTestHelper helper_;
};
class TestingDelegate : public IPC::MojoBootstrap::Delegate {
public:
- TestingDelegate() : passed_(false) {}
+ explicit TestingDelegate(const base::Closure& quit_callback)
+ : passed_(false), quit_callback_(quit_callback) {}
- void OnPipeAvailable(mojo::embedder::ScopedPlatformHandle handle,
- int32_t peer_pid) override;
+ void OnPipesAvailable(IPC::mojom::ChannelAssociatedPtrInfo send_channel,
+ IPC::mojom::ChannelAssociatedRequest receive_channel,
+ int32_t peer_pid) override;
void OnBootstrapError() override;
bool passed() const { return passed_; }
private:
bool passed_;
+ const base::Closure quit_callback_;
};
-void TestingDelegate::OnPipeAvailable(
- mojo::embedder::ScopedPlatformHandle handle,
+void TestingDelegate::OnPipesAvailable(
+ IPC::mojom::ChannelAssociatedPtrInfo send_channel,
+ IPC::mojom::ChannelAssociatedRequest receive_channel,
int32_t peer_pid) {
passed_ = true;
- base::MessageLoop::current()->QuitWhenIdle();
+ quit_callback_.Run();
}
void TestingDelegate::OnBootstrapError() {
- base::MessageLoop::current()->QuitWhenIdle();
+ quit_callback_.Run();
}
// Times out on Android; see http://crbug.com/502290
@@ -54,41 +65,37 @@ void TestingDelegate::OnBootstrapError() {
#define MAYBE_Connect Connect
#endif
TEST_F(IPCMojoBootstrapTest, MAYBE_Connect) {
- Init("IPCMojoBootstrapTestClient");
-
- TestingDelegate delegate;
+ base::MessageLoop message_loop;
+ base::RunLoop run_loop;
+ TestingDelegate delegate(run_loop.QuitClosure());
scoped_ptr<IPC::MojoBootstrap> bootstrap = IPC::MojoBootstrap::Create(
- GetTestChannelHandle(), IPC::Channel::MODE_SERVER, &delegate);
-
- ASSERT_TRUE(bootstrap->Connect());
-#if defined(OS_POSIX)
- ASSERT_TRUE(StartClientWithFD(bootstrap->GetClientFileDescriptor()));
-#else
- ASSERT_TRUE(StartClient());
-#endif
+ helper_.StartChild("IPCMojoBootstrapTestClient"),
+ IPC::Channel::MODE_SERVER, &delegate);
- base::MessageLoop::current()->Run();
+ bootstrap->Connect();
+ run_loop.Run();
EXPECT_TRUE(delegate.passed());
- EXPECT_TRUE(WaitForClientShutdown());
+ EXPECT_TRUE(helper_.WaitForChildTestShutdown());
}
// A long running process that connects to us.
-MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCMojoBootstrapTestClient) {
- base::MessageLoopForIO main_message_loop;
-
- TestingDelegate delegate;
+MULTIPROCESS_TEST_MAIN_WITH_SETUP(
+ IPCMojoBootstrapTestClientTestChildMain,
+ ::mojo::edk::test::MultiprocessTestHelper::ChildSetup) {
+ base::MessageLoop message_loop;
+ base::RunLoop run_loop;
+ TestingDelegate delegate(run_loop.QuitClosure());
scoped_ptr<IPC::MojoBootstrap> bootstrap = IPC::MojoBootstrap::Create(
- IPCTestBase::GetChannelName("IPCMojoBootstrapTestClient"),
+ mojo::edk::CreateChildMessagePipe(
+ mojo::edk::test::MultiprocessTestHelper::primordial_pipe_token),
IPC::Channel::MODE_CLIENT, &delegate);
bootstrap->Connect();
- base::MessageLoop::current()->Run();
-
- EXPECT_TRUE(delegate.passed());
+ run_loop.Run();
- return 0;
+ return delegate.passed() ? 0 : 1;
}
} // namespace
diff --git a/chromium/ipc/mojo/ipc_mojo_handle_attachment.cc b/chromium/ipc/mojo/ipc_mojo_handle_attachment.cc
index 70b80c57b13..b2e16f121c5 100644
--- a/chromium/ipc/mojo/ipc_mojo_handle_attachment.cc
+++ b/chromium/ipc/mojo/ipc_mojo_handle_attachment.cc
@@ -8,7 +8,7 @@
#include "build/build_config.h"
#include "ipc/ipc_message_attachment_set.h"
-#include "third_party/mojo/src/mojo/edk/embedder/embedder.h"
+#include "mojo/edk/embedder/embedder.h"
namespace IPC {
namespace internal {
@@ -25,16 +25,15 @@ MessageAttachment::Type MojoHandleAttachment::GetType() const {
#if defined(OS_POSIX)
base::PlatformFile MojoHandleAttachment::TakePlatformFile() {
- mojo::embedder::ScopedPlatformHandle platform_handle;
- MojoResult unwrap_result = mojo::embedder::PassWrappedPlatformHandle(
- handle_.get().value(), &platform_handle);
- handle_.reset();
+ mojo::edk::ScopedPlatformHandle platform_handle;
+ MojoResult unwrap_result = mojo::edk::PassWrappedPlatformHandle(
+ handle_.release().value(), &platform_handle);
if (unwrap_result != MOJO_RESULT_OK) {
LOG(ERROR) << "Pipe failed to covert handles. Closing: " << unwrap_result;
return -1;
}
- return platform_handle.release().fd;
+ return platform_handle.release().handle;
}
#endif // OS_POSIX
diff --git a/chromium/ipc/mojo/ipc_mojo_message_helper.cc b/chromium/ipc/mojo/ipc_mojo_message_helper.cc
index 8b8344ec766..ae5e83a2cdb 100644
--- a/chromium/ipc/mojo/ipc_mojo_message_helper.cc
+++ b/chromium/ipc/mojo/ipc_mojo_message_helper.cc
@@ -12,7 +12,7 @@ namespace IPC {
// static
bool MojoMessageHelper::WriteMessagePipeTo(
- Message* message,
+ base::Pickle* message,
mojo::ScopedMessagePipeHandle handle) {
message->WriteAttachment(new internal::MojoHandleAttachment(
mojo::ScopedHandle::From(std::move(handle))));
@@ -21,17 +21,19 @@ bool MojoMessageHelper::WriteMessagePipeTo(
// static
bool MojoMessageHelper::ReadMessagePipeFrom(
- const Message* message,
+ const base::Pickle* message,
base::PickleIterator* iter,
mojo::ScopedMessagePipeHandle* handle) {
- scoped_refptr<MessageAttachment> attachment;
+ scoped_refptr<base::Pickle::Attachment> attachment;
if (!message->ReadAttachment(iter, &attachment)) {
LOG(ERROR) << "Failed to read attachment for message pipe.";
return false;
}
- if (attachment->GetType() != MessageAttachment::TYPE_MOJO_HANDLE) {
- LOG(ERROR) << "Unxpected attachment type:" << attachment->GetType();
+ MessageAttachment::Type type =
+ static_cast<MessageAttachment*>(attachment.get())->GetType();
+ if (type != MessageAttachment::TYPE_MOJO_HANDLE) {
+ LOG(ERROR) << "Unxpected attachment type:" << type;
return false;
}
diff --git a/chromium/ipc/mojo/ipc_mojo_message_helper.h b/chromium/ipc/mojo/ipc_mojo_message_helper.h
index 3dc840e92e3..e0e44d075d0 100644
--- a/chromium/ipc/mojo/ipc_mojo_message_helper.h
+++ b/chromium/ipc/mojo/ipc_mojo_message_helper.h
@@ -14,9 +14,9 @@ namespace IPC {
// Reads and writes |mojo::MessagePipe| from/to |Message|.
class IPC_MOJO_EXPORT MojoMessageHelper {
public:
- static bool WriteMessagePipeTo(Message* message,
+ static bool WriteMessagePipeTo(base::Pickle* message,
mojo::ScopedMessagePipeHandle handle);
- static bool ReadMessagePipeFrom(const Message* message,
+ static bool ReadMessagePipeFrom(const base::Pickle* message,
base::PickleIterator* iter,
mojo::ScopedMessagePipeHandle* handle);
diff --git a/chromium/ipc/mojo/ipc_mojo_perftest.cc b/chromium/ipc/mojo/ipc_mojo_perftest.cc
index d782c77ee59..b1c6c86b6c7 100644
--- a/chromium/ipc/mojo/ipc_mojo_perftest.cc
+++ b/chromium/ipc/mojo/ipc_mojo_perftest.cc
@@ -4,55 +4,45 @@
#include <stddef.h>
-#include "base/lazy_instance.h"
#include "base/run_loop.h"
+#include "base/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "ipc/ipc_perftest_support.h"
#include "ipc/mojo/ipc_channel_mojo.h"
-#include "third_party/mojo/src/mojo/edk/embedder/embedder.h"
-#include "third_party/mojo/src/mojo/edk/embedder/platform_channel_pair.h"
+#include "mojo/edk/embedder/embedder.h"
+#include "mojo/edk/embedder/platform_channel_pair.h"
+#include "mojo/edk/test/multiprocess_test_helper.h"
+#include "mojo/edk/test/scoped_ipc_support.h"
+namespace IPC {
namespace {
-// This is needed because we rely on //base/test:test_support_perf and
-// it provides main() which doesn't have Mojo initialization. We need
-// some way to call Init() only once before using Mojo.
-struct MojoInitialier {
- MojoInitialier() {
- mojo::embedder::Init();
- }
-};
-
-base::LazyInstance<MojoInitialier> g_mojo_initializer
- = LAZY_INSTANCE_INITIALIZER;
-
-class MojoChannelPerfTest : public IPC::test::IPCChannelPerfTestBase {
-public:
- typedef IPC::test::IPCChannelPerfTestBase Super;
-
- MojoChannelPerfTest();
-
+class MojoChannelPerfTest : public test::IPCChannelPerfTestBase {
+ public:
void TearDown() override {
- IPC::test::IPCChannelPerfTestBase::TearDown();
+ ipc_support_.reset();
+ test::IPCChannelPerfTestBase::TearDown();
}
- scoped_ptr<IPC::ChannelFactory> CreateChannelFactory(
- const IPC::ChannelHandle& handle,
+ scoped_ptr<ChannelFactory> CreateChannelFactory(
+ const ChannelHandle& handle,
base::SequencedTaskRunner* runner) override {
- return IPC::ChannelMojo::CreateServerFactory(runner, handle);
+ ipc_support_.reset(new mojo::edk::test::ScopedIPCSupport(io_task_runner()));
+ return ChannelMojo::CreateServerFactory(
+ helper_.StartChild("MojoPerfTestClient"));
}
- bool DidStartClient() override {
- bool ok = IPCTestBase::DidStartClient();
- DCHECK(ok);
- return ok;
+ bool StartClient() override {
+ return true;
}
-};
-MojoChannelPerfTest::MojoChannelPerfTest() {
- g_mojo_initializer.Get();
-}
+ bool WaitForClientShutdown() override {
+ return helper_.WaitForChildTestShutdown();
+ }
+ mojo::edk::test::MultiprocessTestHelper helper_;
+ scoped_ptr<mojo::edk::test::ScopedIPCSupport> ipc_support_;
+};
TEST_F(MojoChannelPerfTest, ChannelPingPong) {
RunTestChannelPingPong(GetDefaultTestParams());
@@ -75,36 +65,47 @@ TEST_F(MojoChannelPerfTest, DISABLED_MaxChannelCount) {
base::SetFdLimit(20000);
#endif
- std::vector<mojo::embedder::PlatformChannelPair*> channels;
+ std::vector<mojo::edk::PlatformChannelPair*> channels;
for (size_t i = 0; i < 10000; ++i) {
LOG(INFO) << "channels size: " << channels.size();
- channels.push_back(new mojo::embedder::PlatformChannelPair());
+ channels.push_back(new mojo::edk::PlatformChannelPair());
}
}
-class MojoTestClient : public IPC::test::PingPongTestClient {
+class MojoPerfTestClient : public test::PingPongTestClient {
public:
- typedef IPC::test::PingPongTestClient SuperType;
+ typedef test::PingPongTestClient SuperType;
+
+ MojoPerfTestClient();
- MojoTestClient();
+ scoped_ptr<Channel> CreateChannel(Listener* listener) override;
- scoped_ptr<IPC::Channel> CreateChannel(IPC::Listener* listener) override;
+ int Run(MojoHandle handle);
+
+ private:
+ mojo::edk::test::ScopedIPCSupport ipc_support_;
+ mojo::ScopedMessagePipeHandle handle_;
};
-MojoTestClient::MojoTestClient() {
- g_mojo_initializer.Get();
+MojoPerfTestClient::MojoPerfTestClient()
+ : ipc_support_(base::ThreadTaskRunnerHandle::Get()) {
+ mojo::edk::test::MultiprocessTestHelper::ChildSetup();
+}
+
+scoped_ptr<Channel> MojoPerfTestClient::CreateChannel(Listener* listener) {
+ return scoped_ptr<Channel>(
+ ChannelMojo::Create(std::move(handle_), Channel::MODE_CLIENT, listener));
}
-scoped_ptr<IPC::Channel> MojoTestClient::CreateChannel(
- IPC::Listener* listener) {
- return scoped_ptr<IPC::Channel>(IPC::ChannelMojo::Create(
- task_runner(), IPCTestBase::GetChannelName("PerformanceClient"),
- IPC::Channel::MODE_CLIENT, listener));
+int MojoPerfTestClient::Run(MojoHandle handle) {
+ handle_ = mojo::MakeScopedHandle(mojo::MessagePipeHandle(handle));
+ return RunMain();
}
-MULTIPROCESS_IPC_TEST_CLIENT_MAIN(PerformanceClient) {
- MojoTestClient client;
- int rv = client.RunMain();
+MULTIPROCESS_TEST_MAIN(MojoPerfTestClientTestChildMain) {
+ MojoPerfTestClient client;
+ int rv = mojo::edk::test::MultiprocessTestHelper::RunClientMain(
+ base::Bind(&MojoPerfTestClient::Run, base::Unretained(&client)));
base::RunLoop run_loop;
run_loop.RunUntilIdle();
@@ -113,3 +114,4 @@ MULTIPROCESS_IPC_TEST_CLIENT_MAIN(PerformanceClient) {
}
} // namespace
+} // namespace IPC
diff --git a/chromium/ipc/mojo/run_all_perftests.cc b/chromium/ipc/mojo/run_all_perftests.cc
new file mode 100644
index 00000000000..a942b8b5749
--- /dev/null
+++ b/chromium/ipc/mojo/run_all_perftests.cc
@@ -0,0 +1,17 @@
+// Copyright 2013 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.
+
+// Copied from mojo/edk/test/run_all_perftests.cc.
+
+#include "base/command_line.h"
+#include "base/test/perf_test_suite.h"
+#include "mojo/edk/embedder/embedder.h"
+
+int main(int argc, char** argv) {
+ base::PerfTestSuite test(argc, argv);
+
+ mojo::edk::Init();
+
+ return test.Run();
+}
diff --git a/chromium/ipc/mojo/run_all_unittests.cc b/chromium/ipc/mojo/run_all_unittests.cc
index 43a1e4e0e8d..4416932e731 100644
--- a/chromium/ipc/mojo/run_all_unittests.cc
+++ b/chromium/ipc/mojo/run_all_unittests.cc
@@ -5,9 +5,11 @@
#include "base/at_exit.h"
#include "base/bind.h"
#include "base/test/launcher/unit_test_launcher.h"
+#include "base/test/test_io_thread.h"
#include "base/test/test_suite.h"
#include "build/build_config.h"
-#include "third_party/mojo/src/mojo/edk/embedder/embedder.h"
+#include "mojo/edk/embedder/embedder.h"
+#include "mojo/edk/test/scoped_ipc_support.h"
#if defined(OS_ANDROID)
#include "base/android/jni_android.h"
@@ -20,7 +22,12 @@ int main(int argc, char** argv) {
base::RegisterContentUriTestUtils(env);
#endif
base::TestSuite test_suite(argc, argv);
- mojo::embedder::Init();
+ mojo::edk::Init();
+ base::TestIOThread test_io_thread(base::TestIOThread::kAutoStart);
+ // Leak this because its destructor calls mojo::edk::ShutdownIPCSupport which
+ // really does nothing in the new EDK but does depend on the current message
+ // loop, which is destructed inside base::LaunchUnitTests.
+ new mojo::edk::test::ScopedIPCSupport(test_io_thread.task_runner());
return base::LaunchUnitTestsSerially(
argc, argv,
base::Bind(&base::TestSuite::Run, base::Unretained(&test_suite)));
diff --git a/chromium/ipc/mojo/scoped_ipc_support.cc b/chromium/ipc/mojo/scoped_ipc_support.cc
index 15575444e64..65947bece9c 100644
--- a/chromium/ipc/mojo/scoped_ipc_support.cc
+++ b/chromium/ipc/mojo/scoped_ipc_support.cc
@@ -4,156 +4,44 @@
#include "ipc/mojo/scoped_ipc_support.h"
-#include <stddef.h>
-
-#include "base/bind.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/macros.h"
-#include "base/message_loop/message_loop.h"
-#include "base/synchronization/condition_variable.h"
-#include "base/synchronization/lock.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/thread_task_runner_handle.h"
-#include "third_party/mojo/src/mojo/edk/embedder/embedder.h"
-#include "third_party/mojo/src/mojo/edk/embedder/process_delegate.h"
+#include "mojo/edk/embedder/embedder.h"
+#include "mojo/edk/embedder/process_delegate.h"
namespace IPC {
namespace {
-// TODO(use_chrome_edk)
-//class IPCSupportInitializer : public mojo::edk::ProcessDelegate {
-class IPCSupportInitializer : public mojo::embedder::ProcessDelegate {
+class IPCSupportInitializer : public mojo::edk::ProcessDelegate {
public:
- IPCSupportInitializer()
- : init_count_(0),
- shutting_down_(false),
- was_shut_down_(false),
- observer_(nullptr) {}
-
- ~IPCSupportInitializer() override { DCHECK(!observer_); }
-
- void Init(scoped_refptr<base::TaskRunner> io_thread_task_runner);
- void ShutDown(bool force);
-
- private:
- // This watches for destruction of the MessageLoop that IPCSupportInitializer
- // uses for IO, and guarantees that the initializer is shut down if it still
- // exists when the loop is being destroyed.
- class MessageLoopObserver : public base::MessageLoop::DestructionObserver {
- public:
- MessageLoopObserver(IPCSupportInitializer* initializer)
- : initializer_(initializer) {}
-
- ~MessageLoopObserver() override {
- base::MessageLoop::current()->RemoveDestructionObserver(this);
- }
-
- private:
- // base::MessageLoop::DestructionObserver:
- void WillDestroyCurrentMessageLoop() override {
- initializer_->ShutDown(true);
- }
-
- IPCSupportInitializer* initializer_;
-
- DISALLOW_COPY_AND_ASSIGN(MessageLoopObserver);
- };
-
- void ShutDownOnIOThread();
-
- // mojo::embedder::ProcessDelegate:
- void OnShutdownComplete() override {}
-
- static void WatchMessageLoopOnIOThread(MessageLoopObserver* observer);
-
- base::Lock lock_;
- size_t init_count_;
- bool shutting_down_;
-
- // This is used to track whether shutdown has occurred yet, since we can be
- // shut down by either the scoper or IO MessageLoop destruction.
- bool was_shut_down_;
-
- // The message loop destruction observer we have watching our IO loop. This
- // is created on the initializer's own thread but is used and destroyed on the
- // IO thread.
- MessageLoopObserver* observer_;
-
- scoped_refptr<base::TaskRunner> io_thread_task_runner_;
+ IPCSupportInitializer() {}
+ ~IPCSupportInitializer() override {}
- DISALLOW_COPY_AND_ASSIGN(IPCSupportInitializer);
-};
-
-void IPCSupportInitializer::Init(
- scoped_refptr<base::TaskRunner> io_thread_task_runner) {
- base::AutoLock locker(lock_);
- DCHECK((init_count_ == 0 && !io_thread_task_runner_) ||
- io_thread_task_runner_ == io_thread_task_runner);
-
- if (shutting_down_) {
- // If reinitialized before a pending shutdown task is executed, we
- // effectively cancel the shutdown task.
- DCHECK(init_count_ == 1);
- shutting_down_ = false;
- return;
- }
-
- init_count_++;
- if (init_count_ == 1) {
- was_shut_down_ = false;
- observer_ = new MessageLoopObserver(this);
+ void Init(scoped_refptr<base::TaskRunner> io_thread_task_runner) {
+ CHECK(!io_thread_task_runner_);
+ CHECK(io_thread_task_runner);
io_thread_task_runner_ = io_thread_task_runner;
- io_thread_task_runner_->PostTask(
- FROM_HERE, base::Bind(&WatchMessageLoopOnIOThread, observer_));
- mojo::embedder::InitIPCSupport(
- mojo::embedder::ProcessType::NONE, this, io_thread_task_runner_,
- mojo::embedder::ScopedPlatformHandle());
- }
-}
-void IPCSupportInitializer::ShutDown(bool force) {
- base::AutoLock locker(lock_);
- if (shutting_down_ || was_shut_down_)
- return;
- DCHECK(init_count_ > 0);
- if (init_count_ > 1 && !force) {
- init_count_--;
- return;
+ mojo::edk::InitIPCSupport(this, io_thread_task_runner_);
}
- shutting_down_ = true;
- if (base::MessageLoop::current() &&
- base::MessageLoop::current()->task_runner() == io_thread_task_runner_) {
- base::AutoUnlock unlocker_(lock_);
- ShutDownOnIOThread();
- } else {
- io_thread_task_runner_->PostTask(
- FROM_HERE, base::Bind(&IPCSupportInitializer::ShutDownOnIOThread,
- base::Unretained(this)));
+ void ShutDown() {
+ CHECK(io_thread_task_runner_);
+ mojo::edk::ShutdownIPCSupport();
}
-}
-void IPCSupportInitializer::ShutDownOnIOThread() {
- base::AutoLock locker(lock_);
- if (shutting_down_ && !was_shut_down_) {
- mojo::embedder::ShutdownIPCSupportOnIOThread();
- init_count_ = 0;
- shutting_down_ = false;
- io_thread_task_runner_ = nullptr;
- was_shut_down_ = true;
- if (observer_) {
- delete observer_;
- observer_ = nullptr;
- }
+ private:
+ // mojo::edk::ProcessDelegate:
+ void OnShutdownComplete() override {
+ // TODO(rockot): We should ensure that IO runner shutdown is blocked until
+ // this is called.
}
-}
-// static
-void IPCSupportInitializer::WatchMessageLoopOnIOThread(
- MessageLoopObserver* observer) {
- base::MessageLoop::current()->AddDestructionObserver(observer);
-}
+ scoped_refptr<base::TaskRunner> io_thread_task_runner_;
+
+ DISALLOW_COPY_AND_ASSIGN(IPCSupportInitializer);
+};
base::LazyInstance<IPCSupportInitializer>::Leaky ipc_support_initializer;
@@ -165,7 +53,7 @@ ScopedIPCSupport::ScopedIPCSupport(
}
ScopedIPCSupport::~ScopedIPCSupport() {
- ipc_support_initializer.Get().ShutDown(false);
+ ipc_support_initializer.Get().ShutDown();
}
} // namespace IPC
diff --git a/chromium/ipc/mojo/scoped_ipc_support.h b/chromium/ipc/mojo/scoped_ipc_support.h
index 21013fa75c0..29c50bf4a48 100644
--- a/chromium/ipc/mojo/scoped_ipc_support.h
+++ b/chromium/ipc/mojo/scoped_ipc_support.h
@@ -12,14 +12,12 @@
namespace IPC {
-// Perform any necessary Mojo IPC initialization. A ScopedIPCSupport object
-// should be instantiated and retained by any component which makes direct calls
-// to the Mojo EDK. This is used to ensure that the EDK is initialized within
-// the current process and that it is shutdown cleanly when no longer in use.
+// Performs any necessary Mojo IPC initialization on construction, and shuts
+// down Mojo IPC on destruction.
//
-// NOTE: Unless you are making explicit calls to functions in the
-// mojo::embedder namespace, you almost definitely DO NOT need this and should
-// not be using it.
+// This should be instantiated once per process and retained as long as Mojo IPC
+// is needed. The TaskRunner passed to the constructor should outlive this
+// object.
class IPC_MOJO_EXPORT ScopedIPCSupport {
public:
ScopedIPCSupport(scoped_refptr<base::TaskRunner> io_thread_task_runner);
diff --git a/chromium/ipc/param_traits_macros.h b/chromium/ipc/param_traits_macros.h
index 317f31228d9..10034402382 100644
--- a/chromium/ipc/param_traits_macros.h
+++ b/chromium/ipc/param_traits_macros.h
@@ -8,16 +8,19 @@
#include <string>
// Traits generation for structs.
-#define IPC_STRUCT_TRAITS_BEGIN(struct_name) \
- namespace IPC { \
- template <> \
- struct IPC_MESSAGE_EXPORT ParamTraits<struct_name> { \
- typedef struct_name param_type; \
- static void Write(Message* m, const param_type& p); \
- static bool Read(const Message* m, base::PickleIterator* iter, \
- param_type* p); \
- static void Log(const param_type& p, std::string* l); \
- }; \
+#define IPC_STRUCT_TRAITS_BEGIN(struct_name) \
+ namespace IPC { \
+ template <> \
+ struct IPC_MESSAGE_EXPORT ParamTraits<struct_name> { \
+ typedef struct_name param_type; \
+ static void GetSize(base::PickleSizer* sizer, \
+ const param_type& p); \
+ 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); \
+ }; \
}
#define IPC_STRUCT_TRAITS_MEMBER(name)
@@ -48,15 +51,18 @@
// Traits generation for enums. This macro may be redefined later.
#define IPC_ENUM_TRAITS_VALIDATE(enum_name, validation_expression) \
- namespace IPC { \
- template <> \
- struct IPC_MESSAGE_EXPORT ParamTraits<enum_name> { \
- typedef enum_name param_type; \
- static void Write(Message* m, const param_type& p); \
- static bool Read(const Message* m, base::PickleIterator* iter, \
- param_type* p); \
- static void Log(const param_type& p, std::string* l); \
- }; \
+ namespace IPC { \
+ template <> \
+ struct IPC_MESSAGE_EXPORT ParamTraits<enum_name> { \
+ typedef enum_name param_type; \
+ static void GetSize(base::PickleSizer* sizer, \
+ const param_type& p); \
+ 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); \
+ }; \
}
#endif // IPC_PARAM_TRAITS_MACROS_H_
diff --git a/chromium/ipc/param_traits_read_macros.h b/chromium/ipc/param_traits_read_macros.h
index a66c89a8d0e..45e635285a9 100644
--- a/chromium/ipc/param_traits_read_macros.h
+++ b/chromium/ipc/param_traits_read_macros.h
@@ -22,25 +22,25 @@
#undef IPC_STRUCT_TRAITS_MEMBER
#undef IPC_STRUCT_TRAITS_PARENT
#undef IPC_STRUCT_TRAITS_END
-#define IPC_STRUCT_TRAITS_BEGIN(struct_name) \
- bool ParamTraits<struct_name>:: \
- Read(const Message* m, base::PickleIterator* iter, param_type* p) { \
- return
+#define IPC_STRUCT_TRAITS_BEGIN(struct_name) \
+ bool ParamTraits<struct_name>::Read( \
+ const base::Pickle* m, base::PickleIterator* iter, param_type* p) { \
+ return
#define IPC_STRUCT_TRAITS_MEMBER(name) ReadParam(m, iter, &p->name) &&
#define IPC_STRUCT_TRAITS_PARENT(type) ParamTraits<type>::Read(m, iter, p) &&
#define IPC_STRUCT_TRAITS_END() 1; }
#undef IPC_ENUM_TRAITS_VALIDATE
-#define IPC_ENUM_TRAITS_VALIDATE(enum_name, validation_expression) \
- bool ParamTraits<enum_name>:: \
- Read(const Message* m, base::PickleIterator* iter, param_type* p) { \
- int value; \
- if (!iter->ReadInt(&value)) \
- return false; \
- if (!(validation_expression)) \
- return false; \
- *p = static_cast<param_type>(value); \
- return true; \
+#define IPC_ENUM_TRAITS_VALIDATE(enum_name, validation_expression) \
+ bool ParamTraits<enum_name>::Read( \
+ const base::Pickle* m, base::PickleIterator* iter, param_type* p) { \
+ int value; \
+ if (!iter->ReadInt(&value)) \
+ return false; \
+ if (!(validation_expression)) \
+ return false; \
+ *p = static_cast<param_type>(value); \
+ return true; \
}
#endif // IPC_PARAM_TRAITS_READ_MACROS_H_
diff --git a/chromium/ipc/param_traits_size_macros.h b/chromium/ipc/param_traits_size_macros.h
new file mode 100644
index 00000000000..142b55a32d6
--- /dev/null
+++ b/chromium/ipc/param_traits_size_macros.h
@@ -0,0 +1,40 @@
+// Copyright 2016 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_PARAM_TRAITS_SIZE_MACROS_H_
+#define IPC_PARAM_TRAITS_SIZE_MACROS_H_
+
+// Null out all the macros that need nulling.
+#include "ipc/ipc_message_null_macros.h"
+
+// STRUCT declarations cause corresponding STRUCT_TRAITS declarations to occur.
+#undef IPC_STRUCT_BEGIN_WITH_PARENT
+#undef IPC_STRUCT_MEMBER
+#undef IPC_STRUCT_END
+#define IPC_STRUCT_BEGIN_WITH_PARENT(struct_name, parent) \
+ IPC_STRUCT_TRAITS_BEGIN(struct_name)
+#define IPC_STRUCT_MEMBER(type, name, ...) IPC_STRUCT_TRAITS_MEMBER(name)
+#define IPC_STRUCT_END() IPC_STRUCT_TRAITS_END()
+
+// Set up so next include will generate size methods.
+#undef IPC_STRUCT_TRAITS_BEGIN
+#undef IPC_STRUCT_TRAITS_MEMBER
+#undef IPC_STRUCT_TRAITS_PARENT
+#undef IPC_STRUCT_TRAITS_END
+#define IPC_STRUCT_TRAITS_BEGIN(struct_name) \
+ void ParamTraits<struct_name>::GetSize(base::PickleSizer* sizer, \
+ const param_type& p) {
+#define IPC_STRUCT_TRAITS_MEMBER(name) GetParamSize(sizer, p.name);
+#define IPC_STRUCT_TRAITS_PARENT(type) ParamTraits<type>::GetSize(sizer, p);
+#define IPC_STRUCT_TRAITS_END() }
+
+#undef IPC_ENUM_TRAITS_VALIDATE
+#define IPC_ENUM_TRAITS_VALIDATE(enum_name, validation_expression) \
+ void ParamTraits<enum_name>::GetSize(base::PickleSizer* sizer, \
+ const param_type& value) { \
+ sizer->AddInt(); \
+ }
+
+#endif // IPC_PARAM_TRAITS_SIZE_MACROS_H_
+
diff --git a/chromium/ipc/param_traits_write_macros.h b/chromium/ipc/param_traits_write_macros.h
index 81f915ffff8..a1aca4374eb 100644
--- a/chromium/ipc/param_traits_write_macros.h
+++ b/chromium/ipc/param_traits_write_macros.h
@@ -23,16 +23,17 @@
#undef IPC_STRUCT_TRAITS_PARENT
#undef IPC_STRUCT_TRAITS_END
#define IPC_STRUCT_TRAITS_BEGIN(struct_name) \
- void ParamTraits<struct_name>::Write(Message* m, const param_type& p) {
+ void ParamTraits<struct_name>::Write(base::Pickle* m, const param_type& p) {
#define IPC_STRUCT_TRAITS_MEMBER(name) WriteParam(m, p.name);
#define IPC_STRUCT_TRAITS_PARENT(type) ParamTraits<type>::Write(m, p);
#define IPC_STRUCT_TRAITS_END() }
#undef IPC_ENUM_TRAITS_VALIDATE
#define IPC_ENUM_TRAITS_VALIDATE(enum_name, validation_expression) \
- void ParamTraits<enum_name>::Write(Message* m, const param_type& value) { \
- DCHECK(validation_expression); \
- m->WriteInt(static_cast<int>(value)); \
+ void ParamTraits<enum_name>::Write(base::Pickle* m, \
+ const param_type& value) { \
+ DCHECK(validation_expression); \
+ m->WriteInt(static_cast<int>(value)); \
}
#endif // IPC_PARAM_TRAITS_WRITE_MACROS_H_
diff --git a/chromium/ipc/unix_domain_socket_util.cc b/chromium/ipc/unix_domain_socket_util.cc
index fb64cb29165..ee82560bddb 100644
--- a/chromium/ipc/unix_domain_socket_util.cc
+++ b/chromium/ipc/unix_domain_socket_util.cc
@@ -5,10 +5,7 @@
#include "ipc/unix_domain_socket_util.h"
#include <errno.h>
-#include <fcntl.h>
-#include <stddef.h>
#include <sys/socket.h>
-#include <sys/stat.h>
#include <sys/un.h>
#include <unistd.h>
@@ -27,37 +24,25 @@ static_assert(sizeof(((sockaddr_un*)0)->sun_path) >= kMaxSocketNameLength,
namespace {
-// Returns fd (>= 0) on success, -1 on failure. If successful, fills in
-// |unix_addr| with the appropriate data for the socket, and sets
-// |unix_addr_len| to the length of the data therein.
-int MakeUnixAddrForPath(const std::string& socket_name,
- struct sockaddr_un* unix_addr,
- size_t* unix_addr_len) {
+// This function fills in |unix_addr| with the appropriate data for the socket,
+// and sets |unix_addr_len| to the length of the data therein.
+// Returns true on success, or false on failure (typically because |socket_name|
+// violated the naming rules).
+bool MakeUnixAddrForPath(const std::string& socket_name,
+ struct sockaddr_un* unix_addr,
+ size_t* unix_addr_len) {
DCHECK(unix_addr);
DCHECK(unix_addr_len);
if (socket_name.length() == 0) {
LOG(ERROR) << "Empty socket name provided for unix socket address.";
- return -1;
+ return false;
}
// We reject socket_name.length() == kMaxSocketNameLength to make room for
// the NUL terminator at the end of the string.
if (socket_name.length() >= kMaxSocketNameLength) {
LOG(ERROR) << "Socket name too long: " << socket_name;
- return -1;
- }
-
- // Create socket.
- base::ScopedFD fd(socket(AF_UNIX, SOCK_STREAM, 0));
- if (!fd.is_valid()) {
- PLOG(ERROR) << "socket";
- return -1;
- }
-
- // Make socket non-blocking
- if (HANDLE_EINTR(fcntl(fd.get(), F_SETFL, O_NONBLOCK)) < 0) {
- PLOG(ERROR) << "fcntl(O_NONBLOCK)";
- return -1;
+ return false;
}
// Create unix_addr structure.
@@ -66,7 +51,36 @@ int MakeUnixAddrForPath(const std::string& socket_name,
strncpy(unix_addr->sun_path, socket_name.c_str(), kMaxSocketNameLength);
*unix_addr_len =
offsetof(struct sockaddr_un, sun_path) + socket_name.length();
- return fd.release();
+ return true;
+}
+
+// This functions creates a unix domain socket, and set it as non-blocking.
+// If successful, |out_fd| will be set to the new file descriptor, and the
+// function will return true. Otherwise returns false.
+bool CreateUnixDomainSocket(base::ScopedFD* out_fd) {
+ DCHECK(out_fd);
+
+ // Create the unix domain socket.
+ base::ScopedFD fd(socket(AF_UNIX, SOCK_STREAM, 0));
+ if (!fd.is_valid()) {
+ PLOG(ERROR) << "Failed to create AF_UNIX socket.";
+ return false;
+ }
+
+ // Now set it as non-blocking.
+ if (!base::SetNonBlocking(fd.get())) {
+ PLOG(ERROR) << "base::SetNonBlocking() failed " << fd.get();
+ return false;
+ }
+
+ fd.swap(*out_fd);
+
+ return true;
+}
+
+bool IsRecoverableError() {
+ return errno == ECONNABORTED || errno == EMFILE || errno == ENFILE ||
+ errno == ENOMEM || errno == ENOBUFS;
}
} // namespace
@@ -75,38 +89,40 @@ bool CreateServerUnixDomainSocket(const base::FilePath& socket_path,
int* server_listen_fd) {
DCHECK(server_listen_fd);
- std::string socket_name = socket_path.value();
- base::FilePath socket_dir = socket_path.DirName();
-
- struct sockaddr_un unix_addr;
- size_t unix_addr_len;
- base::ScopedFD fd(
- MakeUnixAddrForPath(socket_name, &unix_addr, &unix_addr_len));
- if (!fd.is_valid())
- return false;
-
// Make sure the path we need exists.
+ base::FilePath socket_dir = socket_path.DirName();
if (!base::CreateDirectory(socket_dir)) {
LOG(ERROR) << "Couldn't create directory: " << socket_dir.value();
return false;
}
+ const std::string socket_name = socket_path.value();
+
// Delete any old FS instances.
if (unlink(socket_name.c_str()) < 0 && errno != ENOENT) {
PLOG(ERROR) << "unlink " << socket_name;
return false;
}
+ struct sockaddr_un unix_addr;
+ size_t unix_addr_len;
+ if (!MakeUnixAddrForPath(socket_name, &unix_addr, &unix_addr_len))
+ return false;
+
+ base::ScopedFD fd;
+ if (!CreateUnixDomainSocket(&fd))
+ return false;
+
// Bind the socket.
if (bind(fd.get(), reinterpret_cast<const sockaddr*>(&unix_addr),
unix_addr_len) < 0) {
- PLOG(ERROR) << "bind " << socket_path.value();
+ PLOG(ERROR) << "bind " << socket_name;
return false;
}
// Start listening on the socket.
if (listen(fd.get(), SOMAXCONN) < 0) {
- PLOG(ERROR) << "listen " << socket_path.value();
+ PLOG(ERROR) << "listen " << socket_name;
unlink(socket_name.c_str());
return false;
}
@@ -119,14 +135,13 @@ bool CreateClientUnixDomainSocket(const base::FilePath& socket_path,
int* client_socket) {
DCHECK(client_socket);
- std::string socket_name = socket_path.value();
- base::FilePath socket_dir = socket_path.DirName();
-
struct sockaddr_un unix_addr;
size_t unix_addr_len;
- base::ScopedFD fd(
- MakeUnixAddrForPath(socket_name, &unix_addr, &unix_addr_len));
- if (!fd.is_valid())
+ if (!MakeUnixAddrForPath(socket_path.value(), &unix_addr, &unix_addr_len))
+ return false;
+
+ base::ScopedFD fd;
+ if (!CreateUnixDomainSocket(&fd))
return false;
if (HANDLE_EINTR(connect(fd.get(), reinterpret_cast<sockaddr*>(&unix_addr),
@@ -177,20 +192,16 @@ bool IsPeerAuthorized(int peer_fd) {
return true;
}
-bool IsRecoverableError(int err) {
- return errno == ECONNABORTED || errno == EMFILE || errno == ENFILE ||
- errno == ENOMEM || errno == ENOBUFS;
-}
-
bool ServerAcceptConnection(int server_listen_fd, int* server_socket) {
DCHECK(server_socket);
*server_socket = -1;
base::ScopedFD accept_fd(HANDLE_EINTR(accept(server_listen_fd, NULL, 0)));
if (!accept_fd.is_valid())
- return IsRecoverableError(errno);
- if (HANDLE_EINTR(fcntl(accept_fd.get(), F_SETFL, O_NONBLOCK)) < 0) {
- PLOG(ERROR) << "fcntl(O_NONBLOCK) " << accept_fd.get();
+ return IsRecoverableError();
+
+ if (!base::SetNonBlocking(accept_fd.get())) {
+ PLOG(ERROR) << "base::SetNonBlocking() failed " << accept_fd.get();
// It's safe to keep listening on |server_listen_fd| even if the attempt to
// set O_NONBLOCK failed on the client fd.
return true;
diff --git a/chromium/ipc/unix_domain_socket_util.h b/chromium/ipc/unix_domain_socket_util.h
index 13590722950..78d98644cb9 100644
--- a/chromium/ipc/unix_domain_socket_util.h
+++ b/chromium/ipc/unix_domain_socket_util.h
@@ -8,8 +8,6 @@
#include <stddef.h>
#include <sys/types.h>
-#include <string>
-
#include "ipc/ipc_export.h"
namespace base {
diff --git a/chromium/ipc/unix_domain_socket_util_unittest.cc b/chromium/ipc/unix_domain_socket_util_unittest.cc
index 49c1c024c1f..2ba8cfe5a72 100644
--- a/chromium/ipc/unix_domain_socket_util_unittest.cc
+++ b/chromium/ipc/unix_domain_socket_util_unittest.cc
@@ -9,6 +9,7 @@
#include "base/files/file_path.h"
#include "base/location.h"
#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
#include "base/path_service.h"
#include "base/posix/eintr_wrapper.h"
#include "base/single_thread_task_runner.h"