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