1// Copyright 2015 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_ENDPOINT_CLIENT_H_
6#define MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_ENDPOINT_CLIENT_H_
7
8#include <stdint.h>
9
10#include <map>
11#include <memory>
12
13#include "base/callback.h"
14#include "base/compiler_specific.h"
15#include "base/logging.h"
16#include "base/macros.h"
17#include "base/memory/ref_counted.h"
18#include "base/memory/weak_ptr.h"
19#include "base/optional.h"
20#include "base/single_thread_task_runner.h"
21#include "base/threading/thread_checker.h"
22#include "mojo/public/cpp/bindings/bindings_export.h"
23#include "mojo/public/cpp/bindings/connection_error_callback.h"
24#include "mojo/public/cpp/bindings/disconnect_reason.h"
25#include "mojo/public/cpp/bindings/filter_chain.h"
26#include "mojo/public/cpp/bindings/lib/control_message_handler.h"
27#include "mojo/public/cpp/bindings/lib/control_message_proxy.h"
28#include "mojo/public/cpp/bindings/message.h"
29#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h"
30
31namespace mojo {
32
33class AssociatedGroup;
34class InterfaceEndpointController;
35
36// InterfaceEndpointClient handles message sending and receiving of an interface
37// endpoint, either the implementation side or the client side.
38// It should only be accessed and destructed on the creating thread.
39class MOJO_CPP_BINDINGS_EXPORT InterfaceEndpointClient
40    : NON_EXPORTED_BASE(public MessageReceiverWithResponder) {
41 public:
42  // |receiver| is okay to be null. If it is not null, it must outlive this
43  // object.
44  InterfaceEndpointClient(ScopedInterfaceEndpointHandle handle,
45                          MessageReceiverWithResponderStatus* receiver,
46                          std::unique_ptr<MessageReceiver> payload_validator,
47                          bool expect_sync_requests,
48                          scoped_refptr<base::SingleThreadTaskRunner> runner,
49                          uint32_t interface_version);
50  ~InterfaceEndpointClient() override;
51
52  // Sets the error handler to receive notifications when an error is
53  // encountered.
54  void set_connection_error_handler(const base::Closure& error_handler) {
55    DCHECK(thread_checker_.CalledOnValidThread());
56    error_handler_ = error_handler;
57    error_with_reason_handler_.Reset();
58  }
59
60  void set_connection_error_with_reason_handler(
61      const ConnectionErrorWithReasonCallback& error_handler) {
62    DCHECK(thread_checker_.CalledOnValidThread());
63    error_with_reason_handler_ = error_handler;
64    error_handler_.Reset();
65  }
66
67  // Returns true if an error was encountered.
68  bool encountered_error() const {
69    DCHECK(thread_checker_.CalledOnValidThread());
70    return encountered_error_;
71  }
72
73  // Returns true if this endpoint has any pending callbacks.
74  bool has_pending_responders() const {
75    DCHECK(thread_checker_.CalledOnValidThread());
76    return !async_responders_.empty() || !sync_responses_.empty();
77  }
78
79  AssociatedGroup* associated_group();
80
81  // Adds a MessageReceiver which can filter a message after validation but
82  // before dispatch.
83  void AddFilter(std::unique_ptr<MessageReceiver> filter);
84
85  // After this call the object is in an invalid state and shouldn't be reused.
86  ScopedInterfaceEndpointHandle PassHandle();
87
88  // Raises an error on the underlying message pipe. It disconnects the pipe
89  // and notifies all interfaces running on this pipe.
90  void RaiseError();
91
92  void CloseWithReason(uint32_t custom_reason, const std::string& description);
93
94  // MessageReceiverWithResponder implementation:
95  // They must only be called when the handle is not in pending association
96  // state.
97  bool Accept(Message* message) override;
98  bool AcceptWithResponder(Message* message,
99                           MessageReceiver* responder) override;
100
101  // The following methods are called by the router. They must be called
102  // outside of the router's lock.
103
104  // NOTE: |message| must have passed message header validation.
105  bool HandleIncomingMessage(Message* message);
106  void NotifyError(const base::Optional<DisconnectReason>& reason);
107
108  // The following methods send interface control messages.
109  // They must only be called when the handle is not in pending association
110  // state.
111  void QueryVersion(const base::Callback<void(uint32_t)>& callback);
112  void RequireVersion(uint32_t version);
113  void FlushForTesting();
114
115 private:
116  // Maps from the id of a response to the MessageReceiver that handles the
117  // response.
118  using AsyncResponderMap =
119      std::map<uint64_t, std::unique_ptr<MessageReceiver>>;
120
121  struct SyncResponseInfo {
122   public:
123    explicit SyncResponseInfo(bool* in_response_received);
124    ~SyncResponseInfo();
125
126    Message response;
127
128    // Points to a stack-allocated variable.
129    bool* response_received;
130
131   private:
132    DISALLOW_COPY_AND_ASSIGN(SyncResponseInfo);
133  };
134
135  using SyncResponseMap = std::map<uint64_t, std::unique_ptr<SyncResponseInfo>>;
136
137  // Used as the sink for |payload_validator_| and forwards messages to
138  // HandleValidatedMessage().
139  class HandleIncomingMessageThunk : public MessageReceiver {
140   public:
141    explicit HandleIncomingMessageThunk(InterfaceEndpointClient* owner);
142    ~HandleIncomingMessageThunk() override;
143
144    // MessageReceiver implementation:
145    bool Accept(Message* message) override;
146
147   private:
148    InterfaceEndpointClient* const owner_;
149
150    DISALLOW_COPY_AND_ASSIGN(HandleIncomingMessageThunk);
151  };
152
153  void InitControllerIfNecessary();
154
155  void OnAssociationEvent(
156      ScopedInterfaceEndpointHandle::AssociationEvent event);
157
158  bool HandleValidatedMessage(Message* message);
159
160  const bool expect_sync_requests_ = false;
161
162  ScopedInterfaceEndpointHandle handle_;
163  std::unique_ptr<AssociatedGroup> associated_group_;
164  InterfaceEndpointController* controller_ = nullptr;
165
166  MessageReceiverWithResponderStatus* const incoming_receiver_ = nullptr;
167  HandleIncomingMessageThunk thunk_;
168  FilterChain filters_;
169
170  AsyncResponderMap async_responders_;
171  SyncResponseMap sync_responses_;
172
173  uint64_t next_request_id_ = 1;
174
175  base::Closure error_handler_;
176  ConnectionErrorWithReasonCallback error_with_reason_handler_;
177  bool encountered_error_ = false;
178
179  scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
180
181  internal::ControlMessageProxy control_message_proxy_;
182  internal::ControlMessageHandler control_message_handler_;
183
184  base::ThreadChecker thread_checker_;
185
186  base::WeakPtrFactory<InterfaceEndpointClient> weak_ptr_factory_;
187
188  DISALLOW_COPY_AND_ASSIGN(InterfaceEndpointClient);
189};
190
191}  // namespace mojo
192
193#endif  // MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_ENDPOINT_CLIENT_H_
194