|
1 // Copyright (c) 2006-2008 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 CHROME_COMMON_IPC_MESSAGE_H__ |
|
6 #define CHROME_COMMON_IPC_MESSAGE_H__ |
|
7 |
|
8 #include <string> |
|
9 |
|
10 #include "base/basictypes.h" |
|
11 #include "base/pickle.h" |
|
12 |
|
13 #ifdef MOZ_TASK_TRACER |
|
14 #include "GeckoTaskTracer.h" |
|
15 #endif |
|
16 |
|
17 #ifndef NDEBUG |
|
18 #define IPC_MESSAGE_LOG_ENABLED |
|
19 #endif |
|
20 |
|
21 #if defined(OS_POSIX) |
|
22 #include "base/ref_counted.h" |
|
23 #endif |
|
24 |
|
25 namespace base { |
|
26 struct FileDescriptor; |
|
27 } |
|
28 |
|
29 class FileDescriptorSet; |
|
30 |
|
31 namespace IPC { |
|
32 |
|
33 //------------------------------------------------------------------------------ |
|
34 |
|
35 class Channel; |
|
36 class Message; |
|
37 struct LogData; |
|
38 |
|
39 class Message : public Pickle { |
|
40 public: |
|
41 typedef uint32_t msgid_t; |
|
42 |
|
43 // Implemented by objects that can send IPC messages across a channel. |
|
44 class Sender { |
|
45 public: |
|
46 virtual ~Sender() {} |
|
47 |
|
48 // Sends the given IPC message. The implementor takes ownership of the |
|
49 // given Message regardless of whether or not this method succeeds. This |
|
50 // is done to make this method easier to use. Returns true on success and |
|
51 // false otherwise. |
|
52 virtual bool Send(Message* msg) = 0; |
|
53 }; |
|
54 |
|
55 enum PriorityValue { |
|
56 PRIORITY_LOW = 1, |
|
57 PRIORITY_NORMAL, |
|
58 PRIORITY_HIGH |
|
59 }; |
|
60 |
|
61 enum MessageCompression { |
|
62 COMPRESSION_NONE, |
|
63 COMPRESSION_ENABLED |
|
64 }; |
|
65 |
|
66 virtual ~Message(); |
|
67 |
|
68 Message(); |
|
69 |
|
70 // Initialize a message with a user-defined type, priority value, and |
|
71 // destination WebView ID. |
|
72 Message(int32_t routing_id, msgid_t type, PriorityValue priority, |
|
73 MessageCompression compression = COMPRESSION_NONE, |
|
74 const char* const name="???"); |
|
75 |
|
76 // Initializes a message from a const block of data. The data is not copied; |
|
77 // instead the data is merely referenced by this message. Only const methods |
|
78 // should be used on the message when initialized this way. |
|
79 Message(const char* data, int data_len); |
|
80 |
|
81 Message(const Message& other); |
|
82 Message& operator=(const Message& other); |
|
83 |
|
84 PriorityValue priority() const { |
|
85 return static_cast<PriorityValue>(header()->flags & PRIORITY_MASK); |
|
86 } |
|
87 |
|
88 // True if this is a synchronous message. |
|
89 bool is_sync() const { |
|
90 return (header()->flags & SYNC_BIT) != 0; |
|
91 } |
|
92 |
|
93 // True if this is a synchronous message. |
|
94 bool is_interrupt() const { |
|
95 return (header()->flags & INTERRUPT_BIT) != 0; |
|
96 } |
|
97 |
|
98 // True if this is an urgent message. |
|
99 bool is_urgent() const { |
|
100 return (header()->flags & URGENT_BIT) != 0; |
|
101 } |
|
102 |
|
103 // True if this is an RPC message. |
|
104 bool is_rpc() const { |
|
105 return (header()->flags & RPC_BIT) != 0; |
|
106 } |
|
107 |
|
108 // True if compression is enabled for this message. |
|
109 bool compress() const { |
|
110 return (header()->flags & COMPRESS_BIT) != 0; |
|
111 } |
|
112 |
|
113 // Set this on a reply to a synchronous message. |
|
114 void set_reply() { |
|
115 header()->flags |= REPLY_BIT; |
|
116 } |
|
117 |
|
118 bool is_reply() const { |
|
119 return (header()->flags & REPLY_BIT) != 0; |
|
120 } |
|
121 |
|
122 // Set this on a reply to a synchronous message to indicate that no receiver |
|
123 // was found. |
|
124 void set_reply_error() { |
|
125 header()->flags |= REPLY_ERROR_BIT; |
|
126 } |
|
127 |
|
128 bool is_reply_error() const { |
|
129 return (header()->flags & REPLY_ERROR_BIT) != 0; |
|
130 } |
|
131 |
|
132 // Normally when a receiver gets a message and they're blocked on a |
|
133 // synchronous message Send, they buffer a message. Setting this flag causes |
|
134 // the receiver to be unblocked and the message to be dispatched immediately. |
|
135 void set_unblock(bool unblock) { |
|
136 if (unblock) { |
|
137 header()->flags |= UNBLOCK_BIT; |
|
138 } else { |
|
139 header()->flags &= ~UNBLOCK_BIT; |
|
140 } |
|
141 } |
|
142 |
|
143 bool should_unblock() const { |
|
144 return (header()->flags & UNBLOCK_BIT) != 0; |
|
145 } |
|
146 |
|
147 // Tells the receiver that the caller is pumping messages while waiting |
|
148 // for the result. |
|
149 bool is_caller_pumping_messages() const { |
|
150 return (header()->flags & PUMPING_MSGS_BIT) != 0; |
|
151 } |
|
152 |
|
153 msgid_t type() const { |
|
154 return header()->type; |
|
155 } |
|
156 |
|
157 int32_t routing_id() const { |
|
158 return header()->routing; |
|
159 } |
|
160 |
|
161 void set_routing_id(int32_t new_id) { |
|
162 header()->routing = new_id; |
|
163 } |
|
164 |
|
165 int32_t transaction_id() const { |
|
166 return header()->txid; |
|
167 } |
|
168 |
|
169 void set_transaction_id(int32_t txid) { |
|
170 header()->txid = txid; |
|
171 } |
|
172 |
|
173 uint32_t interrupt_remote_stack_depth_guess() const { |
|
174 return header()->interrupt_remote_stack_depth_guess; |
|
175 } |
|
176 |
|
177 void set_interrupt_remote_stack_depth_guess(uint32_t depth) { |
|
178 DCHECK(is_interrupt()); |
|
179 header()->interrupt_remote_stack_depth_guess = depth; |
|
180 } |
|
181 |
|
182 uint32_t interrupt_local_stack_depth() const { |
|
183 return header()->interrupt_local_stack_depth; |
|
184 } |
|
185 |
|
186 void set_interrupt_local_stack_depth(uint32_t depth) { |
|
187 DCHECK(is_interrupt()); |
|
188 header()->interrupt_local_stack_depth = depth; |
|
189 } |
|
190 |
|
191 int32_t seqno() const { |
|
192 return header()->seqno; |
|
193 } |
|
194 |
|
195 void set_seqno(int32_t seqno) { |
|
196 header()->seqno = seqno; |
|
197 } |
|
198 |
|
199 const char* const name() const { |
|
200 return name_; |
|
201 } |
|
202 |
|
203 void set_name(const char* const name) { |
|
204 name_ = name; |
|
205 } |
|
206 |
|
207 template<class T> |
|
208 static bool Dispatch(const Message* msg, T* obj, void (T::*func)()) { |
|
209 (obj->*func)(); |
|
210 return true; |
|
211 } |
|
212 |
|
213 template<class T> |
|
214 static bool Dispatch(const Message* msg, T* obj, void (T::*func)() const) { |
|
215 (obj->*func)(); |
|
216 return true; |
|
217 } |
|
218 |
|
219 template<class T> |
|
220 static bool Dispatch(const Message* msg, T* obj, |
|
221 void (T::*func)(const Message&)) { |
|
222 (obj->*func)(*msg); |
|
223 return true; |
|
224 } |
|
225 |
|
226 template<class T> |
|
227 static bool Dispatch(const Message* msg, T* obj, |
|
228 void (T::*func)(const Message&) const) { |
|
229 (obj->*func)(*msg); |
|
230 return true; |
|
231 } |
|
232 |
|
233 // Used for async messages with no parameters. |
|
234 static void Log(const Message* msg, std::wstring* l) { |
|
235 } |
|
236 |
|
237 // Find the end of the message data that starts at range_start. Returns NULL |
|
238 // if the entire message is not found in the given data range. |
|
239 static const char* FindNext(const char* range_start, const char* range_end) { |
|
240 return Pickle::FindNext(sizeof(Header), range_start, range_end); |
|
241 } |
|
242 |
|
243 #if defined(OS_POSIX) |
|
244 // On POSIX, a message supports reading / writing FileDescriptor objects. |
|
245 // This is used to pass a file descriptor to the peer of an IPC channel. |
|
246 |
|
247 // Add a descriptor to the end of the set. Returns false iff the set is full. |
|
248 bool WriteFileDescriptor(const base::FileDescriptor& descriptor); |
|
249 // Get a file descriptor from the message. Returns false on error. |
|
250 // iter: a Pickle iterator to the current location in the message. |
|
251 bool ReadFileDescriptor(void** iter, base::FileDescriptor* descriptor) const; |
|
252 |
|
253 #if defined(OS_MACOSX) |
|
254 void set_fd_cookie(uint32_t cookie) { |
|
255 header()->cookie = cookie; |
|
256 } |
|
257 uint32_t fd_cookie() const { |
|
258 return header()->cookie; |
|
259 } |
|
260 #endif |
|
261 #endif |
|
262 |
|
263 #ifdef IPC_MESSAGE_LOG_ENABLED |
|
264 // Adds the outgoing time from Time::Now() at the end of the message and sets |
|
265 // a bit to indicate that it's been added. |
|
266 void set_sent_time(int64_t time); |
|
267 int64_t sent_time() const; |
|
268 |
|
269 void set_received_time(int64_t time) const; |
|
270 int64_t received_time() const { return received_time_; } |
|
271 void set_output_params(const std::wstring& op) const { output_params_ = op; } |
|
272 const std::wstring& output_params() const { return output_params_; } |
|
273 // The following four functions are needed so we can log sync messages with |
|
274 // delayed replies. We stick the log data from the sent message into the |
|
275 // reply message, so that when it's sent and we have the output parameters |
|
276 // we can log it. As such, we set a flag on the sent message to not log it. |
|
277 void set_sync_log_data(LogData* data) const { log_data_ = data; } |
|
278 LogData* sync_log_data() const { return log_data_; } |
|
279 void set_dont_log() const { dont_log_ = true; } |
|
280 bool dont_log() const { return dont_log_; } |
|
281 #endif |
|
282 |
|
283 friend class Channel; |
|
284 friend class MessageReplyDeserializer; |
|
285 friend class SyncMessage; |
|
286 |
|
287 void set_sync() { |
|
288 header()->flags |= SYNC_BIT; |
|
289 } |
|
290 |
|
291 void set_interrupt() { |
|
292 header()->flags |= INTERRUPT_BIT; |
|
293 } |
|
294 |
|
295 void set_urgent() { |
|
296 header()->flags |= URGENT_BIT; |
|
297 } |
|
298 |
|
299 void set_rpc() { |
|
300 header()->flags |= RPC_BIT; |
|
301 } |
|
302 |
|
303 #if !defined(OS_MACOSX) |
|
304 protected: |
|
305 #endif |
|
306 |
|
307 // flags |
|
308 enum { |
|
309 PRIORITY_MASK = 0x0003, |
|
310 SYNC_BIT = 0x0004, |
|
311 REPLY_BIT = 0x0008, |
|
312 REPLY_ERROR_BIT = 0x0010, |
|
313 UNBLOCK_BIT = 0x0020, |
|
314 PUMPING_MSGS_BIT= 0x0040, |
|
315 HAS_SENT_TIME_BIT = 0x0080, |
|
316 INTERRUPT_BIT = 0x0100, |
|
317 COMPRESS_BIT = 0x0200, |
|
318 URGENT_BIT = 0x0400, |
|
319 RPC_BIT = 0x0800 |
|
320 }; |
|
321 |
|
322 struct Header : Pickle::Header { |
|
323 int32_t routing; // ID of the view that this message is destined for |
|
324 msgid_t type; // specifies the user-defined message type |
|
325 uint32_t flags; // specifies control flags for the message |
|
326 #if defined(OS_POSIX) |
|
327 uint32_t num_fds; // the number of descriptors included with this message |
|
328 # if defined(OS_MACOSX) |
|
329 uint32_t cookie; // cookie to ACK that the descriptors have been read. |
|
330 # endif |
|
331 #endif |
|
332 union { |
|
333 // For Interrupt messages, a guess at what the *other* side's stack depth is. |
|
334 uint32_t interrupt_remote_stack_depth_guess; |
|
335 |
|
336 // For RPC and Urgent messages, a transaction ID for message ordering. |
|
337 int32_t txid; |
|
338 }; |
|
339 // The actual local stack depth. |
|
340 uint32_t interrupt_local_stack_depth; |
|
341 // Sequence number |
|
342 int32_t seqno; |
|
343 #ifdef MOZ_TASK_TRACER |
|
344 uint64_t source_event_id; |
|
345 uint64_t parent_task_id; |
|
346 mozilla::tasktracer::SourceEventType source_event_type; |
|
347 #endif |
|
348 }; |
|
349 |
|
350 Header* header() { |
|
351 return headerT<Header>(); |
|
352 } |
|
353 const Header* header() const { |
|
354 return headerT<Header>(); |
|
355 } |
|
356 |
|
357 void InitLoggingVariables(const char* const name="???"); |
|
358 |
|
359 #if defined(OS_POSIX) |
|
360 // The set of file descriptors associated with this message. |
|
361 scoped_refptr<FileDescriptorSet> file_descriptor_set_; |
|
362 |
|
363 // Ensure that a FileDescriptorSet is allocated |
|
364 void EnsureFileDescriptorSet(); |
|
365 |
|
366 FileDescriptorSet* file_descriptor_set() { |
|
367 EnsureFileDescriptorSet(); |
|
368 return file_descriptor_set_.get(); |
|
369 } |
|
370 const FileDescriptorSet* file_descriptor_set() const { |
|
371 return file_descriptor_set_.get(); |
|
372 } |
|
373 #endif |
|
374 |
|
375 const char* name_; |
|
376 |
|
377 #ifdef IPC_MESSAGE_LOG_ENABLED |
|
378 // Used for logging. |
|
379 mutable int64_t received_time_; |
|
380 mutable std::wstring output_params_; |
|
381 mutable LogData* log_data_; |
|
382 mutable bool dont_log_; |
|
383 #endif |
|
384 }; |
|
385 |
|
386 //------------------------------------------------------------------------------ |
|
387 |
|
388 } // namespace IPC |
|
389 |
|
390 enum SpecialRoutingIDs { |
|
391 // indicates that we don't have a routing ID yet. |
|
392 MSG_ROUTING_NONE = kint32min, |
|
393 |
|
394 // indicates a general message not sent to a particular tab. |
|
395 MSG_ROUTING_CONTROL = kint32max |
|
396 }; |
|
397 |
|
398 #define IPC_REPLY_ID 0xFFF0 // Special message id for replies |
|
399 #define IPC_LOGGING_ID 0xFFF1 // Special message id for logging |
|
400 |
|
401 #endif // CHROME_COMMON_IPC_MESSAGE_H__ |