// 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/string_util.h" #include "base/tuple.h" #include "chrome/common/ipc_sync_message.h" #include "chrome/common/thumbnail_score.h" #include "webkit/glue/cache_manager.h" #include "webkit/glue/console_message_level.h" #include "webkit/glue/window_open_disposition.h" // Forward declarations. class GURL; class SkBitmap; class WebCursor; namespace gfx { class Point; class Rect; class Size; } // namespace gfx namespace webkit_glue { struct WebApplicationInfo; } // namespace webkit_glue 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: explicit 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(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"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(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"%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; } }; template <> struct ParamTraits<SkBitmap> { typedef SkBitmap param_type; static void Write(Message* m, const param_type& p); // 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); static void Log(const param_type& p, std::wstring* l); }; 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); static bool Read(const Message* m, void** iter, param_type* p); static void Log(const param_type& p, std::wstring* l); }; // 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); static bool Read(const Message* m, void** iter, param_type* r); static void Log(const param_type& p, std::wstring* l); }; template <> struct ParamTraits<gfx::Rect> { typedef gfx::Rect 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 ParamTraits<gfx::Size> { typedef gfx::Size 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 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>"); } }; template <> struct ParamTraits<WebCursor> { typedef WebCursor 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); }; 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); static bool Read(const Message* m, void** iter, param_type* r); static void Log(const param_type& p, std::wstring* l); }; //----------------------------------------------------------------------------- // 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: explicit 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); } }; //----------------------------------------------------------------------------- } // namespace IPC #endif // CHROME_COMMON_IPC_MESSAGE_UTILS_H_