// 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 #include #include #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 struct ParamTraits {}; template static inline void WriteParam(Message* m, const P& p) { ParamTraits

::Write(m, p); } template static inline bool ReadParam(const Message* m, void** iter, P* p) { return ParamTraits

::Read(m, iter, p); } template static inline void LogParam(const P& p, std::wstring* l) { ParamTraits

::Log(p, l); } template <> struct ParamTraits { 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 { 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 { 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 { 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 { typedef uint64 param_type; static void Write(Message* m, const param_type& p) { m->WriteInt64(static_cast(p)); } static bool Read(const Message* m, void** iter, param_type* r) { return m->ReadInt64(iter, reinterpret_cast(r)); } static void Log(const param_type& p, std::wstring* l) { l->append(StringPrintf(L"%I64u", p)); } }; template <> struct ParamTraits { typedef double param_type; static void Write(Message* m, const param_type& p) { m->WriteData(reinterpret_cast(&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 { typedef wchar_t param_type; static void Write(Message* m, const param_type& p) { m->WriteData(reinterpret_cast(&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

param_type; static void Write(Message* m, const param_type& p) { WriteParam(m, static_cast(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 struct ParamTraits > { typedef std::map param_type; static void Write(Message* m, const param_type& p) { WriteParam(m, static_cast(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""); } }; template <> struct ParamTraits { 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 { 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 { typedef HANDLE param_type; static void Write(Message* m, const param_type& p) { m->WriteIntPtr(reinterpret_cast(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(r)); } static void Log(const param_type& p, std::wstring* l) { l->append(StringPrintf(L"0x%X", p)); } }; template <> struct ParamTraits { typedef HCURSOR param_type; static void Write(Message* m, const param_type& p) { m->WriteIntPtr(reinterpret_cast(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(r)); } static void Log(const param_type& p, std::wstring* l) { l->append(StringPrintf(L"0x%X", p)); } }; template <> struct ParamTraits { typedef HWND param_type; static void Write(Message* m, const param_type& p) { m->WriteIntPtr(reinterpret_cast(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(r)); } static void Log(const param_type& p, std::wstring* l) { l->append(StringPrintf(L"0x%X", p)); } }; template <> struct ParamTraits { 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(bytes)); m->WriteData(reinterpret_cast(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(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 { typedef HACCEL param_type; static void Write(Message* m, const param_type& p) { m->WriteIntPtr(reinterpret_cast(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(r)); } }; template <> struct ParamTraits { 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 { 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 { 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 { 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 { typedef ThumbnailScore param_type; static void Write(Message* m, const param_type& p) { IPC::ParamTraits::Write(m, p.boring_score); IPC::ParamTraits::Write(m, p.good_clipping); IPC::ParamTraits::Write(m, p.at_top); IPC::ParamTraits