|  | // Copyright 2014 The Chromium Authors | 
|  | // 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_MESSAGE_H_ | 
|  | #define MOJO_PUBLIC_CPP_BINDINGS_MESSAGE_H_ | 
|  |  | 
|  | #include <stddef.h> | 
|  | #include <stdint.h> | 
|  |  | 
|  | #include <memory> | 
|  | #include <string_view> | 
|  | #include <vector> | 
|  |  | 
|  | #include "base/check_op.h" | 
|  | #include "base/compiler_specific.h" | 
|  | #include "base/component_export.h" | 
|  | #include "base/containers/span.h" | 
|  | #include "base/functional/callback.h" | 
|  | #include "base/memory/ptr_util.h" | 
|  | #include "base/memory/raw_ptr.h" | 
|  | #include "mojo/public/cpp/bindings/connection_group.h" | 
|  | #include "mojo/public/cpp/bindings/lib/buffer.h" | 
|  | #include "mojo/public/cpp/bindings/lib/message_internal.h" | 
|  | #include "mojo/public/cpp/bindings/lib/unserialized_message_context.h" | 
|  | #include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h" | 
|  | #include "mojo/public/cpp/system/message.h" | 
|  | #include "third_party/perfetto/include/perfetto/tracing/traced_value_forward.h" | 
|  |  | 
|  | namespace mojo { | 
|  |  | 
|  | class AssociatedGroupController; | 
|  |  | 
|  | using ReportBadMessageCallback = | 
|  | base::OnceCallback<void(std::string_view error)>; | 
|  |  | 
|  | // Message is a holder for the data and handles to be sent over a MessagePipe. | 
|  | // Message owns its data and handles, but a consumer of Message is free to | 
|  | // mutate the data and handles. The message's data is comprised of a header | 
|  | // followed by payload. | 
|  | class COMPONENT_EXPORT(MOJO_CPP_BINDINGS_BASE) Message { | 
|  | public: | 
|  | static const uint32_t kFlagExpectsResponse = 1 << 0; | 
|  | static const uint32_t kFlagIsResponse = 1 << 1; | 
|  | static const uint32_t kFlagIsSync = 1 << 2; | 
|  | static const uint32_t kFlagNoInterrupt = 1 << 3; | 
|  | static const uint32_t kFlagIsUrgent = 1 << 4; | 
|  |  | 
|  | // Constructs a new serialized Message object from an existing | 
|  | // ScopedMessageHandle; e.g., one read from a message pipe. | 
|  | // | 
|  | // If the message had any handles attached, they will be extracted and | 
|  | // retrievable via |handles()|. Such messages may NOT be sent back over | 
|  | // another message pipe, but are otherwise safe to inspect and pass around. | 
|  | // | 
|  | // If handles are attached and their extraction fails for any reason, | 
|  | // |*handle| remains unchanged and the returned Message will be null (i.e. | 
|  | // calling IsNull() on it will return |true|). | 
|  | static Message CreateFromMessageHandle(ScopedMessageHandle* message_handle); | 
|  |  | 
|  | // Constructs an uninitialized Message object. | 
|  | Message(); | 
|  |  | 
|  | // Constructs a new message with an unserialized context attached. This | 
|  | // message may be serialized later if necessary. | 
|  | Message(std::unique_ptr<internal::UnserializedMessageContext> context, | 
|  | MojoCreateMessageFlags create_message_flags); | 
|  |  | 
|  | // Constructs a new serialized Message object with optional handles attached. | 
|  | // This message is fully functional and may be exchanged for a | 
|  | // ScopedMessageHandle for transit over a message pipe. See TakeMojoMessage(). | 
|  | // | 
|  | // If |handles| is non-null, any handles in |*handles| are attached to the | 
|  | // newly constructed message. | 
|  | // | 
|  | // Note that |payload_size| is only the initially known size of the message | 
|  | // payload, if any. The payload can be expanded after construction using the | 
|  | // interface returned by |payload_buffer()|. | 
|  | // | 
|  | // |estimated_payload_size| will be used to preallocate an appropriate amount | 
|  | // of memory for the message buffer, based on the history of previous | 
|  | // allocations for this message's |name|. | 
|  | Message(uint32_t name, | 
|  | uint32_t flags, | 
|  | size_t payload_size, | 
|  | size_t payload_interface_id_count, | 
|  | MojoCreateMessageFlags create_message_flags, | 
|  | std::vector<ScopedHandle>* handles, | 
|  | size_t estimated_payload_size = 0); | 
|  |  | 
|  | // Same as above, but the with default MojoCreateMessageFlags. | 
|  | Message(uint32_t name, | 
|  | uint32_t flags, | 
|  | size_t payload_size, | 
|  | size_t payload_interface_id_count, | 
|  | std::vector<ScopedHandle>* handles, | 
|  | size_t estimated_payload_size = 0); | 
|  |  | 
|  | // Constructor for the common case of unknown `payload_size`, unspecified | 
|  | // `payload_interface_id_count`, and no `handles` vector. | 
|  | Message(uint32_t name, | 
|  | uint32_t flags, | 
|  | MojoCreateMessageFlags create_message_flags, | 
|  | size_t estimated_payload_size); | 
|  |  | 
|  | // Same as above, but the with default MojoCreateMessageFlags. | 
|  | Message(uint32_t name, uint32_t flags, size_t estimated_payload_size); | 
|  |  | 
|  | // Constructs a new Message object from an existing message handle. Used | 
|  | // exclusively for serializing an existing unserialized message. | 
|  | Message(ScopedMessageHandle handle, const internal::MessageHeaderV1& header); | 
|  |  | 
|  | // Constructs a new serialized Message object from a fully populated message | 
|  | // payload (including a well-formed message header) and an optional set of | 
|  | // handle attachments. This Message may not be extended with additional | 
|  | // payload or handles once constructed, but its payload remains mutable as | 
|  | // long as the Message is not moved and neither |Reset()| nor | 
|  | // |TakeMojoMessage()| is called. | 
|  | Message(base::span<const uint8_t> payload, base::span<ScopedHandle> handles); | 
|  |  | 
|  | Message(const Message&) = delete; | 
|  | Message& operator=(const Message&) = delete; | 
|  |  | 
|  | // Moves |other| into a new Message object. The moved-from Message becomes | 
|  | // invalid and is effectively in a default-constructed state after this call. | 
|  | Message(Message&& other) noexcept; | 
|  | Message& operator=(Message&& other) noexcept; | 
|  |  | 
|  | ~Message(); | 
|  |  | 
|  | // Resets the Message to an uninitialized state. Upon reset, the Message | 
|  | // exists as if it were default-constructed: it has no data buffer and owns no | 
|  | // handles. | 
|  | void Reset(); | 
|  |  | 
|  | // Indicates whether this Message is uninitialized. | 
|  | bool IsNull() const { return !handle_.is_valid(); } | 
|  |  | 
|  | // Indicates whether this Message is in valid state. A Message may be in an | 
|  | // invalid state iff it failed partial deserialization during construction | 
|  | // over a ScopedMessageHandle. | 
|  | bool IsValid() const; | 
|  |  | 
|  | // Indicates whether this Message is serialized. | 
|  | bool is_serialized() const { return serialized_; } | 
|  |  | 
|  | // Access the raw bytes of the message. | 
|  | const uint8_t* data() const { | 
|  | DCHECK(payload_buffer_.is_valid()); | 
|  | return static_cast<const uint8_t*>(payload_buffer_.data()); | 
|  | } | 
|  | uint8_t* mutable_data() { return const_cast<uint8_t*>(data()); } | 
|  |  | 
|  | size_t data_num_bytes() const { | 
|  | DCHECK(payload_buffer_.is_valid()); | 
|  | return payload_buffer_.cursor(); | 
|  | } | 
|  |  | 
|  | // Access the header. | 
|  | const internal::MessageHeader* header() const { | 
|  | return reinterpret_cast<const internal::MessageHeader*>(data()); | 
|  | } | 
|  | internal::MessageHeader* header() { | 
|  | return reinterpret_cast<internal::MessageHeader*>(mutable_data()); | 
|  | } | 
|  |  | 
|  | const internal::MessageHeaderV1* header_v1() const { | 
|  | DCHECK_GE(version(), 1u); | 
|  | return reinterpret_cast<const internal::MessageHeaderV1*>(data()); | 
|  | } | 
|  | internal::MessageHeaderV1* header_v1() { | 
|  | DCHECK_GE(version(), 1u); | 
|  | return reinterpret_cast<internal::MessageHeaderV1*>(mutable_data()); | 
|  | } | 
|  |  | 
|  | const internal::MessageHeaderV2* header_v2() const { | 
|  | DCHECK_GE(version(), 2u); | 
|  | return reinterpret_cast<const internal::MessageHeaderV2*>(data()); | 
|  | } | 
|  | internal::MessageHeaderV2* header_v2() { | 
|  | DCHECK_GE(version(), 2u); | 
|  | return reinterpret_cast<internal::MessageHeaderV2*>(mutable_data()); | 
|  | } | 
|  |  | 
|  | const internal::MessageHeaderV3* header_v3() const { | 
|  | DCHECK_GE(version(), 3u); | 
|  | return reinterpret_cast<const internal::MessageHeaderV3*>(data()); | 
|  | } | 
|  | internal::MessageHeaderV3* header_v3() { | 
|  | DCHECK_GE(version(), 3u); | 
|  | return reinterpret_cast<internal::MessageHeaderV3*>(mutable_data()); | 
|  | } | 
|  |  | 
|  | uint32_t version() const { return header()->version; } | 
|  |  | 
|  | uint32_t interface_id() const { return header()->interface_id; } | 
|  | void set_interface_id(uint32_t id) { header()->interface_id = id; } | 
|  |  | 
|  | uint32_t name() const { return header()->name; } | 
|  | bool has_flag(uint32_t flag) const { return !!(header()->flags & flag); } | 
|  |  | 
|  | // Access the request_id field (if present). | 
|  | uint64_t request_id() const { return header_v1()->request_id; } | 
|  | void set_request_id(uint64_t request_id) { | 
|  | header_v1()->request_id = request_id; | 
|  | } | 
|  |  | 
|  | void set_trace_nonce(uint32_t trace_nonce) { | 
|  | header()->trace_nonce = trace_nonce; | 
|  | } | 
|  |  | 
|  | // Access the payload. | 
|  | const uint8_t* payload() const; | 
|  | uint8_t* mutable_payload() { return const_cast<uint8_t*>(payload()); } | 
|  | uint32_t payload_num_bytes() const; | 
|  |  | 
|  | uint32_t payload_num_interface_ids() const; | 
|  | const uint32_t* payload_interface_ids() const; | 
|  |  | 
|  | internal::Buffer* payload_buffer() { return &payload_buffer_; } | 
|  |  | 
|  | // Access the handles of a received message. Note that these are unused on | 
|  | // outgoing messages. | 
|  | const std::vector<ScopedHandle>* handles() const { return &handles_; } | 
|  | std::vector<ScopedHandle>* mutable_handles() { return &handles_; } | 
|  |  | 
|  | const std::vector<ScopedInterfaceEndpointHandle>* | 
|  | associated_endpoint_handles() const { | 
|  | return &associated_endpoint_handles_; | 
|  | } | 
|  | std::vector<ScopedInterfaceEndpointHandle>* | 
|  | mutable_associated_endpoint_handles() { | 
|  | return &associated_endpoint_handles_; | 
|  | } | 
|  |  | 
|  | // Sets the ConnectionGroup to which this Message's local receiver belongs, if | 
|  | // any. This is called immediately after a Message is read from a message pipe | 
|  | // but before it's deserialized. If non-null, |ref| must point to a Ref that | 
|  | // outlives this Message object. | 
|  | void set_receiver_connection_group(const ConnectionGroup::Ref* ref) { | 
|  | receiver_connection_group_ = ref; | 
|  | } | 
|  | const ConnectionGroup::Ref* receiver_connection_group() const { | 
|  | return receiver_connection_group_; | 
|  | } | 
|  |  | 
|  | // Takes a scoped MessageHandle which may be passed to |WriteMessageNew()| for | 
|  | // transmission. Note that this invalidates this Message object, taking | 
|  | // ownership of its internal storage and any attached handles. | 
|  | ScopedMessageHandle TakeMojoMessage(); | 
|  |  | 
|  | // Notifies the system that this message is "bad," in this case meaning it was | 
|  | // rejected by bindings validation code. | 
|  | void NotifyBadMessage(std::string_view error); | 
|  |  | 
|  | // Serializes and attaches Mojo handles and associated endpoint handles from | 
|  | // |handles_| and |associated_endpoint_handles_| respectively. | 
|  | void SerializeHandles(AssociatedGroupController* group_controller); | 
|  |  | 
|  | // Deserializes associated endpoint handles from the payload_interface_ids | 
|  | // field, into |associated_endpoint_handles_|. | 
|  | bool DeserializeAssociatedEndpointHandles( | 
|  | AssociatedGroupController* group_controller); | 
|  |  | 
|  | // If this message contains serialized associated interface endponits but is | 
|  | // going to be destroyed without being sent across a pipe, this notifies any | 
|  | // relevant local peer endpoints about peer closure. Must be called on any | 
|  | // unsent Message that is going to be destroyed after calling | 
|  | // SerializeHandles(). | 
|  | void NotifyPeerClosureForSerializedHandles( | 
|  | AssociatedGroupController* group_controller); | 
|  |  | 
|  | // If this Message has an unserialized message context attached, force it to | 
|  | // be serialized immediately. Otherwise this does nothing. | 
|  | void SerializeIfNecessary(); | 
|  |  | 
|  | // Takes the unserialized message context from this Message if its tag matches | 
|  | // |tag|. | 
|  | std::unique_ptr<internal::UnserializedMessageContext> TakeUnserializedContext( | 
|  | uintptr_t tag); | 
|  |  | 
|  | template <typename MessageType> | 
|  | std::unique_ptr<MessageType> TakeUnserializedContext() { | 
|  | auto generic_context = TakeUnserializedContext( | 
|  | reinterpret_cast<uintptr_t>(&MessageType::kMessageTag)); | 
|  | if (!generic_context) | 
|  | return nullptr; | 
|  | return base::WrapUnique( | 
|  | generic_context.release()->template SafeCast<MessageType>()); | 
|  | } | 
|  |  | 
|  | const char* heap_profiler_tag() const { return heap_profiler_tag_; } | 
|  | void set_heap_profiler_tag(const char* heap_profiler_tag) { | 
|  | heap_profiler_tag_ = heap_profiler_tag; | 
|  | } | 
|  |  | 
|  | // Get a global trace id identifying this message. Used for connecting the | 
|  | // sender and the receiver in traces. | 
|  | uint64_t GetTraceId() const; | 
|  |  | 
|  | // Write a representation of this object into a trace. | 
|  | void WriteIntoTrace(perfetto::TracedValue ctx) const; | 
|  |  | 
|  | #if defined(ENABLE_IPC_FUZZER) | 
|  | const char* interface_name() const { return interface_name_; } | 
|  | void set_interface_name(const char* interface_name) { | 
|  | interface_name_ = interface_name; | 
|  | } | 
|  |  | 
|  | const char* method_name() const { return method_name_; } | 
|  | void set_method_name(const char* method_name) { method_name_ = method_name; } | 
|  | #endif | 
|  |  | 
|  | int64_t creation_timeticks_us() const; | 
|  |  | 
|  | private: | 
|  | // Internal constructor used by |CreateFromMessageHandle()| when either there | 
|  | // are no attached handles or all attached handles are successfully extracted | 
|  | // from the message object. | 
|  | Message(ScopedMessageHandle message_handle, | 
|  | std::vector<ScopedHandle> attached_handles, | 
|  | internal::Buffer payload_buffer, | 
|  | bool serialized); | 
|  |  | 
|  | ScopedMessageHandle handle_; | 
|  |  | 
|  | // A Buffer which may be used to allocate blocks of data within the message | 
|  | // payload for reading or writing. | 
|  | internal::Buffer payload_buffer_; | 
|  |  | 
|  | std::vector<ScopedHandle> handles_; | 
|  | std::vector<ScopedInterfaceEndpointHandle> associated_endpoint_handles_; | 
|  | raw_ptr<const ConnectionGroup::Ref, DanglingUntriaged> | 
|  | receiver_connection_group_ = nullptr; | 
|  |  | 
|  | // Indicates whether this Message object is transferable, i.e. can be sent | 
|  | // elsewhere. In general this is true unless |handle_| is invalid or | 
|  | // serialized handles have been extracted from the serialized message object | 
|  | // identified by |handle_|. | 
|  | bool transferable_ = false; | 
|  |  | 
|  | // Indicates whether this Message object is serialized. | 
|  | bool serialized_ = false; | 
|  |  | 
|  | const char* heap_profiler_tag_ = nullptr; | 
|  | #if defined(ENABLE_IPC_FUZZER) | 
|  | const char* interface_name_ = nullptr; | 
|  | const char* method_name_ = nullptr; | 
|  | #endif | 
|  | }; | 
|  |  | 
|  | class COMPONENT_EXPORT(MOJO_CPP_BINDINGS_BASE) MessageFilter { | 
|  | public: | 
|  | virtual ~MessageFilter() = default; | 
|  |  | 
|  | // The filter may mutate the given message.  This method is called before | 
|  | // the message is dispatched to the associated MessageReceiver. Returns true | 
|  | // if the message was accepted and false otherwise, indicating that the | 
|  | // message was invalid or malformed. | 
|  | [[nodiscard]] virtual bool WillDispatch(Message* message) = 0; | 
|  |  | 
|  | // The filter receives notification that the message was dispatched or | 
|  | // rejected. Since the message filter is owned by the receiver it will not be | 
|  | // invoked if the receiver is closed during a dispatch of a message. | 
|  | virtual void DidDispatchOrReject(Message* message, bool accepted) = 0; | 
|  | }; | 
|  |  | 
|  | class COMPONENT_EXPORT(MOJO_CPP_BINDINGS_BASE) MessageReceiver { | 
|  | public: | 
|  | virtual ~MessageReceiver() = default; | 
|  |  | 
|  | // Indicates whether the receiver prefers to receive serialized messages. | 
|  | virtual bool PrefersSerializedMessages(); | 
|  |  | 
|  | // The receiver may mutate the given message.  Returns true if the message | 
|  | // was accepted and false otherwise, indicating that the message was invalid | 
|  | // or malformed. | 
|  | [[nodiscard]] virtual bool Accept(Message* message) = 0; | 
|  | }; | 
|  |  | 
|  | class MessageReceiverWithResponder : public MessageReceiver { | 
|  | public: | 
|  | ~MessageReceiverWithResponder() override = default; | 
|  |  | 
|  | // A variant on Accept that registers a MessageReceiver (known as the | 
|  | // responder) to handle the response message generated from the given | 
|  | // message. The responder's Accept method may be called during | 
|  | // AcceptWithResponder or some time after its return. | 
|  | [[nodiscard]] virtual bool AcceptWithResponder( | 
|  | Message* message, | 
|  | std::unique_ptr<MessageReceiver> responder) = 0; | 
|  | }; | 
|  |  | 
|  | // A MessageReceiver that is also able to provide status about the state | 
|  | // of the underlying MessagePipe to which it will be forwarding messages | 
|  | // received via the |Accept()| call. | 
|  | class MessageReceiverWithStatus : public MessageReceiver { | 
|  | public: | 
|  | ~MessageReceiverWithStatus() override = default; | 
|  |  | 
|  | // Returns |true| if this MessageReceiver is currently bound to a MessagePipe, | 
|  | // the pipe has not been closed, and the pipe has not encountered an error. | 
|  | virtual bool IsConnected() = 0; | 
|  |  | 
|  | // Determines if this MessageReceiver is still bound to a message pipe and has | 
|  | // not encountered any errors. This is asynchronous but may be called from any | 
|  | // sequence. |callback| is eventually invoked from an arbitrary sequence with | 
|  | // the result of the query. | 
|  | virtual void IsConnectedAsync(base::OnceCallback<void(bool)> callback) = 0; | 
|  | }; | 
|  |  | 
|  | // An alternative to MessageReceiverWithResponder for cases in which it | 
|  | // is necessary for the implementor of this interface to know about the status | 
|  | // of the MessagePipe which will carry the responses. | 
|  | class MessageReceiverWithResponderStatus : public MessageReceiver { | 
|  | public: | 
|  | ~MessageReceiverWithResponderStatus() override = default; | 
|  |  | 
|  | // A variant on Accept that registers a MessageReceiverWithStatus (known as | 
|  | // the responder) to handle the response message generated from the given | 
|  | // message. Any of the responder's methods (Accept or IsValid) may be called | 
|  | // during  AcceptWithResponder or some time after its return. | 
|  | [[nodiscard]] virtual bool AcceptWithResponder( | 
|  | Message* message, | 
|  | std::unique_ptr<MessageReceiverWithStatus> responder) = 0; | 
|  | }; | 
|  |  | 
|  | class COMPONENT_EXPORT(MOJO_CPP_BINDINGS_BASE) PassThroughFilter | 
|  | : public MessageReceiver { | 
|  | public: | 
|  | PassThroughFilter(); | 
|  |  | 
|  | PassThroughFilter(const PassThroughFilter&) = delete; | 
|  | PassThroughFilter& operator=(const PassThroughFilter&) = delete; | 
|  |  | 
|  | ~PassThroughFilter() override; | 
|  |  | 
|  | // MessageReceiver: | 
|  | bool Accept(Message* message) override; | 
|  | }; | 
|  |  | 
|  | // Reports the currently dispatching Message as bad. Note that this is only | 
|  | // legal to call from directly within the stack frame of a message dispatch. If | 
|  | // you need to do asynchronous work before you can determine the legitimacy of | 
|  | // a message, use GetBadMessageCallback() and retain its result until you're | 
|  | // ready to invoke or discard it. | 
|  | NOT_TAIL_CALLED COMPONENT_EXPORT(MOJO_CPP_BINDINGS_BASE) void ReportBadMessage( | 
|  | std::string_view error); | 
|  |  | 
|  | // Acquires a callback which may be run to report the currently dispatching | 
|  | // Message as bad. Note that this is only legal to call from directly within the | 
|  | // stack frame of a message dispatch, but the returned callback may be called | 
|  | // exactly once any time thereafter to report the message as bad. This may only | 
|  | // be called once per message. | 
|  | COMPONENT_EXPORT(MOJO_CPP_BINDINGS_BASE) | 
|  | ReportBadMessageCallback GetBadMessageCallback(); | 
|  |  | 
|  | // Returns true if called directly within the stack frame of a message dispatch. | 
|  | // Unlike GetBadMessageCallback(), this can be called multiple times. | 
|  | COMPONENT_EXPORT(MOJO_CPP_BINDINGS_BASE) | 
|  | bool IsInMessageDispatch(); | 
|  |  | 
|  | }  // namespace mojo | 
|  |  | 
|  | #endif  // MOJO_PUBLIC_CPP_BINDINGS_MESSAGE_H_ |