• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 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_MESSAGE_H_
6 #define MOJO_PUBLIC_CPP_BINDINGS_MESSAGE_H_
7 
8 #include <stddef.h>
9 #include <stdint.h>
10 
11 #include <limits>
12 #include <memory>
13 #include <string>
14 #include <vector>
15 
16 #include "base/callback.h"
17 #include "base/compiler_specific.h"
18 #include "base/logging.h"
19 #include "mojo/public/cpp/bindings/bindings_export.h"
20 #include "mojo/public/cpp/bindings/lib/message_buffer.h"
21 #include "mojo/public/cpp/bindings/lib/message_internal.h"
22 #include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h"
23 #include "mojo/public/cpp/system/message.h"
24 
25 namespace mojo {
26 
27 class AssociatedGroupController;
28 
29 using ReportBadMessageCallback = base::Callback<void(const std::string& error)>;
30 
31 // Message is a holder for the data and handles to be sent over a MessagePipe.
32 // Message owns its data and handles, but a consumer of Message is free to
33 // mutate the data and handles. The message's data is comprised of a header
34 // followed by payload.
35 class MOJO_CPP_BINDINGS_EXPORT Message {
36  public:
37   static const uint32_t kFlagExpectsResponse = 1 << 0;
38   static const uint32_t kFlagIsResponse = 1 << 1;
39   static const uint32_t kFlagIsSync = 1 << 2;
40 
41   Message();
42   Message(Message&& other);
43 
44   ~Message();
45 
46   Message& operator=(Message&& other);
47 
48   // Resets the Message to an uninitialized state. Upon reset, the Message
49   // exists as if it were default-constructed: it has no data buffer and owns no
50   // handles.
51   void Reset();
52 
53   // Indicates whether this Message is uninitialized.
IsNull()54   bool IsNull() const { return !buffer_; }
55 
56   // Initializes a Message with enough space for |capacity| bytes.
57   void Initialize(size_t capacity, bool zero_initialized);
58 
59   // Initializes a Message from an existing Mojo MessageHandle.
60   void InitializeFromMojoMessage(ScopedMessageHandle message,
61                                  uint32_t num_bytes,
62                                  std::vector<Handle>* handles);
63 
data_num_bytes()64   uint32_t data_num_bytes() const {
65     return static_cast<uint32_t>(buffer_->size());
66   }
67 
68   // Access the raw bytes of the message.
data()69   const uint8_t* data() const {
70     return static_cast<const uint8_t*>(buffer_->data());
71   }
72 
mutable_data()73   uint8_t* mutable_data() { return static_cast<uint8_t*>(buffer_->data()); }
74 
75   // Access the header.
header()76   const internal::MessageHeader* header() const {
77     return static_cast<const internal::MessageHeader*>(buffer_->data());
78   }
header()79   internal::MessageHeader* header() {
80     return static_cast<internal::MessageHeader*>(buffer_->data());
81   }
82 
header_v1()83   const internal::MessageHeaderV1* header_v1() const {
84     DCHECK_GE(version(), 1u);
85     return static_cast<const internal::MessageHeaderV1*>(buffer_->data());
86   }
header_v1()87   internal::MessageHeaderV1* header_v1() {
88     DCHECK_GE(version(), 1u);
89     return static_cast<internal::MessageHeaderV1*>(buffer_->data());
90   }
91 
header_v2()92   const internal::MessageHeaderV2* header_v2() const {
93     DCHECK_GE(version(), 2u);
94     return static_cast<const internal::MessageHeaderV2*>(buffer_->data());
95   }
header_v2()96   internal::MessageHeaderV2* header_v2() {
97     DCHECK_GE(version(), 2u);
98     return static_cast<internal::MessageHeaderV2*>(buffer_->data());
99   }
100 
version()101   uint32_t version() const { return header()->version; }
102 
interface_id()103   uint32_t interface_id() const { return header()->interface_id; }
set_interface_id(uint32_t id)104   void set_interface_id(uint32_t id) { header()->interface_id = id; }
105 
name()106   uint32_t name() const { return header()->name; }
has_flag(uint32_t flag)107   bool has_flag(uint32_t flag) const { return !!(header()->flags & flag); }
108 
109   // Access the request_id field (if present).
request_id()110   uint64_t request_id() const { return header_v1()->request_id; }
set_request_id(uint64_t request_id)111   void set_request_id(uint64_t request_id) {
112     header_v1()->request_id = request_id;
113   }
114 
115   // Access the payload.
116   const uint8_t* payload() const;
mutable_payload()117   uint8_t* mutable_payload() { return const_cast<uint8_t*>(payload()); }
118   uint32_t payload_num_bytes() const;
119 
120   uint32_t payload_num_interface_ids() const;
121   const uint32_t* payload_interface_ids() const;
122 
123   // Access the handles.
handles()124   const std::vector<Handle>* handles() const { return &handles_; }
mutable_handles()125   std::vector<Handle>* mutable_handles() { return &handles_; }
126 
127   const std::vector<ScopedInterfaceEndpointHandle>*
associated_endpoint_handles()128   associated_endpoint_handles() const {
129     return &associated_endpoint_handles_;
130   }
131   std::vector<ScopedInterfaceEndpointHandle>*
mutable_associated_endpoint_handles()132   mutable_associated_endpoint_handles() {
133     return &associated_endpoint_handles_;
134   }
135 
136   // Access the underlying Buffer interface.
buffer()137   internal::Buffer* buffer() { return buffer_.get(); }
138 
139   // Takes a scoped MessageHandle which may be passed to |WriteMessageNew()| for
140   // transmission. Note that this invalidates this Message object, taking
141   // ownership of its internal storage and any attached handles.
142   ScopedMessageHandle TakeMojoMessage();
143 
144   // Notifies the system that this message is "bad," in this case meaning it was
145   // rejected by bindings validation code.
146   void NotifyBadMessage(const std::string& error);
147 
148   // Serializes |associated_endpoint_handles_| into the payload_interface_ids
149   // field.
150   void SerializeAssociatedEndpointHandles(
151       AssociatedGroupController* group_controller);
152 
153   // Deserializes |associated_endpoint_handles_| from the payload_interface_ids
154   // field.
155   bool DeserializeAssociatedEndpointHandles(
156       AssociatedGroupController* group_controller);
157 
158  private:
159   void CloseHandles();
160 
161   std::unique_ptr<internal::MessageBuffer> buffer_;
162   std::vector<Handle> handles_;
163   std::vector<ScopedInterfaceEndpointHandle> associated_endpoint_handles_;
164 
165   DISALLOW_COPY_AND_ASSIGN(Message);
166 };
167 
168 class MessageReceiver {
169  public:
~MessageReceiver()170   virtual ~MessageReceiver() {}
171 
172   // The receiver may mutate the given message.  Returns true if the message
173   // was accepted and false otherwise, indicating that the message was invalid
174   // or malformed.
175   virtual bool Accept(Message* message) WARN_UNUSED_RESULT = 0;
176 };
177 
178 class MessageReceiverWithResponder : public MessageReceiver {
179  public:
~MessageReceiverWithResponder()180   ~MessageReceiverWithResponder() override {}
181 
182   // A variant on Accept that registers a MessageReceiver (known as the
183   // responder) to handle the response message generated from the given
184   // message. The responder's Accept method may be called during
185   // AcceptWithResponder or some time after its return.
186   //
187   // NOTE: Upon returning true, AcceptWithResponder assumes ownership of
188   // |responder| and will delete it after calling |responder->Accept| or upon
189   // its own destruction.
190   //
191   // TODO(yzshen): consider changing |responder| to
192   // std::unique_ptr<MessageReceiver>.
193   virtual bool AcceptWithResponder(Message* message, MessageReceiver* responder)
194       WARN_UNUSED_RESULT = 0;
195 };
196 
197 // A MessageReceiver that is also able to provide status about the state
198 // of the underlying MessagePipe to which it will be forwarding messages
199 // received via the |Accept()| call.
200 class MessageReceiverWithStatus : public MessageReceiver {
201  public:
~MessageReceiverWithStatus()202   ~MessageReceiverWithStatus() override {}
203 
204   // Returns |true| if this MessageReceiver is currently bound to a MessagePipe,
205   // the pipe has not been closed, and the pipe has not encountered an error.
206   virtual bool IsValid() = 0;
207 
208   // DCHECKs if this MessageReceiver is currently bound to a MessagePipe, the
209   // pipe has not been closed, and the pipe has not encountered an error.
210   // This function may be called on any thread.
211   virtual void DCheckInvalid(const std::string& message) = 0;
212 };
213 
214 // An alternative to MessageReceiverWithResponder for cases in which it
215 // is necessary for the implementor of this interface to know about the status
216 // of the MessagePipe which will carry the responses.
217 class MessageReceiverWithResponderStatus : public MessageReceiver {
218  public:
~MessageReceiverWithResponderStatus()219   ~MessageReceiverWithResponderStatus() override {}
220 
221   // A variant on Accept that registers a MessageReceiverWithStatus (known as
222   // the responder) to handle the response message generated from the given
223   // message. Any of the responder's methods (Accept or IsValid) may be called
224   // during  AcceptWithResponder or some time after its return.
225   //
226   // NOTE: Upon returning true, AcceptWithResponder assumes ownership of
227   // |responder| and will delete it after calling |responder->Accept| or upon
228   // its own destruction.
229   //
230   // TODO(yzshen): consider changing |responder| to
231   // std::unique_ptr<MessageReceiver>.
232   virtual bool AcceptWithResponder(Message* message,
233                                    MessageReceiverWithStatus* responder)
234       WARN_UNUSED_RESULT = 0;
235 };
236 
237 class MOJO_CPP_BINDINGS_EXPORT PassThroughFilter
NON_EXPORTED_BASE(public MessageReceiver)238     : NON_EXPORTED_BASE(public MessageReceiver) {
239  public:
240   PassThroughFilter();
241   ~PassThroughFilter() override;
242 
243   // MessageReceiver:
244   bool Accept(Message* message) override;
245 
246  private:
247   DISALLOW_COPY_AND_ASSIGN(PassThroughFilter);
248 };
249 
250 namespace internal {
251 class SyncMessageResponseSetup;
252 }
253 
254 // An object which should be constructed on the stack immediately before making
255 // a sync request for which the caller wishes to perform custom validation of
256 // the response value(s). It is illegal to make more than one sync call during
257 // the lifetime of the topmost SyncMessageResponseContext, but it is legal to
258 // nest contexts to support reentrancy.
259 //
260 // Usage should look something like:
261 //
262 //     SyncMessageResponseContext response_context;
263 //     foo_interface->SomeSyncCall(&response_value);
264 //     if (response_value.IsBad())
265 //       response_context.ReportBadMessage("Bad response_value!");
266 //
267 class MOJO_CPP_BINDINGS_EXPORT SyncMessageResponseContext {
268  public:
269   SyncMessageResponseContext();
270   ~SyncMessageResponseContext();
271 
272   static SyncMessageResponseContext* current();
273 
274   void ReportBadMessage(const std::string& error);
275 
276   const ReportBadMessageCallback& GetBadMessageCallback();
277 
278  private:
279   friend class internal::SyncMessageResponseSetup;
280 
281   SyncMessageResponseContext* outer_context_;
282   Message response_;
283   ReportBadMessageCallback bad_message_callback_;
284 
285   DISALLOW_COPY_AND_ASSIGN(SyncMessageResponseContext);
286 };
287 
288 // Read a single message from the pipe. The caller should have created the
289 // Message, but not called Initialize(). Returns MOJO_RESULT_SHOULD_WAIT if
290 // the caller should wait on the handle to become readable. Returns
291 // MOJO_RESULT_OK if the message was read successfully and should be
292 // dispatched, otherwise returns an error code if something went wrong.
293 //
294 // NOTE: The message hasn't been validated and may be malformed!
295 MojoResult ReadMessage(MessagePipeHandle handle, Message* message);
296 
297 // Reports the currently dispatching Message as bad. Note that this is only
298 // legal to call from directly within the stack frame of a message dispatch. If
299 // you need to do asynchronous work before you can determine the legitimacy of
300 // a message, use TakeBadMessageCallback() and retain its result until you're
301 // ready to invoke or discard it.
302 MOJO_CPP_BINDINGS_EXPORT
303 void ReportBadMessage(const std::string& error);
304 
305 // Acquires a callback which may be run to report the currently dispatching
306 // Message as bad. Note that this is only legal to call from directly within the
307 // stack frame of a message dispatch, but the returned callback may be called
308 // exactly once any time thereafter to report the message as bad. This may only
309 // be called once per message.
310 MOJO_CPP_BINDINGS_EXPORT
311 ReportBadMessageCallback GetBadMessageCallback();
312 
313 }  // namespace mojo
314 
315 #endif  // MOJO_PUBLIC_CPP_BINDINGS_MESSAGE_H_
316