LCOV - code coverage report
Current view: top level - ipc/chromium/src/chrome/common - ipc_message_utils.h (source / functions) Hit Total Coverage
Test: output.info Lines: 65 108 60.2 %
Date: 2017-07-14 16:53:18 Functions: 300 901 33.3 %
Legend: Lines: hit not hit

          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_

Generated by: LCOV version 1.13