[Chrome源码阅读]IPC通信初探
2012-08-23 11:47
337 查看
RenderWidgetHost继承于IPC::Channel::Listener,所以它必然需要实现Listener::OnMessageReceived纯虚函数。
Chrome对这个函数进行了宏的封装,宏的写法有点类似于MFC/wxWidget的事件响应表,不同点在于Chrome里的宏是对函数的实现封装,而MFC/wxWidget里却是对事件表的初始化。
IPC::Channel::Sender类的实现
RenderWidgetHost类需要处理RenderProcess(进程)发过来的一部分Message,更准确的说是RenderProcessHost接收到Render Process的消息,然后一层一层传递过来的。
RenderWidgetHost里的宏,用来实现OnMessageReceived函数。以ViewHostMsg开头的message class是从Render Process发向Render Process Host(browser)进程的。相反,ViewMsg开头的类是从Render Process Host(browser) 发向Render Process的。它们都定义在文件\src\chrome\common\render_messages_internal.h中。
首先是IPC_DEFINE_MESSAGE_MAP宏,传递的参数是一个类的名字:
如果传递的class_name是RenderWidgetHost,那么这个宏展开就是:
宏IPC_MESSAGE_HANDLER(ViewHostMsg_RenderViewReady, OnMsgRenderViewReady):
看到case...关键字了。展开来就是:
所有的Msg_class类都继承于IPC::Message,各种message class也是用宏来定义的。
IPC::Message这个类根据消息响应函数参数的不同,提供了4个重载的Dispatch模板函数:
所以总体来看,这一套宏定义了一个IPC::Channel::Listener继承类的OnMessageReceived函数体,根据message的不同类型,转调用响应的成员函数体。
Chrome对这个函数进行了宏的封装,宏的写法有点类似于MFC/wxWidget的事件响应表,不同点在于Chrome里的宏是对函数的实现封装,而MFC/wxWidget里却是对事件表的初始化。
IPC::Channel::Sender类的实现
class Channel : public Message ::Sender { // Security tests need access to the pipe handle. friend class ChannelTest ; public: // Implemented by consumers of a Channel to receive messages. class Listener { public: virtual ~ Listener () {} // Called when a message is received. virtual void OnMessageReceived ( const Message & message ) = 0; // Called when the channel is connected and we have received the internal // Hello message from the peer. virtual void OnChannelConnected ( int32 peer_pid ) {} // Called when an error is detected that causes the channel to close. // This method is not called when a channel is closed normally. virtual void OnChannelError () {} };
RenderWidgetHost类需要处理RenderProcess(进程)发过来的一部分Message,更准确的说是RenderProcessHost接收到Render Process的消息,然后一层一层传递过来的。
RenderWidgetHost里的宏,用来实现OnMessageReceived函数。以ViewHostMsg开头的message class是从Render Process发向Render Process Host(browser)进程的。相反,ViewMsg开头的类是从Render Process Host(browser) 发向Render Process的。它们都定义在文件\src\chrome\common\render_messages_internal.h中。
IPC_DEFINE_MESSAGE_MAP (RenderWidgetHost ) IPC_MESSAGE_HANDLER( ViewHostMsg_RenderViewReady , OnMsgRenderViewReady ) IPC_MESSAGE_HANDLER( ViewHostMsg_RenderViewGone , OnMsgRenderViewGone ) IPC_MESSAGE_HANDLER( ViewHostMsg_Close , OnMsgClose ) IPC_MESSAGE_HANDLER( ViewHostMsg_RequestMove , OnMsgRequestMove ) IPC_MESSAGE_HANDLER( ViewHostMsg_PaintRect , OnMsgPaintRect ) IPC_MESSAGE_HANDLER( ViewHostMsg_ScrollRect , OnMsgScrollRect ) IPC_MESSAGE_HANDLER( ViewHostMsg_HandleInputEvent_ACK , OnMsgInputEventAck ) IPC_MESSAGE_HANDLER( ViewHostMsg_Focus , OnMsgFocus ) IPC_MESSAGE_HANDLER( ViewHostMsg_Blur , OnMsgBlur ) IPC_MESSAGE_HANDLER( ViewHostMsg_SetCursor , OnMsgSetCursor ) IPC_MESSAGE_HANDLER( ViewHostMsg_ImeUpdateStatus , OnMsgImeUpdateStatus ) IPC_MESSAGE_UNHANDLED_ERROR() IPC_END_MESSAGE_MAP ()我们现在尝试着来拆解这些宏。这些宏定义在文件\src\chrome\common\ipc_message_macros.h中。
首先是IPC_DEFINE_MESSAGE_MAP宏,传递的参数是一个类的名字:
#define IPC_DEFINE_MESSAGE_MAP(class_name) \ void class_name::OnMessageReceived(const IPC::Message& msg) \ IPC_BEGIN_MESSAGE_MAP(class_name, msg)
如果传递的class_name是RenderWidgetHost,那么这个宏展开就是:
void RenderWidgetHost::OnMessageReceived(const IPC::Message& msg) IPC_BEGIN_MESSAGE_MAP(RenderWidgetHost, msg)很明显的就是它是函数OnMessageReceived的定义,接下来展开IPC_BEGIN_MESSAGE_MAP宏:
#define IPC_BEGIN_MESSAGE_MAP(class_name, msg) \ { \ typedef class_name _IpcMessageHandlerClass; \ const IPC::Message& ipc_message__ = msg; \ bool msg_is_ok__ = true; \ switch (ipc_message__.type()) { \继续展开来就是:
{ typedef RenderWidgetHost _IpcMessageHandlerClass; const IPC::Message& ipc_message__ = msg; bool msg_is_ok__ = true; switch (ipc_message__.type()) {看到这里,差不多明了函数要干的事情了,就是switch...case的组合,来判断当前的Message是什么类型,然后执行响应的函数体。
宏IPC_MESSAGE_HANDLER(ViewHostMsg_RenderViewReady, OnMsgRenderViewReady):
#define IPC_MESSAGE_FORWARD(msg_class, obj, member_func) \ case msg_class::ID: \ msg_is_ok__ = msg_class::Dispatch(&ipc_message__, obj, &member_func); \ break; #define IPC_MESSAGE_HANDLER(msg_class, member_func) \ IPC_MESSAGE_FORWARD(msg_class, this, _IpcMessageHandlerClass::member_func)
看到case...关键字了。展开来就是:
case ViewHostMsg_RenderViewReady::ID: msg_is_ok__ = ViewHostMsg_RenderViewReady::Dispatch(&ipc_message__, this, _IpcMessageHandlerClass::OnMsgRenderViewReady); break;
所有的Msg_class类都继承于IPC::Message,各种message class也是用宏来定义的。
#define IPC_MESSAGE_ROUTED0(msg_class) \ class msg_class : public IPC::Message { \ public: \ enum { ID = msg_class##__ID }; \ msg_class(int32 routing_id) \ : IPC::Message(routing_id, ID, PRIORITY_NORMAL) {} \ };ID就是类的名字与"__ID"字符串的链接。
IPC::Message这个类根据消息响应函数参数的不同,提供了4个重载的Dispatch模板函数:
template<class T> static bool Dispatch(const Message* msg, T* obj, void (T::*func)()) { (obj->*func)(); return true; } template<class T> static bool Dispatch(const Message* msg, T* obj, void (T::*func)() const) { (obj->*func)(); return true; } template<class T> static bool Dispatch(const Message* msg, T* obj, void (T::*func)(const Message&)) { (obj->*func)(*msg); return true; } template<class T> static bool Dispatch(const Message* msg, T* obj, void (T::*func)(const Message&) const) { (obj->*func)(*msg); return true; }仅仅是简单的转调用传入进来的类成员函数。
所以总体来看,这一套宏定义了一个IPC::Channel::Listener继承类的OnMessageReceived函数体,根据message的不同类型,转调用响应的成员函数体。
相关文章推荐
- [Chrome源码阅读] 理解Chrome导航网址的流程及render进程启动模式
- [Chrome源码阅读] 理解Browser进程
- [Chrome源码阅读] 理解Chrome的smart pointer
- [Chrome源码阅读] Browser相关的类
- [Chrome源码阅读] 理解Thread类实现
- [Chrome源码阅读] 理解Browser进程
- [Chrome源码阅读]Chrome启动代码流程3
- [Chrome源码阅读] Chrome的多进程调试方法
- [Chrome源码阅读]Chrome启动代码流程3
- [Chrome源码阅读]Chrome增加一个New Tab时都干了些什么
- [Chrome源码阅读] MessageLoop类的点点滴滴
- [Chrome源码阅读]Chrome启动代码流程1
- [Chrome源码阅读] 理解ObserverList类的实现技巧
- [Chrome源码阅读]2个重要的类RenderViewHost和TabStripModel
- [Chrome源码阅读] 理解Chrome的smart pointer
- [Chrome源码阅读] Browser相关的类
- [Chrome源码阅读]Chrome启动代码流程2
- [Chrome源码阅读]Chrome增加一个New Tab时都干了些什么
- 《java.util.concurrent 包源码阅读》03 锁
- linux内核源码阅读之facebook硬盘加速利器flashcache之一