• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2012 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 IPC_IPC_MESSAGE_H_
6 #define IPC_IPC_MESSAGE_H_
7 
8 #include <string>
9 
10 #include "base/basictypes.h"
11 #include "base/debug/trace_event.h"
12 #include "base/files/file.h"
13 #include "base/pickle.h"
14 #include "ipc/ipc_export.h"
15 
16 #if !defined(NDEBUG)
17 #define IPC_MESSAGE_LOG_ENABLED
18 #endif
19 
20 #if defined(OS_POSIX)
21 #include "base/memory/ref_counted.h"
22 #endif
23 
24 class FileDescriptorSet;
25 
26 namespace IPC {
27 
28 //------------------------------------------------------------------------------
29 
30 struct LogData;
31 
32 class IPC_EXPORT Message : public Pickle {
33  public:
34   enum PriorityValue {
35     PRIORITY_LOW = 1,
36     PRIORITY_NORMAL,
37     PRIORITY_HIGH
38   };
39 
40   // Bit values used in the flags field.
41   // Upper 24 bits of flags store a reference number, so this enum is limited to
42   // 8 bits.
43   enum {
44     PRIORITY_MASK     = 0x03,  // Low 2 bits of store the priority value.
45     SYNC_BIT          = 0x04,
46     REPLY_BIT         = 0x08,
47     REPLY_ERROR_BIT   = 0x10,
48     UNBLOCK_BIT       = 0x20,
49     PUMPING_MSGS_BIT  = 0x40,
50     HAS_SENT_TIME_BIT = 0x80,
51   };
52 
53   virtual ~Message();
54 
55   Message();
56 
57   // Initialize a message with a user-defined type, priority value, and
58   // destination WebView ID.
59   Message(int32 routing_id, uint32 type, PriorityValue priority);
60 
61   // Initializes a message from a const block of data.  The data is not copied;
62   // instead the data is merely referenced by this message.  Only const methods
63   // should be used on the message when initialized this way.
64   Message(const char* data, int data_len);
65 
66   Message(const Message& other);
67   Message& operator=(const Message& other);
68 
priority()69   PriorityValue priority() const {
70     return static_cast<PriorityValue>(header()->flags & PRIORITY_MASK);
71   }
72 
73   // True if this is a synchronous message.
set_sync()74   void set_sync() {
75     header()->flags |= SYNC_BIT;
76   }
is_sync()77   bool is_sync() const {
78     return (header()->flags & SYNC_BIT) != 0;
79   }
80 
81   // Set this on a reply to a synchronous message.
set_reply()82   void set_reply() {
83     header()->flags |= REPLY_BIT;
84   }
85 
is_reply()86   bool is_reply() const {
87     return (header()->flags & REPLY_BIT) != 0;
88   }
89 
90   // Set this on a reply to a synchronous message to indicate that no receiver
91   // was found.
set_reply_error()92   void set_reply_error() {
93     header()->flags |= REPLY_ERROR_BIT;
94   }
95 
is_reply_error()96   bool is_reply_error() const {
97     return (header()->flags & REPLY_ERROR_BIT) != 0;
98   }
99 
100   // Normally when a receiver gets a message and they're blocked on a
101   // synchronous message Send, they buffer a message.  Setting this flag causes
102   // the receiver to be unblocked and the message to be dispatched immediately.
set_unblock(bool unblock)103   void set_unblock(bool unblock) {
104     if (unblock) {
105       header()->flags |= UNBLOCK_BIT;
106     } else {
107       header()->flags &= ~UNBLOCK_BIT;
108     }
109   }
110 
should_unblock()111   bool should_unblock() const {
112     return (header()->flags & UNBLOCK_BIT) != 0;
113   }
114 
115   // Tells the receiver that the caller is pumping messages while waiting
116   // for the result.
is_caller_pumping_messages()117   bool is_caller_pumping_messages() const {
118     return (header()->flags & PUMPING_MSGS_BIT) != 0;
119   }
120 
set_dispatch_error()121   void set_dispatch_error() const {
122     dispatch_error_ = true;
123   }
124 
dispatch_error()125   bool dispatch_error() const {
126     return dispatch_error_;
127   }
128 
type()129   uint32 type() const {
130     return header()->type;
131   }
132 
routing_id()133   int32 routing_id() const {
134     return header()->routing;
135   }
136 
set_routing_id(int32 new_id)137   void set_routing_id(int32 new_id) {
138     header()->routing = new_id;
139   }
140 
flags()141   uint32 flags() const {
142     return header()->flags;
143   }
144 
145   // Sets all the given header values. The message should be empty at this
146   // call.
147   void SetHeaderValues(int32 routing, uint32 type, uint32 flags);
148 
149   template<class T, class S, class P>
Dispatch(const Message * msg,T * obj,S * sender,P * parameter,void (T::* func)())150   static bool Dispatch(const Message* msg, T* obj, S* sender, P* parameter,
151                        void (T::*func)()) {
152     (obj->*func)();
153     return true;
154   }
155 
156   template<class T, class S, class P>
Dispatch(const Message * msg,T * obj,S * sender,P * parameter,void (T::* func)(P *))157   static bool Dispatch(const Message* msg, T* obj, S* sender, P* parameter,
158                        void (T::*func)(P*)) {
159     (obj->*func)(parameter);
160     return true;
161   }
162 
163   // Used for async messages with no parameters.
Log(std::string * name,const Message * msg,std::string * l)164   static void Log(std::string* name, const Message* msg, std::string* l) {
165   }
166 
167   // Find the end of the message data that starts at range_start.  Returns NULL
168   // if the entire message is not found in the given data range.
FindNext(const char * range_start,const char * range_end)169   static const char* FindNext(const char* range_start, const char* range_end) {
170     return Pickle::FindNext(sizeof(Header), range_start, range_end);
171   }
172 
173 #if defined(OS_POSIX)
174   // On POSIX, a message supports reading / writing FileDescriptor objects.
175   // This is used to pass a file descriptor to the peer of an IPC channel.
176 
177   // Add a descriptor to the end of the set. Returns false if the set is full.
178   bool WriteFile(base::ScopedFD descriptor);
179   bool WriteBorrowingFile(const base::PlatformFile& descriptor);
180 
181   // Get a file descriptor from the message. Returns false on error.
182   //   iter: a Pickle iterator to the current location in the message.
183   bool ReadFile(PickleIterator* iter, base::ScopedFD* file) const;
184 
185   // Returns true if there are any file descriptors in this message.
186   bool HasFileDescriptors() const;
187 #endif
188 
189 #ifdef IPC_MESSAGE_LOG_ENABLED
190   // Adds the outgoing time from Time::Now() at the end of the message and sets
191   // a bit to indicate that it's been added.
192   void set_sent_time(int64 time);
193   int64 sent_time() const;
194 
195   void set_received_time(int64 time) const;
received_time()196   int64 received_time() const { return received_time_; }
set_output_params(const std::string & op)197   void set_output_params(const std::string& op) const { output_params_ = op; }
output_params()198   const std::string& output_params() const { return output_params_; }
199   // The following four functions are needed so we can log sync messages with
200   // delayed replies.  We stick the log data from the sent message into the
201   // reply message, so that when it's sent and we have the output parameters
202   // we can log it.  As such, we set a flag on the sent message to not log it.
set_sync_log_data(LogData * data)203   void set_sync_log_data(LogData* data) const { log_data_ = data; }
sync_log_data()204   LogData* sync_log_data() const { return log_data_; }
set_dont_log()205   void set_dont_log() const { dont_log_ = true; }
dont_log()206   bool dont_log() const { return dont_log_; }
207 #endif
208 
209   // Called to trace when message is sent.
TraceMessageBegin()210   void TraceMessageBegin() {
211     TRACE_EVENT_FLOW_BEGIN0(TRACE_DISABLED_BY_DEFAULT("ipc.flow"), "IPC",
212         header()->flags);
213   }
214   // Called to trace when message is received.
TraceMessageEnd()215   void TraceMessageEnd() {
216     TRACE_EVENT_FLOW_END0(TRACE_DISABLED_BY_DEFAULT("ipc.flow"), "IPC",
217         header()->flags);
218   }
219 
220  protected:
221   friend class Channel;
222   friend class ChannelMojo;
223   friend class ChannelNacl;
224   friend class ChannelPosix;
225   friend class ChannelWin;
226   friend class MessageReplyDeserializer;
227   friend class SyncMessage;
228 
229 #pragma pack(push, 4)
230   struct Header : Pickle::Header {
231     int32 routing;  // ID of the view that this message is destined for
232     uint32 type;    // specifies the user-defined message type
233     uint32 flags;   // specifies control flags for the message
234 #if defined(OS_POSIX)
235     uint16 num_fds; // the number of descriptors included with this message
236     uint16 pad;     // explicitly initialize this to appease valgrind
237 #endif
238   };
239 #pragma pack(pop)
240 
header()241   Header* header() {
242     return headerT<Header>();
243   }
header()244   const Header* header() const {
245     return headerT<Header>();
246   }
247 
248   void Init();
249 
250   // Used internally to support IPC::Listener::OnBadMessageReceived.
251   mutable bool dispatch_error_;
252 
253 #if defined(OS_POSIX)
254   // The set of file descriptors associated with this message.
255   scoped_refptr<FileDescriptorSet> file_descriptor_set_;
256 
257   // Ensure that a FileDescriptorSet is allocated
258   void EnsureFileDescriptorSet();
259 
file_descriptor_set()260   FileDescriptorSet* file_descriptor_set() {
261     EnsureFileDescriptorSet();
262     return file_descriptor_set_.get();
263   }
file_descriptor_set()264   const FileDescriptorSet* file_descriptor_set() const {
265     return file_descriptor_set_.get();
266   }
267 #endif
268 
269 #ifdef IPC_MESSAGE_LOG_ENABLED
270   // Used for logging.
271   mutable int64 received_time_;
272   mutable std::string output_params_;
273   mutable LogData* log_data_;
274   mutable bool dont_log_;
275 #endif
276 };
277 
278 //------------------------------------------------------------------------------
279 
280 }  // namespace IPC
281 
282 enum SpecialRoutingIDs {
283   // indicates that we don't have a routing ID yet.
284   MSG_ROUTING_NONE = -2,
285 
286   // indicates a general message not sent to a particular tab.
287   MSG_ROUTING_CONTROL = kint32max,
288 };
289 
290 #define IPC_REPLY_ID 0xFFFFFFF0  // Special message id for replies
291 #define IPC_LOGGING_ID 0xFFFFFFF1  // Special message id for logging
292 
293 #endif  // IPC_IPC_MESSAGE_H_
294