Bug 836438 - Refactor IPC::ParamTraits specializations so that we don't have to manually guard against the possibility of multiple parameter types being the same type. r=ehsan
authorJeff Walden <jwalden@mit.edu>
Thu, 31 Jan 2013 14:08:16 -0800
changeset 130395 14550ec92519d20f5a325b18e32b693be7825f27
parent 130394 ef7cba7370272c647403bc93d3cf4a81aebeeed4
child 130396 091c6ec1944429d16789846c46fd62f368241302
push id2323
push userbbajaj@mozilla.com
push dateMon, 01 Apr 2013 19:47:02 +0000
treeherdermozilla-beta@7712be144d91 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersehsan
bugs836438
milestone21.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 836438 - Refactor IPC::ParamTraits specializations so that we don't have to manually guard against the possibility of multiple parameter types being the same type. r=ehsan
dom/browser-element/BrowserElementParent.js
ipc/chromium/src/chrome/common/ipc_message_utils.h
--- a/ipc/chromium/src/chrome/common/ipc_message_utils.h
+++ b/ipc/chromium/src/chrome/common/ipc_message_utils.h
@@ -61,18 +61,59 @@ class MessageIterator {
   }
  private:
   const Message& msg_;
   mutable void* iter_;
 };
 
 //-----------------------------------------------------------------------------
 // ParamTraits specializations, etc.
+//
+// The full set of types ParamTraits is specialized upon contains *possibly*
+// repeated types: unsigned long may be uint32_t or size_t, unsigned long long
+// may be uint64_t or size_t, nsresult may be uint32_t, and so on.  You can't
+// have ParamTraits<unsigned int> *and* ParamTraits<uint32_t> if unsigned int
+// is uint32_t -- that's multiple definitions, and you can only have one.
+//
+// You could use #ifs and macro conditions to avoid duplicates, but they'd be
+// hairy: heavily dependent upon OS and compiler author choices, forced to
+// address all conflicts by hand.  Happily there's a better way.  The basic
+// idea looks like this, where T -> U represents T inheriting from U:
+//
+// class ParamTraits<P>
+// |
+// --> class ParamTraits1<P>
+//     |
+//     --> class ParamTraits2<P>
+//         |
+//         --> class ParamTraitsN<P> // or however many levels
+//
+// The default specialization of ParamTraits{M}<P> is an empty class that
+// inherits from ParamTraits{M + 1}<P> (or nothing in the base case).
+//
+// Now partition the set of parameter types into sets without duplicates.
+// Assign each set of types to a level M.  Then specialize ParamTraitsM for
+// each of those types.  A reference to ParamTraits<P> will consist of some
+// number of empty classes inheriting in sequence, ending in a non-empty
+// ParamTraits{N}<P>.  It's okay for the parameter types to be duplicative:
+// either name of a type will resolve to the same ParamTraits{N}<P>.
+//
+// The nice thing is that because templates are instantiated lazily, if we
+// indeed have uint32_t == unsigned int, say, with the former in level N and
+// the latter in M > N, ParamTraitsM<unsigned int> won't be created (as long as
+// nobody uses ParamTraitsM<unsigned int>, but why would you), and no duplicate
+// code will be compiled or extra symbols generated.  It's as efficient at
+// runtime as manually figuring out and avoiding conflicts by #ifs.
+//
+// The scheme we follow below names the various classes according to the types
+// in them, and the number of ParamTraits levels is larger, but otherwise it's
+// exactly the above idea.
+//
 
-template <class P> struct ParamTraits {};
+template <class P> struct ParamTraits;
 
 template <class P>
 static inline void WriteParam(Message* m, const P& p) {
   ParamTraits<P>::Write(m, p);
 }
 
 template <class P>
 static inline bool WARN_UNUSED_RESULT ReadParam(const Message* m, void** iter,
@@ -80,119 +121,102 @@ static inline bool WARN_UNUSED_RESULT Re
   return ParamTraits<P>::Read(m, iter, p);
 }
 
 template <class P>
 static inline void LogParam(const P& p, std::wstring* l) {
   ParamTraits<P>::Log(p, l);
 }
 
+// Fundamental types.
+
+template <class P>
+struct ParamTraitsFundamental {};
+
 template <>
-struct ParamTraits<bool> {
+struct ParamTraitsFundamental<bool> {
   typedef bool param_type;
   static void Write(Message* m, const param_type& p) {
     m->WriteBool(p);
   }
   static bool Read(const Message* m, void** iter, param_type* r) {
     return m->ReadBool(iter, r);
   }
   static void Log(const param_type& p, std::wstring* l) {
     l->append(p ? L"true" : L"false");
   }
 };
 
 template <>
-struct ParamTraits<int16_t> {
-  typedef int16_t param_type;
-  static void Write(Message* m, const param_type& p) {
-    m->WriteInt(p);
-  }
-  static bool Read(const Message* m, void** iter, param_type* r) {
-    return m->ReadInt16(iter, r);
-  }
-  static void Log(const param_type& p, std::wstring* l) {
-    l->append(StringPrintf(L"%hd", p));
-  }
-};
-
-template <>
-struct ParamTraits<uint16_t> {
-  typedef uint16_t param_type;
-  static void Write(Message* m, const param_type& p) {
-    m->WriteInt(p);
-  }
-  static bool Read(const Message* m, void** iter, param_type* r) {
-    return m->ReadUInt16(iter, r);
-  }
-  static void Log(const param_type& p, std::wstring* l) {
-    l->append(StringPrintf(L"%hu", p));
-  }
-};
-
-template <>
-struct ParamTraits<int> {
+struct ParamTraitsFundamental<int> {
   typedef int param_type;
   static void Write(Message* m, const param_type& p) {
     m->WriteInt(p);
   }
   static bool Read(const Message* m, void** iter, param_type* r) {
     return m->ReadInt(iter, r);
   }
   static void Log(const param_type& p, std::wstring* l) {
     l->append(StringPrintf(L"%d", p));
   }
 };
 
 template <>
-struct ParamTraits<long> {
+struct ParamTraitsFundamental<long> {
   typedef long param_type;
   static void Write(Message* m, const param_type& p) {
     m->WriteLong(p);
   }
   static bool Read(const Message* m, void** iter, param_type* r) {
     return m->ReadLong(iter, r);
   }
   static void Log(const param_type& p, std::wstring* l) {
     l->append(StringPrintf(L"%l", p));
   }
 };
 
 template <>
-struct ParamTraits<unsigned long> {
+struct ParamTraitsFundamental<unsigned long> {
   typedef unsigned long param_type;
   static void Write(Message* m, const param_type& p) {
     m->WriteULong(p);
   }
   static bool Read(const Message* m, void** iter, param_type* r) {
     return m->ReadULong(iter, r);
   }
   static void Log(const param_type& p, std::wstring* l) {
     l->append(StringPrintf(L"%ul", p));
   }
 };
 
 template <>
-struct ParamTraits<nsresult> {
-  typedef nsresult param_type;
+struct ParamTraitsFundamental<long long> {
+  typedef long long param_type;
   static void Write(Message* m, const param_type& p) {
-    m->WriteUInt32(static_cast<uint32_t>(p));
-  }
+    m->WriteData(reinterpret_cast<const char*>(&p), sizeof(param_type));
+ }
   static bool Read(const Message* m, void** iter, param_type* r) {
-    return m->ReadUInt32(iter, reinterpret_cast<uint32_t*>(r));
+    const char *data;
+    int data_size = 0;
+    bool result = m->ReadData(iter, &data, &data_size);
+    if (result && data_size == sizeof(param_type)) {
+      memcpy(r, data, sizeof(param_type));
+    } else {
+      result = false;
+      NOTREACHED();
+    }
+    return result;
   }
   static void Log(const param_type& p, std::wstring* l) {
-    l->append(StringPrintf(L"%u", static_cast<uint32_t>(p)));
+    l->append(StringPrintf(L"%ll", p));
   }
 };
 
-#if (defined(OS_OPENBSD) && defined(ARCH_CPU_64_BITS))
-// On OpenBSD, uint64_t is unsigned long long
-// see https://bugzilla.mozilla.org/show_bug.cgi?id=648735#c27
 template <>
-struct ParamTraits<unsigned long long> {
+struct ParamTraitsFundamental<unsigned long long> {
   typedef unsigned long long param_type;
   static void Write(Message* m, const param_type& p) {
     m->WriteData(reinterpret_cast<const char*>(&p), sizeof(param_type));
  }
   static bool Read(const Message* m, void** iter, param_type* r) {
     const char *data;
     int data_size = 0;
     bool result = m->ReadData(iter, &data, &data_size);
@@ -205,125 +229,17 @@ struct ParamTraits<unsigned long long> {
     return result;
   }
   static void Log(const param_type& p, std::wstring* l) {
     l->append(StringPrintf(L"%ull", p));
   }
 };
 
 template <>
-struct ParamTraits<long long> {
-  typedef long long param_type;
-  static void Write(Message* m, const param_type& p) {
-    m->WriteData(reinterpret_cast<const char*>(&p), sizeof(param_type));
- }
-  static bool Read(const Message* m, void** iter, param_type* r) {
-    const char *data;
-    int data_size = 0;
-    bool result = m->ReadData(iter, &data, &data_size);
-    if (result && data_size == sizeof(param_type)) {
-      memcpy(r, data, sizeof(param_type));
-    } else {
-      result = false;
-      NOTREACHED();
-    }
-    return result;
-  }
-  static void Log(const param_type& p, std::wstring* l) {
-    l->append(StringPrintf(L"%ll", p));
-  }
-};
-#endif
-
-#if !(defined(OS_MACOSX) || defined(OS_OPENBSD) || defined(OS_WIN) || ((defined(OS_BSD) || defined(OS_LINUX)) && defined(ARCH_CPU_64_BITS)) || defined(ARCH_CPU_S390))
-// There size_t is a synonym for |unsigned long| ...
-template <>
-struct ParamTraits<size_t> {
-  typedef size_t param_type;
-  static void Write(Message* m, const param_type& p) {
-    m->WriteSize(p);
-  }
-  static bool Read(const Message* m, void** iter, param_type* r) {
-    return m->ReadSize(iter, r);
-  }
-  static void Log(const param_type& p, std::wstring* l) {
-    l->append(StringPrintf(L"%u", p));
-  }
-};
-
-#elif !defined(OS_MACOSX)
-// ... so we need to define traits for |unsigned int|.
-// XXX duplicating OS_MACOSX version below so as not to conflict
-template <>
-struct ParamTraits<uint32_t> {
-  typedef uint32_t param_type;
-  static void Write(Message* m, const param_type& p) {
-    m->WriteUInt32(p);
-  }
-  static bool Read(const Message* m, void** iter, param_type* r) {
-    return m->ReadUInt32(iter, r);
-  }
-  static void Log(const param_type& p, std::wstring* l) {
-    l->append(StringPrintf(L"%u", p));
-  }
-};
-
-#endif // if !(defined(OS_LINUX) && defined(ARCH_CPU_64_BITS))
-
-#if defined(OS_MACOSX)
-// On Linux size_t & uint32_t can be the same type.
-// TODO(playmobil): Fix compilation if this is not the case.
-template <>
-struct ParamTraits<uint32_t> {
-  typedef uint32_t param_type;
-  static void Write(Message* m, const param_type& p) {
-    m->WriteUInt32(p);
-  }
-  static bool Read(const Message* m, void** iter, param_type* r) {
-    return m->ReadUInt32(iter, r);
-  }
-  static void Log(const param_type& p, std::wstring* l) {
-    l->append(StringPrintf(L"%u", p));
-  }
-};
-#endif  // defined(OS_MACOSX)
-
-#if !((defined(OS_BSD) || defined(OS_LINUX)) && defined(ARCH_CPU_64_BITS))
-// int64_t is |long int| on 64-bit systems, uint64_t is |unsigned long|
-template <>
-struct ParamTraits<int64_t> {
-  typedef int64_t param_type;
-  static void Write(Message* m, const param_type& p) {
-    m->WriteInt64(p);
-  }
-  static bool Read(const Message* m, void** iter, param_type* r) {
-    return m->ReadInt64(iter, r);
-  }
-  static void Log(const param_type& p, std::wstring* l) {
-    l->append(StringPrintf(L"%" PRId64L, p));
-  }
-};
-
-template <>
-struct ParamTraits<uint64_t> {
-  typedef uint64_t param_type;
-  static void Write(Message* m, const param_type& p) {
-    m->WriteInt64(static_cast<int64_t>(p));
-  }
-  static bool Read(const Message* m, void** iter, param_type* r) {
-    return m->ReadInt64(iter, reinterpret_cast<int64_t*>(r));
-  }
-  static void Log(const param_type& p, std::wstring* l) {
-    l->append(StringPrintf(L"%" PRIu64L, p));
-  }
-};
-#endif // if !(defined(OS_LINUX) && defined(ARCH_CPU_64_BITS))
-
-template <>
-struct ParamTraits<double> {
+struct ParamTraitsFundamental<double> {
   typedef double param_type;
   static void Write(Message* m, const param_type& p) {
     m->WriteData(reinterpret_cast<const char*>(&p), sizeof(param_type));
   }
   static bool Read(const Message* m, void** iter, param_type* r) {
     const char *data;
     int data_size = 0;
     bool result = m->ReadData(iter, &data, &data_size);
@@ -336,97 +252,145 @@ struct ParamTraits<double> {
 
     return result;
   }
   static void Log(const param_type& p, std::wstring* l) {
     l->append(StringPrintf(L"e", p));
   }
 };
 
+// Fixed-size <stdint.h> types.
+
+template <class P>
+struct ParamTraitsFixed : ParamTraitsFundamental<P> {};
+
 template <>
-struct ParamTraits<base::Time> {
-  typedef base::Time param_type;
+struct ParamTraitsFixed<int16_t> {
+  typedef int16_t param_type;
   static void Write(Message* m, const param_type& p) {
-    ParamTraits<int64_t>::Write(m, p.ToInternalValue());
+    m->WriteInt(p);
   }
   static bool Read(const Message* m, void** iter, param_type* r) {
-    int64_t value;
-    if (!ParamTraits<int64_t>::Read(m, iter, &value))
-      return false;
-    *r = base::Time::FromInternalValue(value);
-    return true;
+    return m->ReadInt16(iter, r);
   }
   static void Log(const param_type& p, std::wstring* l) {
-    ParamTraits<int64_t>::Log(p.ToInternalValue(), l);
+    l->append(StringPrintf(L"%hd", p));
   }
 };
 
-#if defined(OS_WIN)
 template <>
-struct ParamTraits<LOGFONT> {
-  typedef LOGFONT param_type;
+struct ParamTraitsFixed<uint16_t> {
+  typedef uint16_t param_type;
   static void Write(Message* m, const param_type& p) {
-    m->WriteData(reinterpret_cast<const char*>(&p), sizeof(LOGFONT));
+    m->WriteInt(p);
   }
   static bool Read(const Message* m, void** iter, param_type* r) {
-    const char *data;
-    int data_size = 0;
-    bool result = m->ReadData(iter, &data, &data_size);
-    if (result && data_size == sizeof(LOGFONT)) {
-      memcpy(r, data, sizeof(LOGFONT));
-    } else {
-      result = false;
-      NOTREACHED();
-    }
-
-    return result;
+    return m->ReadUInt16(iter, r);
   }
   static void Log(const param_type& p, std::wstring* l) {
-    l->append(StringPrintf(L"<LOGFONT>"));
+    l->append(StringPrintf(L"%hu", p));
+  }
+};
+
+template <>
+struct ParamTraitsFixed<uint32_t> {
+  typedef uint32_t param_type;
+  static void Write(Message* m, const param_type& p) {
+    m->WriteUInt32(p);
+  }
+  static bool Read(const Message* m, void** iter, param_type* r) {
+    return m->ReadUInt32(iter, r);
+  }
+  static void Log(const param_type& p, std::wstring* l) {
+    l->append(StringPrintf(L"%u", p));
   }
 };
 
 template <>
-struct ParamTraits<MSG> {
-  typedef MSG param_type;
+struct ParamTraitsFixed<int64_t> {
+  typedef int64_t param_type;
   static void Write(Message* m, const param_type& p) {
-    m->WriteData(reinterpret_cast<const char*>(&p), sizeof(MSG));
+    m->WriteInt64(p);
+  }
+  static bool Read(const Message* m, void** iter, param_type* r) {
+    return m->ReadInt64(iter, r);
+  }
+  static void Log(const param_type& p, std::wstring* l) {
+    l->append(StringPrintf(L"%" PRId64L, p));
+  }
+};
+
+template <>
+struct ParamTraitsFixed<uint64_t> {
+  typedef uint64_t param_type;
+  static void Write(Message* m, const param_type& p) {
+    m->WriteInt64(static_cast<int64_t>(p));
   }
   static bool Read(const Message* m, void** iter, param_type* r) {
-    const char *data;
-    int data_size = 0;
-    bool result = m->ReadData(iter, &data, &data_size);
-    if (result && data_size == sizeof(MSG)) {
-      memcpy(r, data, sizeof(MSG));
-    } else {
-      result = false;
-      NOTREACHED();
-    }
-
-    return result;
+    return m->ReadInt64(iter, reinterpret_cast<int64_t*>(r));
+  }
+  static void Log(const param_type& p, std::wstring* l) {
+    l->append(StringPrintf(L"%" PRIu64L, p));
   }
 };
-#endif  // defined(OS_WIN)
+
+// Other standard C types.
+
+template <class P>
+struct ParamTraitsLibC : ParamTraitsFixed<P> {};
 
 template <>
-struct ParamTraits<std::string> {
+struct ParamTraitsLibC<size_t> {
+  typedef size_t param_type;
+  static void Write(Message* m, const param_type& p) {
+    m->WriteSize(p);
+  }
+  static bool Read(const Message* m, void** iter, param_type* r) {
+    return m->ReadSize(iter, r);
+  }
+  static void Log(const param_type& p, std::wstring* l) {
+    l->append(StringPrintf(L"%u", p));
+  }
+};
+
+// std::* types.
+
+template <class P>
+struct ParamTraitsStd : ParamTraitsLibC<P> {};
+
+template <>
+struct ParamTraitsStd<std::string> {
   typedef std::string param_type;
   static void Write(Message* m, const param_type& p) {
     m->WriteString(p);
   }
   static bool Read(const Message* m, void** iter, param_type* r) {
     return m->ReadString(iter, r);
   }
   static void Log(const param_type& p, std::wstring* l) {
     l->append(UTF8ToWide(p));
   }
 };
 
 template <>
-struct ParamTraits<std::vector<unsigned char> > {
+struct ParamTraitsStd<std::wstring> {
+  typedef std::wstring param_type;
+  static void Write(Message* m, const param_type& p) {
+    m->WriteWString(p);
+  }
+  static bool Read(const Message* m, void** iter, param_type* r) {
+    return m->ReadWString(iter, r);
+  }
+  static void Log(const param_type& p, std::wstring* l) {
+    l->append(p);
+  }
+};
+
+template <>
+struct ParamTraitsStd<std::vector<unsigned char> > {
   typedef std::vector<unsigned char> param_type;
   static void Write(Message* m, const param_type& p) {
     if (p.size() == 0) {
       m->WriteData(NULL, 0);
     } else {
       m->WriteData(reinterpret_cast<const char*>(&p.front()),
                    static_cast<int>(p.size()));
     }
@@ -443,17 +407,17 @@ struct ParamTraits<std::vector<unsigned 
   }
   static void Log(const param_type& p, std::wstring* l) {
     for (size_t i = 0; i < p.size(); ++i)
       l->push_back(p[i]);
   }
 };
 
 template <>
-struct ParamTraits<std::vector<char> > {
+struct ParamTraitsStd<std::vector<char> > {
   typedef std::vector<char> param_type;
   static void Write(Message* m, const param_type& p) {
     if (p.size() == 0) {
       m->WriteData(NULL, 0);
     } else {
       m->WriteData(&p.front(), static_cast<int>(p.size()));
     }
   }
@@ -469,17 +433,17 @@ struct ParamTraits<std::vector<char> > {
   }
   static void Log(const param_type& p, std::wstring* l) {
     for (size_t i = 0; i < p.size(); ++i)
       l->push_back(p[i]);
   }
 };
 
 template <class P>
-struct ParamTraits<std::vector<P> > {
+struct ParamTraitsStd<std::vector<P> > {
   typedef std::vector<P> param_type;
   static void Write(Message* m, const param_type& p) {
     WriteParam(m, static_cast<int>(p.size()));
     for (size_t i = 0; i < p.size(); i++)
       WriteParam(m, p[i]);
   }
   static bool Read(const Message* m, void** iter, param_type* r) {
     int size;
@@ -508,17 +472,17 @@ struct ParamTraits<std::vector<P> > {
         l->append(L" ");
 
       LogParam((p[i]), l);
     }
   }
 };
 
 template <class K, class V>
-struct ParamTraits<std::map<K, V> > {
+struct ParamTraitsStd<std::map<K, V> > {
   typedef std::map<K, V> param_type;
   static void Write(Message* m, const param_type& p) {
     WriteParam(m, static_cast<int>(p.size()));
     typename param_type::const_iterator iter;
     for (iter = p.begin(); iter != p.end(); ++iter) {
       WriteParam(m, iter->first);
       WriteParam(m, iter->second);
     }
@@ -537,110 +501,126 @@ struct ParamTraits<std::map<K, V> > {
     }
     return true;
   }
   static void Log(const param_type& p, std::wstring* l) {
     l->append(L"<std::map>");
   }
 };
 
+// Windows-specific types.
 
+template <class P>
+struct ParamTraitsWindows : ParamTraitsStd<P> {};
+
+#if defined(OS_WIN)
 template <>
-struct ParamTraits<std::wstring> {
-  typedef std::wstring param_type;
+struct ParamTraitsWindows<LOGFONT> {
+  typedef LOGFONT param_type;
   static void Write(Message* m, const param_type& p) {
-    m->WriteWString(p);
+    m->WriteData(reinterpret_cast<const char*>(&p), sizeof(LOGFONT));
   }
   static bool Read(const Message* m, void** iter, param_type* r) {
-    return m->ReadWString(iter, r);
+    const char *data;
+    int data_size = 0;
+    bool result = m->ReadData(iter, &data, &data_size);
+    if (result && data_size == sizeof(LOGFONT)) {
+      memcpy(r, data, sizeof(LOGFONT));
+    } else {
+      result = false;
+      NOTREACHED();
+    }
+
+    return result;
   }
   static void Log(const param_type& p, std::wstring* l) {
-    l->append(p);
+    l->append(StringPrintf(L"<LOGFONT>"));
   }
 };
 
-// If WCHAR_T_IS_UTF16 is defined, then string16 is a std::wstring so we don't
-// need this trait.
-#if !defined(WCHAR_T_IS_UTF16)
 template <>
-struct ParamTraits<string16> {
-  typedef string16 param_type;
+struct ParamTraitsWindows<MSG> {
+  typedef MSG param_type;
   static void Write(Message* m, const param_type& p) {
-    m->WriteString16(p);
+    m->WriteData(reinterpret_cast<const char*>(&p), sizeof(MSG));
   }
   static bool Read(const Message* m, void** iter, param_type* r) {
-    return m->ReadString16(iter, r);
-  }
-  static void Log(const param_type& p, std::wstring* l) {
-    l->append(UTF16ToWide(p));
+    const char *data;
+    int data_size = 0;
+    bool result = m->ReadData(iter, &data, &data_size);
+    if (result && data_size == sizeof(MSG)) {
+      memcpy(r, data, sizeof(MSG));
+    } else {
+      result = false;
+      NOTREACHED();
+    }
+
+    return result;
   }
 };
-#endif
 
-// and, a few more useful types...
-#if defined(OS_WIN)
 template <>
-struct ParamTraits<HANDLE> {
+struct ParamTraitsWindows<HANDLE> {
   typedef HANDLE param_type;
   static void Write(Message* m, const param_type& p) {
     m->WriteIntPtr(reinterpret_cast<intptr_t>(p));
   }
   static bool Read(const Message* m, void** iter, param_type* r) {
     DCHECK_EQ(sizeof(param_type), sizeof(intptr_t));
     return m->ReadIntPtr(iter, reinterpret_cast<intptr_t*>(r));
   }
   static void Log(const param_type& p, std::wstring* l) {
     l->append(StringPrintf(L"0x%X", p));
   }
 };
 
 template <>
-struct ParamTraits<HCURSOR> {
+struct ParamTraitsWindows<HCURSOR> {
   typedef HCURSOR param_type;
   static void Write(Message* m, const param_type& p) {
     m->WriteIntPtr(reinterpret_cast<intptr_t>(p));
   }
   static bool Read(const Message* m, void** iter, param_type* r) {
     DCHECK_EQ(sizeof(param_type), sizeof(intptr_t));
     return m->ReadIntPtr(iter, reinterpret_cast<intptr_t*>(r));
   }
   static void Log(const param_type& p, std::wstring* l) {
     l->append(StringPrintf(L"0x%X", p));
   }
 };
 
 template <>
-struct ParamTraits<HWND> {
+struct ParamTraitsWindows<HWND> {
   typedef HWND param_type;
   static void Write(Message* m, const param_type& p) {
     m->WriteIntPtr(reinterpret_cast<intptr_t>(p));
   }
   static bool Read(const Message* m, void** iter, param_type* r) {
     DCHECK_EQ(sizeof(param_type), sizeof(intptr_t));
     return m->ReadIntPtr(iter, reinterpret_cast<intptr_t*>(r));
   }
   static void Log(const param_type& p, std::wstring* l) {
     l->append(StringPrintf(L"0x%X", p));
   }
 };
 
 template <>
-struct ParamTraits<HACCEL> {
+struct ParamTraitsWindows<HACCEL> {
   typedef HACCEL param_type;
   static void Write(Message* m, const param_type& p) {
     m->WriteIntPtr(reinterpret_cast<intptr_t>(p));
   }
   static bool Read(const Message* m, void** iter, param_type* r) {
     DCHECK_EQ(sizeof(param_type), sizeof(intptr_t));
     return m->ReadIntPtr(iter, reinterpret_cast<intptr_t*>(r));
   }
 };
 
 template <>
-struct ParamTraits<POINT> {
+struct ParamTraitsWindows<POINT> {
   typedef POINT param_type;
   static void Write(Message* m, const param_type& p) {
     m->WriteInt(p.x);
     m->WriteInt(p.y);
   }
   static bool Read(const Message* m, void** iter, param_type* r) {
     int x, y;
     if (!m->ReadInt(iter, &x) || !m->ReadInt(iter, &y))
@@ -648,35 +628,54 @@ struct ParamTraits<POINT> {
     r->x = x;
     r->y = y;
     return true;
   }
   static void Log(const param_type& p, std::wstring* l) {
     l->append(StringPrintf(L"(%d, %d)", p.x, p.y));
   }
 };
-#endif  // defined(OS_WIN)
 
 template <>
-struct ParamTraits<FilePath> {
-  typedef FilePath param_type;
+struct ParamTraitsWindows<XFORM> {
+  typedef XFORM param_type;
   static void Write(Message* m, const param_type& p) {
-    ParamTraits<FilePath::StringType>::Write(m, p.value());
+    m->WriteData(reinterpret_cast<const char*>(&p), sizeof(XFORM));
   }
   static bool Read(const Message* m, void** iter, param_type* r) {
-    FilePath::StringType value;
-    if (!ParamTraits<FilePath::StringType>::Read(m, iter, &value))
-      return false;
-    *r = FilePath(value);
-    return true;
+    const char *data;
+    int data_size = 0;
+    bool result = m->ReadData(iter, &data, &data_size);
+    if (result && data_size == sizeof(XFORM)) {
+      memcpy(r, data, sizeof(XFORM));
+    } else {
+      result = false;
+      NOTREACHED();
+    }
+
+    return result;
   }
   static void Log(const param_type& p, std::wstring* l) {
-    ParamTraits<FilePath::StringType>::Log(p.value(), l);
+    l->append(L"<XFORM>");
   }
 };
+#endif  // defined(OS_WIN)
+
+// Various ipc/chromium types.
+
+template <class P>
+struct ParamTraitsIPC : ParamTraitsWindows<P> {};
+
+template <>
+struct ParamTraitsIPC<base::Time> {
+  typedef base::Time param_type;
+  static inline void Write(Message* m, const param_type& p);
+  static inline bool Read(const Message* m, void** iter, param_type* r);
+  static inline void Log(const param_type& p, std::wstring* l);
+};
 
 #if defined(OS_POSIX)
 // FileDescriptors may be serialised over IPC channels on POSIX. On the
 // receiving side, the FileDescriptor is a valid duplicate of the file
 // descriptor which was transmitted: *it is not just a copy of the integer like
 // HANDLEs on Windows*. The only exception is if the file descriptor is < 0. In
 // this case, the receiving end will see a value of -1. *Zero is a valid file
 // descriptor*.
@@ -685,17 +684,17 @@ struct ParamTraits<FilePath> {
 // code which handles the message is responsible for taking ownership of it.
 // File descriptors are OS resources and must be closed when no longer needed.
 //
 // When sending a file descriptor, the file descriptor must be valid at the time
 // of transmission. Since transmission is not synchronous, one should consider
 // dup()ing any file descriptors to be transmitted and setting the |auto_close|
 // flag, which causes the file descriptor to be closed after writing.
 template<>
-struct ParamTraits<base::FileDescriptor> {
+struct ParamTraitsIPC<base::FileDescriptor> {
   typedef base::FileDescriptor param_type;
   static void Write(Message* m, const param_type& p) {
     const bool valid = p.fd >= 0;
     WriteParam(m, valid);
 
     if (valid) {
       if (!m->WriteFileDescriptor(p))
         NOTREACHED();
@@ -719,89 +718,65 @@ struct ParamTraits<base::FileDescriptor>
       l->append(StringPrintf(L"FD(%d auto-close)", p.fd));
     } else {
       l->append(StringPrintf(L"FD(%d)", p.fd));
     }
   }
 };
 #endif // defined(OS_POSIX)
 
-template<>
-struct ParamTraits<ThumbnailScore> {
-  typedef ThumbnailScore param_type;
+template <>
+struct ParamTraitsIPC<string16> {
+  typedef string16 param_type;
   static void Write(Message* m, const param_type& p) {
-    IPC::ParamTraits<double>::Write(m, p.boring_score);
-    IPC::ParamTraits<bool>::Write(m, p.good_clipping);
-    IPC::ParamTraits<bool>::Write(m, p.at_top);
-    IPC::ParamTraits<base::Time>::Write(m, p.time_at_snapshot);
+    m->WriteString16(p);
   }
   static bool Read(const Message* m, void** iter, param_type* r) {
-    double boring_score;
-    bool good_clipping, at_top;
-    base::Time time_at_snapshot;
-    if (!IPC::ParamTraits<double>::Read(m, iter, &boring_score) ||
-        !IPC::ParamTraits<bool>::Read(m, iter, &good_clipping) ||
-        !IPC::ParamTraits<bool>::Read(m, iter, &at_top) ||
-        !IPC::ParamTraits<base::Time>::Read(m, iter, &time_at_snapshot))
-      return false;
+    return m->ReadString16(iter, r);
+  }
+  static void Log(const param_type& p, std::wstring* l) {
+    l->append(UTF16ToWide(p));
+  }
+};
 
-    r->boring_score = boring_score;
-    r->good_clipping = good_clipping;
-    r->at_top = at_top;
-    r->time_at_snapshot = time_at_snapshot;
-    return true;
-  }
+template <>
+struct ParamTraitsIPC<FilePath> {
+  typedef FilePath param_type;
+  static void Write(Message* m, const param_type& p);
+  static bool Read(const Message* m, void** iter, param_type* r);
+  static void Log(const param_type& p, std::wstring* l);
+};
+
+template<>
+struct ParamTraitsIPC<ThumbnailScore> {
+  typedef ThumbnailScore param_type;
+  static void Write(Message* m, const param_type& p);
+  static bool Read(const Message* m, void** iter, param_type* r);
   static void Log(const param_type& p, std::wstring* l) {
     l->append(StringPrintf(L"(%f, %d, %d)",
                            p.boring_score, p.good_clipping, p.at_top));
   }
 };
 
-#if defined(OS_WIN)
-template <>
-struct ParamTraits<XFORM> {
-  typedef XFORM param_type;
-  static void Write(Message* m, const param_type& p) {
-    m->WriteData(reinterpret_cast<const char*>(&p), sizeof(XFORM));
-  }
-  static bool Read(const Message* m, void** iter, param_type* r) {
-    const char *data;
-    int data_size = 0;
-    bool result = m->ReadData(iter, &data, &data_size);
-    if (result && data_size == sizeof(XFORM)) {
-      memcpy(r, data, sizeof(XFORM));
-    } else {
-      result = false;
-      NOTREACHED();
-    }
-
-    return result;
-  }
-  static void Log(const param_type& p, std::wstring* l) {
-    l->append(L"<XFORM>");
-  }
-};
-#endif  // defined(OS_WIN)
-
 struct LogData {
   std::wstring channel;
   int32_t routing_id;
   uint16_t type;
   std::wstring flags;
   int64_t sent;  // Time that the message was sent (i.e. at Send()).
   int64_t receive;  // Time before it was dispatched (i.e. before calling
                   // OnMessageReceived).
   int64_t dispatch;  // Time after it was dispatched (i.e. after calling
                    // OnMessageReceived).
   std::wstring message_name;
   std::wstring params;
 };
 
 template <>
-struct ParamTraits<LogData> {
+struct ParamTraitsIPC<LogData> {
   typedef LogData param_type;
   static void Write(Message* m, const param_type& p) {
     WriteParam(m, p.channel);
     WriteParam(m, p.routing_id);
     WriteParam(m, static_cast<int>(p.type));
     WriteParam(m, p.flags);
     WriteParam(m, p.sent);
     WriteParam(m, p.receive);
@@ -824,17 +799,17 @@ struct ParamTraits<LogData> {
   }
   static void Log(const param_type& p, std::wstring* l) {
     // Doesn't make sense to implement this!
   }
 };
 
 #if defined(OS_WIN)
 template<>
-struct ParamTraits<TransportDIB::Id> {
+struct ParamTraitsIPC<TransportDIB::Id> {
   typedef TransportDIB::Id param_type;
   static void Write(Message* m, const param_type& p) {
     WriteParam(m, p.handle);
     WriteParam(m, p.sequence_num);
   }
   static bool Read(const Message* m, void** iter, param_type* r) {
     return (ReadParam(m, iter, &r->handle) &&
             ReadParam(m, iter, &r->sequence_num));
@@ -845,17 +820,17 @@ struct ParamTraits<TransportDIB::Id> {
     l->append(L", ");
     LogParam(p.sequence_num, l);
     l->append(L")");
   }
 };
 #endif
 
 template <>
-struct ParamTraits<Message> {
+struct ParamTraitsIPC<Message> {
   static void Write(Message* m, const Message& p) {
     m->WriteInt(p.size());
     m->WriteData(reinterpret_cast<const char*>(p.data()), p.size());
   }
   static bool Read(const Message* m, void** iter, Message* r) {
     int size;
     if (!m->ReadInt(iter, &size))
       return false;
@@ -866,43 +841,43 @@ struct ParamTraits<Message> {
     return true;
   }
   static void Log(const Message& p, std::wstring* l) {
     l->append(L"<IPC::Message>");
   }
 };
 
 template <>
-struct ParamTraits<Tuple0> {
+struct ParamTraitsIPC<Tuple0> {
   typedef Tuple0 param_type;
   static void Write(Message* m, const param_type& p) {
   }
   static bool Read(const Message* m, void** iter, param_type* r) {
     return true;
   }
   static void Log(const param_type& p, std::wstring* l) {
   }
 };
 
 template <class A>
-struct ParamTraits< Tuple1<A> > {
+struct ParamTraitsIPC< Tuple1<A> > {
   typedef Tuple1<A> param_type;
   static void Write(Message* m, const param_type& p) {
     WriteParam(m, p.a);
   }
   static bool Read(const Message* m, void** iter, param_type* r) {
     return ReadParam(m, iter, &r->a);
   }
   static void Log(const param_type& p, std::wstring* l) {
     LogParam(p.a, l);
   }
 };
 
 template <class A, class B>
-struct ParamTraits< Tuple2<A, B> > {
+struct ParamTraitsIPC< Tuple2<A, B> > {
   typedef Tuple2<A, B> param_type;
   static void Write(Message* m, const param_type& p) {
     WriteParam(m, p.a);
     WriteParam(m, p.b);
   }
   static bool Read(const Message* m, void** iter, param_type* r) {
     return (ReadParam(m, iter, &r->a) &&
             ReadParam(m, iter, &r->b));
@@ -910,17 +885,17 @@ struct ParamTraits< Tuple2<A, B> > {
   static void Log(const param_type& p, std::wstring* l) {
     LogParam(p.a, l);
     l->append(L", ");
     LogParam(p.b, l);
   }
 };
 
 template <class A, class B, class C>
-struct ParamTraits< Tuple3<A, B, C> > {
+struct ParamTraitsIPC< Tuple3<A, B, C> > {
   typedef Tuple3<A, B, C> param_type;
   static void Write(Message* m, const param_type& p) {
     WriteParam(m, p.a);
     WriteParam(m, p.b);
     WriteParam(m, p.c);
   }
   static bool Read(const Message* m, void** iter, param_type* r) {
     return (ReadParam(m, iter, &r->a) &&
@@ -932,17 +907,17 @@ struct ParamTraits< Tuple3<A, B, C> > {
     l->append(L", ");
     LogParam(p.b, l);
     l->append(L", ");
     LogParam(p.c, l);
   }
 };
 
 template <class A, class B, class C, class D>
-struct ParamTraits< Tuple4<A, B, C, D> > {
+struct ParamTraitsIPC< Tuple4<A, B, C, D> > {
   typedef Tuple4<A, B, C, D> param_type;
   static void Write(Message* m, const param_type& p) {
     WriteParam(m, p.a);
     WriteParam(m, p.b);
     WriteParam(m, p.c);
     WriteParam(m, p.d);
   }
   static bool Read(const Message* m, void** iter, param_type* r) {
@@ -958,17 +933,17 @@ struct ParamTraits< Tuple4<A, B, C, D> >
     l->append(L", ");
     LogParam(p.c, l);
     l->append(L", ");
     LogParam(p.d, l);
   }
 };
 
 template <class A, class B, class C, class D, class E>
-struct ParamTraits< Tuple5<A, B, C, D, E> > {
+struct ParamTraitsIPC< Tuple5<A, B, C, D, E> > {
   typedef Tuple5<A, B, C, D, E> param_type;
   static void Write(Message* m, const param_type& p) {
     WriteParam(m, p.a);
     WriteParam(m, p.b);
     WriteParam(m, p.c);
     WriteParam(m, p.d);
     WriteParam(m, p.e);
   }
@@ -988,17 +963,17 @@ struct ParamTraits< Tuple5<A, B, C, D, E
     l->append(L", ");
     LogParam(p.d, l);
     l->append(L", ");
     LogParam(p.e, l);
   }
 };
 
 template <class A, class B, class C, class D, class E, class F>
-struct ParamTraits< Tuple6<A, B, C, D, E, F> > {
+struct ParamTraitsIPC< Tuple6<A, B, C, D, E, F> > {
   typedef Tuple6<A, B, C, D, E, F> param_type;
   static void Write(Message* m, const param_type& p) {
     WriteParam(m, p.a);
     WriteParam(m, p.b);
     WriteParam(m, p.c);
     WriteParam(m, p.d);
     WriteParam(m, p.e);
     WriteParam(m, p.f);
@@ -1021,17 +996,99 @@ struct ParamTraits< Tuple6<A, B, C, D, E
     LogParam(p.d, l);
     l->append(L", ");
     LogParam(p.e, l);
     l->append(L", ");
     LogParam(p.f, l);
   }
 };
 
+// Mozilla-specific types.
 
+template <class P>
+struct ParamTraitsMozilla : ParamTraitsIPC<P> {};
+
+template <>
+struct ParamTraitsMozilla<nsresult> {
+  typedef nsresult param_type;
+  static void Write(Message* m, const param_type& p) {
+    m->WriteUInt32(static_cast<uint32_t>(p));
+  }
+  static bool Read(const Message* m, void** iter, param_type* r) {
+    return m->ReadUInt32(iter, reinterpret_cast<uint32_t*>(r));
+  }
+  static void Log(const param_type& p, std::wstring* l) {
+    l->append(StringPrintf(L"%u", static_cast<uint32_t>(p)));
+  }
+};
+
+// Finally, ParamTraits itself.
+
+template <class P> struct ParamTraits : ParamTraitsMozilla<P> {};
+
+// Now go back and define inlines dependent upon various ParamTraits<P>.
+inline void
+ParamTraitsIPC<base::Time>::Write(Message* m, const param_type& p) {
+  ParamTraits<int64_t>::Write(m, p.ToInternalValue());
+}
+inline bool
+ParamTraitsIPC<base::Time>::Read(const Message* m, void** iter, param_type* r) {
+  int64_t value;
+  if (!ParamTraits<int64_t>::Read(m, iter, &value))
+    return false;
+  *r = base::Time::FromInternalValue(value);
+  return true;
+}
+inline void
+ParamTraitsIPC<base::Time>::Log(const param_type& p, std::wstring* l) {
+  ParamTraits<int64_t>::Log(p.ToInternalValue(), l);
+}
+
+inline void
+ParamTraitsIPC<FilePath>::Write(Message* m, const param_type& p) {
+  ParamTraits<FilePath::StringType>::Write(m, p.value());
+}
+inline bool
+ParamTraitsIPC<FilePath>::Read(const Message* m, void** iter, param_type* r) {
+  FilePath::StringType value;
+  if (!ParamTraits<FilePath::StringType>::Read(m, iter, &value))
+    return false;
+  *r = FilePath(value);
+  return true;
+}
+inline void
+ParamTraitsIPC<FilePath>::Log(const param_type& p, std::wstring* l) {
+  ParamTraits<FilePath::StringType>::Log(p.value(), l);
+}
+
+
+inline void
+ParamTraitsIPC<ThumbnailScore>::Write(Message* m, const param_type& p) {
+  IPC::ParamTraits<double>::Write(m, p.boring_score);
+  IPC::ParamTraits<bool>::Write(m, p.good_clipping);
+  IPC::ParamTraits<bool>::Write(m, p.at_top);
+  IPC::ParamTraits<base::Time>::Write(m, p.time_at_snapshot);
+}
+inline bool
+ParamTraitsIPC<ThumbnailScore>::Read(const Message* m, void** iter, param_type* r) {
+  double boring_score;
+  bool good_clipping, at_top;
+  base::Time time_at_snapshot;
+  if (!IPC::ParamTraits<double>::Read(m, iter, &boring_score) ||
+      !IPC::ParamTraits<bool>::Read(m, iter, &good_clipping) ||
+      !IPC::ParamTraits<bool>::Read(m, iter, &at_top) ||
+      !IPC::ParamTraits<base::Time>::Read(m, iter, &time_at_snapshot))
+    return false;
+
+  r->boring_score = boring_score;
+  r->good_clipping = good_clipping;
+  r->at_top = at_top;
+  r->time_at_snapshot = time_at_snapshot;
+  return true;
+}
 
 //-----------------------------------------------------------------------------
 // Generic message subclasses
 
 // Used for asynchronous messages.
 template <class ParamType>
 class MessageWithTuple : public Message {
  public: