diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc index a8c447f4cf185a..7cd263465468da 100644 --- a/content/browser/site_per_process_browsertest.cc +++ b/content/browser/site_per_process_browsertest.cc @@ -78,7 +78,7 @@ #include "content/shell/browser/shell.h" #include "content/test/content_browser_test_utils_internal.h" #include "content/test/mock_overscroll_observer.h" -#include "ipc/ipc.mojom.h" +#include "ipc/constants.mojom.h" #include "ipc/ipc_security_test_util.h" #include "mojo/public/cpp/bindings/strong_binding.h" #include "net/dns/mock_host_resolver.h" diff --git a/content/common/BUILD.gn b/content/common/BUILD.gn index 711ef8ec90caca..ec5554b4441215 100644 --- a/content/common/BUILD.gn +++ b/content/common/BUILD.gn @@ -651,7 +651,7 @@ mojom("mojo_bindings") { public_deps = [ "//components/leveldb/public/interfaces", "//content/public/common:interfaces", - "//ipc:mojom", + "//ipc:mojom_constants", "//media/capture/mojo:capture_types", "//media/mojo/interfaces", "//mojo/common:common_custom_types", diff --git a/content/common/renderer.mojom b/content/common/renderer.mojom index 642090b31508c0..62ad23e6c805f2 100644 --- a/content/common/renderer.mojom +++ b/content/common/renderer.mojom @@ -6,7 +6,7 @@ module content.mojom; import "content/common/native_types.mojom"; import "content/common/service_worker/embedded_worker.mojom"; -import "ipc/ipc.mojom"; +import "ipc/constants.mojom"; import "mojo/common/time.mojom"; import "ui/gfx/geometry/mojo/geometry.mojom"; import "ui/gfx/mojo/icc_profile.mojom"; @@ -171,7 +171,7 @@ interface Renderer { // EffectiveConnectionType is the connection type whose typical performance is // most similar to the measured performance of the network in use. // The downstream throughput is computed in kilobits per second. If an - // estimate of the HTTP or transport RTT is unavailable, it will be set to + // estimate of the HTTP or transport RTT is unavailable, it will be set to // net::nqe::internal::InvalidRTT(). If the throughput estimate is // unavailable, it will be set to net::nqe::internal::kInvalidThroughput. OnNetworkQualityChanged(EffectiveConnectionType effective_connection_type, diff --git a/ipc/BUILD.gn b/ipc/BUILD.gn index 5753bd5c0fbc1e..a63907022b583d 100644 --- a/ipc/BUILD.gn +++ b/ipc/BUILD.gn @@ -23,10 +23,6 @@ buildflag_header("ipc_features") { component("ipc") { sources = [ "export_template.h", - "handle_attachment_win.cc", - "handle_attachment_win.h", - "handle_win.cc", - "handle_win.h", "ipc_channel.cc", "ipc_channel.h", "ipc_channel_common.cc", @@ -45,12 +41,6 @@ component("ipc") { "ipc_listener.h", "ipc_logging.cc", "ipc_logging.h", - "ipc_message.cc", - "ipc_message.h", - "ipc_message_attachment.cc", - "ipc_message_attachment.h", - "ipc_message_attachment_set.cc", - "ipc_message_attachment_set.h", "ipc_message_macros.h", "ipc_message_pipe_reader.cc", "ipc_message_pipe_reader.h", @@ -61,27 +51,13 @@ component("ipc") { "ipc_message_utils.h", "ipc_mojo_bootstrap.cc", "ipc_mojo_bootstrap.h", - "ipc_mojo_handle_attachment.cc", - "ipc_mojo_handle_attachment.h", - "ipc_mojo_message_helper.cc", - "ipc_mojo_message_helper.h", "ipc_mojo_param_traits.cc", "ipc_mojo_param_traits.h", - "ipc_platform_file.cc", - "ipc_platform_file.h", - "ipc_platform_file_attachment_posix.cc", - "ipc_platform_file_attachment_posix.h", "ipc_sender.h", "ipc_sync_channel.cc", "ipc_sync_channel.h", - "ipc_sync_message.cc", - "ipc_sync_message.h", "ipc_sync_message_filter.cc", "ipc_sync_message_filter.h", - "mach_port_attachment_mac.cc", - "mach_port_attachment_mac.h", - "mach_port_mac.cc", - "mach_port_mac.h", "message_filter.cc", "message_filter.h", "message_filter_router.cc", @@ -105,20 +81,13 @@ component("ipc") { ] } - if (is_fuchsia) { - sources += [ - "handle_attachment_fuchsia.cc", - "handle_attachment_fuchsia.h", - "handle_fuchsia.cc", - "handle_fuchsia.h", - ] - } - defines = [ "IPC_IMPLEMENTATION" ] public_deps = [ ":ipc_features", + ":message_support", ":mojom", + ":native_handle_type_converters", ":param_traits", "//mojo/public/cpp/bindings", "//mojo/public/cpp/system", @@ -134,15 +103,76 @@ component("ipc") { "//base", ] + if (enable_ipc_fuzzer) { + public_configs = [ "//tools/ipc_fuzzer:ipc_fuzzer_config" ] + } +} + +component("message_support") { + sources = [ + "handle_attachment_win.cc", + "handle_attachment_win.h", + "handle_win.cc", + "handle_win.h", + "ipc_message.cc", + "ipc_message.h", + "ipc_message_attachment.cc", + "ipc_message_attachment.h", + "ipc_message_attachment_set.cc", + "ipc_message_attachment_set.h", + "ipc_message_support_export.h", + "ipc_mojo_handle_attachment.cc", + "ipc_mojo_handle_attachment.h", + "ipc_mojo_message_helper.cc", + "ipc_mojo_message_helper.h", + "ipc_platform_file.cc", + "ipc_platform_file.h", + "ipc_platform_file_attachment_posix.cc", + "ipc_platform_file_attachment_posix.h", + "ipc_sync_message.cc", + "ipc_sync_message.h", + "mach_port_attachment_mac.cc", + "mach_port_attachment_mac.h", + "mach_port_mac.cc", + "mach_port_mac.h", + ] + + if (is_fuchsia) { + sources += [ + "handle_attachment_fuchsia.cc", + "handle_attachment_fuchsia.h", + "handle_fuchsia.cc", + "handle_fuchsia.h", + ] + } + + defines = [ "IPC_MESSAGE_SUPPORT_IMPL" ] + + public_deps = [ + ":ipc_features", + ":param_traits", + "//base", + "//mojo/public/cpp/system", + ] + if (is_win || is_mac) { # On Windows HandleAttachmentWin needs to generate random IDs. # On Mac MachPortAttachmentMac needs to generate random IDs. - deps += [ "//crypto" ] + deps = [ + "//crypto", + ] } +} - if (enable_ipc_fuzzer) { - public_configs = [ "//tools/ipc_fuzzer:ipc_fuzzer_config" ] - } +source_set("native_handle_type_converters") { + sources = [ + "native_handle_type_converters.cc", + "native_handle_type_converters.h", + ] + public_deps = [ + ":message_support", + "//mojo/public/interfaces/bindings:bindings_shared__generator", + ] } mojom_component("mojom") { @@ -154,6 +184,16 @@ mojom_component("mojom") { public_deps = [ "//mojo/common:read_only_buffer", ] + + # Don't generate a variant sources since we depend on generated internal + # bindings types and we don't generate or build variants of those. + disable_variants = true +} + +mojom("mojom_constants") { + sources = [ + "constants.mojom", + ] } mojom("test_interfaces") { diff --git a/ipc/OWNERS b/ipc/OWNERS index 22545c9c625b06..6c813f21d1e73c 100644 --- a/ipc/OWNERS +++ b/ipc/OWNERS @@ -16,6 +16,8 @@ per-file *.mojom=set noparent per-file *.mojom=file://ipc/SECURITY_OWNERS per-file *_param_traits*.*=set noparent per-file *_param_traits*.*=file://ipc/SECURITY_OWNERS +per-file *_type_converter*.*=set noparent +per-file *_type_converter*.*=file://ipc/SECURITY_OWNERS per-file SECURITY_OWNERS=file://ipc/SECURITY_OWNERS diff --git a/ipc/constants.mojom b/ipc/constants.mojom new file mode 100644 index 00000000000000..502187f2e2a693 --- /dev/null +++ b/ipc/constants.mojom @@ -0,0 +1,8 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +module IPC.mojom; + +// NOTE: This MUST match the value of MSG_ROUTING_NONE in src/ipc/ipc_message.h. +const int32 kRoutingIdNone = -2; diff --git a/ipc/handle_attachment_fuchsia.h b/ipc/handle_attachment_fuchsia.h index 915e41663b8f3e..d1fa545a05233a 100644 --- a/ipc/handle_attachment_fuchsia.h +++ b/ipc/handle_attachment_fuchsia.h @@ -9,14 +9,15 @@ #include "base/fuchsia/scoped_mx_handle.h" #include "ipc/handle_fuchsia.h" -#include "ipc/ipc_export.h" #include "ipc/ipc_message_attachment.h" +#include "ipc/ipc_message_support_export.h" namespace IPC { namespace internal { // This class represents a Fuchsia mx_handle_t attached to a Chrome IPC message. -class IPC_EXPORT HandleAttachmentFuchsia : public MessageAttachment { +class IPC_MESSAGE_SUPPORT_EXPORT HandleAttachmentFuchsia + : public MessageAttachment { public: // This constructor makes a copy of |handle| and takes ownership of the // result. Should only be called by the sender of a Chrome IPC message. diff --git a/ipc/handle_attachment_win.h b/ipc/handle_attachment_win.h index 3ee9f43683ac2a..730afc829947b7 100644 --- a/ipc/handle_attachment_win.h +++ b/ipc/handle_attachment_win.h @@ -9,14 +9,15 @@ #include "base/win/scoped_handle.h" #include "ipc/handle_win.h" -#include "ipc/ipc_export.h" #include "ipc/ipc_message_attachment.h" +#include "ipc/ipc_message_support_export.h" namespace IPC { namespace internal { // This class represents a Windows HANDLE attached to a Chrome IPC message. -class IPC_EXPORT HandleAttachmentWin : public MessageAttachment { +class IPC_MESSAGE_SUPPORT_EXPORT HandleAttachmentWin + : public MessageAttachment { public: // This constructor makes a copy of |handle| and takes ownership of the // result. Should only be called by the sender of a Chrome IPC message. diff --git a/ipc/handle_fuchsia.h b/ipc/handle_fuchsia.h index babfe14f0438f6..83c6512f62fd82 100644 --- a/ipc/handle_fuchsia.h +++ b/ipc/handle_fuchsia.h @@ -9,7 +9,7 @@ #include -#include "ipc/ipc_export.h" +#include "ipc/ipc_message_support_export.h" #include "ipc/ipc_param_traits.h" namespace base { @@ -19,7 +19,7 @@ class PickleIterator; namespace IPC { -class IPC_EXPORT HandleFuchsia { +class IPC_MESSAGE_SUPPORT_EXPORT HandleFuchsia { public: // Default constructor makes an invalid mx_handle_t. HandleFuchsia(); @@ -33,7 +33,7 @@ class IPC_EXPORT HandleFuchsia { }; template <> -struct IPC_EXPORT ParamTraits { +struct IPC_MESSAGE_SUPPORT_EXPORT ParamTraits { typedef HandleFuchsia param_type; static void Write(base::Pickle* m, const param_type& p); static bool Read(const base::Pickle* m, diff --git a/ipc/handle_win.h b/ipc/handle_win.h index 0120597c15221b..68afc67cbbd456 100644 --- a/ipc/handle_win.h +++ b/ipc/handle_win.h @@ -9,7 +9,7 @@ #include -#include "ipc/ipc_export.h" +#include "ipc/ipc_message_support_export.h" #include "ipc/ipc_param_traits.h" namespace base { @@ -26,7 +26,7 @@ namespace IPC { // The ownership semantics for the underlying |handle_| are complex. See // ipc/mach_port_mac.h (the OSX analog of this class) for an extensive // discussion. -class IPC_EXPORT HandleWin { +class IPC_MESSAGE_SUPPORT_EXPORT HandleWin { public: // Default constructor makes an invalid HANDLE. HandleWin(); @@ -40,7 +40,7 @@ class IPC_EXPORT HandleWin { }; template <> -struct IPC_EXPORT ParamTraits { +struct IPC_MESSAGE_SUPPORT_EXPORT ParamTraits { typedef HandleWin param_type; static void Write(base::Pickle* m, const param_type& p); static bool Read(const base::Pickle* m, diff --git a/ipc/ipc.mojom b/ipc/ipc.mojom index 3ab4d4ef063bdf..2332111b2d9924 100644 --- a/ipc/ipc.mojom +++ b/ipc/ipc.mojom @@ -5,23 +5,7 @@ module IPC.mojom; import "mojo/common/read_only_buffer.mojom"; - -// NOTE: This MUST match the value of MSG_ROUTING_NONE in src/ipc/ipc_message.h. -const int32 kRoutingIdNone = -2; - -struct SerializedHandle { - handle the_handle; - - enum Type { - MOJO_HANDLE, - PLATFORM_FILE, - WIN_HANDLE, - MACH_PORT, - FUCHSIA_HANDLE, - }; - - Type type; -}; +import "mojo/public/interfaces/bindings/native_struct.mojom"; // A placeholder interface type since we don't yet support generic associated // message pipe handles. @@ -34,7 +18,7 @@ interface Channel { // Transmits a classical Chrome IPC message. Receive(mojo.common.mojom.ReadOnlyBuffer data, - array? handles); + array? handles); // Requests a Channel-associated interface. GetAssociatedInterface(string name, associated GenericInterface& request); diff --git a/ipc/ipc_channel_mojo.cc b/ipc/ipc_channel_mojo.cc index 29451c6cf64bc6..6471d838ac7033 100644 --- a/ipc/ipc_channel_mojo.cc +++ b/ipc/ipc_channel_mojo.cc @@ -25,26 +25,10 @@ #include "ipc/ipc_message_macros.h" #include "ipc/ipc_mojo_bootstrap.h" #include "ipc/ipc_mojo_handle_attachment.h" +#include "ipc/native_handle_type_converters.h" #include "mojo/public/cpp/bindings/binding.h" #include "mojo/public/cpp/system/platform_handle.h" -#if defined(OS_POSIX) -#include "base/posix/eintr_wrapper.h" -#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 - -#if defined(OS_FUCHSIA) -#include "ipc/handle_attachment_fuchsia.h" -#endif - namespace IPC { namespace { @@ -76,188 +60,6 @@ class MojoChannelFactory : public ChannelFactory { DISALLOW_COPY_AND_ASSIGN(MojoChannelFactory); }; -mojom::SerializedHandlePtr CreateSerializedHandle( - mojo::ScopedHandle handle, - mojom::SerializedHandle::Type type) { - mojom::SerializedHandlePtr serialized_handle = mojom::SerializedHandle::New(); - serialized_handle->the_handle = std::move(handle); - serialized_handle->type = type; - return serialized_handle; -} - -MojoResult WrapPlatformHandle(base::PlatformFile handle, - mojom::SerializedHandle::Type type, - mojom::SerializedHandlePtr* serialized) { - mojo::ScopedHandle wrapped_handle = mojo::WrapPlatformFile(handle); - if (!wrapped_handle.is_valid()) - return MOJO_RESULT_UNKNOWN; - - *serialized = CreateSerializedHandle(std::move(wrapped_handle), type); - return MOJO_RESULT_OK; -} - -#if defined(OS_MACOSX) -MojoResult WrapMachPort(mach_port_t mach_port, - mojom::SerializedHandlePtr* serialized) { - MojoPlatformHandle platform_handle = { - sizeof(MojoPlatformHandle), MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT, - static_cast(mach_port) - }; - - MojoHandle wrapped_handle; - MojoResult result = MojoWrapPlatformHandle(&platform_handle, &wrapped_handle); - if (result != MOJO_RESULT_OK) - return result; - - *serialized = CreateSerializedHandle( - mojo::MakeScopedHandle(mojo::Handle(wrapped_handle)), - mojom::SerializedHandle::Type::MACH_PORT); - return MOJO_RESULT_OK; -} -#elif defined(OS_FUCHSIA) -MojoResult WrapMxHandle(mx_handle_t handle, - mojom::SerializedHandlePtr* serialized) { - MojoPlatformHandle platform_handle = { - sizeof(MojoPlatformHandle), MOJO_PLATFORM_HANDLE_TYPE_FUCHSIA_HANDLE, - static_cast(handle)}; - - MojoHandle wrapped_handle; - MojoResult result = MojoWrapPlatformHandle(&platform_handle, &wrapped_handle); - if (result != MOJO_RESULT_OK) - return result; - - *serialized = CreateSerializedHandle( - mojo::MakeScopedHandle(mojo::Handle(wrapped_handle)), - mojom::SerializedHandle::Type::FUCHSIA_HANDLE); - return MOJO_RESULT_OK; -} -#endif // defined(OS_FUCHSIA) - -#if defined(OS_POSIX) -base::ScopedFD TakeOrDupFile(internal::PlatformFileAttachment* attachment) { - return attachment->Owns() - ? base::ScopedFD(attachment->TakePlatformFile()) - : base::ScopedFD(HANDLE_EINTR(dup(attachment->file()))); -} -#endif // defined(OS_POSIX) - -MojoResult WrapAttachmentImpl(MessageAttachment* attachment, - mojom::SerializedHandlePtr* serialized) { - if (attachment->GetType() == MessageAttachment::Type::MOJO_HANDLE) { - *serialized = CreateSerializedHandle( - static_cast(*attachment).TakeHandle(), - mojom::SerializedHandle::Type::MOJO_HANDLE); - return MOJO_RESULT_OK; - } -#if defined(OS_POSIX) - 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(attachment)); - if (!file.is_valid()) { - DPLOG(WARNING) << "Failed to dup FD to transmit."; - return MOJO_RESULT_UNKNOWN; - } - - return WrapPlatformHandle(file.release(), - mojom::SerializedHandle::Type::PLATFORM_FILE, - serialized); - } -#endif // defined(OS_POSIX) -#if defined(OS_MACOSX) - DCHECK_EQ(attachment->GetType(), MessageAttachment::Type::MACH_PORT); - internal::MachPortAttachmentMac& mach_port_attachment = - static_cast(*attachment); - MojoResult result = WrapMachPort(mach_port_attachment.get_mach_port(), - serialized); - mach_port_attachment.reset_mach_port_ownership(); - return result; -#elif defined(OS_FUCHSIA) - DCHECK_EQ(attachment->GetType(), MessageAttachment::Type::FUCHSIA_HANDLE); - internal::HandleAttachmentFuchsia& handle_attachment = - static_cast(*attachment); - MojoResult result = WrapMxHandle(handle_attachment.Take(), serialized); - return result; -#elif defined(OS_WIN) - DCHECK_EQ(attachment->GetType(), MessageAttachment::Type::WIN_HANDLE); - internal::HandleAttachmentWin& handle_attachment = - static_cast(*attachment); - MojoResult result = - WrapPlatformHandle(handle_attachment.Take(), - mojom::SerializedHandle::Type::WIN_HANDLE, serialized); - return result; -#else - NOTREACHED(); - return MOJO_RESULT_UNKNOWN; -#endif // defined(OS_MACOSX) -} - -MojoResult WrapAttachment(MessageAttachment* attachment, - std::vector* handles) { - mojom::SerializedHandlePtr serialized_handle; - MojoResult wrap_result = WrapAttachmentImpl(attachment, &serialized_handle); - if (wrap_result != MOJO_RESULT_OK) { - LOG(WARNING) << "Pipe failed to wrap handles. Closing: " << wrap_result; - return wrap_result; - } - handles->push_back(std::move(serialized_handle)); - return MOJO_RESULT_OK; -} - -MojoResult UnwrapAttachment(mojom::SerializedHandlePtr handle, - scoped_refptr* attachment) { - if (handle->type == mojom::SerializedHandle::Type::MOJO_HANDLE) { - *attachment = - new IPC::internal::MojoHandleAttachment(std::move(handle->the_handle)); - return MOJO_RESULT_OK; - } - MojoPlatformHandle platform_handle = { sizeof(MojoPlatformHandle), 0, 0 }; - MojoResult unwrap_result = MojoUnwrapPlatformHandle( - handle->the_handle.release().value(), &platform_handle); - if (unwrap_result != MOJO_RESULT_OK) - return unwrap_result; -#if defined(OS_POSIX) - if (handle->type == mojom::SerializedHandle::Type::PLATFORM_FILE) { - base::PlatformFile file = base::kInvalidPlatformFile; - if (platform_handle.type == MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR) - file = static_cast(platform_handle.value); - *attachment = new internal::PlatformFileAttachment(file); - return MOJO_RESULT_OK; - } -#endif // defined(OS_POSIX) -#if defined(OS_MACOSX) - if (handle->type == mojom::SerializedHandle::Type::MACH_PORT) { - mach_port_t mach_port = MACH_PORT_NULL; - if (platform_handle.type == MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT) - mach_port = static_cast(platform_handle.value); - *attachment = new internal::MachPortAttachmentMac( - mach_port, internal::MachPortAttachmentMac::FROM_WIRE); - return MOJO_RESULT_OK; - } -#elif defined(OS_FUCHSIA) - if (handle->type == mojom::SerializedHandle::Type::FUCHSIA_HANDLE) { - base::ScopedMxHandle handle; - if (platform_handle.type == MOJO_PLATFORM_HANDLE_TYPE_FUCHSIA_HANDLE) - handle.reset(static_cast(platform_handle.value)); - *attachment = new internal::HandleAttachmentFuchsia(std::move(handle)); - return MOJO_RESULT_OK; - } -#elif defined(OS_WIN) - if (handle->type == mojom::SerializedHandle::Type::WIN_HANDLE) { - base::PlatformFile handle = base::kInvalidPlatformFile; - if (platform_handle.type == MOJO_PLATFORM_HANDLE_TYPE_WINDOWS_HANDLE) - handle = reinterpret_cast(platform_handle.value); - *attachment = new internal::HandleAttachmentWin( - handle, internal::HandleAttachmentWin::FROM_WIRE); - return MOJO_RESULT_OK; - } -#endif // defined(OS_WIN) - NOTREACHED(); - return MOJO_RESULT_UNKNOWN; -} - base::ProcessId GetSelfPID() { #if defined(OS_LINUX) if (int global_pid = Channel::GetGlobalPid()) @@ -451,18 +253,24 @@ void ChannelMojo::OnMessageReceived(const Message& message) { // static MojoResult ChannelMojo::ReadFromMessageAttachmentSet( Message* message, - base::Optional>* handles) { + base::Optional>* handles) { DCHECK(!*handles); MojoResult result = MOJO_RESULT_OK; if (!message->HasAttachments()) return result; - std::vector output_handles; + std::vector output_handles; MessageAttachmentSet* set = message->attachment_set(); for (unsigned i = 0; result == MOJO_RESULT_OK && i < set->size(); ++i) { - result = WrapAttachment(set->GetAttachmentAt(i).get(), &output_handles); + auto attachment = set->GetAttachmentAt(i); + auto serialized_handle = mojo::native::SerializedHandle::New(); + serialized_handle->the_handle = attachment->TakeMojoHandle(); + serialized_handle->type = + mojo::ConvertTo( + attachment->GetType()); + output_handles.emplace_back(std::move(serialized_handle)); } set->CommitAllDescriptors(); @@ -474,20 +282,20 @@ MojoResult ChannelMojo::ReadFromMessageAttachmentSet( // static MojoResult ChannelMojo::WriteToMessageAttachmentSet( - base::Optional> handle_buffer, + base::Optional> handles, Message* message) { - if (!handle_buffer) + if (!handles) return MOJO_RESULT_OK; - for (size_t i = 0; i < handle_buffer->size(); ++i) { - scoped_refptr 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; + for (size_t i = 0; i < handles->size(); ++i) { + auto& handle = handles->at(i); + scoped_refptr unwrapped_attachment = + MessageAttachment::CreateFromMojoHandle( + std::move(handle->the_handle), + mojo::ConvertTo(handle->type)); + if (!unwrapped_attachment) { + DLOG(WARNING) << "Pipe failed to unwrap handles."; + return MOJO_RESULT_UNKNOWN; } - DCHECK(unwrapped_attachment); bool ok = message->attachment_set()->AddAttachment( std::move(unwrapped_attachment)); diff --git a/ipc/ipc_channel_mojo.h b/ipc/ipc_channel_mojo.h index e8b7b92afcd58f..61bc0dba41ed9f 100644 --- a/ipc/ipc_channel_mojo.h +++ b/ipc/ipc_channel_mojo.h @@ -28,6 +28,7 @@ #include "ipc/ipc_mojo_bootstrap.h" #include "mojo/public/cpp/bindings/thread_safe_interface_ptr.h" #include "mojo/public/cpp/system/core.h" +#include "mojo/public/interfaces/bindings/native_struct.mojom.h" namespace IPC { @@ -77,11 +78,11 @@ class IPC_EXPORT ChannelMojo : public Channel, // These access protected API of IPC::Message, which has ChannelMojo // as a friend class. static MojoResult WriteToMessageAttachmentSet( - base::Optional> handle_buffer, + base::Optional> handles, Message* message); static MojoResult ReadFromMessageAttachmentSet( Message* message, - base::Optional>* handles); + base::Optional>* handles); // MessagePipeReader::Delegate void OnPeerPidReceived(int32_t peer_pid) override; diff --git a/ipc/ipc_message.h b/ipc/ipc_message.h index 3ca75482b189bb..8a924e21952038 100644 --- a/ipc/ipc_message.h +++ b/ipc/ipc_message.h @@ -15,8 +15,14 @@ #include "base/pickle.h" #include "base/trace_event/trace_event.h" #include "build/build_config.h" -#include "ipc/ipc_export.h" #include "ipc/ipc_features.h" +#include "ipc/ipc_message_support_export.h" + +namespace mojo { +namespace internal { +struct UnmappedNativeStructSerializerImpl; +} +} // namespace mojo namespace IPC { @@ -29,7 +35,7 @@ class ChannelReader; struct LogData; class MessageAttachmentSet; -class IPC_EXPORT Message : public base::Pickle { +class IPC_MESSAGE_SUPPORT_EXPORT Message : public base::Pickle { public: enum PriorityValue { PRIORITY_LOW = 1, @@ -166,7 +172,7 @@ class IPC_EXPORT Message : public base::Pickle { // The static method FindNext() returns several pieces of information, which // are aggregated into an instance of this struct. - struct IPC_EXPORT NextMessageInfo { + struct IPC_MESSAGE_SUPPORT_EXPORT NextMessageInfo { NextMessageInfo(); ~NextMessageInfo(); @@ -234,6 +240,8 @@ class IPC_EXPORT Message : public base::Pickle { friend class MessageReplyDeserializer; friend class SyncMessage; + friend struct mojo::internal::UnmappedNativeStructSerializerImpl; + #pragma pack(push, 4) struct Header : base::Pickle::Header { int32_t routing; // ID of the view that this message is destined for diff --git a/ipc/ipc_message_attachment.cc b/ipc/ipc_message_attachment.cc index 83440ae8e00884..63f7e1c3f1b150 100644 --- a/ipc/ipc_message_attachment.cc +++ b/ipc/ipc_message_attachment.cc @@ -4,12 +4,153 @@ #include "ipc/ipc_message_attachment.h" +#include "base/files/scoped_file.h" +#include "base/logging.h" +#include "ipc/ipc_mojo_handle_attachment.h" +#include "mojo/public/cpp/system/platform_handle.h" + +#if defined(OS_POSIX) +#include "base/posix/eintr_wrapper.h" +#include "ipc/ipc_platform_file_attachment_posix.h" +#endif + +#if defined(OS_MACOSX) && !defined(OS_IOS) +#include "ipc/mach_port_attachment_mac.h" +#endif + +#if defined(OS_WIN) +#include "ipc/handle_attachment_win.h" +#endif + +#if defined(OS_FUCHSIA) +#include "ipc/handle_attachment_fuchsia.h" +#endif + namespace IPC { -MessageAttachment::MessageAttachment() { +namespace { + +#if defined(OS_POSIX) +base::ScopedFD TakeOrDupFile(internal::PlatformFileAttachment* attachment) { + return attachment->Owns() + ? base::ScopedFD(attachment->TakePlatformFile()) + : base::ScopedFD(HANDLE_EINTR(dup(attachment->file()))); +} +#endif // defined(OS_POSIX) + +} // namespace + +MessageAttachment::MessageAttachment() = default; + +MessageAttachment::~MessageAttachment() = default; + +mojo::ScopedHandle MessageAttachment::TakeMojoHandle() { + switch (GetType()) { + case Type::MOJO_HANDLE: + return static_cast(this)->TakeHandle(); + +#if defined(OS_POSIX) + case Type::PLATFORM_FILE: { + // We dup() the handles in IPC::Message to transmit. + // IPC::MessageAttachmentSet has intricate lifetime semantics for FDs, so + // just to dup()-and-own them is the safest option. + base::ScopedFD file = + TakeOrDupFile(static_cast(this)); + if (!file.is_valid()) { + DPLOG(WARNING) << "Failed to dup FD to transmit."; + return mojo::ScopedHandle(); + } + return mojo::WrapPlatformFile(file.release()); + } +#endif // defined(OS_POSIX) + +#if defined(OS_MACOSX) && !defined(OS_IOS) + case Type::MACH_PORT: { + auto* attachment = static_cast(this); + MojoPlatformHandle platform_handle = { + sizeof(platform_handle), MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT, + static_cast(attachment->get_mach_port())}; + MojoHandle wrapped_handle; + if (MojoWrapPlatformHandle(&platform_handle, &wrapped_handle) != + MOJO_RESULT_OK) { + return mojo::ScopedHandle(); + } + attachment->reset_mach_port_ownership(); + return mojo::MakeScopedHandle(mojo::Handle(wrapped_handle)); + } +#elif defined(OS_FUCHSIA) + case Type::FUCHSIA_HANDLE: { + auto* attachment = static_cast(this); + MojoPlatformHandle platform_handle = { + sizeof(platform_handle), MOJO_PLATFORM_HANDLE_TYPE_FUCHSIA_HANDLE, + static_cast(attachment->Take())}; + MojoHandle wrapped_handle; + if (MojoWrapPlatformHandle(&platform_handle, &wrapped_handle) != + MOJO_RESULT_OK) { + return mojo::ScopedHandle(); + } + return mojo::MakeScopedHandle(mojo::Handle(wrapped_handle)); + } +#elif defined(OS_WIN) + case Type::WIN_HANDLE: + return mojo::WrapPlatformFile( + static_cast(this)->Take()); +#endif + default: + break; + } + NOTREACHED(); + return mojo::ScopedHandle(); } -MessageAttachment::~MessageAttachment() { +// static +scoped_refptr MessageAttachment::CreateFromMojoHandle( + mojo::ScopedHandle handle, + Type type) { + if (type == Type::MOJO_HANDLE) + return new internal::MojoHandleAttachment(std::move(handle)); + + MojoPlatformHandle platform_handle = {sizeof(platform_handle), 0, 0}; + MojoResult unwrap_result = + MojoUnwrapPlatformHandle(handle.release().value(), &platform_handle); + if (unwrap_result != MOJO_RESULT_OK) + return nullptr; + +#if defined(OS_POSIX) + if (type == Type::PLATFORM_FILE) { + base::PlatformFile file = base::kInvalidPlatformFile; + if (platform_handle.type == MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR) + file = static_cast(platform_handle.value); + return new internal::PlatformFileAttachment(file); + } +#endif // defined(OS_POSIX) + +#if defined(OS_MACOSX) && !defined(OS_IOS) + if (type == Type::MACH_PORT) { + mach_port_t mach_port = MACH_PORT_NULL; + if (platform_handle.type == MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT) + mach_port = static_cast(platform_handle.value); + return new internal::MachPortAttachmentMac( + mach_port, internal::MachPortAttachmentMac::FROM_WIRE); + } +#elif defined(OS_FUCHSIA) + if (type == Type::FUCHSIA_HANDLE) { + base::ScopedMxHandle handle; + if (platform_handle.type == MOJO_PLATFORM_HANDLE_TYPE_FUCHSIA_HANDLE) + handle.reset(static_cast(platform_handle.value)); + return new internal::HandleAttachmentFuchsia(std::move(handle)); + } +#elif defined(OS_WIN) + if (type == Type::WIN_HANDLE) { + base::PlatformFile handle = base::kInvalidPlatformFile; + if (platform_handle.type == MOJO_PLATFORM_HANDLE_TYPE_WINDOWS_HANDLE) + handle = reinterpret_cast(platform_handle.value); + return new internal::HandleAttachmentWin( + handle, internal::HandleAttachmentWin::FROM_WIRE); + } +#endif + NOTREACHED(); + return nullptr; } } // namespace IPC diff --git a/ipc/ipc_message_attachment.h b/ipc/ipc_message_attachment.h index 9ff1de8c32f53b..9c92f37b5ab246 100644 --- a/ipc/ipc_message_attachment.h +++ b/ipc/ipc_message_attachment.h @@ -10,19 +10,32 @@ #include "base/memory/ref_counted.h" #include "base/pickle.h" #include "build/build_config.h" -#include "ipc/ipc.mojom.h" -#include "ipc/ipc_export.h" +#include "ipc/ipc_message_support_export.h" +#include "mojo/public/cpp/system/handle.h" 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::Pickle::Attachment { +class IPC_MESSAGE_SUPPORT_EXPORT MessageAttachment + : public base::Pickle::Attachment { public: - using Type = mojom::SerializedHandle::Type; + enum class Type { + MOJO_HANDLE, + PLATFORM_FILE, + WIN_HANDLE, + MACH_PORT, + FUCHSIA_HANDLE, + }; + + static scoped_refptr CreateFromMojoHandle( + mojo::ScopedHandle handle, + Type type); virtual Type GetType() const = 0; + mojo::ScopedHandle TakeMojoHandle(); + protected: friend class base::RefCountedThreadSafe; MessageAttachment(); diff --git a/ipc/ipc_message_attachment_set.h b/ipc/ipc_message_attachment_set.h index de37211435867e..78bdcb2308ee68 100644 --- a/ipc/ipc_message_attachment_set.h +++ b/ipc/ipc_message_attachment_set.h @@ -12,7 +12,7 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "build/build_config.h" -#include "ipc/ipc_export.h" +#include "ipc/ipc_message_support_export.h" namespace IPC { @@ -26,7 +26,7 @@ class MessageAttachment; // For ChannelNacl under SFI NaCl, only Type::PLATFORM_FILE is supported. In // that case, the FD is sent over socket. // ----------------------------------------------------------------------------- -class IPC_EXPORT MessageAttachmentSet +class IPC_MESSAGE_SUPPORT_EXPORT MessageAttachmentSet : public base::RefCountedThreadSafe { public: MessageAttachmentSet(); diff --git a/ipc/ipc_message_pipe_reader.cc b/ipc/ipc_message_pipe_reader.cc index 8b226817ee1edd..ebc18a3a943d0a 100644 --- a/ipc/ipc_message_pipe_reader.cc +++ b/ipc/ipc_message_pipe_reader.cc @@ -54,7 +54,7 @@ bool MessagePipeReader::Send(std::unique_ptr message) { "MessagePipeReader::Send", message->flags(), TRACE_EVENT_FLAG_FLOW_OUT); - base::Optional> handles; + base::Optional> handles; MojoResult result = MOJO_RESULT_OK; result = ChannelMojo::ReadFromMessageAttachmentSet(message.get(), &handles); if (result != MOJO_RESULT_OK) @@ -86,7 +86,7 @@ void MessagePipeReader::SetPeerPid(int32_t peer_pid) { void MessagePipeReader::Receive( base::span data, - base::Optional> handles) { + base::Optional> handles) { Message message( data.empty() ? "" : reinterpret_cast(data.data()), static_cast(data.size())); diff --git a/ipc/ipc_message_pipe_reader.h b/ipc/ipc_message_pipe_reader.h index b2f5044257f53e..a155dcfb372bcb 100644 --- a/ipc/ipc_message_pipe_reader.h +++ b/ipc/ipc_message_pipe_reader.h @@ -22,6 +22,7 @@ #include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h" #include "mojo/public/cpp/system/core.h" #include "mojo/public/cpp/system/message_pipe.h" +#include "mojo/public/interfaces/bindings/native_struct.mojom.h" namespace IPC { namespace internal { @@ -93,9 +94,9 @@ class IPC_EXPORT MessagePipeReader : public mojom::Channel { private: // mojom::Channel: void SetPeerPid(int32_t peer_pid) override; - void Receive( - base::span data, - base::Optional> handles) override; + void Receive(base::span data, + base::Optional> + handles) override; void GetAssociatedInterface( const std::string& name, mojom::GenericInterfaceAssociatedRequest request) override; diff --git a/ipc/ipc_message_support_export.h b/ipc/ipc_message_support_export.h new file mode 100644 index 00000000000000..abfa67afcb5d4d --- /dev/null +++ b/ipc/ipc_message_support_export.h @@ -0,0 +1,31 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IPC_IPC_MESSAGE_SUPPORT_EXPORT_H_ +#define IPC_IPC_MESSAGE_SUPPORT_EXPORT_H_ + +#if defined(COMPONENT_BUILD) +#if defined(WIN32) + +#if defined(IPC_MESSAGE_SUPPORT_IMPL) +#define IPC_MESSAGE_SUPPORT_EXPORT __declspec(dllexport) +#else +#define IPC_MESSAGE_SUPPORT_EXPORT __declspec(dllimport) +#endif // defined(IPC_MESSAGE_SUPPORT_IMPL) + +#else // defined(WIN32) + +#if defined(IPC_MESSAGE_SUPPORT_IMPL) +#define IPC_MESSAGE_SUPPORT_EXPORT __attribute__((visibility("default"))) +#else +#define IPC_MESSAGE_SUPPORT_EXPORT +#endif + +#endif + +#else // defined(COMPONENT_BUILD) +#define IPC_MESSAGE_SUPPORT_EXPORT +#endif + +#endif // IPC_IPC_MESSAGE_SUPPORT_EXPORT_H_ diff --git a/ipc/ipc_message_utils.h b/ipc/ipc_message_utils.h index 1beac85fc687e0..120ad50f6f5ca5 100644 --- a/ipc/ipc_message_utils.h +++ b/ipc/ipc_message_utils.h @@ -28,6 +28,7 @@ #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "build/build_config.h" +#include "ipc/ipc_export.h" #include "ipc/ipc_message_start.h" #include "ipc/ipc_param_traits.h" #include "ipc/ipc_sync_message.h" diff --git a/ipc/ipc_mojo_bootstrap_unittest.cc b/ipc/ipc_mojo_bootstrap_unittest.cc index 52e261f1caab41..d74903c2e45f39 100644 --- a/ipc/ipc_mojo_bootstrap_unittest.cc +++ b/ipc/ipc_mojo_bootstrap_unittest.cc @@ -43,7 +43,7 @@ class PeerPidReceiver : public IPC::mojom::Channel { } void Receive(base::span data, - base::Optional> + base::Optional> handles) override {} void GetAssociatedInterface( diff --git a/ipc/ipc_mojo_handle_attachment.h b/ipc/ipc_mojo_handle_attachment.h index d6152769efd59e..94e40599aec3a9 100644 --- a/ipc/ipc_mojo_handle_attachment.h +++ b/ipc/ipc_mojo_handle_attachment.h @@ -8,8 +8,8 @@ #include "base/files/file.h" #include "base/macros.h" #include "build/build_config.h" -#include "ipc/ipc_export.h" #include "ipc/ipc_message_attachment.h" +#include "ipc/ipc_message_support_export.h" #include "mojo/public/cpp/system/handle.h" namespace IPC { @@ -20,7 +20,8 @@ namespace internal { // This can hold any type of transferrable Mojo handle (i.e. message pipe, data // pipe, etc), but the receiver is expected to know what type of handle to // expect. -class IPC_EXPORT MojoHandleAttachment : public MessageAttachment { +class IPC_MESSAGE_SUPPORT_EXPORT MojoHandleAttachment + : public MessageAttachment { public: explicit MojoHandleAttachment(mojo::ScopedHandle handle); diff --git a/ipc/ipc_mojo_message_helper.cc b/ipc/ipc_mojo_message_helper.cc index a87a2d694d5f97..41ac70f4084dfe 100644 --- a/ipc/ipc_mojo_message_helper.cc +++ b/ipc/ipc_mojo_message_helper.cc @@ -33,7 +33,7 @@ bool MojoMessageHelper::ReadMessagePipeFrom( MessageAttachment::Type type = static_cast(attachment.get())->GetType(); if (type != MessageAttachment::Type::MOJO_HANDLE) { - LOG(ERROR) << "Unxpected attachment type:" << type; + LOG(ERROR) << "Unxpected attachment type:" << static_cast(type); return false; } diff --git a/ipc/ipc_mojo_message_helper.h b/ipc/ipc_mojo_message_helper.h index 4a71b5c96cd4c5..156c66782988ea 100644 --- a/ipc/ipc_mojo_message_helper.h +++ b/ipc/ipc_mojo_message_helper.h @@ -5,14 +5,14 @@ #ifndef IPC_IPC_MOJO_MESSAGE_HELPER_H_ #define IPC_IPC_MOJO_MESSAGE_HELPER_H_ -#include "ipc/ipc_export.h" #include "ipc/ipc_message.h" +#include "ipc/ipc_message_support_export.h" #include "mojo/public/cpp/system/message_pipe.h" namespace IPC { // Reads and writes |mojo::MessagePipe| from/to |Message|. -class IPC_EXPORT MojoMessageHelper { +class IPC_MESSAGE_SUPPORT_EXPORT MojoMessageHelper { public: static bool WriteMessagePipeTo(base::Pickle* message, mojo::ScopedMessagePipeHandle handle); diff --git a/ipc/ipc_mojo_param_traits.cc b/ipc/ipc_mojo_param_traits.cc index d814bd94235b7f..5eeb9f0fbb7b44 100644 --- a/ipc/ipc_mojo_param_traits.cc +++ b/ipc/ipc_mojo_param_traits.cc @@ -69,7 +69,7 @@ bool ParamTraits::Read(const base::Pickle* m, MessageAttachment::Type type = static_cast(attachment.get())->GetType(); if (type != MessageAttachment::Type::MOJO_HANDLE) { - DLOG(ERROR) << "Unexpected attachment type:" << type; + DLOG(ERROR) << "Unexpected attachment type:" << static_cast(type); return false; } diff --git a/ipc/ipc_platform_file.h b/ipc/ipc_platform_file.h index ea295af8c5455e..1704b943c3cba1 100644 --- a/ipc/ipc_platform_file.h +++ b/ipc/ipc_platform_file.h @@ -8,7 +8,7 @@ #include "base/files/file.h" #include "base/process/process.h" #include "build/build_config.h" -#include "ipc/ipc_export.h" +#include "ipc/ipc_message_support_export.h" #if defined(OS_POSIX) #include "base/file_descriptor_posix.h" @@ -17,7 +17,7 @@ namespace IPC { #if defined(OS_WIN) -class IPC_EXPORT PlatformFileForTransit { +class IPC_MESSAGE_SUPPORT_EXPORT PlatformFileForTransit { public: // Creates an invalid platform file. PlatformFileForTransit(); @@ -72,14 +72,14 @@ inline base::File PlatformFileForTransitToFile( // 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, - bool close_source_handle); +IPC_MESSAGE_SUPPORT_EXPORT PlatformFileForTransit +GetPlatformFileForTransit(base::PlatformFile file, bool close_source_handle); // 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 TakePlatformFileForTransit(base::File file); +IPC_MESSAGE_SUPPORT_EXPORT PlatformFileForTransit +TakePlatformFileForTransit(base::File file); } // namespace IPC diff --git a/ipc/ipc_platform_file_attachment_posix.h b/ipc/ipc_platform_file_attachment_posix.h index 9b0790093b0608..945c3455749e8c 100644 --- a/ipc/ipc_platform_file_attachment_posix.h +++ b/ipc/ipc_platform_file_attachment_posix.h @@ -5,8 +5,8 @@ #ifndef IPC_IPC_PLATFORM_FILE_ATTACHMENT_H_ #define IPC_IPC_PLATFORM_FILE_ATTACHMENT_H_ -#include "ipc/ipc_export.h" #include "ipc/ipc_message_attachment.h" +#include "ipc/ipc_message_support_export.h" namespace IPC { namespace internal { @@ -15,7 +15,8 @@ namespace internal { // PlatformFileAttachment optionally owns the file and |owning_| is set in that // case. Also, |file_| is not cleared even after the ownership is taken. // Some old clients require this strange behavior. -class IPC_EXPORT PlatformFileAttachment : public MessageAttachment { +class IPC_MESSAGE_SUPPORT_EXPORT PlatformFileAttachment + : public MessageAttachment { public: // Non-owning constructor explicit PlatformFileAttachment(base::PlatformFile file); diff --git a/ipc/ipc_sync_message.h b/ipc/ipc_sync_message.h index 7f0555134a222e..c9a1287a66d269 100644 --- a/ipc/ipc_sync_message.h +++ b/ipc/ipc_sync_message.h @@ -16,6 +16,7 @@ #include "build/build_config.h" #include "ipc/ipc_message.h" +#include "ipc/ipc_message_support_export.h" namespace base { class WaitableEvent; @@ -25,7 +26,7 @@ namespace IPC { class MessageReplyDeserializer; -class IPC_EXPORT SyncMessage : public Message { +class IPC_MESSAGE_SUPPORT_EXPORT SyncMessage : public Message { public: SyncMessage(int32_t routing_id, uint32_t type, @@ -79,7 +80,7 @@ class IPC_EXPORT SyncMessage : public Message { }; // Used to deserialize parameters from a reply to a synchronous message -class IPC_EXPORT MessageReplyDeserializer { +class IPC_MESSAGE_SUPPORT_EXPORT MessageReplyDeserializer { public: virtual ~MessageReplyDeserializer() {} bool SerializeOutputParameters(const Message& msg); diff --git a/ipc/mach_port_attachment_mac.h b/ipc/mach_port_attachment_mac.h index 861c4e30656351..ae41cd03d34e2e 100644 --- a/ipc/mach_port_attachment_mac.h +++ b/ipc/mach_port_attachment_mac.h @@ -10,15 +10,16 @@ #include "base/macros.h" #include "base/process/process_handle.h" -#include "ipc/ipc_export.h" #include "ipc/ipc_message_attachment.h" +#include "ipc/ipc_message_support_export.h" #include "ipc/mach_port_mac.h" namespace IPC { namespace internal { // This class represents an OSX mach_port_t attached to a Chrome IPC message. -class IPC_EXPORT MachPortAttachmentMac : public MessageAttachment { +class IPC_MESSAGE_SUPPORT_EXPORT MachPortAttachmentMac + : public MessageAttachment { public: // This constructor increments the ref count of |mach_port_| and takes // ownership of the result. Should only be called by the sender of a Chrome diff --git a/ipc/mach_port_mac.cc b/ipc/mach_port_mac.cc index 67043f2e39fd47..91663641714d7f 100644 --- a/ipc/mach_port_mac.cc +++ b/ipc/mach_port_mac.cc @@ -7,6 +7,7 @@ #include "base/logging.h" #include "base/memory/ref_counted.h" #include "base/strings/string_number_conversions.h" +#include "base/strings/stringprintf.h" #include "ipc/mach_port_attachment_mac.h" namespace IPC { diff --git a/ipc/mach_port_mac.h b/ipc/mach_port_mac.h index b95a37b47d0367..49ca1c3f206b26 100644 --- a/ipc/mach_port_mac.h +++ b/ipc/mach_port_mac.h @@ -8,8 +8,9 @@ #include #include "base/macros.h" -#include "ipc/ipc_export.h" -#include "ipc/ipc_message_macros.h" +#include "base/pickle.h" +#include "ipc/ipc_message_support_export.h" +#include "ipc/ipc_param_traits.h" namespace IPC { @@ -18,7 +19,7 @@ namespace IPC { // to the Mach port will be duplicated into the destination process by the // attachment broker. If needed, attachment brokering can be trivially extended // to support duplication of other types of rights. -class IPC_EXPORT MachPortMac { +class IPC_MESSAGE_SUPPORT_EXPORT MachPortMac { public: MachPortMac() : mach_port_(MACH_PORT_NULL) {} @@ -69,7 +70,7 @@ class IPC_EXPORT MachPortMac { }; template <> -struct IPC_EXPORT ParamTraits { +struct IPC_MESSAGE_SUPPORT_EXPORT ParamTraits { typedef MachPortMac param_type; static void Write(base::Pickle* m, const param_type& p); static bool Read(const base::Pickle* m, diff --git a/ipc/native_handle_type_converters.cc b/ipc/native_handle_type_converters.cc new file mode 100644 index 00000000000000..a0391b69112351 --- /dev/null +++ b/ipc/native_handle_type_converters.cc @@ -0,0 +1,49 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ipc/native_handle_type_converters.h" + +namespace mojo { + +// static +IPC::MessageAttachment::Type +TypeConverter:: + Convert(native::SerializedHandle_Type type) { + switch (type) { + case native::SerializedHandle_Type::MOJO_HANDLE: + return IPC::MessageAttachment::Type::MOJO_HANDLE; + case native::SerializedHandle_Type::PLATFORM_FILE: + return IPC::MessageAttachment::Type::PLATFORM_FILE; + case native::SerializedHandle_Type::WIN_HANDLE: + return IPC::MessageAttachment::Type::WIN_HANDLE; + case native::SerializedHandle_Type::MACH_PORT: + return IPC::MessageAttachment::Type::MACH_PORT; + case native::SerializedHandle_Type::FUCHSIA_HANDLE: + return IPC::MessageAttachment::Type::FUCHSIA_HANDLE; + } + NOTREACHED(); + return IPC::MessageAttachment::Type::MOJO_HANDLE; +} + +// static +native::SerializedHandle_Type TypeConverter< + native::SerializedHandle_Type, + IPC::MessageAttachment::Type>::Convert(IPC::MessageAttachment::Type type) { + switch (type) { + case IPC::MessageAttachment::Type::MOJO_HANDLE: + return native::SerializedHandle_Type::MOJO_HANDLE; + case IPC::MessageAttachment::Type::PLATFORM_FILE: + return native::SerializedHandle_Type::PLATFORM_FILE; + case IPC::MessageAttachment::Type::WIN_HANDLE: + return native::SerializedHandle_Type::WIN_HANDLE; + case IPC::MessageAttachment::Type::MACH_PORT: + return native::SerializedHandle_Type::MACH_PORT; + case IPC::MessageAttachment::Type::FUCHSIA_HANDLE: + return native::SerializedHandle_Type::FUCHSIA_HANDLE; + } + NOTREACHED(); + return native::SerializedHandle_Type::MOJO_HANDLE; +} + +} // namespace mojo diff --git a/ipc/native_handle_type_converters.h b/ipc/native_handle_type_converters.h new file mode 100644 index 00000000000000..81d26c5a9921fd --- /dev/null +++ b/ipc/native_handle_type_converters.h @@ -0,0 +1,30 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IPC_NATIVE_HANDLE_CONVERTER_H_ +#define IPC_NATIVE_HANDLE_CONVERTER_H_ + +#include "ipc/ipc_message_attachment.h" +#include "mojo/public/cpp/bindings/type_converter.h" // nogncheck +#include "mojo/public/interfaces/bindings/native_struct.mojom-shared.h" + +namespace mojo { + +template <> +struct TypeConverter { + static IPC::MessageAttachment::Type Convert( + native::SerializedHandle_Type type); +}; + +template <> +struct TypeConverter { + static native::SerializedHandle_Type Convert( + IPC::MessageAttachment::Type type); +}; + +} // namespace mojo + +#endif // IPC_NATIVE_HANDLE_CONVERTER_H_ diff --git a/mojo/public/cpp/bindings/BUILD.gn b/mojo/public/cpp/bindings/BUILD.gn index b732b54c26629c..d5608a31e468ce 100644 --- a/mojo/public/cpp/bindings/BUILD.gn +++ b/mojo/public/cpp/bindings/BUILD.gn @@ -16,6 +16,11 @@ component("bindings") { "$interfaces_bindings_gen_dir/interface_control_messages.mojom-shared.h", "$interfaces_bindings_gen_dir/interface_control_messages.mojom.cc", "$interfaces_bindings_gen_dir/interface_control_messages.mojom.h", + "$interfaces_bindings_gen_dir/native_struct.mojom-shared-internal.h", + "$interfaces_bindings_gen_dir/native_struct.mojom-shared.cc", + "$interfaces_bindings_gen_dir/native_struct.mojom-shared.h", + "$interfaces_bindings_gen_dir/native_struct.mojom.cc", + "$interfaces_bindings_gen_dir/native_struct.mojom.h", "$interfaces_bindings_gen_dir/pipe_control_messages.mojom-shared-internal.h", "$interfaces_bindings_gen_dir/pipe_control_messages.mojom-shared.cc", "$interfaces_bindings_gen_dir/pipe_control_messages.mojom-shared.h", @@ -86,9 +91,6 @@ component("bindings") { "lib/multiplex_router.h", "lib/native_enum_data.h", "lib/native_enum_serialization.h", - "lib/native_struct.cc", - "lib/native_struct_data.cc", - "lib/native_struct_data.h", "lib/native_struct_serialization.cc", "lib/native_struct_serialization.h", "lib/pipe_control_message_handler.cc", @@ -122,8 +124,6 @@ component("bindings") { "message.h", "message_header_validator.h", "native_enum.h", - "native_struct.h", - "native_struct_data_view.h", "pipe_control_message_handler.h", "pipe_control_message_handler_delegate.h", "pipe_control_message_proxy.h", @@ -149,12 +149,14 @@ component("bindings") { public_deps = [ ":struct_traits", "//base", + "//ipc:message_support", "//ipc:param_traits", "//mojo/public/cpp/system", ] deps = [ "//base", + "//ipc:native_handle_type_converters", "//mojo/public/interfaces/bindings:bindings__generator", "//mojo/public/interfaces/bindings:bindings_shared__generator", ] diff --git a/mojo/public/cpp/bindings/lib/bindings_internal.h b/mojo/public/cpp/bindings/lib/bindings_internal.h index f761145c31f27d..8bdb9c7b771ac3 100644 --- a/mojo/public/cpp/bindings/lib/bindings_internal.h +++ b/mojo/public/cpp/bindings/lib/bindings_internal.h @@ -35,8 +35,6 @@ class InterfaceRequestDataView; template class MapDataView; -class NativeStructDataView; - class StringDataView; namespace internal { @@ -55,8 +53,6 @@ class Array_Data; template class Map_Data; -class NativeStruct_Data; - using String_Data = Array_Data; inline size_t Align(size_t size) { @@ -299,14 +295,6 @@ struct MojomTypeTraits, false> { static const MojomTypeCategory category = MojomTypeCategory::MAP; }; -template <> -struct MojomTypeTraits { - using Data = internal::NativeStruct_Data; - using DataAsArrayElement = Pointer; - - static const MojomTypeCategory category = MojomTypeCategory::STRUCT; -}; - template <> struct MojomTypeTraits { using Data = String_Data; diff --git a/mojo/public/cpp/bindings/lib/native_struct.cc b/mojo/public/cpp/bindings/lib/native_struct.cc deleted file mode 100644 index 7b1a1a6c594f64..00000000000000 --- a/mojo/public/cpp/bindings/lib/native_struct.cc +++ /dev/null @@ -1,34 +0,0 @@ -// 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. - -#include "mojo/public/cpp/bindings/native_struct.h" - -#include "mojo/public/cpp/bindings/lib/hash_util.h" - -namespace mojo { - -// static -NativeStructPtr NativeStruct::New() { - return NativeStructPtr(base::in_place); -} - -NativeStruct::NativeStruct() {} - -NativeStruct::~NativeStruct() {} - -NativeStructPtr NativeStruct::Clone() const { - NativeStructPtr rv(New()); - rv->data = data; - return rv; -} - -bool NativeStruct::Equals(const NativeStruct& other) const { - return data == other.data; -} - -size_t NativeStruct::Hash(size_t seed) const { - return internal::Hash(seed, data); -} - -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/native_struct_data.cc b/mojo/public/cpp/bindings/lib/native_struct_data.cc deleted file mode 100644 index 0e5d2456927f82..00000000000000 --- a/mojo/public/cpp/bindings/lib/native_struct_data.cc +++ /dev/null @@ -1,22 +0,0 @@ -// 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. - -#include "mojo/public/cpp/bindings/lib/native_struct_data.h" - -#include "mojo/public/cpp/bindings/lib/buffer.h" -#include "mojo/public/cpp/bindings/lib/validation_context.h" - -namespace mojo { -namespace internal { - -// static -bool NativeStruct_Data::Validate(const void* data, - ValidationContext* validation_context) { - const ContainerValidateParams data_validate_params(0, false, nullptr); - return Array_Data::Validate(data, validation_context, - &data_validate_params); -} - -} // namespace internal -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/native_struct_data.h b/mojo/public/cpp/bindings/lib/native_struct_data.h deleted file mode 100644 index bf3e8906f70276..00000000000000 --- a/mojo/public/cpp/bindings/lib/native_struct_data.h +++ /dev/null @@ -1,61 +0,0 @@ -// 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 MOJO_PUBLIC_CPP_BINDINGS_LIB_NATIVE_STRUCT_DATA_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_NATIVE_STRUCT_DATA_H_ - -#include - -#include "base/macros.h" -#include "mojo/public/cpp/bindings/bindings_export.h" -#include "mojo/public/cpp/bindings/lib/array_internal.h" -#include "mojo/public/cpp/system/handle.h" - -namespace mojo { -namespace internal { - -class ValidationContext; - -class MOJO_CPP_BINDINGS_EXPORT NativeStruct_Data { - public: - class BufferWriter { - public: - BufferWriter() = default; - - void Allocate(size_t num_bytes, Buffer* buffer) { - array_writer_.Allocate(num_bytes, buffer); - } - - Array_Data::BufferWriter& array_writer() { return array_writer_; } - - bool is_null() const { return array_writer_.is_null(); } - NativeStruct_Data* data() { - return reinterpret_cast(array_writer_.data()); - } - NativeStruct_Data* operator->() { return data(); } - - private: - Array_Data::BufferWriter array_writer_; - - DISALLOW_COPY_AND_ASSIGN(BufferWriter); - }; - - static bool Validate(const void* data, ValidationContext* validation_context); - - // Unlike normal structs, the memory layout is exactly the same as an array - // of uint8_t. - Array_Data data; - - private: - NativeStruct_Data() = delete; - ~NativeStruct_Data() = delete; -}; - -static_assert(sizeof(Array_Data) == sizeof(NativeStruct_Data), - "Mismatched NativeStruct_Data and Array_Data size"); - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_NATIVE_STRUCT_DATA_H_ diff --git a/mojo/public/cpp/bindings/lib/native_struct_serialization.cc b/mojo/public/cpp/bindings/lib/native_struct_serialization.cc index 5834be7c053ca5..a31f8e4ec82eea 100644 --- a/mojo/public/cpp/bindings/lib/native_struct_serialization.cc +++ b/mojo/public/cpp/bindings/lib/native_struct_serialization.cc @@ -4,42 +4,121 @@ #include "mojo/public/cpp/bindings/lib/native_struct_serialization.h" +#include "ipc/ipc_message_attachment.h" +#include "ipc/ipc_message_attachment_set.h" +#include "ipc/native_handle_type_converters.h" +#include "mojo/public/cpp/bindings/lib/handle_interface_serialization.h" #include "mojo/public/cpp/bindings/lib/serialization.h" +#include "mojo/public/cpp/bindings/lib/serialization_forward.h" namespace mojo { namespace internal { // static void UnmappedNativeStructSerializerImpl::Serialize( - const NativeStructPtr& input, + const native::NativeStructPtr& input, Buffer* buffer, - NativeStruct_Data::BufferWriter* writer, + native::internal::NativeStruct_Data::BufferWriter* writer, SerializationContext* context) { if (!input) return; - const ContainerValidateParams params(0, false, nullptr); - internal::Serialize>( - input->data, buffer, &writer->array_writer(), ¶ms, context); + writer->Allocate(buffer); + + Array_Data::BufferWriter data_writer; + const mojo::internal::ContainerValidateParams data_validate_params(0, false, + nullptr); + mojo::internal::Serialize>( + input->data, buffer, &data_writer, &data_validate_params, context); + writer->data()->data.Set(data_writer.data()); + + mojo::internal::Array_Data>::BufferWriter handles_writer; + const mojo::internal::ContainerValidateParams handles_validate_params( + 0, false, nullptr); + mojo::internal::Serialize< + mojo::ArrayDataView<::mojo::native::SerializedHandleDataView>>( + input->handles, buffer, &handles_writer, &handles_validate_params, + context); + writer->data()->handles.Set(handles_writer.is_null() ? nullptr + : handles_writer.data()); } // static bool UnmappedNativeStructSerializerImpl::Deserialize( - NativeStruct_Data* input, - NativeStructPtr* output, + native::internal::NativeStruct_Data* input, + native::NativeStructPtr* output, + SerializationContext* context) { + if (!input) { + output->reset(); + return true; + } + + native::NativeStructDataView data_view(input, context); + return StructTraits<::mojo::native::NativeStructDataView, + native::NativeStructPtr>::Read(data_view, output); +} + +// static +void UnmappedNativeStructSerializerImpl::SerializeMessageContents( + IPC::Message* message, + Buffer* buffer, + native::internal::NativeStruct_Data::BufferWriter* writer, SerializationContext* context) { - Array_Data* data = reinterpret_cast*>(input); + writer->Allocate(buffer); + + // Allocate a uint8 array, initialize its header, and copy the Pickle in. + Array_Data::BufferWriter data_writer; + data_writer.Allocate(message->payload_size(), buffer); + memcpy(data_writer->storage(), message->payload(), message->payload_size()); + writer->data()->data.Set(data_writer.data()); + + if (message->attachment_set()->empty()) { + writer->data()->handles.Set(nullptr); + return; + } + + mojo::internal::Array_Data>::BufferWriter handles_writer; + auto* attachments = message->attachment_set(); + handles_writer.Allocate(attachments->size(), buffer); + for (unsigned i = 0; i < attachments->size(); ++i) { + native::internal::SerializedHandle_Data::BufferWriter handle_writer; + handle_writer.Allocate(buffer); + + auto attachment = attachments->GetAttachmentAt(i); + ScopedHandle handle = attachment->TakeMojoHandle(); + internal::Serializer::Serialize( + handle, &handle_writer->the_handle, context); + handle_writer->type = static_cast( + mojo::ConvertTo(attachment->GetType())); + handles_writer.data()->at(i).Set(handle_writer.data()); + } + writer->data()->handles.Set(handles_writer.data()); +} + +// static +bool UnmappedNativeStructSerializerImpl::DeserializeMessageAttachments( + native::internal::NativeStruct_Data* data, + SerializationContext* context, + IPC::Message* message) { + if (data->handles.is_null()) + return true; - NativeStructPtr result(NativeStruct::New()); - if (!internal::Deserialize>(data, &result->data, - context)) { - output = nullptr; - return false; + auto* handles_data = data->handles.Get(); + for (size_t i = 0; i < handles_data->size(); ++i) { + auto* handle_data = handles_data->at(i).Get(); + if (!handle_data) + return false; + ScopedHandle handle; + internal::Serializer::Deserialize( + &handle_data->the_handle, &handle, context); + auto attachment = IPC::MessageAttachment::CreateFromMojoHandle( + std::move(handle), + mojo::ConvertTo( + static_cast(handle_data->type))); + message->attachment_set()->AddAttachment(std::move(attachment)); } - if (!result->data) - *output = nullptr; - else - result.Swap(output); return true; } diff --git a/mojo/public/cpp/bindings/lib/native_struct_serialization.h b/mojo/public/cpp/bindings/lib/native_struct_serialization.h index 0983ec64a5b588..6aa4c3a4a85f94 100644 --- a/mojo/public/cpp/bindings/lib/native_struct_serialization.h +++ b/mojo/public/cpp/bindings/lib/native_struct_serialization.h @@ -12,38 +12,63 @@ #include "base/logging.h" #include "base/pickle.h" +#include "ipc/ipc_message.h" #include "ipc/ipc_param_traits.h" #include "mojo/public/cpp/bindings/bindings_export.h" #include "mojo/public/cpp/bindings/lib/array_internal.h" #include "mojo/public/cpp/bindings/lib/bindings_internal.h" -#include "mojo/public/cpp/bindings/lib/native_struct_data.h" #include "mojo/public/cpp/bindings/lib/serialization_forward.h" #include "mojo/public/cpp/bindings/lib/serialization_util.h" -#include "mojo/public/cpp/bindings/native_struct.h" -#include "mojo/public/cpp/bindings/native_struct_data_view.h" +#include "mojo/public/interfaces/bindings/native_struct.mojom.h" namespace mojo { namespace internal { +// Base class for the templated native struct serialization interface below, +// used to consolidated some shared logic and provide a basic +// Serialize/Deserialize for [Native] mojom structs which do not have a +// registered typemap in the current configuration (i.e. structs that are +// represented by a raw native::NativeStruct mojom struct in C++ bindings.) +struct MOJO_CPP_BINDINGS_EXPORT UnmappedNativeStructSerializerImpl { + static void Serialize( + const native::NativeStructPtr& input, + Buffer* buffer, + native::internal::NativeStruct_Data::BufferWriter* writer, + SerializationContext* context); + + static bool Deserialize(native::internal::NativeStruct_Data* input, + native::NativeStructPtr* output, + SerializationContext* context); + + static void SerializeMessageContents( + IPC::Message* message, + Buffer* buffer, + native::internal::NativeStruct_Data::BufferWriter* writer, + SerializationContext* context); + + static bool DeserializeMessageAttachments( + native::internal::NativeStruct_Data* data, + SerializationContext* context, + IPC::Message* message); +}; + template struct NativeStructSerializerImpl { using UserType = typename std::remove_const::type; using Traits = IPC::ParamTraits; - static void Serialize(MaybeConstUserType& value, - Buffer* buffer, - NativeStruct_Data::BufferWriter* writer, - SerializationContext* context) { - base::Pickle pickle; - Traits::Write(&pickle, value); - - // Allocate a uint8 array, initialize its header, and copy the Pickle in. - writer->Allocate(pickle.payload_size(), buffer); - memcpy(writer->array_writer()->storage(), pickle.payload(), - pickle.payload_size()); + static void Serialize( + MaybeConstUserType& value, + Buffer* buffer, + native::internal::NativeStruct_Data::BufferWriter* writer, + SerializationContext* context) { + IPC::Message message; + Traits::Write(&message, value); + UnmappedNativeStructSerializerImpl::SerializeMessageContents( + &message, buffer, writer, context); } - static bool Deserialize(NativeStruct_Data* data, + static bool Deserialize(native::internal::NativeStruct_Data* data, UserType* out, SerializationContext* context) { if (!data) @@ -61,7 +86,7 @@ struct NativeStructSerializerImpl { // Because ArrayHeader's num_bytes includes the length of the header and // Pickle's payload_size does not, we need to adjust the stored value // momentarily so Pickle can view the data. - ArrayHeader* header = reinterpret_cast(data); + ArrayHeader* header = reinterpret_cast(data->data.Get()); DCHECK_GE(header->num_bytes, sizeof(ArrayHeader)); header->num_bytes -= sizeof(ArrayHeader); @@ -69,10 +94,15 @@ struct NativeStructSerializerImpl { // Construct a view over the full Array_Data, including our hacked up // header. Pickle will infer from this that the header is 8 bytes long, // and the payload will contain all of the pickled bytes. - base::Pickle pickle_view(reinterpret_cast(header), - header->num_bytes + sizeof(ArrayHeader)); - base::PickleIterator iter(pickle_view); - if (!Traits::Read(&pickle_view, &iter, out)) + IPC::Message message_view(reinterpret_cast(header), + header->num_bytes + sizeof(ArrayHeader)); + base::PickleIterator iter(message_view); + if (!UnmappedNativeStructSerializerImpl::DeserializeMessageAttachments( + data, context, &message_view)) { + return false; + } + + if (!Traits::Read(&message_view, &iter, out)) return false; } @@ -83,26 +113,16 @@ struct NativeStructSerializerImpl { } }; -struct MOJO_CPP_BINDINGS_EXPORT UnmappedNativeStructSerializerImpl { - static void Serialize(const NativeStructPtr& input, - Buffer* buffer, - NativeStruct_Data::BufferWriter* writer, - SerializationContext* context); - static bool Deserialize(NativeStruct_Data* input, - NativeStructPtr* output, - SerializationContext* context); -}; - template <> -struct NativeStructSerializerImpl +struct NativeStructSerializerImpl : public UnmappedNativeStructSerializerImpl {}; template <> -struct NativeStructSerializerImpl +struct NativeStructSerializerImpl : public UnmappedNativeStructSerializerImpl {}; template -struct Serializer +struct Serializer : public NativeStructSerializerImpl {}; } // namespace internal diff --git a/mojo/public/cpp/bindings/lib/serialization.h b/mojo/public/cpp/bindings/lib/serialization.h index f5e89e29334226..90f64f3059f293 100644 --- a/mojo/public/cpp/bindings/lib/serialization.h +++ b/mojo/public/cpp/bindings/lib/serialization.h @@ -15,7 +15,6 @@ #include "mojo/public/cpp/bindings/lib/handle_interface_serialization.h" #include "mojo/public/cpp/bindings/lib/map_serialization.h" #include "mojo/public/cpp/bindings/lib/native_enum_serialization.h" -#include "mojo/public/cpp/bindings/lib/native_struct_serialization.h" #include "mojo/public/cpp/bindings/lib/string_serialization.h" #include "mojo/public/cpp/bindings/lib/template_util.h" #include "mojo/public/cpp/bindings/map_traits_stl.h" diff --git a/mojo/public/cpp/bindings/native_struct.h b/mojo/public/cpp/bindings/native_struct.h deleted file mode 100644 index ac27250bcc4221..00000000000000 --- a/mojo/public/cpp/bindings/native_struct.h +++ /dev/null @@ -1,51 +0,0 @@ -// 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 MOJO_PUBLIC_CPP_BINDINGS_NATIVE_STRUCT_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_NATIVE_STRUCT_H_ - -#include - -#include "base/optional.h" -#include "mojo/public/cpp/bindings/bindings_export.h" -#include "mojo/public/cpp/bindings/lib/native_struct_data.h" -#include "mojo/public/cpp/bindings/struct_ptr.h" -#include "mojo/public/cpp/bindings/type_converter.h" - -namespace mojo { - -class NativeStruct; -using NativeStructPtr = StructPtr; - -// Native-only structs correspond to "[Native] struct Foo;" definitions in -// mojom. -class MOJO_CPP_BINDINGS_EXPORT NativeStruct { - public: - using Data_ = internal::NativeStruct_Data; - - static NativeStructPtr New(); - - template - static NativeStructPtr From(const U& u) { - return TypeConverter::Convert(u); - } - - template - U To() const { - return TypeConverter::Convert(*this); - } - - NativeStruct(); - ~NativeStruct(); - - NativeStructPtr Clone() const; - bool Equals(const NativeStruct& other) const; - size_t Hash(size_t seed) const; - - base::Optional> data; -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_NATIVE_STRUCT_H_ diff --git a/mojo/public/cpp/bindings/native_struct_data_view.h b/mojo/public/cpp/bindings/native_struct_data_view.h deleted file mode 100644 index 613bd7a0b0e8b8..00000000000000 --- a/mojo/public/cpp/bindings/native_struct_data_view.h +++ /dev/null @@ -1,36 +0,0 @@ -// 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 MOJO_PUBLIC_CPP_BINDINGS_NATIVE_STRUCT_DATA_VIEW_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_NATIVE_STRUCT_DATA_VIEW_H_ - -#include "mojo/public/cpp/bindings/lib/native_struct_data.h" -#include "mojo/public/cpp/bindings/lib/serialization_context.h" - -namespace mojo { - -class NativeStructDataView { - public: - using Data_ = internal::NativeStruct_Data; - - NativeStructDataView() {} - - NativeStructDataView(Data_* data, internal::SerializationContext* context) - : data_(data) {} - - bool is_null() const { return !data_; } - - size_t size() const { return data_->data.size(); } - - uint8_t operator[](size_t index) const { return data_->data.at(index); } - - const uint8_t* data() const { return data_->data.storage(); } - - private: - Data_* data_ = nullptr; -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_NATIVE_STRUCT_DATA_VIEW_H_ diff --git a/mojo/public/cpp/bindings/tests/BUILD.gn b/mojo/public/cpp/bindings/tests/BUILD.gn index 456da1300e3cb9..136e8e6aec17de 100644 --- a/mojo/public/cpp/bindings/tests/BUILD.gn +++ b/mojo/public/cpp/bindings/tests/BUILD.gn @@ -28,6 +28,7 @@ source_set("tests") { "message_queue.cc", "message_queue.h", "multiplex_router_unittest.cc", + "native_struct_unittest.cc", "report_bad_message_unittest.cc", "request_response_unittest.cc", "router_test_util.cc", diff --git a/mojo/public/cpp/bindings/tests/data_view_unittest.cc b/mojo/public/cpp/bindings/tests/data_view_unittest.cc index e1bc83a4072cd6..cd88a6f74441eb 100644 --- a/mojo/public/cpp/bindings/tests/data_view_unittest.cc +++ b/mojo/public/cpp/bindings/tests/data_view_unittest.cc @@ -90,21 +90,24 @@ TEST_F(DataViewTest, NestedStruct) { TEST_F(DataViewTest, NativeStruct) { TestStructPtr obj(TestStruct::New()); - obj->f_native_struct = NativeStruct::New(); + obj->f_native_struct = native::NativeStruct::New(); obj->f_native_struct->data = std::vector({3, 2, 1}); auto data_view_holder = SerializeTestStruct(std::move(obj)); auto& data_view = *data_view_holder->data_view; - NativeStructDataView struct_data_view; + native::NativeStructDataView struct_data_view; data_view.GetFNativeStructDataView(&struct_data_view); - ASSERT_FALSE(struct_data_view.is_null()); - ASSERT_EQ(3u, struct_data_view.size()); - EXPECT_EQ(3, struct_data_view[0]); - EXPECT_EQ(2, struct_data_view[1]); - EXPECT_EQ(1, struct_data_view[2]); - EXPECT_EQ(3, *struct_data_view.data()); + ArrayDataView data_data_view; + struct_data_view.GetDataDataView(&data_data_view); + + ASSERT_FALSE(data_data_view.is_null()); + ASSERT_EQ(3u, data_data_view.size()); + EXPECT_EQ(3, data_data_view[0]); + EXPECT_EQ(2, data_data_view[1]); + EXPECT_EQ(1, data_data_view[2]); + EXPECT_EQ(3, *data_data_view.data()); } TEST_F(DataViewTest, BoolArray) { diff --git a/mojo/public/cpp/bindings/tests/hash_unittest.cc b/mojo/public/cpp/bindings/tests/hash_unittest.cc index 9ce1f5bc7b7e73..3a5bf4791c6a5b 100644 --- a/mojo/public/cpp/bindings/tests/hash_unittest.cc +++ b/mojo/public/cpp/bindings/tests/hash_unittest.cc @@ -22,14 +22,6 @@ TEST_F(HashTest, NestedStruct) { SimpleNestedStruct::New(ContainsOther::New(1)))); } -TEST_F(HashTest, UnmappedNativeStruct) { - // Just check that this template instantiation compiles. - ASSERT_EQ(::mojo::internal::Hash(::mojo::internal::kHashSeed, - UnmappedNativeStruct::New()), - ::mojo::internal::Hash(::mojo::internal::kHashSeed, - UnmappedNativeStruct::New())); -} - } // namespace } // namespace test } // namespace mojo diff --git a/mojo/public/cpp/bindings/tests/native_struct_unittest.cc b/mojo/public/cpp/bindings/tests/native_struct_unittest.cc new file mode 100644 index 00000000000000..6e3cbcbe3610b3 --- /dev/null +++ b/mojo/public/cpp/bindings/tests/native_struct_unittest.cc @@ -0,0 +1,98 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include + +#include + +#include "base/bind.h" +#include "base/macros.h" +#include "base/run_loop.h" +#include "base/test/scoped_task_environment.h" +#include "ipc/ipc_param_traits.h" +#include "mojo/public/cpp/bindings/binding.h" +#include "mojo/public/cpp/bindings/tests/bindings_test_base.h" +#include "mojo/public/cpp/system/message_pipe.h" +#include "mojo/public/cpp/system/wait.h" +#include "mojo/public/interfaces/bindings/tests/test_native_types.mojom.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace mojo { + +class NativeStructTest : public BindingsTestBase, + public test::NativeTypeTester { + public: + NativeStructTest() : binding_(this, mojo::MakeRequest(&proxy_)) {} + ~NativeStructTest() override = default; + + test::NativeTypeTester* proxy() { return proxy_.get(); } + + private: + // test::NativeTypeTester: + void PassNativeStruct(const test::TestNativeStruct& s, + const PassNativeStructCallback& callback) override { + callback.Run(s); + } + + void PassNativeStructWithAttachments( + test::TestNativeStructWithAttachments s, + const PassNativeStructWithAttachmentsCallback& callback) override { + callback.Run(std::move(s)); + } + + test::NativeTypeTesterPtr proxy_; + Binding binding_; + + DISALLOW_COPY_AND_ASSIGN(NativeStructTest); +}; + +TEST_P(NativeStructTest, NativeStruct) { + test::TestNativeStruct s("hello world", 5, 42); + base::RunLoop loop; + proxy()->PassNativeStruct( + s, base::Bind( + [](test::TestNativeStruct* expected_struct, base::RunLoop* loop, + const test::TestNativeStruct& passed) { + EXPECT_EQ(expected_struct->message(), passed.message()); + EXPECT_EQ(expected_struct->x(), passed.x()); + EXPECT_EQ(expected_struct->y(), passed.y()); + loop->Quit(); + }, + &s, &loop)); + loop.Run(); +} + +TEST_P(NativeStructTest, NativeStructWithAttachments) { + mojo::MessagePipe pipe; + const std::string kTestMessage = "hey hi"; + test::TestNativeStructWithAttachments s(kTestMessage, + std::move(pipe.handle0)); + base::RunLoop loop; + proxy()->PassNativeStructWithAttachments( + std::move(s), + base::Bind( + [](const std::string& expected_message, + mojo::ScopedMessagePipeHandle peer_pipe, base::RunLoop* loop, + test::TestNativeStructWithAttachments passed) { + // To ensure that the received pipe handle is functioning, we write + // to its peer and wait for the message to be received. + WriteMessageRaw(peer_pipe.get(), "ping", 4, nullptr, 0, + MOJO_WRITE_MESSAGE_FLAG_NONE); + auto pipe = passed.PassPipe(); + EXPECT_EQ(MOJO_RESULT_OK, + Wait(pipe.get(), MOJO_HANDLE_SIGNAL_READABLE)); + std::vector bytes; + EXPECT_EQ(MOJO_RESULT_OK, + ReadMessageRaw(pipe.get(), &bytes, nullptr, + MOJO_READ_MESSAGE_FLAG_NONE)); + EXPECT_EQ("ping", std::string(bytes.begin(), bytes.end())); + loop->Quit(); + }, + kTestMessage, base::Passed(&pipe.handle1), &loop)); + loop.Run(); +} + +INSTANTIATE_MOJO_BINDINGS_TEST_CASE_P(NativeStructTest); + +} // namespace mojo diff --git a/mojo/public/cpp/bindings/tests/struct_unittest.cc b/mojo/public/cpp/bindings/tests/struct_unittest.cc index 842b6ed665f895..b9b16b2c5e73fe 100644 --- a/mojo/public/cpp/bindings/tests/struct_unittest.cc +++ b/mojo/public/cpp/bindings/tests/struct_unittest.cc @@ -34,8 +34,8 @@ struct SerializeStructHelperTraits { }; template <> -struct SerializeStructHelperTraits { - using DataView = NativeStructDataView; +struct SerializeStructHelperTraits { + using DataView = native::NativeStructDataView; }; template @@ -375,10 +375,10 @@ TEST_F(StructTest, Versioning_NewToOld) { // Serialization test for native struct. TEST_F(StructTest, Serialization_NativeStruct) { - using Data = mojo::internal::NativeStruct_Data; + using Data = native::internal::NativeStruct_Data; { // Serialization of a null native struct. - NativeStructPtr native; + native::NativeStructPtr native; mojo::Message message; mojo::internal::SerializationContext context; @@ -386,46 +386,46 @@ TEST_F(StructTest, Serialization_NativeStruct) { EXPECT_EQ(0u, SerializeStruct(native, &message, &context, &data)); EXPECT_EQ(nullptr, data); - NativeStructPtr output_native; - mojo::internal::Deserialize(data, &output_native, - &context); + native::NativeStructPtr output_native; + mojo::internal::Deserialize( + data, &output_native, &context); EXPECT_TRUE(output_native.is_null()); } { // Serialization of a native struct with null data. - NativeStructPtr native(NativeStruct::New()); + native::NativeStructPtr native(native::NativeStruct::New()); mojo::Message message; mojo::internal::SerializationContext context; Data* data = nullptr; - EXPECT_EQ(0u, SerializeStruct(native, &message, &context, &data)); - EXPECT_EQ(nullptr, data); + EXPECT_EQ(32u, SerializeStruct(native, &message, &context, &data)); + EXPECT_EQ(0u, data->data.Get()->size()); - NativeStructPtr output_native; - mojo::internal::Deserialize(data, &output_native, - &context); - EXPECT_TRUE(output_native.is_null()); + native::NativeStructPtr output_native; + mojo::internal::Deserialize( + data, &output_native, &context); + EXPECT_TRUE(output_native->data.empty()); } { - NativeStructPtr native(NativeStruct::New()); + native::NativeStructPtr native(native::NativeStruct::New()); native->data = std::vector{'X', 'Y'}; mojo::Message message; mojo::internal::SerializationContext context; Data* data = nullptr; - EXPECT_EQ(16u, SerializeStruct(native, &message, &context, &data)); - EXPECT_NE(nullptr, data); + EXPECT_EQ(40u, SerializeStruct(native, &message, &context, &data)); + EXPECT_EQ(2u, data->data.Get()->size()); - NativeStructPtr output_native; - mojo::internal::Deserialize(data, &output_native, - &context); + native::NativeStructPtr output_native; + mojo::internal::Deserialize( + data, &output_native, &context); ASSERT_TRUE(output_native); - ASSERT_FALSE(output_native->data->empty()); - EXPECT_EQ(2u, output_native->data->size()); - EXPECT_EQ('X', (*output_native->data)[0]); - EXPECT_EQ('Y', (*output_native->data)[1]); + ASSERT_FALSE(output_native->data.empty()); + EXPECT_EQ(2u, output_native->data.size()); + EXPECT_EQ('X', output_native->data[0]); + EXPECT_EQ('Y', output_native->data[1]); } } diff --git a/mojo/public/cpp/bindings/tests/test_native_types.cc b/mojo/public/cpp/bindings/tests/test_native_types.cc new file mode 100644 index 00000000000000..b11cc231728808 --- /dev/null +++ b/mojo/public/cpp/bindings/tests/test_native_types.cc @@ -0,0 +1,99 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "mojo/public/cpp/bindings/tests/test_native_types.h" + +#include "base/macros.h" +#include "ipc/ipc_mojo_message_helper.h" + +namespace mojo { +namespace test { + +TestNativeStruct::TestNativeStruct() = default; + +TestNativeStruct::TestNativeStruct(const std::string& message, int x, int y) + : message_(message), x_(x), y_(y) {} + +TestNativeStruct::~TestNativeStruct() = default; + +TestNativeStructWithAttachments::TestNativeStructWithAttachments() = default; + +TestNativeStructWithAttachments::TestNativeStructWithAttachments( + TestNativeStructWithAttachments&& other) = default; + +TestNativeStructWithAttachments::TestNativeStructWithAttachments( + const std::string& message, + mojo::ScopedMessagePipeHandle pipe) + : message_(message), pipe_(std::move(pipe)) {} + +TestNativeStructWithAttachments::~TestNativeStructWithAttachments() = default; + +TestNativeStructWithAttachments& TestNativeStructWithAttachments::operator=( + TestNativeStructWithAttachments&& other) = default; + +} // namespace test +} // namespace mojo + +namespace IPC { + +// static +void ParamTraits::Write(base::Pickle* m, + const param_type& p) { + m->WriteString(p.message()); + m->WriteInt(p.x()); + m->WriteInt(p.y()); +} + +// static +bool ParamTraits::Read(const base::Pickle* m, + base::PickleIterator* iter, + param_type* r) { + std::string message; + if (!iter->ReadString(&message)) + return false; + int x, y; + if (!iter->ReadInt(&x) || !iter->ReadInt(&y)) + return false; + r->set_message(message); + r->set_x(x); + r->set_y(y); + return true; +} + +// static +void ParamTraits::Log(const param_type& p, + std::string* l) {} + +// static +void ParamTraits::Write( + Message* m, + const param_type& p) { + m->WriteString(p.message()); + IPC::MojoMessageHelper::WriteMessagePipeTo(m, p.PassPipe()); +} + +// static +bool ParamTraits::Read( + const Message* m, + base::PickleIterator* iter, + param_type* r) { + std::string message; + if (!iter->ReadString(&message)) + return false; + r->set_message(message); + + mojo::ScopedMessagePipeHandle pipe; + if (!IPC::MojoMessageHelper::ReadMessagePipeFrom(m, iter, &pipe)) + return false; + + r->set_pipe(std::move(pipe)); + return true; +} + +// static +void ParamTraits::Log( + const param_type& p, + std::string* l) {} + +} // namespace IPC diff --git a/mojo/public/cpp/bindings/tests/test_native_types.h b/mojo/public/cpp/bindings/tests/test_native_types.h new file mode 100644 index 00000000000000..f16bf2b462e0ec --- /dev/null +++ b/mojo/public/cpp/bindings/tests/test_native_types.h @@ -0,0 +1,84 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include + +#include "base/macros.h" +#include "ipc/ipc_message.h" +#include "ipc/ipc_param_traits.h" +#include "mojo/public/cpp/system/message_pipe.h" + +namespace mojo { +namespace test { + +class TestNativeStruct { + public: + TestNativeStruct(); + TestNativeStruct(const std::string& message, int x, int y); + ~TestNativeStruct(); + + const std::string& message() const { return message_; } + void set_message(const std::string& message) { message_ = message; } + + int x() const { return x_; } + void set_x(int x) { x_ = x; } + + int y() const { return y_; } + void set_y(int y) { y_ = y; } + + private: + std::string message_; + int x_, y_; +}; + +class TestNativeStructWithAttachments { + public: + TestNativeStructWithAttachments(); + TestNativeStructWithAttachments(TestNativeStructWithAttachments&& other); + TestNativeStructWithAttachments(const std::string& message, + ScopedMessagePipeHandle pipe); + ~TestNativeStructWithAttachments(); + + TestNativeStructWithAttachments& operator=( + TestNativeStructWithAttachments&& other); + + const std::string& message() const { return message_; } + void set_message(const std::string& message) { message_ = message; } + + void set_pipe(mojo::ScopedMessagePipeHandle pipe) { pipe_ = std::move(pipe); } + mojo::ScopedMessagePipeHandle PassPipe() const { return std::move(pipe_); } + + private: + std::string message_; + mutable mojo::ScopedMessagePipeHandle pipe_; + + DISALLOW_COPY_AND_ASSIGN(TestNativeStructWithAttachments); +}; + +} // namespace test +} // namespace mojo + +namespace IPC { + +template <> +struct ParamTraits { + using param_type = mojo::test::TestNativeStruct; + + 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 { + using param_type = mojo::test::TestNativeStructWithAttachments; + + static void Write(Message* m, const param_type& p); + static bool Read(const Message* m, base::PickleIterator* iter, param_type* r); + static void Log(const param_type& p, std::string* l); +}; + +} // namespace IPC diff --git a/mojo/public/cpp/bindings/tests/test_native_types_chromium.typemap b/mojo/public/cpp/bindings/tests/test_native_types_chromium.typemap index 50e8076a505893..da99a1a8d7b2fd 100644 --- a/mojo/public/cpp/bindings/tests/test_native_types_chromium.typemap +++ b/mojo/public/cpp/bindings/tests/test_native_types_chromium.typemap @@ -3,9 +3,13 @@ # found in the LICENSE file. mojom = "//mojo/public/interfaces/bindings/tests/test_native_types.mojom" -public_headers = [ "//mojo/public/cpp/bindings/tests/pickled_types_chromium.h" ] +public_headers = [ + "//mojo/public/cpp/bindings/tests/pickled_types_chromium.h", + "//mojo/public/cpp/bindings/tests/test_native_types.h", +] sources = [ "//mojo/public/cpp/bindings/tests/pickled_types_chromium.cc", + "//mojo/public/cpp/bindings/tests/test_native_types.cc", ] deps = [ "//ipc", @@ -14,4 +18,6 @@ deps = [ type_mappings = [ "mojo.test.PickledEnum=mojo::test::PickledEnumChromium", "mojo.test.PickledStruct=mojo::test::PickledStructChromium[move_only]", + "mojo.test.TestNativeStructMojom=mojo::test::TestNativeStruct", + "mojo.test.TestNativeStructWithAttachmentsMojom=mojo::test::TestNativeStructWithAttachments[move_only]", ] diff --git a/mojo/public/cpp/bindings/tests/wtf_hash_unittest.cc b/mojo/public/cpp/bindings/tests/wtf_hash_unittest.cc index 9ee97c3c2fb8aa..aaf1c1077dda98 100644 --- a/mojo/public/cpp/bindings/tests/wtf_hash_unittest.cc +++ b/mojo/public/cpp/bindings/tests/wtf_hash_unittest.cc @@ -25,14 +25,6 @@ TEST_F(WTFHashTest, NestedStruct) { blink::SimpleNestedStruct::New(blink::ContainsOther::New(1)))); } -TEST_F(WTFHashTest, UnmappedNativeStruct) { - // Just check that this template instantiation compiles. - ASSERT_EQ(::mojo::internal::Hash(::mojo::internal::kHashSeed, - blink::UnmappedNativeStruct::New()), - ::mojo::internal::Hash(::mojo::internal::kHashSeed, - blink::UnmappedNativeStruct::New())); -} - TEST_F(WTFHashTest, Enum) { // Just check that this template instantiation compiles. diff --git a/mojo/public/interfaces/bindings/BUILD.gn b/mojo/public/interfaces/bindings/BUILD.gn index 3bd98de02f4c51..4608db085ebd9f 100644 --- a/mojo/public/interfaces/bindings/BUILD.gn +++ b/mojo/public/interfaces/bindings/BUILD.gn @@ -8,9 +8,12 @@ mojom("bindings") { visibility = [] sources = [ "interface_control_messages.mojom", + "native_struct.mojom", "pipe_control_messages.mojom", ] + allow_native_structs = false + component_output_prefix = "mojo_public_interfaces_bindings" export_class_attribute = "MOJO_CPP_BINDINGS_EXPORT" export_define = "MOJO_CPP_BINDINGS_IMPLEMENTATION" diff --git a/mojo/public/interfaces/bindings/native_struct.mojom b/mojo/public/interfaces/bindings/native_struct.mojom new file mode 100644 index 00000000000000..f2e869cf620572 --- /dev/null +++ b/mojo/public/interfaces/bindings/native_struct.mojom @@ -0,0 +1,26 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +[JavaPackage="org.chromium.mojo.native_types"] +module mojo.native; + +struct SerializedHandle { + handle the_handle; + + enum Type { + MOJO_HANDLE, + PLATFORM_FILE, + WIN_HANDLE, + MACH_PORT, + FUCHSIA_HANDLE, + }; + + Type type; +}; + +[CustomSerializer] +struct NativeStruct { + array data; + array? handles; +}; diff --git a/mojo/public/interfaces/bindings/tests/test_native_types.mojom b/mojo/public/interfaces/bindings/tests/test_native_types.mojom index 3df43182a37ed9..caa6a71c569cc8 100644 --- a/mojo/public/interfaces/bindings/tests/test_native_types.mojom +++ b/mojo/public/interfaces/bindings/tests/test_native_types.mojom @@ -36,3 +36,15 @@ interface RectService { GetLargestRect() => (TypemappedRect largest); PassSharedRect(SharedTypemappedRect r) => (SharedTypemappedRect passed); }; + +[Native] +struct TestNativeStructMojom; + +[Native] +struct TestNativeStructWithAttachmentsMojom; + +interface NativeTypeTester { + PassNativeStruct(TestNativeStructMojom s) => (TestNativeStructMojom passed); + PassNativeStructWithAttachments(TestNativeStructWithAttachmentsMojom s) + => (TestNativeStructWithAttachmentsMojom s); +}; diff --git a/mojo/public/tools/bindings/generators/cpp_templates/module-shared-internal.h.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/module-shared-internal.h.tmpl index 3033a997e06e8f..21e502584382de 100644 --- a/mojo/public/tools/bindings/generators/cpp_templates/module-shared-internal.h.tmpl +++ b/mojo/public/tools/bindings/generators/cpp_templates/module-shared-internal.h.tmpl @@ -15,13 +15,16 @@ #include "mojo/public/cpp/bindings/lib/bindings_internal.h" #include "mojo/public/cpp/bindings/lib/map_data_internal.h" #include "mojo/public/cpp/bindings/lib/native_enum_data.h" -#include "mojo/public/cpp/bindings/lib/native_struct_data.h" #include "mojo/public/cpp/bindings/lib/buffer.h" {%- for import in imports %} #include "{{import.path}}-shared-internal.h" {%- endfor %} +{%- if allow_native_structs %} +#include "mojo/public/interfaces/bindings/native_struct.mojom-shared-internal.h" +{%- endif %} + {%- if export_header %} #include "{{export_header}}" {%- endif %} @@ -40,7 +43,7 @@ namespace internal { {#--- Internal forward declarations #} {%- for struct in structs %} {%- if struct|is_native_only_kind %} -using {{struct.name}}_Data = mojo::internal::NativeStruct_Data; +using {{struct.name}}_Data = mojo::native::internal::NativeStruct_Data; {%- else %} class {{struct.name}}_Data; {%- endif %} diff --git a/mojo/public/tools/bindings/generators/cpp_templates/module-shared.h.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/module-shared.h.tmpl index 148dc7aeb51248..58ced630ee497d 100644 --- a/mojo/public/tools/bindings/generators/cpp_templates/module-shared.h.tmpl +++ b/mojo/public/tools/bindings/generators/cpp_templates/module-shared.h.tmpl @@ -50,13 +50,16 @@ namespace {{namespace}} { #include "mojo/public/cpp/bindings/lib/serialization.h" #include "mojo/public/cpp/bindings/map_data_view.h" #include "mojo/public/cpp/bindings/native_enum.h" -#include "mojo/public/cpp/bindings/native_struct_data_view.h" #include "mojo/public/cpp/bindings/string_data_view.h" #include "{{module.path}}-shared-internal.h" {%- for import in imports %} #include "{{import.path}}-shared.h" {%- endfor %} +{% if allow_native_structs %} +#include "mojo/public/cpp/bindings/lib/native_struct_serialization.h" +{%- endif %} + {%- if export_header %} #include "{{export_header}}" {%- endif %} @@ -66,7 +69,7 @@ namespace {{namespace}} { {#--- Struct Forward Declarations -#} {%- for struct in structs %} {%- if struct|is_native_only_kind %} -using {{struct.name}}DataView = mojo::NativeStructDataView; +using {{struct.name}}DataView = mojo::native::NativeStructDataView; {%- else %} class {{struct.name}}DataView; {%- endif %} diff --git a/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl index 6460ebac40847e..a90f64228129f1 100644 --- a/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl +++ b/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl @@ -52,7 +52,6 @@ namespace {{variant}} { #include "mojo/public/cpp/bindings/lib/control_message_handler.h" #include "mojo/public/cpp/bindings/lib/control_message_proxy.h" #include "mojo/public/cpp/bindings/lib/serialization.h" -#include "mojo/public/cpp/bindings/native_struct.h" #include "mojo/public/cpp/bindings/raw_ptr_impl_ref_traits.h" #include "mojo/public/cpp/bindings/struct_ptr.h" #include "mojo/public/cpp/bindings/struct_traits.h" @@ -78,6 +77,10 @@ namespace {{variant}} { #include "third_party/WebKit/Source/platform/wtf/text/WTFString.h" {%- endif %} +{% if allow_native_structs %} +#include "mojo/public/cpp/bindings/lib/native_struct_serialization.h" +{%- endif %} + {%- for header in extra_public_headers %} #include "{{header}}" {%- endfor %} @@ -131,8 +134,8 @@ using {{interface.name}}AssociatedRequest = {#--- Struct Forward Declarations -#} {% for struct in structs %} {%- if struct|is_native_only_kind %} -using {{struct.name}} = mojo::NativeStruct; -using {{struct.name}}Ptr = mojo::NativeStructPtr; +using {{struct.name}} = mojo::native::NativeStruct; +using {{struct.name}}Ptr = mojo::native::NativeStructPtr; {%- else %} class {{struct.name}}; {%- if struct|should_inline %} diff --git a/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_declaration.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_declaration.tmpl index 61799a8f26ca89..5571e8449f9d9c 100644 --- a/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_declaration.tmpl +++ b/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_declaration.tmpl @@ -2,6 +2,8 @@ {%- set data_view = struct|get_qualified_name_for_kind ~ "DataView" %} {%- set data_type = struct|get_qualified_name_for_kind(internal=True) %} +{%- if not struct|use_custom_serializer %} + namespace internal { template @@ -35,3 +37,5 @@ struct Serializer<{{data_view}}, MaybeConstUserType> { }; } // namespace internal + +{%- endif %} diff --git a/mojo/public/tools/bindings/generators/mojom_cpp_generator.py b/mojo/public/tools/bindings/generators/mojom_cpp_generator.py index 08514cb7b5cf95..c60e36d593a378 100644 --- a/mojo/public/tools/bindings/generators/mojom_cpp_generator.py +++ b/mojo/public/tools/bindings/generators/mojom_cpp_generator.py @@ -134,6 +134,10 @@ def IsNativeOnlyKind(kind): kind.native_only +def UseCustomSerializer(kind): + return mojom.IsStructKind(kind) and kind.custom_serializer + + def AllEnumValues(enum): """Return all enum values associated with an enum. @@ -286,6 +290,7 @@ def _GetJinjaExports(self): return { "all_enums": all_enums, + "allow_native_structs": self.allow_native_structs, "enums": self.module.enums, "export_attribute": self.export_attribute, "export_header": self.export_header, @@ -359,6 +364,7 @@ def GetFilters(self): "struct_constructors": self._GetStructConstructors, "under_to_camel": generator.ToCamel, "unmapped_type_for_serializer": self._GetUnmappedTypeForSerializer, + "use_custom_serializer": UseCustomSerializer, "wtf_hash_fn_name_for_enum": GetWtfHashFnNameForEnum, } return cpp_filters @@ -457,6 +463,8 @@ def Check(kind): if mojom.IsNullableKind(kind): return False elif mojom.IsStructKind(kind): + if kind.native_only: + return False if (self._IsTypemappedKind(kind) and not self.typemap[self._GetFullMojomNameForKind(kind)]["hashable"]): return False diff --git a/mojo/public/tools/bindings/mojom.gni b/mojo/public/tools/bindings/mojom.gni index 5018a7b0932da1..5fa42bfff98823 100644 --- a/mojo/public/tools/bindings/mojom.gni +++ b/mojo/public/tools/bindings/mojom.gni @@ -174,6 +174,16 @@ if (enable_mojom_typemapping) { # deserialization, and validation logic at the expensive of increased # code size. Defaults to |false|. # +# disable_variants (optional) +# If |true|, no variant sources will be generated for the target. Defaults +# to |false|. +# +# allow_native_structs (optional) +# If set to |true| (the default), mojoms in this target may apply the +# [Native] attribute to struct declarations, causing that mojom struct to +# be serialized and deserialized using a legacy IPC::ParamTraits +# specialization. +# # component_output_prefix (optional) # The prefix to use for the output_name of any component library emitted # for generated C++ bindings. If this is omitted, C++ bindings targets are @@ -313,6 +323,10 @@ template("mojom") { rebase_path("$root_gen_dir/mojo/public/tools/bindings", root_build_dir), ] + if (!defined(invoker.allow_native_structs) || invoker.allow_native_structs) { + common_generator_args += [ "--allow_native_structs" ] + } + if (defined(invoker.import_dirs)) { foreach(import_dir, invoker.import_dirs) { common_generator_args += [ @@ -476,7 +490,14 @@ template("mojom") { } # Generate code for variants. - foreach(bindings_configuration, _bindings_configurations) { + if (!defined(invoker.disable_variants) || !invoker.disable_variants) { + enabled_configurations = _bindings_configurations + } else { + first_config = _bindings_configurations[0] + assert(!defined(first_config.variant)) + enabled_configurations = [ first_config ] + } + foreach(bindings_configuration, enabled_configurations) { cpp_only = false if (defined(invoker.cpp_only)) { cpp_only = invoker.cpp_only diff --git a/mojo/public/tools/bindings/mojom_bindings_generator.py b/mojo/public/tools/bindings/mojom_bindings_generator.py index cc8101613ea865..a12f8917b56947 100755 --- a/mojo/public/tools/bindings/mojom_bindings_generator.py +++ b/mojo/public/tools/bindings/mojom_bindings_generator.py @@ -208,7 +208,8 @@ def _GenerateModule(self, args, remaining_args, generator_modules, export_attribute=args.export_attribute, export_header=args.export_header, generate_non_variant_code=args.generate_non_variant_code, - support_lazy_serialization=args.support_lazy_serialization) + support_lazy_serialization=args.support_lazy_serialization, + allow_native_structs=args.allow_native_structs) filtered_args = [] if hasattr(generator_module, 'GENERATOR_PREFIX'): prefix = '--' + generator_module.GENERATOR_PREFIX + '_' @@ -367,6 +368,11 @@ def main(): "--support_lazy_serialization", help="If set, generated bindings will serialize lazily when possible.", action="store_true") + generate_parser.add_argument( + "--allow_native_structs", + help="Allows the [Native] attribute to be specified on structs within " + "the mojom file. Must not be specified on internal bindings mojom or " + "other dependencies thereof.", action="store_true") generate_parser.set_defaults(func=_Generate) precompile_parser = subparsers.add_parser("precompile", diff --git a/mojo/public/tools/bindings/pylib/mojom/generate/generator.py b/mojo/public/tools/bindings/pylib/mojom/generate/generator.py index 4d81a13dbd99c2..f59c33db21c3a7 100644 --- a/mojo/public/tools/bindings/pylib/mojom/generate/generator.py +++ b/mojo/public/tools/bindings/pylib/mojom/generate/generator.py @@ -157,7 +157,7 @@ def __init__(self, module, output_dir=None, typemap=None, variant=None, bytecode_path=None, for_blink=False, use_once_callback=False, js_bindings_mode="new", export_attribute=None, export_header=None, generate_non_variant_code=False, - support_lazy_serialization=False): + support_lazy_serialization=False, allow_native_structs=False): self.module = module self.output_dir = output_dir self.typemap = typemap or {} @@ -170,6 +170,7 @@ def __init__(self, module, output_dir=None, typemap=None, variant=None, self.export_header = export_header self.generate_non_variant_code = generate_non_variant_code self.support_lazy_serialization = support_lazy_serialization + self.allow_native_structs = allow_native_structs def Write(self, contents, filename): if self.output_dir is None: diff --git a/mojo/public/tools/bindings/pylib/mojom/generate/module.py b/mojo/public/tools/bindings/pylib/mojom/generate/module.py index 8208f7b5dd582f..ebe5601b0a35b6 100644 --- a/mojo/public/tools/bindings/pylib/mojom/generate/module.py +++ b/mojo/public/tools/bindings/pylib/mojom/generate/module.py @@ -316,6 +316,8 @@ class Struct(ReferenceKind): name: {str} The stylized name. native_only: {bool} Does the struct have a body (i.e. any fields) or is it purely a native struct. + custom_serializer: {bool} Should we generate a serializer for the struct or + will one be provided by non-generated code. fields: {List[StructField]} The members of the struct. enums: {List[Enum]} The enums defined in the struct scope. constants: {List[Constant]} The constants defined in the struct scope. @@ -326,6 +328,7 @@ class Struct(ReferenceKind): ReferenceKind.AddSharedProperty('mojom_name') ReferenceKind.AddSharedProperty('name') ReferenceKind.AddSharedProperty('native_only') + ReferenceKind.AddSharedProperty('custom_serializer') ReferenceKind.AddSharedProperty('fields') ReferenceKind.AddSharedProperty('enums') ReferenceKind.AddSharedProperty('constants') @@ -339,6 +342,7 @@ def __init__(self, mojom_name=None, module=None, attributes=None): ReferenceKind.__init__(self, spec, False, module) self.mojom_name = mojom_name self.native_only = False + self.custom_serializer = False self.fields = [] self.enums = [] self.constants = [] diff --git a/mojo/public/tools/bindings/pylib/mojom/generate/translate.py b/mojo/public/tools/bindings/pylib/mojom/generate/translate.py index f1d8f4264ec5dc..4153e7456cfa63 100644 --- a/mojo/public/tools/bindings/pylib/mojom/generate/translate.py +++ b/mojo/public/tools/bindings/pylib/mojom/generate/translate.py @@ -273,6 +273,9 @@ def _Struct(module, parsed_struct): raise Exception("Native-only struct declarations must include a " + "Native attribute.") + if struct.attributes and struct.attributes.get('CustomSerializer', False): + struct.custom_serializer = True + return struct def _Union(module, parsed_union):