summaryrefslogtreecommitdiffstats
path: root/chrome/common/ipc_message_utils.h
diff options
context:
space:
mode:
authorinitial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98>2008-07-26 23:55:29 +0000
committerinitial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98>2008-07-26 23:55:29 +0000
commit09911bf300f1a419907a9412154760efd0b7abc3 (patch)
treef131325fb4e2ad12c6d3504ab75b16dd92facfed /chrome/common/ipc_message_utils.h
parent586acc5fe142f498261f52c66862fa417c3d52d2 (diff)
downloadchromium_src-09911bf300f1a419907a9412154760efd0b7abc3.zip
chromium_src-09911bf300f1a419907a9412154760efd0b7abc3.tar.gz
chromium_src-09911bf300f1a419907a9412154760efd0b7abc3.tar.bz2
Add chrome to the repository.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@15 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/common/ipc_message_utils.h')
-rw-r--r--chrome/common/ipc_message_utils.h1414
1 files changed, 1414 insertions, 0 deletions
diff --git a/chrome/common/ipc_message_utils.h b/chrome/common/ipc_message_utils.h
new file mode 100644
index 0000000..7599b4fb
--- /dev/null
+++ b/chrome/common/ipc_message_utils.h
@@ -0,0 +1,1414 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef CHROME_COMMON_IPC_MESSAGE_UTILS_H__
+#define CHROME_COMMON_IPC_MESSAGE_UTILS_H__
+
+#include <string>
+#include <vector>
+#include <map>
+
+#include "base/basictypes.h"
+#include "base/gfx/rect.h"
+#include "base/gfx/size.h"
+#include "base/logging.h"
+#include "base/string_util.h"
+#include "base/time.h"
+#include "base/tuple.h"
+#include "chrome/common/ipc_message.h"
+#include "chrome/common/ipc_sync_message.h"
+#include "chrome/common/thumbnail_score.h"
+#include "googleurl/src/gurl.h"
+#include "skia/include/SkBitmap.h"
+#include "webkit/glue/cache_manager.h"
+#include "webkit/glue/console_message_level.h"
+#include "webkit/glue/dom_operations.h"
+#include "webkit/glue/window_open_disposition.h"
+#include "webkit/glue/webcursor.h"
+
+namespace IPC {
+
+// Used by the message macros to register a logging function based on the
+// message class.
+typedef void (LogFunction)(uint16 type,
+ std::wstring* name,
+ const IPC::Message* msg,
+ std::wstring* params);
+void RegisterMessageLogger(int msg_start, LogFunction* func);
+
+
+//-----------------------------------------------------------------------------
+// An iterator class for reading the fields contained within a Message.
+
+class MessageIterator {
+ public:
+ MessageIterator(const Message& m) : msg_(m), iter_(NULL) {
+ }
+ int NextInt() const {
+ int val;
+ if (!msg_.ReadInt(&iter_, &val))
+ NOTREACHED();
+ return val;
+ }
+ intptr_t NextIntPtr() const {
+ intptr_t val;
+ if (!msg_.ReadIntPtr(&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;
+ }
+ const void NextData(const char** data, int* length) const {
+ if (!msg_.ReadData(&iter_, data, length)) {
+ NOTREACHED();
+ }
+ }
+ private:
+ const Message& msg_;
+ mutable void* iter_;
+};
+
+//-----------------------------------------------------------------------------
+// ParamTraits specializations, etc.
+
+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 ReadParam(const Message* m, void** iter, P* p) {
+ 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);
+}
+
+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::wstring* l) {
+ l->append(p ? L"true" : L"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);
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(StringPrintf(L"%d", p));
+ }
+};
+
+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));
+ }
+};
+
+template <>
+struct ParamTraits<int64> {
+ typedef int64 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"%I64d", p));
+ }
+};
+
+template <>
+struct ParamTraits<uint64> {
+ typedef uint64 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));
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(StringPrintf(L"%I64u", 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(double));
+ }
+ 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(double)) {
+ memcpy(r, data, sizeof(double));
+ } else {
+ result = false;
+ NOTREACHED();
+ }
+
+ return result;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(StringPrintf(L"e", p));
+ }
+};
+
+template <>
+struct ParamTraits<wchar_t> {
+ typedef wchar_t param_type;
+ static void Write(Message* m, const param_type& p) {
+ m->WriteData(reinterpret_cast<const char*>(&p), sizeof(wchar_t));
+ }
+ 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(wchar_t)) {
+ memcpy(r, data, sizeof(wchar_t));
+ } else {
+ result = false;
+ NOTREACHED();
+ }
+
+ return result;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(StringPrintf(L"%c", p));
+ }
+};
+
+template <>
+struct ParamTraits<Time> {
+ typedef Time param_type;
+ static void Write(Message* m, const param_type& p) {
+ ParamTraits<int64>::Write(m, p.ToInternalValue());
+ }
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ int64 value;
+ if (!ParamTraits<int64>::Read(m, iter, &value))
+ return false;
+ *r = Time::FromInternalValue(value);
+ return true;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ ParamTraits<int64>::Log(p.ToInternalValue(), l);
+ }
+};
+
+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::wstring* l) {
+ l->append(StringPrintf(L"<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;
+ }
+};
+
+struct SkBitmap_Data {
+ // The configuration for the bitmap (bits per pixel, etc).
+ SkBitmap::Config fConfig;
+
+ // The width of the bitmap in pixels.
+ uint32 fWidth;
+
+ // The height of the bitmap in pixels.
+ uint32 fHeight;
+
+ // The number of bytes between subsequent rows of the bitmap.
+ uint32 fRowBytes;
+
+ void InitSkBitmapDataForTransfer(const SkBitmap& bitmap) {
+ fConfig = bitmap.config();
+ fWidth = bitmap.width();
+ fHeight = bitmap.height();
+ fRowBytes = bitmap.rowBytes();
+ }
+
+ void InitSkBitmapFromData(SkBitmap* bitmap, const char* pixels,
+ size_t total_pixels) const {
+ if (total_pixels) {
+ bitmap->setConfig(fConfig, fWidth, fHeight, fRowBytes);
+ bitmap->allocPixels();
+ memcpy(bitmap->getPixels(), pixels, total_pixels);
+ }
+ }
+};
+
+template <>
+struct ParamTraits<SkBitmap> {
+ typedef SkBitmap param_type;
+ static void Write(Message* m, const param_type& p) {
+ size_t fixed_size = sizeof(SkBitmap_Data);
+ SkBitmap_Data bmp_data;
+ bmp_data.InitSkBitmapDataForTransfer(p);
+ m->WriteData(reinterpret_cast<const char*>(&bmp_data),
+ static_cast<int>(fixed_size));
+ size_t pixel_size = p.getSize();
+ SkAutoLockPixels p_lock(p);
+ m->WriteData(reinterpret_cast<const char*>(p.getPixels()),
+ static_cast<int>(pixel_size));
+ }
+ // Note: This function expects parameter |r| to be of type &SkBitmap since
+ // r->SetConfig() and r->SetPixels() are called.
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ const char* fixed_data;
+ int fixed_data_size = 0;
+ if (!m->ReadData(iter, &fixed_data, &fixed_data_size) ||
+ (fixed_data_size <= 0)) {
+ NOTREACHED();
+ return false;
+ }
+ if (fixed_data_size != sizeof(SkBitmap_Data))
+ return false; // Message is malformed.
+
+ const char* variable_data;
+ int variable_data_size = 0;
+ if (!m->ReadData(iter, &variable_data, &variable_data_size) ||
+ (variable_data_size < 0)) {
+ NOTREACHED();
+ return false;
+ }
+ const SkBitmap_Data* bmp_data =
+ reinterpret_cast<const SkBitmap_Data*>(fixed_data);
+ bmp_data->InitSkBitmapFromData(r, variable_data, variable_data_size);
+ return true;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(StringPrintf(L"<SkBitmap>"));
+ }
+};
+
+template <>
+struct ParamTraits<MONITORINFOEX> {
+ typedef MONITORINFOEX param_type;
+ static void Write(Message* m, const param_type& p) {
+ m->WriteData(reinterpret_cast<const char*>(&p), sizeof(MONITORINFOEX));
+ }
+ 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(MONITORINFOEX)) {
+ memcpy(r, data, sizeof(MONITORINFOEX));
+ } else {
+ result = false;
+ NOTREACHED();
+ }
+
+ return result;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(StringPrintf(L"<MONITORINFOEX>"));
+ }
+};
+
+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::wstring* l) {
+ l->append(UTF8ToWide(p));
+ }
+};
+
+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.size() == 0) {
+ 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::wstring* l) {
+ for (size_t i = 0; i < p.size(); ++i)
+ l->push_back(p[i]);
+ }
+};
+
+template <>
+struct ParamTraits<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()));
+ }
+ }
+ 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::wstring* l) {
+ for (size_t i = 0; i < p.size(); ++i)
+ l->push_back(p[i]);
+ }
+};
+
+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;
+ if (!m->ReadLength(iter, &size))
+ return false;
+ // Resizing beforehand is not safe, see BUG 1006367 for details.
+ if (m->IteratorHasRoomFor(*iter, size * sizeof(P))) {
+ r->resize(size);
+ for (int i = 0; i < size; i++) {
+ if (!ReadParam(m, iter, &(*r)[i]))
+ return false;
+ }
+ } else {
+ for (int i = 0; i < size; i++) {
+ P element;
+ if (!ReadParam(m, iter, &element))
+ return false;
+ r->push_back(element);
+ }
+ }
+ return true;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ for (size_t i = 0; i < p.size(); ++i) {
+ if (i != 0)
+ l->append(L" ");
+
+ LogParam((p[i]), l);
+ }
+ }
+};
+
+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()));
+ 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::wstring* l) {
+ l->append(L"<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);
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(p);
+ }
+};
+
+template <>
+struct ParamTraits<GURL> {
+ typedef GURL param_type;
+ static void Write(Message* m, const param_type& p) {
+ m->WriteString(p.possibly_invalid_spec());
+ // TODO(brettw) bug 684583: Add encoding for query params.
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ std::string s;
+ if (!m->ReadString(iter, &s)) {
+ *p = GURL();
+ return false;
+ }
+ *p = GURL(s);
+ return true;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(UTF8ToWide(p.spec()));
+ }
+};
+
+// and, a few more useful types...
+template <>
+struct ParamTraits<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> {
+ 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> {
+ 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<HRGN> {
+ typedef HRGN param_type;
+ static void Write(Message* m, const param_type& p) {
+ int data_size = GetRegionData(p, 0, NULL);
+ if (data_size) {
+ char* bytes = new char[data_size];
+ GetRegionData(p, data_size, reinterpret_cast<LPRGNDATA>(bytes));
+ m->WriteData(reinterpret_cast<const char*>(bytes), data_size);
+ delete [] bytes;
+ } else {
+ m->WriteData(NULL, 0);
+ }
+ }
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ bool res = FALSE;
+ const char *data;
+ int data_size = 0;
+ res = m->ReadData(iter, &data, &data_size);
+ if (data_size) {
+ *r = ExtCreateRegion(NULL, data_size,
+ reinterpret_cast<CONST RGNDATA*>(data));
+ } else {
+ res = TRUE;
+ *r = CreateRectRgn(0, 0, 0, 0);
+ }
+ return res;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(StringPrintf(L"0x%X", p));
+ }
+};
+
+template <>
+struct ParamTraits<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> {
+ 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::wstring* l) {
+ l->append(StringPrintf(L"(%d, %d)", p.x, p.y));
+ }
+};
+
+template <>
+struct ParamTraits<gfx::Point> {
+ typedef gfx::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->set_x(x);
+ r->set_y(y);
+ return true;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(StringPrintf(L"(%d, %d)", p.x(), p.y()));
+ }
+};
+
+template <>
+struct ParamTraits<gfx::Rect> {
+ typedef gfx::Rect param_type;
+ static void Write(Message* m, const param_type& p) {
+ m->WriteInt(p.x());
+ m->WriteInt(p.y());
+ m->WriteInt(p.width());
+ m->WriteInt(p.height());
+ }
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ int x, y, w, h;
+ if (!m->ReadInt(iter, &x) ||
+ !m->ReadInt(iter, &y) ||
+ !m->ReadInt(iter, &w) ||
+ !m->ReadInt(iter, &h))
+ return false;
+ r->set_x(x);
+ r->set_y(y);
+ r->set_width(w);
+ r->set_height(h);
+ return true;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(StringPrintf(L"(%d, %d, %d, %d)", p.x(), p.y(), p.width(), p.height()));
+ }
+};
+
+template <>
+struct ParamTraits<gfx::Size> {
+ typedef gfx::Size param_type;
+ static void Write(Message* m, const param_type& p) {
+ m->WriteInt(p.width());
+ m->WriteInt(p.height());
+ }
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ int w, h;
+ if (!m->ReadInt(iter, &w) ||
+ !m->ReadInt(iter, &h))
+ return false;
+ r->set_width(w);
+ r->set_height(h);
+ return true;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(StringPrintf(L"(%d, %d)", p.width(), p.height()));
+ }
+};
+
+template<>
+struct ParamTraits<ThumbnailScore> {
+ typedef ThumbnailScore 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<Time>::Write(m, p.time_at_snapshot);
+ }
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ double boring_score;
+ bool good_clipping, at_top;
+ 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<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;
+ }
+ 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));
+ }
+};
+
+template <>
+struct ParamTraits<WindowOpenDisposition> {
+ typedef WindowOpenDisposition 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) {
+ int temp;
+ bool res = m->ReadInt(iter, &temp);
+ *r = static_cast<WindowOpenDisposition>(temp);
+ return res;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(StringPrintf(L"%d", p));
+ }
+};
+
+template <>
+struct ParamTraits<ConsoleMessageLevel> {
+ typedef ConsoleMessageLevel 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) {
+ int temp;
+ bool res = m->ReadInt(iter, &temp);
+ *r = static_cast<ConsoleMessageLevel>(temp);
+ return res;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(StringPrintf(L"%d", p));
+ }
+};
+
+template <>
+struct ParamTraits<CacheManager::ResourceTypeStat> {
+ typedef CacheManager::ResourceTypeStat param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.count);
+ WriteParam(m, p.size);
+ WriteParam(m, p.live_size);
+ WriteParam(m, p.decoded_size);
+ }
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ bool result =
+ ReadParam(m, iter, &r->count) &&
+ ReadParam(m, iter, &r->size) &&
+ ReadParam(m, iter, &r->live_size) &&
+ ReadParam(m, iter, &r->decoded_size);
+ return result;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(StringPrintf(L"%d %d %d %d", p.count, p.size, p.live_size,
+ p.decoded_size));
+ }
+};
+
+template <>
+struct ParamTraits<CacheManager::ResourceTypeStats> {
+ typedef CacheManager::ResourceTypeStats param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.images);
+ WriteParam(m, p.css_stylesheets);
+ WriteParam(m, p.scripts);
+ WriteParam(m, p.xsl_stylesheets);
+ WriteParam(m, p.fonts);
+ }
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ bool result =
+ ReadParam(m, iter, &r->images) &&
+ ReadParam(m, iter, &r->css_stylesheets) &&
+ ReadParam(m, iter, &r->scripts) &&
+ ReadParam(m, iter, &r->xsl_stylesheets) &&
+ ReadParam(m, iter, &r->fonts);
+ return result;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"<WebCoreStats>");
+ LogParam(p.images, l);
+ LogParam(p.css_stylesheets, l);
+ LogParam(p.scripts, l);
+ LogParam(p.xsl_stylesheets, l);
+ LogParam(p.fonts, l);
+ l->append(L"</WebCoreStats>");
+ }
+};
+
+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>");
+ }
+};
+
+struct WebCursor_Data {
+ WebCursor::Type cursor_type;
+ int hotspot_x;
+ int hotspot_y;
+ SkBitmap_Data bitmap_info;
+};
+
+template <>
+struct ParamTraits<WebCursor> {
+ typedef WebCursor param_type;
+ static void Write(Message* m, const param_type& p) {
+ const SkBitmap& src_bitmap = p.bitmap();
+ WebCursor_Data web_cursor_info;
+ web_cursor_info.cursor_type = p.type();
+ web_cursor_info.hotspot_x = p.hotspot_x();
+ web_cursor_info.hotspot_y = p.hotspot_y();
+ web_cursor_info.bitmap_info.InitSkBitmapDataForTransfer(src_bitmap);
+
+ size_t fixed_data = sizeof(web_cursor_info);
+ m->WriteData(reinterpret_cast<const char*>(&web_cursor_info),
+ static_cast<int>(fixed_data));
+ size_t pixel_size = src_bitmap.getSize();
+ m->WriteBool(pixel_size != 0);
+ if (pixel_size) {
+ SkAutoLockPixels src_bitmap_lock(src_bitmap);
+ m->WriteData(reinterpret_cast<const char*>(src_bitmap.getPixels()),
+ static_cast<int>(pixel_size));
+ }
+ }
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ const char* fixed_data = NULL;
+ int fixed_data_size = 0;
+ if (!m->ReadData(iter, &fixed_data, &fixed_data_size) ||
+ (fixed_data_size <= 0)) {
+ NOTREACHED();
+ return false;
+ }
+ DCHECK(fixed_data_size == sizeof(WebCursor_Data));
+
+ const WebCursor_Data* web_cursor_info =
+ reinterpret_cast<const WebCursor_Data*>(fixed_data);
+
+ bool variable_data_avail;
+ if (!m->ReadBool(iter, &variable_data_avail)) {
+ NOTREACHED();
+ return false;
+ }
+
+ // No variable data indicates that this is not a custom cursor.
+ if (variable_data_avail) {
+ const char* variable_data = NULL;
+ int variable_data_size = 0;
+ if (!m->ReadData(iter, &variable_data, &variable_data_size) ||
+ variable_data_size <= 0) {
+ NOTREACHED();
+ return false;
+ }
+
+ SkBitmap dest_bitmap;
+ web_cursor_info->bitmap_info.InitSkBitmapFromData(&dest_bitmap,
+ variable_data,
+ variable_data_size);
+ r->set_bitmap(dest_bitmap);
+ r->set_hotspot(web_cursor_info->hotspot_x, web_cursor_info->hotspot_y);
+ }
+
+ r->set_type(web_cursor_info->cursor_type);
+ return true;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"<WebCursor>");
+ }
+};
+
+struct LogData {
+ std::wstring channel;
+ uint16 type;
+ std::wstring 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::wstring params;
+};
+
+template <>
+struct ParamTraits<LogData> {
+ typedef LogData param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.channel);
+ WriteParam(m, static_cast<int>(p.type));
+ WriteParam(m, p.flags);
+ WriteParam(m, p.sent);
+ WriteParam(m, p.receive);
+ WriteParam(m, p.dispatch);
+ WriteParam(m, p.params);
+ }
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ int type;
+ bool result =
+ ReadParam(m, iter, &r->channel) &&
+ ReadParam(m, iter, &type) &&
+ ReadParam(m, iter, &r->flags) &&
+ ReadParam(m, iter, &r->sent) &&
+ ReadParam(m, iter, &r->receive) &&
+ ReadParam(m, iter, &r->dispatch) &&
+ ReadParam(m, iter, &r->params);
+ r->type = static_cast<uint16>(type);
+ return result;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ // Doesn't make sense to implement this!
+ }
+};
+
+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::wstring* 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::wstring* 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::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> > {
+ 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::wstring* l) {
+ LogParam(p.a, l);
+ 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> > {
+ 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::wstring* l) {
+ LogParam(p.a, l);
+ l->append(L", ");
+ LogParam(p.b, l);
+ 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> > {
+ 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::wstring* l) {
+ LogParam(p.a, l);
+ l->append(L", ");
+ LogParam(p.b, l);
+ l->append(L", ");
+ LogParam(p.c, l);
+ l->append(L", ");
+ LogParam(p.d, l);
+ l->append(L", ");
+ LogParam(p.e, l);
+ }
+};
+
+template <>
+struct ParamTraits<webkit_glue::WebApplicationInfo> {
+ typedef webkit_glue::WebApplicationInfo param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.title);
+ WriteParam(m, p.description);
+ WriteParam(m, p.app_url);
+ WriteParam(m, p.icons.size());
+ for (size_t i = 0; i < p.icons.size(); ++i) {
+ WriteParam(m, p.icons[i].url);
+ WriteParam(m, p.icons[i].width);
+ WriteParam(m, p.icons[i].height);
+ }
+ }
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ size_t icon_count;
+ bool result =
+ ReadParam(m, iter, &r->title) &&
+ ReadParam(m, iter, &r->description) &&
+ ReadParam(m, iter, &r->app_url) &&
+ ReadParam(m, iter, &icon_count);
+ if (!result)
+ return false;
+ for (size_t i = 0; i < icon_count && result; ++i) {
+ param_type::IconInfo icon_info;
+ result =
+ ReadParam(m, iter, &icon_info.url) &&
+ ReadParam(m, iter, &icon_info.width) &&
+ ReadParam(m, iter, &icon_info.height);
+ r->icons.push_back(icon_info);
+ }
+ return result;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"<WebApplicationInfo>");
+ }
+};
+
+
+//-----------------------------------------------------------------------------
+// Generic message subclasses
+
+// Used for asynchronous messages.
+template <class Param>
+class MessageWithTuple : public Message {
+ public:
+ MessageWithTuple(int32 routing_id, WORD type, const Param& p)
+ : Message(routing_id, type, PRIORITY_NORMAL) {
+ WriteParam(this, p);
+ }
+
+ static bool Read(const Message* msg, Param* p) {
+ void* iter = NULL;
+ bool rv = ReadParam(msg, &iter, p);
+ DCHECK(rv) << "Error deserializing message " << msg->type();
+ return rv;
+ }
+
+ // Generic dispatcher. Should cover most cases.
+ template<class T, class Method>
+ static bool Dispatch(const Message* msg, T* obj, 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, typename TA>
+ static bool Dispatch(const Message* msg, T* obj,
+ void (T::*func)(const Message&, TA)) {
+ Param p;
+ if (Read(msg, &p)) {
+ (obj->*func)(*msg, p);
+ return true;
+ }
+ return false;
+ }
+
+ template<class T, typename TA, typename TB>
+ static bool Dispatch(const Message* msg, T* obj,
+ 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, typename TA, typename TB, typename TC>
+ static bool Dispatch(const Message* msg, T* obj,
+ 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, typename TA, typename TB, typename TC, typename TD>
+ static bool Dispatch(const Message* msg, T* obj,
+ 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, typename TA, typename TB, typename TC, typename TD,
+ typename TE>
+ static bool Dispatch(const Message* msg, T* obj,
+ 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;
+ }
+
+ static void Log(const Message* msg, std::wstring* l) {
+ Param p;
+ if (Read(msg, &p))
+ LogParam(p, l);
+ }
+};
+
+// This class assumes that its template argument is a RefTuple (a Tuple with
+// reference elements).
+template <class RefTuple>
+class ParamDeserializer : public MessageReplyDeserializer {
+ public:
+ ParamDeserializer(const RefTuple& out) : out_(out) { }
+
+ bool SerializeOutputParameters(const IPC::Message& msg, void* iter) {
+ return ReadParam(&msg, &iter, &out_);
+ }
+
+ RefTuple out_;
+};
+
+// defined in ipc_logging.cc
+void GenerateLogData(const std::wstring& channel, const Message& message,
+ LogData* data);
+
+// Used for synchronous messages.
+template <class SendParam, class ReplyParam>
+class MessageWithReply : public SyncMessage {
+ public:
+ MessageWithReply(int32 routing_id, WORD type,
+ const SendParam& send, const ReplyParam& reply)
+ : SyncMessage(routing_id, type, PRIORITY_NORMAL,
+ new ParamDeserializer<ReplyParam>(reply)) {
+ WriteParam(this, send);
+ }
+
+ static void Log(const Message* msg, std::wstring* l) {
+ if (msg->is_sync()) {
+ SendParam p;
+ void* iter = SyncMessage::GetDataIterator(msg);
+ ReadParam(msg, &iter, &p);
+ LogParam(p, l);
+
+ const std::wstring& output_params = msg->output_params();
+ if (!l->empty() && !output_params.empty())
+ l->append(L", ");
+
+ l->append(output_params);
+ } else {
+ // This is an outgoing reply. Now that we have the output parameters, we
+ // can finally log the message.
+ ReplyParam::ValueTuple p;
+ void* iter = SyncMessage::GetDataIterator(msg);
+ ReadParam(msg, &iter, &p);
+ LogParam(p, l);
+ }
+ }
+
+ template<class T, class Method>
+ static bool Dispatch(const Message* msg, T* obj, Method func) {
+ SendParam send_params;
+ void* iter = GetDataIterator(msg);
+ Message* reply = GenerateReply(msg);
+ bool error;
+ if (ReadParam(msg, &iter, &send_params)) {
+ ReplyParam::ValueTuple reply_params;
+ DispatchToMethod(obj, func, send_params, &reply_params);
+ WriteParam(reply, reply_params);
+ error = false;
+#ifdef IPC_MESSAGE_LOG_ENABLED
+ if (msg->received_time() != 0) {
+ std::wstring output_params;
+ LogParam(reply_params, &output_params);
+ msg->set_output_params(output_params);
+ }
+#endif
+ } else {
+ NOTREACHED() << "Error deserializing message " << msg->type();
+ reply->set_reply_error();
+ error = true;
+ }
+
+ obj->Send(reply);
+ return !error;
+ }
+
+ template<class T, class Method>
+ static bool DispatchDelayReply(const Message* msg, T* obj, Method func) {
+ SendParam send_params;
+ void* iter = GetDataIterator(msg);
+ Message* reply = GenerateReply(msg);
+ bool error;
+ if (ReadParam(msg, &iter, &send_params)) {
+ Tuple1<Message&> t = MakeRefTuple(*reply);
+
+#ifdef IPC_MESSAGE_LOG_ENABLED
+ 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(L"", *msg, data);
+ msg->set_dont_log();
+ reply->set_sync_log_data(data);
+ }
+#endif
+ 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);
+ }
+};
+
+//-----------------------------------------------------------------------------
+}
+
+#endif // CHROME_COMMON_IPC_MESSAGE_UTILS_H__