summaryrefslogtreecommitdiff
path: root/ipc/ipc_message_utils.h
diff options
context:
space:
mode:
Diffstat (limited to 'ipc/ipc_message_utils.h')
-rwxr-xr-xipc/ipc_message_utils.h1237
1 files changed, 1237 insertions, 0 deletions
diff --git a/ipc/ipc_message_utils.h b/ipc/ipc_message_utils.h
new file mode 100755
index 000000000000..a7b78959fb02
--- /dev/null
+++ b/ipc/ipc_message_utils.h
@@ -0,0 +1,1237 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IPC_IPC_MESSAGE_UTILS_H_
+#define IPC_IPC_MESSAGE_UTILS_H_
+#pragma once
+
+#include <algorithm>
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+
+#include "base/compiler_specific.h"
+//#include "base/format_macros.h"
+//#include "base/string16.h"
+//#include "base/stringprintf.h"
+//#include "base/string_util.h"
+#include "base/tuple.h"
+#include "ipc/ipc_param_traits.h"
+#include "ipc/ipc_sync_message.h"
+
+#if defined(COMPILER_GCC)
+// GCC "helpfully" tries to inline template methods in release mode. Except we
+// want the majority of the template junk being expanded once in the
+// implementation file (and only provide the definitions in
+// ipc_message_utils_impl.h in those files) and exported, instead of expanded
+// at every call site. Special note: GCC happily accepts the attribute before
+// the method declaration, but only acts on it if it is after.
+#if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100) >= 40500
+// Starting in gcc 4.5, the noinline no longer implies the concept covered by
+// the introduced noclone attribute, which will create specialized versions of
+// functions/methods when certain types are constant.
+// www.gnu.org/software/gcc/gcc-4.5/changes.html
+#define IPC_MSG_NOINLINE __attribute__((noinline, noclone));
+#else
+#define IPC_MSG_NOINLINE __attribute__((noinline));
+#endif
+#elif defined(COMPILER_MSVC)
+// MSVC++ doesn't do this.
+#define IPC_MSG_NOINLINE
+#else
+#error "Please add the noinline property for your new compiler here."
+#endif
+
+// Used by IPC_BEGIN_MESSAGES so that each message class starts from a unique
+// base. Messages have unique IDs across channels in order for the IPC logging
+// code to figure out the message class from its ID.
+enum IPCMessageStart {
+ AutomationMsgStart = 0,
+ CmcStrRegistryManagerStart,
+ LastIPCMsgStart
+};
+
+class FilePath;
+class NullableString16;
+
+namespace base {
+class DictionaryValue;
+class ListValue;
+class Time;
+class TimeDelta;
+struct FileDescriptor;
+}
+
+namespace IPC {
+
+struct ChannelHandle;
+
+//-----------------------------------------------------------------------------
+// An iterator class for reading the fields contained within a Message.
+
+class MessageIterator {
+ public:
+ explicit MessageIterator(const Message& m) : msg_(m), iter_(NULL) {
+ }
+ int NextInt() const {
+ int val = -1;
+ if (!msg_.ReadInt(&iter_, &val))
+ NOTREACHED();
+ return val;
+ }
+/*
+ const std::string NextString() const {
+ std::string val;
+ if (!msg_.ReadString(&iter_, &val))
+ NOTREACHED();
+ return val;
+ }
+ const std::wstring NextWString() const {
+ std::wstring val;
+ if (!msg_.ReadWString(&iter_, &val))
+ NOTREACHED();
+ return val;
+ }
+*/
+ void NextData(const char** data, int* length) const {
+ if (!msg_.ReadData(&iter_, data, length)) {
+ NOTREACHED();
+ }
+ }
+ private:
+ const Message& msg_;
+ mutable void* iter_;
+};
+
+//-----------------------------------------------------------------------------
+// A dummy struct to place first just to allow leading commas for all
+// members in the macro-generated constructor initializer lists.
+struct NoParams {
+};
+
+//-----------------------------------------------------------------------------
+// ParamTraits specializations, etc.
+
+template <class P>
+static inline void WriteParam(Message* m, const P& p) {
+ typedef typename SimilarTypeTraits<P>::Type Type;
+ ParamTraits<Type>::Write(m, static_cast<const Type& >(p));
+}
+
+template <class P>
+static inline bool WARN_UNUSED_RESULT ReadParam(const Message* m, void** iter,
+ P* p) {
+ typedef typename SimilarTypeTraits<P>::Type Type;
+ return ParamTraits<Type>::Read(m, iter, reinterpret_cast<Type* >(p));
+}
+
+
+template <class P>
+static inline void LogParam(const P& p, std::string* l) {
+ typedef typename SimilarTypeTraits<P>::Type Type;
+ ParamTraits<Type>::Log(static_cast<const Type& >(p), l);
+}
+
+
+template <>
+struct ParamTraits<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::string* l) {
+ l->append(p ? "true" : "false");
+ }
+};
+
+template <>
+struct ParamTraits<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);
+ }
+ IPC_EXPORT static void Log(const param_type& p, std::string* l);
+};
+
+template <>
+struct ParamTraits<unsigned int> {
+ typedef unsigned 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, reinterpret_cast<int*>(r));
+ }
+ IPC_EXPORT static void Log(const param_type& p, std::string* l);
+};
+
+template <>
+struct ParamTraits<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);
+ }
+ IPC_EXPORT static void Log(const param_type& p, std::string* l);
+};
+
+template <>
+struct ParamTraits<unsigned long> {
+ typedef unsigned 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, reinterpret_cast<long*>(r));
+ }
+ IPC_EXPORT static void Log(const param_type& p, std::string* l);
+};
+
+template <>
+struct ParamTraits<long long> {
+ typedef long long param_type;
+ static void Write(Message* m, const param_type& p) {
+ m->WriteInt64(static_cast<int64>(p));
+ }
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ return m->ReadInt64(iter, reinterpret_cast<int64*>(r));
+ }
+ IPC_EXPORT static void Log(const param_type& p, std::string* l);
+};
+
+template <>
+struct ParamTraits<unsigned long long> {
+ typedef unsigned long long 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, reinterpret_cast<int64*>(r));
+ }
+ IPC_EXPORT static void Log(const param_type& p, std::string* l);
+};
+
+template <>
+struct IPC_EXPORT ParamTraits<unsigned short> {
+ typedef unsigned short 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::string* l);
+};
+
+// Note that the IPC layer doesn't sanitize NaNs and +/- INF values. Clients
+// should be sure to check the sanity of these values after receiving them over
+// IPC.
+template <>
+struct ParamTraits<float> {
+ typedef float 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;
+ if (!m->ReadData(iter, &data, &data_size) ||
+ data_size != sizeof(param_type)) {
+ NOTREACHED();
+ return false;
+ }
+ memcpy(r, data, sizeof(param_type));
+ return true;
+ }
+
+ static void Log(const param_type& p, std::string* l) {
+ //l->append(StringPrintf("%e", p));
+ }
+
+};
+
+template <>
+struct ParamTraits<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;
+ if (!m->ReadData(iter, &data, &data_size) ||
+ data_size != sizeof(param_type)) {
+ NOTREACHED();
+ return false;
+ }
+ memcpy(r, data, sizeof(param_type));
+ return true;
+ }
+
+ static void Log(const param_type& p, std::string* l) {
+ //l->append(StringPrintf("%e", p));
+ }
+
+};
+
+/*
+template <>
+struct IPC_EXPORT ParamTraits<base::Time> {
+ typedef base::Time 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::string* l);
+};
+
+template <>
+struct IPC_EXPORT ParamTraits<base::TimeDelta> {
+ typedef base::TimeDelta 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::string* l);
+};
+
+#if defined(OS_WIN)
+template <>
+struct ParamTraits<LOGFONT> {
+ typedef LOGFONT param_type;
+ static void Write(Message* m, const param_type& p) {
+ m->WriteData(reinterpret_cast<const char*>(&p), sizeof(LOGFONT));
+ }
+ 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;
+ }
+ static void Log(const param_type& p, std::string* l) {
+// l->append(StringPrintf("<LOGFONT>"));
+ }
+};
+
+template <>
+struct ParamTraits<MSG> {
+ typedef MSG param_type;
+ static void Write(Message* m, const param_type& p) {
+ m->WriteData(reinterpret_cast<const char*>(&p), sizeof(MSG));
+ }
+ 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;
+ }
+ static void Log(const param_type& p, std::string* l) {
+ l->append("<MSG>");
+ }
+};
+#endif // defined(OS_WIN)
+
+template <>
+struct IPC_EXPORT ParamTraits<base::DictionaryValue> {
+ typedef base::DictionaryValue 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::string* l);
+};
+
+template <>
+struct IPC_EXPORT ParamTraits<base::ListValue> {
+ typedef base::ListValue 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::string* l);
+};
+
+*/
+template <>
+struct ParamTraits<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::string* l) {
+ l->append(p);
+ }
+};
+
+/*
+template<typename CharType>
+static void LogBytes(const std::vector<CharType>& data, std::string* out) {
+#if defined(OS_WIN)
+ // Windows has a GUI for logging, which can handle arbitrary binary data.
+ for (size_t i = 0; i < data.size(); ++i)
+ out->push_back(data[i]);
+#else
+ // On POSIX, we log to stdout, which we assume can display ASCII.
+ static const size_t kMaxBytesToLog = 100;
+ for (size_t i = 0; i < std::min(data.size(), kMaxBytesToLog); ++i) {
+ if (isprint(data[i]))
+ out->push_back(data[i]);
+ else
+ {
+ // out->append(StringPrintf("[%02X]", static_cast<unsigned char>(data[i])));
+ }
+ }
+ if (data.size() > kMaxBytesToLog) {
+// out->append(
+// StringPrintf(" and %u more bytes",
+// static_cast<unsigned>(data.size() - kMaxBytesToLog)));
+ }
+#endif
+}
+*/
+
+template <>
+struct ParamTraits<std::vector<unsigned char> > {
+ typedef std::vector<unsigned char> param_type;
+ static void Write(Message* m, const param_type& p) {
+ if (p.empty()) {
+ m->WriteData(NULL, 0);
+ } else {
+ m->WriteData(reinterpret_cast<const char*>(&p.front()),
+ static_cast<int>(p.size()));
+ }
+ }
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ const char *data;
+ int data_size = 0;
+ if (!m->ReadData(iter, &data, &data_size) || data_size < 0)
+ return false;
+ r->resize(data_size);
+ if (data_size)
+ memcpy(&r->front(), data, data_size);
+ return true;
+ }
+ static void Log(const param_type& p, std::string* l) {
+ // LogBytes(p, l);
+ }
+};
+
+template <>
+struct ParamTraits<std::vector<char> > {
+ typedef std::vector<char> param_type;
+ static void Write(Message* m, const param_type& p) {
+ if (p.empty()) {
+ m->WriteData(NULL, 0);
+ } else {
+ m->WriteData(&p.front(), static_cast<int>(p.size()));
+ }
+ }
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ const char *data;
+ int data_size = 0;
+ if (!m->ReadData(iter, &data, &data_size) || data_size < 0)
+ return false;
+ r->resize(data_size);
+ if (data_size)
+ memcpy(&r->front(), data, data_size);
+ return true;
+ }
+ static void Log(const param_type& p, std::string* l) {
+ //LogBytes(p, l);
+ }
+};
+
+template <class P>
+struct ParamTraits<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;
+ // ReadLength() checks for < 0 itself.
+ if (!m->ReadLength(iter, &size))
+ return false;
+ // Resizing beforehand is not safe, see BUG 1006367 for details.
+ if (INT_MAX / sizeof(P) <= static_cast<size_t>(size))
+ return false;
+ r->resize(size);
+ for (int i = 0; i < size; i++) {
+ if (!ReadParam(m, iter, &(*r)[i]))
+ return false;
+ }
+ return true;
+ }
+ static void Log(const param_type& p, std::string* l) {
+// for (size_t i = 0; i < p.size(); ++i) {
+// if (i != 0)
+// l->append(" ");
+// LogParam((p[i]), l);
+// }
+ }
+};
+
+/*
+template <class P>
+struct ParamTraits<std::set<P> > {
+ typedef std::set<P> 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);
+ }
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ int size;
+ if (!m->ReadLength(iter, &size))
+ return false;
+ for (int i = 0; i < size; ++i) {
+ P item;
+ if (!ReadParam(m, iter, &item))
+ return false;
+ r->insert(item);
+ }
+ return true;
+ }
+ static void Log(const param_type& p, std::string* l) {
+ l->append("<std::set>");
+ }
+};
+
+
+template <class K, class V>
+struct ParamTraits<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);
+ }
+ }
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ int size;
+ if (!ReadParam(m, iter, &size) || size < 0)
+ return false;
+ for (int i = 0; i < size; ++i) {
+ K k;
+ if (!ReadParam(m, iter, &k))
+ return false;
+ V& value = (*r)[k];
+ if (!ReadParam(m, iter, &value))
+ return false;
+ }
+ return true;
+ }
+ static void Log(const param_type& p, std::string* l) {
+ l->append("<std::map>");
+ }
+};
+
+
+template <>
+struct ParamTraits<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);
+ }
+ IPC_EXPORT static void Log(const param_type& p, std::string* l);
+};
+
+template <class A, class B>
+struct ParamTraits<std::pair<A, B> > {
+ typedef std::pair<A, B> param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.first);
+ WriteParam(m, p.second);
+ }
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ return ReadParam(m, iter, &r->first) && ReadParam(m, iter, &r->second);
+ }
+ static void Log(const param_type& p, std::string* l) {
+ l->append("(");
+ LogParam(p.first, l);
+ l->append(", ");
+ LogParam(p.second, l);
+ l->append(")");
+ }
+};
+
+template <>
+struct IPC_EXPORT ParamTraits<NullableString16> {
+ typedef NullableString16 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::string* l);
+};
+
+// 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;
+ static void Write(Message* m, const param_type& p) {
+ m->WriteString16(p);
+ }
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ return m->ReadString16(iter, r);
+ }
+ IPC_EXPORT static void Log(const param_type& p, std::string* l);
+};
+#endif
+
+// and, a few more useful types...
+#if defined(OS_WIN)
+template <>
+struct ParamTraits<HANDLE> {
+ typedef HANDLE param_type;
+ static void Write(Message* m, const param_type& p) {
+ // Note that HWNDs/HANDLE/HCURSOR/HACCEL etc are always 32 bits, even on 64
+ // bit systems.
+ m->WriteUInt32(reinterpret_cast<uint32>(p));
+ }
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ DCHECK_EQ(sizeof(param_type), sizeof(uint32));
+ return m->ReadUInt32(iter, reinterpret_cast<uint32*>(r));
+ }
+ static void Log(const param_type& p, std::string* l) {
+// l->append(StringPrintf("0x%X", p));
+ }
+};
+
+template <>
+struct ParamTraits<HCURSOR> {
+ typedef HCURSOR param_type;
+ static void Write(Message* m, const param_type& p) {
+ m->WriteUInt32(reinterpret_cast<uint32>(p));
+ }
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ DCHECK_EQ(sizeof(param_type), sizeof(uint32));
+ return m->ReadUInt32(iter, reinterpret_cast<uint32*>(r));
+ }
+ static void Log(const param_type& p, std::string* l) {
+// l->append(StringPrintf("0x%X", p));
+ }
+};
+
+template <>
+struct ParamTraits<HACCEL> {
+ typedef HACCEL param_type;
+ static void Write(Message* m, const param_type& p) {
+ m->WriteUInt32(reinterpret_cast<uint32>(p));
+ }
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ DCHECK_EQ(sizeof(param_type), sizeof(uint32));
+ return m->ReadUInt32(iter, reinterpret_cast<uint32*>(r));
+ }
+};
+
+template <>
+struct ParamTraits<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))
+ return false;
+ r->x = x;
+ r->y = y;
+ return true;
+ }
+ static void Log(const param_type& p, std::string* l) {
+// l->append(StringPrintf("(%d, %d)", p.x, p.y));
+ }
+};
+#endif // defined(OS_WIN)
+
+template <>
+struct IPC_EXPORT ParamTraits<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::string* 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*.
+//
+// The received file descriptor will have the |auto_close| flag set to true. The
+// 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 IPC_EXPORT ParamTraits<base::FileDescriptor> {
+ typedef base::FileDescriptor 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::string* l);
+};
+#endif // defined(OS_POSIX)
+
+// A ChannelHandle is basically a platform-inspecific wrapper around the
+// fact that IPC endpoints are handled specially on POSIX. See above comments
+// on FileDescriptor for more background.
+template<>
+struct IPC_EXPORT ParamTraits<IPC::ChannelHandle> {
+ typedef ChannelHandle 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::string* l);
+};
+
+#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::string* l) {
+ l->append("<XFORM>");
+ }
+};
+#endif // defined(OS_WIN)
+
+struct IPC_EXPORT LogData {
+ LogData();
+ ~LogData();
+
+ std::string channel;
+ int32 routing_id;
+ uint32 type; // "User-defined" message type, from ipc_message.h.
+ std::string flags;
+ int64 sent; // Time that the message was sent (i.e. at Send()).
+ int64 receive; // Time before it was dispatched (i.e. before calling
+ // OnMessageReceived).
+ int64 dispatch; // Time after it was dispatched (i.e. after calling
+ // OnMessageReceived).
+ std::string message_name;
+ std::string params;
+};
+
+template <>
+struct IPC_EXPORT ParamTraits<LogData> {
+ typedef LogData 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::string* l) {
+ // Doesn't make sense to implement this!
+ }
+};
+
+*/
+template <>
+struct ParamTraits<Message> {
+ static void Write(Message* m, const Message& p) {
+ DCHECK(p.size() <= INT_MAX);
+ int message_size = static_cast<int>(p.size());
+ m->WriteInt(message_size);
+ m->WriteData(reinterpret_cast<const char*>(p.data()), message_size);
+ }
+ static bool Read(const Message* m, void** iter, Message* r) {
+ int size;
+ if (!m->ReadInt(iter, &size))
+ return false;
+ const char* data;
+ if (!m->ReadData(iter, &data, &size))
+ return false;
+ *r = Message(data, size);
+ return true;
+ }
+ static void Log(const Message& p, std::string* l) {
+ l->append("<IPC::Message>");
+ }
+};
+
+template <>
+struct ParamTraits<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::string* l) {
+ }
+};
+
+template <class A>
+struct ParamTraits< 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::string* l) {
+ LogParam(p.a, l);
+ }
+};
+
+template <class A, class B>
+struct ParamTraits< 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));
+ }
+ static void Log(const param_type& p, std::string* l) {
+ LogParam(p.a, l);
+ l->append(", ");
+ LogParam(p.b, l);
+ }
+};
+
+template <class A, class B, class C>
+struct ParamTraits< 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) &&
+ ReadParam(m, iter, &r->b) &&
+ ReadParam(m, iter, &r->c));
+ }
+ static void Log(const param_type& p, std::string* l) {
+ LogParam(p.a, l);
+ l->append(", ");
+ LogParam(p.b, l);
+ l->append(", ");
+ LogParam(p.c, l);
+ }
+};
+
+template <class A, class B, class C, class D>
+struct ParamTraits< 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) {
+ return (ReadParam(m, iter, &r->a) &&
+ ReadParam(m, iter, &r->b) &&
+ ReadParam(m, iter, &r->c) &&
+ ReadParam(m, iter, &r->d));
+ }
+ static void Log(const param_type& p, std::string* l) {
+ LogParam(p.a, l);
+ l->append(", ");
+ LogParam(p.b, l);
+ l->append(", ");
+ LogParam(p.c, l);
+ l->append(", ");
+ LogParam(p.d, l);
+ }
+};
+
+template <class A, class B, class C, class D, class E>
+struct ParamTraits< 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);
+ }
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ return (ReadParam(m, iter, &r->a) &&
+ ReadParam(m, iter, &r->b) &&
+ ReadParam(m, iter, &r->c) &&
+ ReadParam(m, iter, &r->d) &&
+ ReadParam(m, iter, &r->e));
+ }
+ static void Log(const param_type& p, std::string* l) {
+ LogParam(p.a, l);
+ l->append(", ");
+ LogParam(p.b, l);
+ l->append(", ");
+ LogParam(p.c, l);
+ l->append(", ");
+ LogParam(p.d, l);
+ l->append(", ");
+ 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> > {
+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);
+ }
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ return (ReadParam(m, iter, &r->a) &&
+ ReadParam(m, iter, &r->b) &&
+ ReadParam(m, iter, &r->c) &&
+ ReadParam(m, iter, &r->d) &&
+ ReadParam(m, iter, &r->e) &&
+ ReadParam(m, iter, &r->f));
+ }
+ static void Log(const param_type& p, std::string* l) {
+ LogParam(p.a, l);
+ l->append(", ");
+ LogParam(p.b, l);
+ l->append(", ");
+ LogParam(p.c, l);
+ l->append(", ");
+ LogParam(p.d, l);
+ l->append(", ");
+ LogParam(p.e, l);
+ l->append(", ");
+ LogParam(p.f, l);
+ }
+};
+
+//-----------------------------------------------------------------------------
+// Generic message subclasses
+
+// Used for asynchronous messages.
+template <class ParamType>
+class __attribute__((visibility("default"))) MessageWithTuple : public Message {
+ public:
+ typedef ParamType Param;
+ typedef typename TupleTypes<ParamType>::ParamTuple RefParam;
+
+ // The constructor and the Read() method's templated implementations are in
+ // ipc_message_utils_impl.h. The subclass constructor and Log() methods call
+ // the templated versions of these and make sure there are instantiations in
+ // those translation units.
+ MessageWithTuple(int32 routing_id, uint32 type, const RefParam& p);
+
+ static bool Read(const Message* msg, Param* p) IPC_MSG_NOINLINE;
+
+ // Generic dispatcher. Should cover most cases.
+ template<class T, class S, class Method>
+ static bool Dispatch(const Message* msg, T* obj, S* sender, Method func) {
+ Param p;
+ if (Read(msg, &p)) {
+ DispatchToMethod(obj, func, p);
+ return true;
+ }
+ return false;
+ }
+
+ // The following dispatchers exist for the case where the callback function
+ // needs the message as well. They assume that "Param" is a type of Tuple
+ // (except the one arg case, as there is no Tuple1).
+ template<class T, class S, typename TA>
+ static bool Dispatch(const Message* msg, T* obj, S* sender,
+ void (T::*func)(const Message&, TA)) {
+ Param p;
+ if (Read(msg, &p)) {
+ (obj->*func)(*msg, p.a);
+ return true;
+ }
+ return false;
+ }
+
+ template<class T, class S, typename TA, typename TB>
+ static bool Dispatch(const Message* msg, T* obj, S* sender,
+ void (T::*func)(const Message&, TA, TB)) {
+ Param p;
+ if (Read(msg, &p)) {
+ (obj->*func)(*msg, p.a, p.b);
+ return true;
+ }
+ return false;
+ }
+
+ template<class T, class S, typename TA, typename TB, typename TC>
+ static bool Dispatch(const Message* msg, T* obj, S* sender,
+ void (T::*func)(const Message&, TA, TB, TC)) {
+ Param p;
+ if (Read(msg, &p)) {
+ (obj->*func)(*msg, p.a, p.b, p.c);
+ return true;
+ }
+ return false;
+ }
+
+ template<class T, class S, typename TA, typename TB, typename TC, typename TD>
+ static bool Dispatch(const Message* msg, T* obj, S* sender,
+ void (T::*func)(const Message&, TA, TB, TC, TD)) {
+ Param p;
+ if (Read(msg, &p)) {
+ (obj->*func)(*msg, p.a, p.b, p.c, p.d);
+ return true;
+ }
+ return false;
+ }
+
+ template<class T, class S, typename TA, typename TB, typename TC, typename TD,
+ typename TE>
+ static bool Dispatch(const Message* msg, T* obj, S* sender,
+ void (T::*func)(const Message&, TA, TB, TC, TD, TE)) {
+ Param p;
+ if (Read(msg, &p)) {
+ (obj->*func)(*msg, p.a, p.b, p.c, p.d, p.e);
+ return true;
+ }
+ return false;
+ }
+
+ // Functions used to do manual unpacking. Only used by the automation code,
+ // these should go away once that code uses SyncChannel.
+ template<typename TA, typename TB>
+ static bool Read(const IPC::Message* msg, TA* a, TB* b) {
+ ParamType params;
+ if (!Read(msg, &params))
+ return false;
+ *a = params.a;
+ *b = params.b;
+ return true;
+ }
+
+ template<typename TA, typename TB, typename TC>
+ static bool Read(const IPC::Message* msg, TA* a, TB* b, TC* c) {
+ ParamType params;
+ if (!Read(msg, &params))
+ return false;
+ *a = params.a;
+ *b = params.b;
+ *c = params.c;
+ return true;
+ }
+
+ template<typename TA, typename TB, typename TC, typename TD>
+ static bool Read(const IPC::Message* msg, TA* a, TB* b, TC* c, TD* d) {
+ ParamType params;
+ if (!Read(msg, &params))
+ return false;
+ *a = params.a;
+ *b = params.b;
+ *c = params.c;
+ *d = params.d;
+ return true;
+ }
+
+ template<typename TA, typename TB, typename TC, typename TD, typename TE>
+ static bool Read(const IPC::Message* msg, TA* a, TB* b, TC* c, TD* d, TE* e) {
+ ParamType params;
+ if (!Read(msg, &params))
+ return false;
+ *a = params.a;
+ *b = params.b;
+ *c = params.c;
+ *d = params.d;
+ *e = params.e;
+ return true;
+ }
+};
+
+// defined in ipc_logging.cc
+IPC_EXPORT void GenerateLogData(const std::string& channel,
+ const Message& message,
+ LogData* data);
+
+
+#if defined(IPC_MESSAGE_LOG_ENABLED)
+inline void AddOutputParamsToLog(const Message* msg, std::string* l) {
+ const std::string& output_params = msg->output_params();
+ if (!l->empty() && !output_params.empty())
+ l->append(", ");
+
+ l->append(output_params);
+}
+
+template <class ReplyParamType>
+inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
+ const Message* msg) {
+ if (msg->received_time() != 0) {
+ std::string output_params;
+ LogParam(reply_params, &output_params);
+ msg->set_output_params(output_params);
+ }
+}
+
+inline void ConnectMessageAndReply(const Message* msg, Message* reply) {
+ if (msg->sent_time()) {
+ // Don't log the sync message after dispatch, as we don't have the
+ // output parameters at that point. Instead, save its data and log it
+ // with the outgoing reply message when it's sent.
+ LogData* data = new LogData;
+ GenerateLogData("", *msg, data);
+ msg->set_dont_log();
+ reply->set_sync_log_data(data);
+ }
+}
+#else
+inline void AddOutputParamsToLog(const Message* msg, std::string* l) {}
+
+template <class ReplyParamType>
+inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
+ const Message* msg) {}
+
+inline void ConnectMessageAndReply(const Message* msg, Message* reply) {}
+#endif
+
+// This class assumes that its template argument is a RefTuple (a Tuple with
+// reference elements). This would go into ipc_message_utils_impl.h, but it is
+// also used by chrome_frame.
+template <class RefTuple>
+class ParamDeserializer : public MessageReplyDeserializer {
+ public:
+ explicit ParamDeserializer(const RefTuple& out) : out_(out) { }
+
+ bool SerializeOutputParameters(const IPC::Message& msg, void* iter) {
+ return ReadParam(&msg, &iter, &out_);
+ }
+
+ RefTuple out_;
+};
+
+// Used for synchronous messages.
+template <class SendParamType, class ReplyParamType>
+class __attribute__((visibility("default"))) MessageWithReply : public SyncMessage {
+ public:
+ typedef SendParamType SendParam;
+ typedef typename TupleTypes<SendParam>::ParamTuple RefSendParam;
+ typedef ReplyParamType ReplyParam;
+
+ MessageWithReply(int32 routing_id, uint32 type,
+ const RefSendParam& send, const ReplyParam& reply);
+ static bool ReadSendParam(const Message* msg, SendParam* p) IPC_MSG_NOINLINE;
+ static bool ReadReplyParam(
+ const Message* msg,
+ typename TupleTypes<ReplyParam>::ValueTuple* p) IPC_MSG_NOINLINE;
+
+ template<class T, class S, class Method>
+ static bool Dispatch(const Message* msg, T* obj, S* sender, Method func) {
+ SendParam send_params;
+ Message* reply = GenerateReply(msg);
+ bool error;
+ if (ReadSendParam(msg, &send_params)) {
+ typename TupleTypes<ReplyParam>::ValueTuple reply_params;
+ DispatchToMethod(obj, func, send_params, &reply_params);
+ WriteParam(reply, reply_params);
+ error = false;
+ LogReplyParamsToMessage(reply_params, msg);
+ } else {
+ NOTREACHED() << "Error deserializing message " << msg->type();
+ reply->set_reply_error();
+ error = true;
+ }
+
+ sender->Send(reply);
+ return !error;
+ }
+
+ template<class T, class Method>
+ static bool DispatchDelayReply(const Message* msg, T* obj, Method func) {
+ SendParam send_params;
+ Message* reply = GenerateReply(msg);
+ bool error;
+ if (ReadSendParam(msg, &send_params)) {
+ Tuple1<Message&> t = MakeRefTuple(*reply);
+ ConnectMessageAndReply(msg, reply);
+ DispatchToMethod(obj, func, send_params, &t);
+ error = false;
+ } else {
+ NOTREACHED() << "Error deserializing message " << msg->type();
+ reply->set_reply_error();
+ obj->Send(reply);
+ error = true;
+ }
+ return !error;
+ }
+
+ template<typename TA>
+ static void WriteReplyParams(Message* reply, TA a) {
+ ReplyParam p(a);
+ WriteParam(reply, p);
+ }
+
+ template<typename TA, typename TB>
+ static void WriteReplyParams(Message* reply, TA a, TB b) {
+ ReplyParam p(a, b);
+ WriteParam(reply, p);
+ }
+
+ template<typename TA, typename TB, typename TC>
+ static void WriteReplyParams(Message* reply, TA a, TB b, TC c) {
+ ReplyParam p(a, b, c);
+ WriteParam(reply, p);
+ }
+
+ template<typename TA, typename TB, typename TC, typename TD>
+ static void WriteReplyParams(Message* reply, TA a, TB b, TC c, TD d) {
+ ReplyParam p(a, b, c, d);
+ WriteParam(reply, p);
+ }
+
+ template<typename TA, typename TB, typename TC, typename TD, typename TE>
+ static void WriteReplyParams(Message* reply, TA a, TB b, TC c, TD d, TE e) {
+ ReplyParam p(a, b, c, d, e);
+ WriteParam(reply, p);
+ }
+};
+
+//-----------------------------------------------------------------------------
+
+} // namespace IPC
+
+#endif // IPC_IPC_MESSAGE_UTILS_H_