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 { |