| Index: ipc/ipc_message_utils.h
|
| diff --git a/ipc/ipc_message_utils.h b/ipc/ipc_message_utils.h
|
| index 4667d4b234f75c102f2d19dbd2d29ef14d9e318d..05d39165f248fc0aebd4ed6a7af0fd005cee353e 100644
|
| --- a/ipc/ipc_message_utils.h
|
| +++ b/ipc/ipc_message_utils.h
|
| @@ -12,22 +12,29 @@
|
| #include <map>
|
| #include <set>
|
|
|
| -#include "base/file_path.h"
|
| #include "base/format_macros.h"
|
| -#include "base/nullable_string16.h"
|
| #include "base/string16.h"
|
| #include "base/string_number_conversions.h"
|
| #include "base/string_util.h"
|
| -#include "base/time.h"
|
| #include "base/tuple.h"
|
| #include "base/utf_string_conversions.h"
|
| -#include "base/values.h"
|
| -#if defined(OS_POSIX)
|
| -#include "ipc/file_descriptor_set_posix.h"
|
| -#endif
|
| -#include "ipc/ipc_channel_handle.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.
|
| +#define IPC_MSG_NOINLINE __attribute__((noinline));
|
| +#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.
|
| @@ -67,8 +74,20 @@ enum IPCMessageStart {
|
| LastMsgIndex
|
| };
|
|
|
| +class DictionaryValue;
|
| +class FilePath;
|
| +class ListValue;
|
| +class NullableString16;
|
| +
|
| +namespace base {
|
| +class Time;
|
| +struct FileDescriptor;
|
| +}
|
| +
|
| namespace IPC {
|
|
|
| +struct ChannelHandle;
|
| +
|
| //-----------------------------------------------------------------------------
|
| // An iterator class for reading the fields contained within a Message.
|
|
|
| @@ -306,19 +325,9 @@ struct ParamTraits<wchar_t> {
|
| template <>
|
| struct ParamTraits<base::Time> {
|
| typedef base::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 = base::Time::FromInternalValue(value);
|
| - return true;
|
| - }
|
| - static void Log(const param_type& p, std::wstring* l) {
|
| - ParamTraits<int64>::Log(p.ToInternalValue(), l);
|
| - }
|
| + 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);
|
| };
|
|
|
| #if defined(OS_WIN)
|
| @@ -365,6 +374,9 @@ struct ParamTraits<MSG> {
|
|
|
| return result;
|
| }
|
| + static void Log(const param_type& p, std::wstring* l) {
|
| + l->append(L"<MSG>");
|
| + }
|
| };
|
| #endif // defined(OS_WIN)
|
|
|
| @@ -598,27 +610,9 @@ struct ParamTraits<std::pair<A, B> > {
|
| template <>
|
| struct ParamTraits<NullableString16> {
|
| typedef NullableString16 param_type;
|
| - static void Write(Message* m, const param_type& p) {
|
| - WriteParam(m, p.string());
|
| - WriteParam(m, p.is_null());
|
| - }
|
| - static bool Read(const Message* m, void** iter, param_type* r) {
|
| - string16 string;
|
| - if (!ReadParam(m, iter, &string))
|
| - return false;
|
| - bool is_null;
|
| - if (!ReadParam(m, iter, &is_null))
|
| - return false;
|
| - *r = NullableString16(string, is_null);
|
| - return true;
|
| - }
|
| - static void Log(const param_type& p, std::wstring* l) {
|
| - l->append(L"(");
|
| - LogParam(p.string(), l);
|
| - l->append(L", ");
|
| - LogParam(p.is_null(), l);
|
| - l->append(L")");
|
| - }
|
| + 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);
|
| };
|
|
|
| // If WCHAR_T_IS_UTF16 is defined, then string16 is a std::wstring so we don't
|
| @@ -709,19 +703,9 @@ struct ParamTraits<POINT> {
|
| template <>
|
| struct ParamTraits<FilePath> {
|
| typedef FilePath param_type;
|
| - static void Write(Message* m, const param_type& p) {
|
| - ParamTraits<FilePath::StringType>::Write(m, p.value());
|
| - }
|
| - static bool Read(const Message* m, void** iter, param_type* r) {
|
| - FilePath::StringType value;
|
| - if (!ParamTraits<FilePath::StringType>::Read(m, iter, &value))
|
| - return false;
|
| - *r = FilePath(value);
|
| - return true;
|
| - }
|
| - static void Log(const param_type& p, std::wstring* l) {
|
| - ParamTraits<FilePath::StringType>::Log(p.value(), l);
|
| - }
|
| + 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);
|
| };
|
|
|
| #if defined(OS_POSIX)
|
| @@ -743,35 +727,9 @@ struct ParamTraits<FilePath> {
|
| template<>
|
| struct ParamTraits<base::FileDescriptor> {
|
| typedef base::FileDescriptor param_type;
|
| - static void Write(Message* m, const param_type& p) {
|
| - const bool valid = p.fd >= 0;
|
| - WriteParam(m, valid);
|
| -
|
| - if (valid) {
|
| - if (!m->WriteFileDescriptor(p))
|
| - NOTREACHED();
|
| - }
|
| - }
|
| - static bool Read(const Message* m, void** iter, param_type* r) {
|
| - bool valid;
|
| - if (!ReadParam(m, iter, &valid))
|
| - return false;
|
| -
|
| - if (!valid) {
|
| - r->fd = -1;
|
| - r->auto_close = false;
|
| - return true;
|
| - }
|
| -
|
| - return m->ReadFileDescriptor(iter, r);
|
| - }
|
| - static void Log(const param_type& p, std::wstring* l) {
|
| - if (p.auto_close) {
|
| - l->append(StringPrintf(L"FD(%d auto-close)", p.fd));
|
| - } else {
|
| - l->append(StringPrintf(L"FD(%d)", p.fd));
|
| - }
|
| - }
|
| + 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);
|
| };
|
| #endif // defined(OS_POSIX)
|
|
|
| @@ -781,26 +739,9 @@ struct ParamTraits<base::FileDescriptor> {
|
| template<>
|
| struct ParamTraits<IPC::ChannelHandle> {
|
| typedef ChannelHandle param_type;
|
| - static void Write(Message* m, const param_type& p) {
|
| - WriteParam(m, p.name);
|
| -#if defined(OS_POSIX)
|
| - WriteParam(m, p.socket);
|
| -#endif
|
| - }
|
| - static bool Read(const Message* m, void** iter, param_type* r) {
|
| - return ReadParam(m, iter, &r->name)
|
| -#if defined(OS_POSIX)
|
| - && ReadParam(m, iter, &r->socket)
|
| -#endif
|
| - ;
|
| - }
|
| - static void Log(const param_type& p, std::wstring* l) {
|
| - l->append(ASCIIToWide(StringPrintf("ChannelHandle(%s", p.name.c_str())));
|
| -#if defined(OS_POSIX)
|
| - ParamTraits<base::FileDescriptor>::Log(p.socket, l);
|
| -#endif
|
| - l->append(L")");
|
| - }
|
| + 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);
|
| };
|
|
|
| #if defined(OS_WIN)
|
| @@ -1026,20 +967,15 @@ template <class ParamType>
|
| class MessageWithTuple : public Message {
|
| public:
|
| typedef ParamType Param;
|
| - typedef typename ParamType::ParamTuple RefParam;
|
| + typedef typename TupleTypes<ParamType>::ParamTuple RefParam;
|
|
|
| - MessageWithTuple(int32 routing_id, uint32 type, const RefParam& p)
|
| - : Message(routing_id, type, PRIORITY_NORMAL) {
|
| - WriteParam(this, p);
|
| - }
|
| + // 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) {
|
| - void* iter = NULL;
|
| - if (ReadParam(msg, &iter, p))
|
| - return true;
|
| - NOTREACHED() << "Error deserializing message " << msg->type();
|
| - return false;
|
| - }
|
| + static bool Read(const Message* msg, Param* p) IPC_MSG_NOINLINE;
|
|
|
| // Generic dispatcher. Should cover most cases.
|
| template<class T, class Method>
|
| @@ -1111,12 +1047,6 @@ class MessageWithTuple : public Message {
|
| return false;
|
| }
|
|
|
| - static void Log(const Message* msg, std::wstring* l) {
|
| - Param p;
|
| - if (Read(msg, &p))
|
| - LogParam(p, l);
|
| - }
|
| -
|
| // 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>
|
| @@ -1166,8 +1096,54 @@ class MessageWithTuple : public Message {
|
| }
|
| };
|
|
|
| +// defined in ipc_logging.cc
|
| +void GenerateLogData(const std::string& channel, const Message& message,
|
| + LogData* data);
|
| +
|
| +
|
| +#if defined(IPC_MESSAGE_LOG_ENABLED)
|
| +inline void AddOutputParamsToLog(const Message* msg, std::wstring* l) {
|
| + const std::wstring& output_params = msg->output_params();
|
| + if (!l->empty() && !output_params.empty())
|
| + l->append(L", ");
|
| +
|
| + l->append(output_params);
|
| +}
|
| +
|
| +template <class ReplyParamType>
|
| +inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
|
| + const Message* msg) {
|
| + if (msg->received_time() != 0) {
|
| + std::wstring 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::wstring* 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).
|
| +// 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:
|
| @@ -1180,67 +1156,32 @@ class ParamDeserializer : public MessageReplyDeserializer {
|
| RefTuple out_;
|
| };
|
|
|
| -// defined in ipc_logging.cc
|
| -void GenerateLogData(const std::string& channel, const Message& message,
|
| - LogData* data);
|
| -
|
| // Used for synchronous messages.
|
| template <class SendParamType, class ReplyParamType>
|
| class MessageWithReply : public SyncMessage {
|
| public:
|
| typedef SendParamType SendParam;
|
| - typedef typename SendParam::ParamTuple RefSendParam;
|
| + typedef typename TupleTypes<SendParam>::ParamTuple RefSendParam;
|
| typedef ReplyParamType ReplyParam;
|
|
|
| MessageWithReply(int32 routing_id, uint32 type,
|
| - const RefSendParam& 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);
|
| - if (ReadParam(msg, &iter, &p))
|
| - LogParam(p, l);
|
| -
|
| -#if defined(IPC_MESSAGE_LOG_ENABLED)
|
| - const std::wstring& output_params = msg->output_params();
|
| - if (!l->empty() && !output_params.empty())
|
| - l->append(L", ");
|
| -
|
| - l->append(output_params);
|
| -#endif
|
| - } else {
|
| - // This is an outgoing reply. Now that we have the output parameters, we
|
| - // can finally log the message.
|
| - typename ReplyParam::ValueTuple p;
|
| - void* iter = SyncMessage::GetDataIterator(msg);
|
| - if (ReadParam(msg, &iter, &p))
|
| - LogParam(p, l);
|
| - }
|
| - }
|
| + 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 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)) {
|
| - typename ReplyParam::ValueTuple reply_params;
|
| + if (ReadSendParam(msg, &send_params)) {
|
| + typename TupleTypes<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
|
| + LogReplyParamsToMessage(reply_params, msg);
|
| } else {
|
| NOTREACHED() << "Error deserializing message " << msg->type();
|
| reply->set_reply_error();
|
| @@ -1254,23 +1195,11 @@ class MessageWithReply : public SyncMessage {
|
| 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)) {
|
| + if (ReadSendParam(msg, &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("", *msg, data);
|
| - msg->set_dont_log();
|
| - reply->set_sync_log_data(data);
|
| - }
|
| -#endif
|
| + ConnectMessageAndReply(msg, reply);
|
| DispatchToMethod(obj, func, send_params, &t);
|
| error = false;
|
| } else {
|
|
|