196 lines
6.6 KiB
C++
196 lines
6.6 KiB
C++
// 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_
|