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_UTILS_H_
8 : #define CHROME_COMMON_IPC_MESSAGE_UTILS_H_
9 :
10 : #include <string>
11 : #include <vector>
12 : #include <map>
13 :
14 : #include "base/file_path.h"
15 : #include "base/string_util.h"
16 : #include "base/string16.h"
17 : #include "base/time.h"
18 :
19 : #if defined(OS_POSIX)
20 : #include "chrome/common/file_descriptor_set_posix.h"
21 : #endif
22 : #include "chrome/common/ipc_message.h"
23 : #include "chrome/common/transport_dib.h"
24 :
25 : namespace IPC {
26 :
27 : //-----------------------------------------------------------------------------
28 : // An iterator class for reading the fields contained within a Message.
29 :
30 : class MessageIterator {
31 : public:
32 23 : explicit MessageIterator(const Message& m) : msg_(m), iter_(m) {
33 23 : }
34 23 : int NextInt() const {
35 : int val;
36 23 : if (!msg_.ReadInt(&iter_, &val))
37 0 : NOTREACHED();
38 23 : return val;
39 : }
40 : intptr_t NextIntPtr() const {
41 : intptr_t val;
42 : if (!msg_.ReadIntPtr(&iter_, &val))
43 : NOTREACHED();
44 : return val;
45 : }
46 : const std::string NextString() const {
47 : std::string val;
48 : if (!msg_.ReadString(&iter_, &val))
49 : NOTREACHED();
50 : return val;
51 : }
52 : const std::wstring NextWString() const {
53 : std::wstring val;
54 : if (!msg_.ReadWString(&iter_, &val))
55 : NOTREACHED();
56 : return val;
57 : }
58 : private:
59 : const Message& msg_;
60 : mutable PickleIterator iter_;
61 : };
62 :
63 : //-----------------------------------------------------------------------------
64 : // ParamTraits specializations, etc.
65 : //
66 : // The full set of types ParamTraits is specialized upon contains *possibly*
67 : // repeated types: unsigned long may be uint32_t or size_t, unsigned long long
68 : // may be uint64_t or size_t, nsresult may be uint32_t, and so on. You can't
69 : // have ParamTraits<unsigned int> *and* ParamTraits<uint32_t> if unsigned int
70 : // is uint32_t -- that's multiple definitions, and you can only have one.
71 : //
72 : // You could use #ifs and macro conditions to avoid duplicates, but they'd be
73 : // hairy: heavily dependent upon OS and compiler author choices, forced to
74 : // address all conflicts by hand. Happily there's a better way. The basic
75 : // idea looks like this, where T -> U represents T inheriting from U:
76 : //
77 : // class ParamTraits<P>
78 : // |
79 : // --> class ParamTraits1<P>
80 : // |
81 : // --> class ParamTraits2<P>
82 : // |
83 : // --> class ParamTraitsN<P> // or however many levels
84 : //
85 : // The default specialization of ParamTraits{M}<P> is an empty class that
86 : // inherits from ParamTraits{M + 1}<P> (or nothing in the base case).
87 : //
88 : // Now partition the set of parameter types into sets without duplicates.
89 : // Assign each set of types to a level M. Then specialize ParamTraitsM for
90 : // each of those types. A reference to ParamTraits<P> will consist of some
91 : // number of empty classes inheriting in sequence, ending in a non-empty
92 : // ParamTraits{N}<P>. It's okay for the parameter types to be duplicative:
93 : // either name of a type will resolve to the same ParamTraits{N}<P>.
94 : //
95 : // The nice thing is that because templates are instantiated lazily, if we
96 : // indeed have uint32_t == unsigned int, say, with the former in level N and
97 : // the latter in M > N, ParamTraitsM<unsigned int> won't be created (as long as
98 : // nobody uses ParamTraitsM<unsigned int>, but why would you), and no duplicate
99 : // code will be compiled or extra symbols generated. It's as efficient at
100 : // runtime as manually figuring out and avoiding conflicts by #ifs.
101 : //
102 : // The scheme we follow below names the various classes according to the types
103 : // in them, and the number of ParamTraits levels is larger, but otherwise it's
104 : // exactly the above idea.
105 : //
106 :
107 : template <class P> struct ParamTraits;
108 :
109 : template <class P>
110 70028 : static inline void WriteParam(Message* m, const P& p) {
111 70028 : ParamTraits<P>::Write(m, p);
112 70028 : }
113 :
114 : template <class P>
115 69466 : static inline bool WARN_UNUSED_RESULT ReadParam(const Message* m, PickleIterator* iter,
116 : P* p) {
117 69466 : return ParamTraits<P>::Read(m, iter, p);
118 : }
119 :
120 : template <class P>
121 0 : static inline void LogParam(const P& p, std::wstring* l) {
122 0 : ParamTraits<P>::Log(p, l);
123 0 : }
124 :
125 : // Fundamental types.
126 :
127 : template <class P>
128 : struct ParamTraitsFundamental {};
129 :
130 : template <>
131 : struct ParamTraitsFundamental<bool> {
132 : typedef bool param_type;
133 4110 : static void Write(Message* m, const param_type& p) {
134 4110 : m->WriteBool(p);
135 4110 : }
136 4104 : static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
137 4104 : return m->ReadBool(iter, r);
138 : }
139 : static void Log(const param_type& p, std::wstring* l) {
140 : l->append(p ? L"true" : L"false");
141 : }
142 : };
143 :
144 : template <>
145 : struct ParamTraitsFundamental<int> {
146 : typedef int param_type;
147 27696 : static void Write(Message* m, const param_type& p) {
148 27696 : m->WriteInt(p);
149 27696 : }
150 27714 : static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
151 27714 : return m->ReadInt(iter, r);
152 : }
153 : static void Log(const param_type& p, std::wstring* l) {
154 : l->append(StringPrintf(L"%d", p));
155 : }
156 : };
157 :
158 : template <>
159 : struct ParamTraitsFundamental<long> {
160 : typedef long param_type;
161 : static void Write(Message* m, const param_type& p) {
162 : m->WriteLong(p);
163 : }
164 : static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
165 : return m->ReadLong(iter, r);
166 : }
167 : static void Log(const param_type& p, std::wstring* l) {
168 : l->append(StringPrintf(L"%l", p));
169 : }
170 : };
171 :
172 : template <>
173 : struct ParamTraitsFundamental<unsigned long> {
174 : typedef unsigned long param_type;
175 : static void Write(Message* m, const param_type& p) {
176 : m->WriteULong(p);
177 : }
178 : static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
179 : return m->ReadULong(iter, r);
180 : }
181 : static void Log(const param_type& p, std::wstring* l) {
182 : l->append(StringPrintf(L"%ul", p));
183 : }
184 : };
185 :
186 : template <>
187 : struct ParamTraitsFundamental<long long> {
188 : typedef long long param_type;
189 : static void Write(Message* m, const param_type& p) {
190 : m->WriteBytes(&p, sizeof(param_type));
191 : }
192 : static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
193 : return m->ReadBytesInto(iter, r, sizeof(*r));
194 : }
195 : static void Log(const param_type& p, std::wstring* l) {
196 : l->append(StringPrintf(L"%ll", p));
197 : }
198 : };
199 :
200 : template <>
201 : struct ParamTraitsFundamental<unsigned long long> {
202 : typedef unsigned long long param_type;
203 : static void Write(Message* m, const param_type& p) {
204 : m->WriteBytes(&p, sizeof(param_type));
205 : }
206 : static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
207 : return m->ReadBytesInto(iter, r, sizeof(*r));
208 : }
209 : static void Log(const param_type& p, std::wstring* l) {
210 : l->append(StringPrintf(L"%ull", p));
211 : }
212 : };
213 :
214 : template <>
215 : struct ParamTraitsFundamental<double> {
216 : typedef double param_type;
217 2 : static void Write(Message* m, const param_type& p) {
218 2 : m->WriteDouble(p);
219 2 : }
220 2 : static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
221 2 : return m->ReadDouble(iter, r);
222 : }
223 : static void Log(const param_type& p, std::wstring* l) {
224 : l->append(StringPrintf(L"e", p));
225 : }
226 : };
227 :
228 : // Fixed-size <stdint.h> types.
229 :
230 : template <class P>
231 : struct ParamTraitsFixed : ParamTraitsFundamental<P> {};
232 :
233 : template <>
234 : struct ParamTraitsFixed<int16_t> {
235 : typedef int16_t param_type;
236 19 : static void Write(Message* m, const param_type& p) {
237 19 : m->WriteInt16(p);
238 19 : }
239 19 : static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
240 19 : return m->ReadInt16(iter, r);
241 : }
242 : static void Log(const param_type& p, std::wstring* l) {
243 : l->append(StringPrintf(L"%hd", p));
244 : }
245 : };
246 :
247 : template <>
248 : struct ParamTraitsFixed<uint16_t> {
249 : typedef uint16_t param_type;
250 29 : static void Write(Message* m, const param_type& p) {
251 29 : m->WriteUInt16(p);
252 29 : }
253 29 : static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
254 29 : return m->ReadUInt16(iter, r);
255 : }
256 : static void Log(const param_type& p, std::wstring* l) {
257 : l->append(StringPrintf(L"%hu", p));
258 : }
259 : };
260 :
261 : template <>
262 : struct ParamTraitsFixed<uint32_t> {
263 : typedef uint32_t param_type;
264 12370 : static void Write(Message* m, const param_type& p) {
265 12370 : m->WriteUInt32(p);
266 12370 : }
267 12097 : static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
268 12097 : return m->ReadUInt32(iter, r);
269 : }
270 0 : static void Log(const param_type& p, std::wstring* l) {
271 0 : l->append(StringPrintf(L"%u", p));
272 0 : }
273 : };
274 :
275 : template <>
276 : struct ParamTraitsFixed<int64_t> {
277 : typedef int64_t param_type;
278 11 : static void Write(Message* m, const param_type& p) {
279 11 : m->WriteInt64(p);
280 11 : }
281 11 : static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
282 11 : return m->ReadInt64(iter, r);
283 : }
284 0 : static void Log(const param_type& p, std::wstring* l) {
285 0 : l->append(StringPrintf(L"%" PRId64L, p));
286 0 : }
287 : };
288 :
289 : template <>
290 : struct ParamTraitsFixed<uint64_t> {
291 : typedef uint64_t param_type;
292 : static void Write(Message* m, const param_type& p) {
293 : m->WriteInt64(static_cast<int64_t>(p));
294 : }
295 : static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
296 : return m->ReadInt64(iter, reinterpret_cast<int64_t*>(r));
297 : }
298 : static void Log(const param_type& p, std::wstring* l) {
299 : l->append(StringPrintf(L"%" PRIu64L, p));
300 : }
301 : };
302 :
303 : // Other standard C types.
304 :
305 : template <class P>
306 : struct ParamTraitsLibC : ParamTraitsFixed<P> {};
307 :
308 : template <>
309 : struct ParamTraitsLibC<size_t> {
310 : typedef size_t param_type;
311 1645 : static void Write(Message* m, const param_type& p) {
312 1645 : m->WriteSize(p);
313 1645 : }
314 1644 : static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
315 1644 : return m->ReadSize(iter, r);
316 : }
317 : static void Log(const param_type& p, std::wstring* l) {
318 : l->append(StringPrintf(L"%u", p));
319 : }
320 : };
321 :
322 : // std::* types.
323 :
324 : template <class P>
325 : struct ParamTraitsStd : ParamTraitsLibC<P> {};
326 :
327 : template <>
328 : struct ParamTraitsStd<std::string> {
329 : typedef std::string param_type;
330 0 : static void Write(Message* m, const param_type& p) {
331 0 : m->WriteString(p);
332 0 : }
333 0 : static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
334 0 : return m->ReadString(iter, r);
335 : }
336 : static void Log(const param_type& p, std::wstring* l) {
337 : l->append(UTF8ToWide(p));
338 : }
339 : };
340 :
341 : template <>
342 : struct ParamTraitsStd<std::wstring> {
343 : typedef std::wstring param_type;
344 0 : static void Write(Message* m, const param_type& p) {
345 0 : m->WriteWString(p);
346 0 : }
347 0 : static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
348 0 : return m->ReadWString(iter, r);
349 : }
350 : static void Log(const param_type& p, std::wstring* l) {
351 : l->append(p);
352 : }
353 : };
354 :
355 : template <class K, class V>
356 : struct ParamTraitsStd<std::map<K, V> > {
357 : typedef std::map<K, V> param_type;
358 0 : static void Write(Message* m, const param_type& p) {
359 0 : WriteParam(m, static_cast<int>(p.size()));
360 0 : typename param_type::const_iterator iter;
361 0 : for (iter = p.begin(); iter != p.end(); ++iter) {
362 0 : WriteParam(m, iter->first);
363 0 : WriteParam(m, iter->second);
364 : }
365 0 : }
366 0 : static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
367 : int size;
368 0 : if (!ReadParam(m, iter, &size) || size < 0)
369 0 : return false;
370 0 : for (int i = 0; i < size; ++i) {
371 0 : K k;
372 0 : if (!ReadParam(m, iter, &k))
373 0 : return false;
374 0 : V& value = (*r)[k];
375 0 : if (!ReadParam(m, iter, &value))
376 0 : return false;
377 : }
378 0 : return true;
379 : }
380 : static void Log(const param_type& p, std::wstring* l) {
381 : l->append(L"<std::map>");
382 : }
383 : };
384 :
385 : // Windows-specific types.
386 :
387 : template <class P>
388 : struct ParamTraitsWindows : ParamTraitsStd<P> {};
389 :
390 : #if defined(OS_WIN)
391 : template <>
392 : struct ParamTraitsWindows<HANDLE> {
393 : typedef HANDLE param_type;
394 : static void Write(Message* m, const param_type& p) {
395 : m->WriteIntPtr(reinterpret_cast<intptr_t>(p));
396 : }
397 : static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
398 : DCHECK_EQ(sizeof(param_type), sizeof(intptr_t));
399 : return m->ReadIntPtr(iter, reinterpret_cast<intptr_t*>(r));
400 : }
401 : static void Log(const param_type& p, std::wstring* l) {
402 : l->append(StringPrintf(L"0x%X", p));
403 : }
404 : };
405 :
406 : template <>
407 : struct ParamTraitsWindows<HWND> {
408 : typedef HWND param_type;
409 : static void Write(Message* m, const param_type& p) {
410 : m->WriteIntPtr(reinterpret_cast<intptr_t>(p));
411 : }
412 : static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
413 : DCHECK_EQ(sizeof(param_type), sizeof(intptr_t));
414 : return m->ReadIntPtr(iter, reinterpret_cast<intptr_t*>(r));
415 : }
416 : static void Log(const param_type& p, std::wstring* l) {
417 : l->append(StringPrintf(L"0x%X", p));
418 : }
419 : };
420 : #endif // defined(OS_WIN)
421 :
422 : // Various ipc/chromium types.
423 :
424 : template <class P>
425 : struct ParamTraitsIPC : ParamTraitsWindows<P> {};
426 :
427 : #if defined(OS_POSIX)
428 : // FileDescriptors may be serialised over IPC channels on POSIX. On the
429 : // receiving side, the FileDescriptor is a valid duplicate of the file
430 : // descriptor which was transmitted: *it is not just a copy of the integer like
431 : // HANDLEs on Windows*. The only exception is if the file descriptor is < 0. In
432 : // this case, the receiving end will see a value of -1. *Zero is a valid file
433 : // descriptor*.
434 : //
435 : // The received file descriptor will have the |auto_close| flag set to true. The
436 : // code which handles the message is responsible for taking ownership of it.
437 : // File descriptors are OS resources and must be closed when no longer needed.
438 : //
439 : // When sending a file descriptor, the file descriptor must be valid at the time
440 : // of transmission. Since transmission is not synchronous, one should consider
441 : // dup()ing any file descriptors to be transmitted and setting the |auto_close|
442 : // flag, which causes the file descriptor to be closed after writing.
443 : template<>
444 : struct ParamTraitsIPC<base::FileDescriptor> {
445 : typedef base::FileDescriptor param_type;
446 55 : static void Write(Message* m, const param_type& p) {
447 55 : const bool valid = p.fd >= 0;
448 55 : WriteParam(m, valid);
449 :
450 55 : if (valid) {
451 55 : if (!m->WriteFileDescriptor(p)) {
452 0 : NOTREACHED() << "Too many file descriptors for one message!";
453 : }
454 : }
455 55 : }
456 52 : static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
457 : bool valid;
458 52 : if (!ReadParam(m, iter, &valid))
459 0 : return false;
460 :
461 52 : if (!valid) {
462 0 : r->fd = -1;
463 0 : r->auto_close = false;
464 0 : return true;
465 : }
466 :
467 52 : return m->ReadFileDescriptor(iter, r);
468 : }
469 : static void Log(const param_type& p, std::wstring* l) {
470 : if (p.auto_close) {
471 : l->append(StringPrintf(L"FD(%d auto-close)", p.fd));
472 : } else {
473 : l->append(StringPrintf(L"FD(%d)", p.fd));
474 : }
475 : }
476 : };
477 : #endif // defined(OS_POSIX)
478 :
479 : #if defined(OS_WIN)
480 : template<>
481 : struct ParamTraitsIPC<TransportDIB::Id> {
482 : typedef TransportDIB::Id param_type;
483 : static void Write(Message* m, const param_type& p) {
484 : WriteParam(m, p.handle);
485 : WriteParam(m, p.sequence_num);
486 : }
487 : static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
488 : return (ReadParam(m, iter, &r->handle) &&
489 : ReadParam(m, iter, &r->sequence_num));
490 : }
491 : static void Log(const param_type& p, std::wstring* l) {
492 : l->append(L"TransportDIB(");
493 : LogParam(p.handle, l);
494 : l->append(L", ");
495 : LogParam(p.sequence_num, l);
496 : l->append(L")");
497 : }
498 : };
499 : #endif
500 :
501 : // Mozilla-specific types.
502 :
503 : template <class P>
504 : struct ParamTraitsMozilla : ParamTraitsIPC<P> {};
505 :
506 : template <>
507 : struct ParamTraitsMozilla<nsresult> {
508 : typedef nsresult param_type;
509 19 : static void Write(Message* m, const param_type& p) {
510 19 : m->WriteUInt32(static_cast<uint32_t>(p));
511 19 : }
512 19 : static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
513 19 : return m->ReadUInt32(iter, reinterpret_cast<uint32_t*>(r));
514 : }
515 : static void Log(const param_type& p, std::wstring* l) {
516 : l->append(StringPrintf(L"%u", static_cast<uint32_t>(p)));
517 : }
518 : };
519 :
520 : // Finally, ParamTraits itself.
521 :
522 : template <class P> struct ParamTraits : ParamTraitsMozilla<P> {};
523 :
524 : } // namespace IPC
525 :
526 : #endif // CHROME_COMMON_IPC_MESSAGE_UTILS_H_
|