Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 : // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
4 : // Use of this source code is governed by a BSD-style license that can be
5 : // found in the LICENSE file.
6 :
7 : #ifndef CHROME_COMMON_IPC_MESSAGE_H__
8 : #define CHROME_COMMON_IPC_MESSAGE_H__
9 :
10 : #include <string>
11 :
12 : #include "base/basictypes.h"
13 : #include "base/pickle.h"
14 : #include "mozilla/TimeStamp.h"
15 :
16 : #ifdef MOZ_TASK_TRACER
17 : #include "GeckoTaskTracer.h"
18 : #endif
19 :
20 : #if defined(OS_POSIX)
21 : #include "nsAutoPtr.h"
22 : #endif
23 :
24 : namespace base {
25 : struct FileDescriptor;
26 : }
27 :
28 : class FileDescriptorSet;
29 :
30 : namespace IPC {
31 :
32 : //------------------------------------------------------------------------------
33 :
34 : class Channel;
35 : class Message;
36 : struct LogData;
37 :
38 : class Message : public Pickle {
39 : public:
40 : typedef uint32_t msgid_t;
41 :
42 : enum NestedLevel {
43 : NOT_NESTED = 1,
44 : NESTED_INSIDE_SYNC = 2,
45 : NESTED_INSIDE_CPOW = 3
46 : };
47 :
48 : enum PriorityValue {
49 : NORMAL_PRIORITY,
50 : HIGH_PRIORITY,
51 : };
52 :
53 : enum MessageCompression {
54 : COMPRESSION_NONE,
55 : COMPRESSION_ENABLED,
56 : COMPRESSION_ALL
57 : };
58 :
59 : virtual ~Message();
60 :
61 : Message();
62 :
63 : // Initialize a message with a user-defined type, priority value, and
64 : // destination WebView ID.
65 : //
66 : // NOTE: `recordWriteLatency` is only passed by IPDL generated message code,
67 : // and is used to trigger the IPC_WRITE_LATENCY_MS telemetry.
68 : Message(int32_t routing_id,
69 : msgid_t type,
70 : uint32_t segmentCapacity = 0, // 0 for the default capacity.
71 : NestedLevel nestedLevel = NOT_NESTED,
72 : PriorityValue priority = NORMAL_PRIORITY,
73 : MessageCompression compression = COMPRESSION_NONE,
74 : const char* const name="???",
75 : bool recordWriteLatency=false);
76 :
77 : Message(const char* data, int data_len);
78 :
79 : Message(const Message& other) = delete;
80 : Message(Message&& other);
81 : Message& operator=(const Message& other) = delete;
82 : Message& operator=(Message&& other);
83 :
84 2513 : NestedLevel nested_level() const {
85 2513 : return static_cast<NestedLevel>(header()->flags & NESTED_MASK);
86 : }
87 :
88 0 : void set_nested_level(NestedLevel nestedLevel) {
89 0 : DCHECK((nestedLevel & ~NESTED_MASK) == 0);
90 0 : header()->flags = (header()->flags & ~NESTED_MASK) | nestedLevel;
91 0 : }
92 :
93 307 : PriorityValue priority() const {
94 307 : if (header()->flags & PRIO_BIT) {
95 36 : return HIGH_PRIORITY;
96 : }
97 271 : return NORMAL_PRIORITY;
98 : }
99 :
100 : void set_priority(PriorityValue prio) {
101 : header()->flags &= ~PRIO_BIT;
102 : if (prio == HIGH_PRIORITY) {
103 : header()->flags |= PRIO_BIT;
104 : }
105 : }
106 :
107 471 : bool is_constructor() const {
108 471 : return (header()->flags & CONSTRUCTOR_BIT) != 0;
109 : }
110 :
111 38 : void set_constructor() {
112 38 : header()->flags |= CONSTRUCTOR_BIT;
113 38 : }
114 :
115 : // True if this is a synchronous message.
116 4832 : bool is_sync() const {
117 4832 : return (header()->flags & SYNC_BIT) != 0;
118 : }
119 :
120 : // True if this is a synchronous message.
121 1880 : bool is_interrupt() const {
122 1880 : return (header()->flags & INTERRUPT_BIT) != 0;
123 : }
124 :
125 : // True if compression is enabled for this message.
126 1571 : MessageCompression compress_type() const {
127 2967 : return (header()->flags & COMPRESS_BIT) ?
128 : COMPRESSION_ENABLED :
129 1396 : (header()->flags & COMPRESSALL_BIT) ?
130 : COMPRESSION_ALL :
131 1571 : COMPRESSION_NONE;
132 : }
133 :
134 : // Set this on a reply to a synchronous message.
135 3 : void set_reply() {
136 3 : header()->flags |= REPLY_BIT;
137 3 : }
138 :
139 9 : bool is_reply() const {
140 9 : return (header()->flags & REPLY_BIT) != 0;
141 : }
142 :
143 : // Set this on a reply to a synchronous message to indicate that no receiver
144 : // was found.
145 0 : void set_reply_error() {
146 0 : header()->flags |= REPLY_ERROR_BIT;
147 0 : }
148 :
149 6 : bool is_reply_error() const {
150 6 : return (header()->flags & REPLY_ERROR_BIT) != 0;
151 : }
152 :
153 2506 : msgid_t type() const {
154 2506 : return header()->type;
155 : }
156 :
157 3897 : int32_t routing_id() const {
158 3897 : return header()->routing;
159 : }
160 :
161 : void set_routing_id(int32_t new_id) {
162 : header()->routing = new_id;
163 : }
164 :
165 916 : int32_t transaction_id() const {
166 916 : return header()->txid;
167 : }
168 :
169 6 : void set_transaction_id(int32_t txid) {
170 6 : header()->txid = txid;
171 6 : }
172 :
173 0 : uint32_t interrupt_remote_stack_depth_guess() const {
174 0 : return header()->interrupt_remote_stack_depth_guess;
175 : }
176 :
177 0 : void set_interrupt_remote_stack_depth_guess(uint32_t depth) {
178 0 : DCHECK(is_interrupt());
179 0 : header()->interrupt_remote_stack_depth_guess = depth;
180 0 : }
181 :
182 : uint32_t interrupt_local_stack_depth() const {
183 : return header()->interrupt_local_stack_depth;
184 : }
185 :
186 0 : void set_interrupt_local_stack_depth(uint32_t depth) {
187 0 : DCHECK(is_interrupt());
188 0 : header()->interrupt_local_stack_depth = depth;
189 0 : }
190 :
191 473 : int32_t seqno() const {
192 473 : return header()->seqno;
193 : }
194 :
195 6 : void set_seqno(int32_t aSeqno) {
196 6 : header()->seqno = aSeqno;
197 6 : }
198 :
199 982 : const char* name() const {
200 982 : return name_;
201 : }
202 :
203 : void set_name(const char* const aName) {
204 : name_ = aName;
205 : }
206 :
207 755 : const mozilla::TimeStamp& create_time() const {
208 755 : return create_time_;
209 : }
210 :
211 : #if defined(OS_POSIX)
212 : uint32_t num_fds() const;
213 : #endif
214 :
215 : template<class T>
216 : static bool Dispatch(const Message* msg, T* obj, void (T::*func)()) {
217 : (obj->*func)();
218 : return true;
219 : }
220 :
221 : template<class T>
222 : static bool Dispatch(const Message* msg, T* obj, void (T::*func)() const) {
223 : (obj->*func)();
224 : return true;
225 : }
226 :
227 : template<class T>
228 : static bool Dispatch(const Message* msg, T* obj,
229 : void (T::*func)(const Message&)) {
230 : (obj->*func)(*msg);
231 : return true;
232 : }
233 :
234 : template<class T>
235 : static bool Dispatch(const Message* msg, T* obj,
236 : void (T::*func)(const Message&) const) {
237 : (obj->*func)(*msg);
238 : return true;
239 : }
240 :
241 : // Used for async messages with no parameters.
242 : static void Log(const Message* msg, std::wstring* l) {
243 : }
244 :
245 388 : static int HeaderSizeFromData(const char* range_start,
246 : const char* range_end) {
247 : #ifdef MOZ_TASK_TRACER
248 : return ((static_cast<unsigned int>(range_end - range_start) >= sizeof(Header)) &&
249 : (reinterpret_cast<const Header*>(range_start)->flags &
250 : TASKTRACER_BIT)) ?
251 : sizeof(HeaderTaskTracer) : sizeof(Header);
252 : #else
253 388 : return sizeof(Header);
254 : #endif
255 : }
256 :
257 : // Figure out how big the message starting at range_start is. Returns 0 if
258 : // there's no enough data to determine (i.e., if [range_start, range_end) does
259 : // not contain enough of the message header to know the size).
260 388 : static uint32_t MessageSize(const char* range_start, const char* range_end) {
261 388 : return Pickle::MessageSize(HeaderSizeFromData(range_start, range_end),
262 388 : range_start, range_end);
263 : }
264 :
265 : #if defined(OS_POSIX)
266 : // On POSIX, a message supports reading / writing FileDescriptor objects.
267 : // This is used to pass a file descriptor to the peer of an IPC channel.
268 :
269 : // Add a descriptor to the end of the set. Returns false iff the set is full.
270 : bool WriteFileDescriptor(const base::FileDescriptor& descriptor);
271 : // Get a file descriptor from the message. Returns false on error.
272 : // iter: a Pickle iterator to the current location in the message.
273 : bool ReadFileDescriptor(PickleIterator* iter, base::FileDescriptor* descriptor) const;
274 :
275 : #if defined(OS_MACOSX)
276 : void set_fd_cookie(uint32_t cookie) {
277 : header()->cookie = cookie;
278 : }
279 : uint32_t fd_cookie() const {
280 : return header()->cookie;
281 : }
282 : #endif
283 : #endif
284 :
285 :
286 : friend class Channel;
287 : friend class MessageReplyDeserializer;
288 : friend class SyncMessage;
289 :
290 6 : void set_sync() {
291 6 : header()->flags |= SYNC_BIT;
292 6 : }
293 :
294 0 : void set_interrupt() {
295 0 : header()->flags |= INTERRUPT_BIT;
296 0 : }
297 :
298 : #ifdef MOZ_TASK_TRACER
299 : void TaskTracerDispatch();
300 : class AutoTaskTracerRun
301 : : public mozilla::tasktracer::AutoSaveCurTraceInfo {
302 : Message& mMsg;
303 : uint64_t mTaskId;
304 : uint64_t mSourceEventId;
305 : public:
306 : explicit AutoTaskTracerRun(Message& aMsg);
307 : ~AutoTaskTracerRun();
308 : };
309 : #endif
310 :
311 : #if !defined(OS_MACOSX)
312 : protected:
313 : #endif
314 :
315 : // flags
316 : enum {
317 : NESTED_MASK = 0x0003,
318 : PRIO_BIT = 0x0004,
319 : SYNC_BIT = 0x0008,
320 : REPLY_BIT = 0x0010,
321 : REPLY_ERROR_BIT = 0x0020,
322 : INTERRUPT_BIT = 0x0040,
323 : COMPRESS_BIT = 0x0080,
324 : COMPRESSALL_BIT = 0x0100,
325 : CONSTRUCTOR_BIT = 0x0200,
326 : #ifdef MOZ_TASK_TRACER
327 : TASKTRACER_BIT = 0x0400,
328 : #endif
329 : };
330 :
331 : struct Header : Pickle::Header {
332 : int32_t routing; // ID of the view that this message is destined for
333 : msgid_t type; // specifies the user-defined message type
334 : uint32_t flags; // specifies control flags for the message
335 : #if defined(OS_POSIX)
336 : uint32_t num_fds; // the number of descriptors included with this message
337 : # if defined(OS_MACOSX)
338 : uint32_t cookie; // cookie to ACK that the descriptors have been read.
339 : # endif
340 : #endif
341 : union {
342 : // For Interrupt messages, a guess at what the *other* side's stack depth is.
343 : uint32_t interrupt_remote_stack_depth_guess;
344 :
345 : // For RPC and Urgent messages, a transaction ID for message ordering.
346 : int32_t txid;
347 : };
348 : // The actual local stack depth.
349 : uint32_t interrupt_local_stack_depth;
350 : // Sequence number
351 : int32_t seqno;
352 : };
353 :
354 : #ifdef MOZ_TASK_TRACER
355 : /**
356 : * The type is used as headers of Messages only if TaskTracer is
357 : * enabled, or type |Header| would be used instead.
358 : */
359 : struct HeaderTaskTracer : public Header {
360 : uint64_t task_id;
361 : uint64_t source_event_id;
362 : uint64_t parent_task_id;
363 : mozilla::tasktracer::SourceEventType source_event_type;
364 : };
365 : #endif
366 :
367 : #ifdef MOZ_TASK_TRACER
368 : bool UseTaskTracerHeader() const {
369 : return sizeof(HeaderTaskTracer) == (size() - payload_size());
370 : }
371 :
372 : Header* header() {
373 : return UseTaskTracerHeader() ?
374 : headerT<HeaderTaskTracer>() : headerT<Header>();
375 : }
376 : const Header* header() const {
377 : return UseTaskTracerHeader() ?
378 : headerT<HeaderTaskTracer>() : headerT<Header>();
379 : }
380 : #else
381 4637 : Header* header() {
382 4637 : return headerT<Header>();
383 : }
384 20777 : const Header* header() const {
385 20777 : return headerT<Header>();
386 : }
387 : #endif
388 :
389 : void InitLoggingVariables(const char* const name="???");
390 :
391 : #if defined(OS_POSIX)
392 : // The set of file descriptors associated with this message.
393 : RefPtr<FileDescriptorSet> file_descriptor_set_;
394 :
395 : // Ensure that a FileDescriptorSet is allocated
396 : void EnsureFileDescriptorSet();
397 :
398 956 : FileDescriptorSet* file_descriptor_set() {
399 956 : EnsureFileDescriptorSet();
400 956 : return file_descriptor_set_.get();
401 : }
402 0 : const FileDescriptorSet* file_descriptor_set() const {
403 0 : return file_descriptor_set_.get();
404 : }
405 : #endif
406 :
407 : const char* name_;
408 :
409 : mozilla::TimeStamp create_time_;
410 :
411 : };
412 :
413 : class MessageInfo {
414 : public:
415 : typedef uint32_t msgid_t;
416 :
417 0 : explicit MessageInfo(const Message& aMsg)
418 0 : : mSeqno(aMsg.seqno()), mType(aMsg.type()) {}
419 :
420 0 : int32_t seqno() const { return mSeqno; }
421 0 : msgid_t type() const { return mType; }
422 :
423 : private:
424 : int32_t mSeqno;
425 : msgid_t mType;
426 : };
427 :
428 : //------------------------------------------------------------------------------
429 :
430 : } // namespace IPC
431 :
432 : enum SpecialRoutingIDs {
433 : // indicates that we don't have a routing ID yet.
434 : MSG_ROUTING_NONE = kint32min,
435 :
436 : // indicates a general message not sent to a particular tab.
437 : MSG_ROUTING_CONTROL = kint32max
438 : };
439 :
440 : #define IPC_REPLY_ID 0xFFF0 // Special message id for replies
441 : #define IPC_LOGGING_ID 0xFFF1 // Special message id for logging
442 :
443 : #endif // CHROME_COMMON_IPC_MESSAGE_H__
|