| // Copyright 2015 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_ENDPOINT_CLIENT_H_ |
| #define MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_ENDPOINT_CLIENT_H_ |
| |
| #include <stdint.h> |
| |
| #include <map> |
| #include <memory> |
| #include <utility> |
| |
| #include "base/callback.h" |
| #include "base/compiler_specific.h" |
| #include "base/logging.h" |
| #include "base/macros.h" |
| #include "base/memory/ref_counted.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/optional.h" |
| #include "base/sequence_checker.h" |
| #include "base/sequenced_task_runner.h" |
| #include "mojo/public/cpp/bindings/bindings_export.h" |
| #include "mojo/public/cpp/bindings/connection_error_callback.h" |
| #include "mojo/public/cpp/bindings/disconnect_reason.h" |
| #include "mojo/public/cpp/bindings/filter_chain.h" |
| #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/message.h" |
| #include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h" |
| |
| namespace mojo { |
| |
| class AssociatedGroup; |
| class InterfaceEndpointController; |
| |
| // InterfaceEndpointClient handles message sending and receiving of an interface |
| // endpoint, either the implementation side or the client side. |
| // It should only be accessed and destructed on the creating sequence. |
| class MOJO_CPP_BINDINGS_EXPORT InterfaceEndpointClient |
| : public MessageReceiverWithResponder { |
| public: |
| // |receiver| is okay to be null. If it is not null, it must outlive this |
| // object. |
| InterfaceEndpointClient(ScopedInterfaceEndpointHandle handle, |
| MessageReceiverWithResponderStatus* receiver, |
| std::unique_ptr<MessageReceiver> payload_validator, |
| bool expect_sync_requests, |
| scoped_refptr<base::SequencedTaskRunner> runner, |
| uint32_t interface_version); |
| ~InterfaceEndpointClient() override; |
| |
| // Sets the error handler to receive notifications when an error is |
| // encountered. |
| void set_connection_error_handler(base::OnceClosure error_handler) { |
| DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| error_handler_ = std::move(error_handler); |
| error_with_reason_handler_.Reset(); |
| } |
| |
| void set_connection_error_with_reason_handler( |
| ConnectionErrorWithReasonCallback error_handler) { |
| DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| error_with_reason_handler_ = std::move(error_handler); |
| error_handler_.Reset(); |
| } |
| |
| // Returns true if an error was encountered. |
| bool encountered_error() const { |
| DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| return encountered_error_; |
| } |
| |
| // Returns true if this endpoint has any pending callbacks. |
| bool has_pending_responders() const { |
| DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| return !async_responders_.empty() || !sync_responses_.empty(); |
| } |
| |
| AssociatedGroup* associated_group(); |
| |
| // Adds a MessageReceiver which can filter a message after validation but |
| // before dispatch. |
| void AddFilter(std::unique_ptr<MessageReceiver> filter); |
| |
| // After this call the object is in an invalid state and shouldn't be reused. |
| ScopedInterfaceEndpointHandle PassHandle(); |
| |
| // Raises an error on the underlying message pipe. It disconnects the pipe |
| // and notifies all interfaces running on this pipe. |
| void RaiseError(); |
| |
| void CloseWithReason(uint32_t custom_reason, const std::string& description); |
| |
| // MessageReceiverWithResponder implementation: |
| // They must only be called when the handle is not in pending association |
| // state. |
| bool PrefersSerializedMessages() override; |
| bool Accept(Message* message) override; |
| bool AcceptWithResponder(Message* message, |
| std::unique_ptr<MessageReceiver> responder) override; |
| |
| // The following methods are called by the router. They must be called |
| // outside of the router's lock. |
| |
| // NOTE: |message| must have passed message header validation. |
| bool HandleIncomingMessage(Message* message); |
| void NotifyError(const base::Optional<DisconnectReason>& reason); |
| |
| // The following methods send interface control messages. |
| // They must only be called when the handle is not in pending association |
| // state. |
| void QueryVersion(const base::Callback<void(uint32_t)>& callback); |
| void RequireVersion(uint32_t version); |
| void FlushForTesting(); |
| |
| private: |
| // Maps from the id of a response to the MessageReceiver that handles the |
| // response. |
| using AsyncResponderMap = |
| std::map<uint64_t, std::unique_ptr<MessageReceiver>>; |
| |
| struct SyncResponseInfo { |
| public: |
| explicit SyncResponseInfo(bool* in_response_received); |
| ~SyncResponseInfo(); |
| |
| Message response; |
| |
| // Points to a stack-allocated variable. |
| bool* response_received; |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(SyncResponseInfo); |
| }; |
| |
| using SyncResponseMap = std::map<uint64_t, std::unique_ptr<SyncResponseInfo>>; |
| |
| // Used as the sink for |payload_validator_| and forwards messages to |
| // HandleValidatedMessage(). |
| class HandleIncomingMessageThunk : public MessageReceiver { |
| public: |
| explicit HandleIncomingMessageThunk(InterfaceEndpointClient* owner); |
| ~HandleIncomingMessageThunk() override; |
| |
| // MessageReceiver implementation: |
| bool Accept(Message* message) override; |
| |
| private: |
| InterfaceEndpointClient* const owner_; |
| |
| DISALLOW_COPY_AND_ASSIGN(HandleIncomingMessageThunk); |
| }; |
| |
| void InitControllerIfNecessary(); |
| |
| void OnAssociationEvent( |
| ScopedInterfaceEndpointHandle::AssociationEvent event); |
| |
| bool HandleValidatedMessage(Message* message); |
| |
| const bool expect_sync_requests_ = false; |
| |
| ScopedInterfaceEndpointHandle handle_; |
| std::unique_ptr<AssociatedGroup> associated_group_; |
| InterfaceEndpointController* controller_ = nullptr; |
| |
| MessageReceiverWithResponderStatus* const incoming_receiver_ = nullptr; |
| HandleIncomingMessageThunk thunk_; |
| FilterChain filters_; |
| |
| AsyncResponderMap async_responders_; |
| SyncResponseMap sync_responses_; |
| |
| uint64_t next_request_id_ = 1; |
| |
| base::OnceClosure error_handler_; |
| ConnectionErrorWithReasonCallback error_with_reason_handler_; |
| bool encountered_error_ = false; |
| |
| scoped_refptr<base::SequencedTaskRunner> task_runner_; |
| |
| internal::ControlMessageProxy control_message_proxy_; |
| internal::ControlMessageHandler control_message_handler_; |
| |
| SEQUENCE_CHECKER(sequence_checker_); |
| |
| base::WeakPtrFactory<InterfaceEndpointClient> weak_ptr_factory_; |
| |
| DISALLOW_COPY_AND_ASSIGN(InterfaceEndpointClient); |
| }; |
| |
| } // namespace mojo |
| |
| #endif // MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_ENDPOINT_CLIENT_H_ |