当前位置:   article > 正文

谷歌chrome浏览器的源码分析(五)_chrome dom 源码分析

chrome dom 源码分析


上一次说到类RenderThread和类RenderView把消息处理,那么这两个类是怎么样处理消息的呢?又是怎么样处理浏览的消息呢?现在就带着这两个问题去分析它的源码,理解它处理消息的方法。类RenderThread处理消息的代码如下:

#001  void RenderThread::OnMessageReceived(const IPC::Message& msg) {

#002    // NOTE: We could subclass router_ to intercept OnControlMessageReceived, but

#003    // it seems simpler to just process any control messages that we care about

#004    // up-front and then send the rest of the messages onto router_.

#005 

 

下面判断是控制消息,如果是控制消息就在本类里处理,否则就分发到别的地方处理,主要是转到类RenderView处理。

#006    if (msg.routing_id() == MSG_ROUTING_CONTROL) {

#007      IPC_BEGIN_MESSAGE_MAP(RenderThread, msg)

#008        IPC_MESSAGE_HANDLER(ViewMsg_VisitedLink_NewTable, OnUpdateVisitedLinks)

#009        IPC_MESSAGE_HANDLER(ViewMsg_SetNextPageID, OnSetNextPageID)

#010        IPC_MESSAGE_HANDLER(ViewMsg_New, OnCreateNewView)

#011        IPC_MESSAGE_HANDLER(ViewMsg_SetCacheCapacities, OnSetCacheCapacities)

#012        IPC_MESSAGE_HANDLER(ViewMsg_GetCacheResourceStats,

#013                           OnGetCacheResourceStats)

#014        // send the rest to the router

#015        IPC_MESSAGE_UNHANDLED(router_.OnMessageReceived(msg))

#016      IPC_END_MESSAGE_MAP()

#017    } else {

 

这里是分发消息到别的地方处理。

#018      router_.OnMessageReceived(msg);

#019    }

#020  }

 

在浏览器里,消息分为两大类:控制消息和路由消息。像使用IPC_MESSAGE_CONTROL宏定义的消息,就是控制消息;使用IPC_MESSAGE_ROUTED宏定义的消息,就是路由消息。

路由消息分发是由类MessageRouter来负责的,主要处理的代码如下:

#001 

#002  void MessageRouter::OnMessageReceived(const IPC::Message& msg) {

#003    if (msg.routing_id() == MSG_ROUTING_CONTROL) {

#004      OnControlMessageReceived(msg);

#005    } else {

#006      RouteMessage(msg);

#007    }

#008  }

在这里又分为MSG_ROUTING_CONTROL消息和其它路由消息,再一次通过函数RouteMessage分发之后,如下:

#001  bool MessageRouter::RouteMessage(const IPC::Message& msg) {

#002    IPC::Channel::Listener* listener = routes_.Lookup(msg.routing_id());

#003    if (!listener)

#004      return false;

#005 

#006    listener->OnMessageReceived(msg);

#007    return true;

#008  }

上面这个函数里又把消息通过发送到listener里去,其实listener是根据消息的目标routing_id来选择的,那么就是说它是选择发送到不同的窗口里去,因为每个TAB一个窗口。消息经过这样的处理之后,就到达了终点地--- RenderView::OnMessageReceived函数。下一次再来分析RenderView::OnMessageReceived函数的代码和后继处理。





上一次说到类RenderThread和类RenderView把消息处理,那么这两个类是怎么样处理消息的呢?又是怎么样处理浏览的消息呢?现在就带着这两个问题去分析它的源码,理解它处理消息的方法。类RenderThread处理消息的代码如下:

#001  void RenderThread::OnMessageReceived(const IPC::Message& msg) {

#002    // NOTE: We could subclass router_ to intercept OnControlMessageReceived, but

#003    // it seems simpler to just process any control messages that we care about

#004    // up-front and then send the rest of the messages onto router_.

#005 

 

下面判断是控制消息,如果是控制消息就在本类里处理,否则就分发到别的地方处理,主要是转到类RenderView处理。

#006    if (msg.routing_id() == MSG_ROUTING_CONTROL) {

#007      IPC_BEGIN_MESSAGE_MAP(RenderThread, msg)

#008        IPC_MESSAGE_HANDLER(ViewMsg_VisitedLink_NewTable, OnUpdateVisitedLinks)

#009        IPC_MESSAGE_HANDLER(ViewMsg_SetNextPageID, OnSetNextPageID)

#010        IPC_MESSAGE_HANDLER(ViewMsg_New, OnCreateNewView)

#011        IPC_MESSAGE_HANDLER(ViewMsg_SetCacheCapacities, OnSetCacheCapacities)

#012        IPC_MESSAGE_HANDLER(ViewMsg_GetCacheResourceStats,

#013                           OnGetCacheResourceStats)

#014        // send the rest to the router

#015        IPC_MESSAGE_UNHANDLED(router_.OnMessageReceived(msg))

#016      IPC_END_MESSAGE_MAP()

#017    } else {

 

这里是分发消息到别的地方处理。

#018      router_.OnMessageReceived(msg);

#019    }

#020  }

 

在浏览器里,消息分为两大类:控制消息和路由消息。像使用IPC_MESSAGE_CONTROL宏定义的消息,就是控制消息;使用IPC_MESSAGE_ROUTED宏定义的消息,就是路由消息。

路由消息分发是由类MessageRouter来负责的,主要处理的代码如下:

#001 

#002  void MessageRouter::OnMessageReceived(const IPC::Message& msg) {

#003    if (msg.routing_id() == MSG_ROUTING_CONTROL) {

#004      OnControlMessageReceived(msg);

#005    } else {

#006      RouteMessage(msg);

#007    }

#008  }

在这里又分为MSG_ROUTING_CONTROL消息和其它路由消息,再一次通过函数RouteMessage分发之后,如下:

#001  bool MessageRouter::RouteMessage(const IPC::Message& msg) {

#002    IPC::Channel::Listener* listener = routes_.Lookup(msg.routing_id());

#003    if (!listener)

#004      return false;

#005 

#006    listener->OnMessageReceived(msg);

#007    return true;

#008  }

上面这个函数里又把消息通过发送到listener里去,其实listener是根据消息的目标routing_id来选择的,那么就是说它是选择发送到不同的窗口里去,因为每个TAB一个窗口。消息经过这样的处理之后,就到达了终点地--- RenderView::OnMessageReceived函数。下一次再来分析RenderView::OnMessageReceived函数的代码和后继处理。




上一次说到消息转发,并分析了RenderThread类里处理消息的函数,其实大部份的消息都是在RenderView类里的OnMessageReceived函数处理,比如浏览的消息也是在这里处理。它的代码如下:

#001  void RenderView::OnMessageReceived(const IPC::Message& message) {

#002    // Let the resource dispatcher intercept resource messages first.

 

如果是资源消息,就直接分发去处理,以便提高效率。

#003    if (resource_dispatcher_->OnMessageReceived(message))

#004      return;

 

下面开始处理RenderView类里所有的消息。

#005    IPC_BEGIN_MESSAGE_MAP(RenderView, message)

#006      IPC_MESSAGE_HANDLER(ViewMsg_CreatingNew_ACK, OnCreatingNewAck)

#007      IPC_MESSAGE_HANDLER(ViewMsg_CaptureThumbnail, SendThumbnail)

#008      IPC_MESSAGE_HANDLER(ViewMsg_GetPrintedPagesCount, OnGetPrintedPagesCount)

#009      IPC_MESSAGE_HANDLER(ViewMsg_PrintPages, OnPrintPages)

#010      IPC_MESSAGE_HANDLER(ViewMsg_Navigate, OnNavigate)

#011      IPC_MESSAGE_HANDLER(ViewMsg_Stop, OnStop)

#012      IPC_MESSAGE_HANDLER(ViewMsg_LoadAlternateHTMLText, OnLoadAlternateHTMLText)

#013      IPC_MESSAGE_HANDLER(ViewMsg_StopFinding, OnStopFinding)

#014      IPC_MESSAGE_HANDLER(ViewMsg_Undo, OnUndo)

#015      IPC_MESSAGE_HANDLER(ViewMsg_Redo, OnRedo)

#016      IPC_MESSAGE_HANDLER(ViewMsg_Cut, OnCut)

#017      IPC_MESSAGE_HANDLER(ViewMsg_Copy, OnCopy)

#018      IPC_MESSAGE_HANDLER(ViewMsg_Paste, OnPaste)

#019      IPC_MESSAGE_HANDLER(ViewMsg_Replace, OnReplace)

#020      IPC_MESSAGE_HANDLER(ViewMsg_Delete, OnDelete)

#021      IPC_MESSAGE_HANDLER(ViewMsg_SelectAll, OnSelectAll)

#022      IPC_MESSAGE_HANDLER(ViewMsg_CopyImageAt, OnCopyImageAt)

#023      IPC_MESSAGE_HANDLER(ViewMsg_Find, OnFind)

#024      IPC_MESSAGE_HANDLER(ViewMsg_AlterTextSize, OnAlterTextSize)

#025      IPC_MESSAGE_HANDLER(ViewMsg_SetPageEncoding, OnSetPageEncoding)

#026      IPC_MESSAGE_HANDLER(ViewMsg_InspectElement, OnInspectElement)

#027      IPC_MESSAGE_HANDLER(ViewMsg_ShowJavaScriptConsole, OnShowJavaScriptConsole)

#028      IPC_MESSAGE_HANDLER(ViewMsg_DownloadImage, OnDownloadImage)

#029      IPC_MESSAGE_HANDLER(ViewMsg_ScriptEvalRequest, OnScriptEvalRequest)

#030      IPC_MESSAGE_HANDLER(ViewMsg_AddMessageToConsole, OnAddMessageToConsole)

#031      IPC_MESSAGE_HANDLER(ViewMsg_DebugAttach, OnDebugAttach)

#032      IPC_MESSAGE_HANDLER(ViewMsg_DebugDetach, OnDebugDetach)

#033      IPC_MESSAGE_HANDLER(ViewMsg_ReservePageIDRange, OnReservePageIDRange)

#034      IPC_MESSAGE_HANDLER(ViewMsg_UploadFile, OnUploadFileRequest)

#035      IPC_MESSAGE_HANDLER(ViewMsg_FormFill, OnFormFill)

#036      IPC_MESSAGE_HANDLER(ViewMsg_FillPasswordForm, OnFillPasswordForm)

#037      IPC_MESSAGE_HANDLER(ViewMsg_DragTargetDragEnter, OnDragTargetDragEnter)

#038      IPC_MESSAGE_HANDLER(ViewMsg_DragTargetDragOver, OnDragTargetDragOver)

#039      IPC_MESSAGE_HANDLER(ViewMsg_DragTargetDragLeave, OnDragTargetDragLeave)

#040      IPC_MESSAGE_HANDLER(ViewMsg_DragTargetDrop, OnDragTargetDrop)

#041      IPC_MESSAGE_HANDLER(ViewMsg_AllowDomAutomationBindings,

#042                         OnAllowDomAutomationBindings)

#043      IPC_MESSAGE_HANDLER(ViewMsg_AllowBindings, OnAllowBindings)

#044      IPC_MESSAGE_HANDLER(ViewMsg_SetDOMUIProperty, OnSetDOMUIProperty)

#045      IPC_MESSAGE_HANDLER(ViewMsg_DragSourceEndedOrMoved, OnDragSourceEndedOrMoved)

#046      IPC_MESSAGE_HANDLER(ViewMsg_DragSourceSystemDragEnded,

#047                         OnDragSourceSystemDragEnded)

#048      IPC_MESSAGE_HANDLER(ViewMsg_SetInitialFocus, OnSetInitialFocus)

#049      IPC_MESSAGE_HANDLER(ViewMsg_FindReplyACK, OnFindReplyAck)

#050      IPC_MESSAGE_HANDLER(ViewMsg_UpdateTargetURL_ACK, OnUpdateTargetURLAck)

#051      IPC_MESSAGE_HANDLER(ViewMsg_UpdateWebPreferences, OnUpdateWebPreferences)

#052      IPC_MESSAGE_HANDLER(ViewMsg_SetAltErrorPageURL, OnSetAltErrorPageURL)

#053      IPC_MESSAGE_HANDLER(ViewMsg_InstallMissingPlugin, OnInstallMissingPlugin)

#054      IPC_MESSAGE_HANDLER(ViewMsg_RunFileChooserResponse, OnFileChooserResponse)

#055      IPC_MESSAGE_HANDLER(ViewMsg_EnableViewSourceMode, OnEnableViewSourceMode)

#056      IPC_MESSAGE_HANDLER(ViewMsg_UpdateBackForwardListCount,

#057                         OnUpdateBackForwardListCount)

#058     IPC_MESSAGE_HANDLER(ViewMsg_GetAllSavableResourceLinksForCurrentPage,

#059                         OnGetAllSavableResourceLinksForCurrentPage)

#060     IPC_MESSAGE_HANDLER(ViewMsg_GetSerializedHtmlDataForCurrentPageWithLocalLinks,

#061                         OnGetSerializedHtmlDataForCurrentPageWithLocalLinks)

#062      IPC_MESSAGE_HANDLER(ViewMsg_GetApplicationInfo, OnGetApplicationInfo)

#063      IPC_MESSAGE_HANDLER(ViewMsg_ShouldClose, OnMsgShouldClose)

#064      IPC_MESSAGE_HANDLER(ViewMsg_ClosePage, OnClosePage)

#065      IPC_MESSAGE_HANDLER(ViewMsg_ThemeChanged, OnThemeChanged)

#066  #ifdef CHROME_PERSONALIZATION

#067      IPC_MESSAGE_HANDLER(ViewMsg_PersonalizationEvent, OnPersonalizationEvent)

#068  #endif

#069      IPC_MESSAGE_HANDLER(ViewMsg_HandleMessageFromExternalHost,

#070                          OnMessageFromExternalHost)

 

这里对于没有处理的消息进行提示。

#071      // Have the super handle all other messages.

#072      IPC_MESSAGE_UNHANDLED(RenderWidget::OnMessageReceived(message))

#073    IPC_END_MESSAGE_MAP()

#074  }

 

从上面这个函数可以看到,它的消息处理是非常多的,下面来分析一个浏览网络连接的消息,它就是ViewMsg_Navigate,可以看到这个消息后面响应函数是OnNavigate,也就是说,当你输入网络地址之后按回车,就会通过上说过的IPC机制把消息发送到这里,接着来看这个函数OnNavigate的代码,如下:

#001  void RenderView::OnNavigate(const ViewMsg_Navigate_Params& params) {

 

判断窗口是否关闭,如果关闭就不用去打开连接地址了。

#002    if (!webview())

#003      return;

#004 

 

处理一些about的连接处理,比如about:crash。

#005    AboutHandler::MaybeHandle(params.url);

#006 

 

保存是否重新加载网页。

#007    bool is_reload = params.reload;

#008 

 

获取WEB的显示框架。

#009    WebFrame* main_frame = webview()->GetMainFrame();

 

判断当是重新加载时,而当前又不是历史网页的情况。

#010    if (is_reload && !main_frame->HasCurrentState()) {

#011      // We cannot reload if we do not have any history state.  This happens, for

#012      // example, when recovering from a crash.  Our workaround here is a bit of

#013      // a hack since it means that reload after a crashed tab does not cause an

#014      // end-to-end cache validation.

#015      is_reload = false;

#016    }

#017 

 

下面设置缓冲策略。

#018    WebRequestCachePolicy cache_policy;

#019    if (is_reload) {

#020      cache_policy = WebRequestReloadIgnoringCacheData;

#021    } else if (params.page_id != -1 || main_frame->GetInViewSourceMode()) {

#022      cache_policy = WebRequestReturnCacheDataElseLoad;

#023    } else {

#024      cache_policy = WebRequestUseProtocolCachePolicy;

#025    }

#026 

 

下面创建一个下载请求,并把相关参数设置到请求里面。

#027    scoped_ptr<WebRequest> request(WebRequest::Create(params.url));

#028    request->SetCachePolicy(cache_policy);

#029    request->SetExtraData(new RenderViewExtraRequestData(

#030        params.page_id, params.transition, params.url));

#031 

 

设置WEBKIT的请求状态。

#032    // If we are reloading, then WebKit will use the state of the current page.

#033    // Otherwise, we give it the state to navigate to.

#034    if (!is_reload)

#035      request->SetHistoryState(params.state);

#036 

 

让主WEB显示框架去下载请求显示。

#037    main_frame->LoadRequest(request.get());

#038  }

 

分析这个函数,就可以知道处理浏览消息的过程,下一次来分析WebFrame里的接口函数LoadRequest处理过程,到底它是怎么样处理JavaScript脚本网页下载的呢?









上一次说到类RenderThread和类RenderView把消息处理,那么这两个类是怎么样处理消息的呢?又是怎么样处理浏览的消息呢?现在就带着这两个问题去分析它的源码,理解它处理消息的方法。类RenderThread处理消息的代码如下:

#001  void RenderThread::OnMessageReceived(const IPC::Message& msg) {

#002    // NOTE: We could subclass router_ to intercept OnControlMessageReceived, but

#003    // it seems simpler to just process any control messages that we care about

#004    // up-front and then send the rest of the messages onto router_.

#005 

 

下面判断是控制消息,如果是控制消息就在本类里处理,否则就分发到别的地方处理,主要是转到类RenderView处理。

#006    if (msg.routing_id() == MSG_ROUTING_CONTROL) {

#007      IPC_BEGIN_MESSAGE_MAP(RenderThread, msg)

#008        IPC_MESSAGE_HANDLER(ViewMsg_VisitedLink_NewTable, OnUpdateVisitedLinks)

#009        IPC_MESSAGE_HANDLER(ViewMsg_SetNextPageID, OnSetNextPageID)

#010        IPC_MESSAGE_HANDLER(ViewMsg_New, OnCreateNewView)

#011        IPC_MESSAGE_HANDLER(ViewMsg_SetCacheCapacities, OnSetCacheCapacities)

#012        IPC_MESSAGE_HANDLER(ViewMsg_GetCacheResourceStats,

#013                           OnGetCacheResourceStats)

#014        // send the rest to the router

#015        IPC_MESSAGE_UNHANDLED(router_.OnMessageReceived(msg))

#016      IPC_END_MESSAGE_MAP()

#017    } else {

 

这里是分发消息到别的地方处理。

#018      router_.OnMessageReceived(msg);

#019    }

#020  }

 

在浏览器里,消息分为两大类:控制消息和路由消息。像使用IPC_MESSAGE_CONTROL宏定义的消息,就是控制消息;使用IPC_MESSAGE_ROUTED宏定义的消息,就是路由消息。

路由消息分发是由类MessageRouter来负责的,主要处理的代码如下:

#001 

#002  void MessageRouter::OnMessageReceived(const IPC::Message& msg) {

#003    if (msg.routing_id() == MSG_ROUTING_CONTROL) {

#004      OnControlMessageReceived(msg);

#005    } else {

#006      RouteMessage(msg);

#007    }

#008  }

在这里又分为MSG_ROUTING_CONTROL消息和其它路由消息,再一次通过函数RouteMessage分发之后,如下:

#001  bool MessageRouter::RouteMessage(const IPC::Message& msg) {

#002    IPC::Channel::Listener* listener = routes_.Lookup(msg.routing_id());

#003    if (!listener)

#004      return false;

#005 

#006    listener->OnMessageReceived(msg);

#007    return true;

#008  }

上面这个函数里又把消息通过发送到listener里去,其实listener是根据消息的目标routing_id来选择的,那么就是说它是选择发送到不同的窗口里去,因为每个TAB一个窗口。消息经过这样的处理之后,就到达了终点地--- RenderView::OnMessageReceived函数。下一次再来分析RenderView::OnMessageReceived函数的代码和后继处理。


上一次说到消息转发,并分析了RenderThread类里处理消息的函数,其实大部份的消息都是在RenderView类里的OnMessageReceived函数处理,比如浏览的消息也是在这里处理。它的代码如下:

#001  void RenderView::OnMessageReceived(const IPC::Message& message) {

#002    // Let the resource dispatcher intercept resource messages first.

 

如果是资源消息,就直接分发去处理,以便提高效率。

#003    if (resource_dispatcher_->OnMessageReceived(message))

#004      return;

 

下面开始处理RenderView类里所有的消息。

#005    IPC_BEGIN_MESSAGE_MAP(RenderView, message)

#006      IPC_MESSAGE_HANDLER(ViewMsg_CreatingNew_ACK, OnCreatingNewAck)

#007      IPC_MESSAGE_HANDLER(ViewMsg_CaptureThumbnail, SendThumbnail)

#008      IPC_MESSAGE_HANDLER(ViewMsg_GetPrintedPagesCount, OnGetPrintedPagesCount)

#009      IPC_MESSAGE_HANDLER(ViewMsg_PrintPages, OnPrintPages)

#010      IPC_MESSAGE_HANDLER(ViewMsg_Navigate, OnNavigate)

#011      IPC_MESSAGE_HANDLER(ViewMsg_Stop, OnStop)

#012      IPC_MESSAGE_HANDLER(ViewMsg_LoadAlternateHTMLText, OnLoadAlternateHTMLText)

#013      IPC_MESSAGE_HANDLER(ViewMsg_StopFinding, OnStopFinding)

#014      IPC_MESSAGE_HANDLER(ViewMsg_Undo, OnUndo)

#015      IPC_MESSAGE_HANDLER(ViewMsg_Redo, OnRedo)

#016      IPC_MESSAGE_HANDLER(ViewMsg_Cut, OnCut)

#017      IPC_MESSAGE_HANDLER(ViewMsg_Copy, OnCopy)

#018      IPC_MESSAGE_HANDLER(ViewMsg_Paste, OnPaste)

#019      IPC_MESSAGE_HANDLER(ViewMsg_Replace, OnReplace)

#020      IPC_MESSAGE_HANDLER(ViewMsg_Delete, OnDelete)

#021      IPC_MESSAGE_HANDLER(ViewMsg_SelectAll, OnSelectAll)

#022      IPC_MESSAGE_HANDLER(ViewMsg_CopyImageAt, OnCopyImageAt)

#023      IPC_MESSAGE_HANDLER(ViewMsg_Find, OnFind)

#024      IPC_MESSAGE_HANDLER(ViewMsg_AlterTextSize, OnAlterTextSize)

#025      IPC_MESSAGE_HANDLER(ViewMsg_SetPageEncoding, OnSetPageEncoding)

#026      IPC_MESSAGE_HANDLER(ViewMsg_InspectElement, OnInspectElement)

#027      IPC_MESSAGE_HANDLER(ViewMsg_ShowJavaScriptConsole, OnShowJavaScriptConsole)

#028      IPC_MESSAGE_HANDLER(ViewMsg_DownloadImage, OnDownloadImage)

#029      IPC_MESSAGE_HANDLER(ViewMsg_ScriptEvalRequest, OnScriptEvalRequest)

#030      IPC_MESSAGE_HANDLER(ViewMsg_AddMessageToConsole, OnAddMessageToConsole)

#031      IPC_MESSAGE_HANDLER(ViewMsg_DebugAttach, OnDebugAttach)

#032      IPC_MESSAGE_HANDLER(ViewMsg_DebugDetach, OnDebugDetach)

#033      IPC_MESSAGE_HANDLER(ViewMsg_ReservePageIDRange, OnReservePageIDRange)

#034      IPC_MESSAGE_HANDLER(ViewMsg_UploadFile, OnUploadFileRequest)

#035      IPC_MESSAGE_HANDLER(ViewMsg_FormFill, OnFormFill)

#036      IPC_MESSAGE_HANDLER(ViewMsg_FillPasswordForm, OnFillPasswordForm)

#037      IPC_MESSAGE_HANDLER(ViewMsg_DragTargetDragEnter, OnDragTargetDragEnter)

#038      IPC_MESSAGE_HANDLER(ViewMsg_DragTargetDragOver, OnDragTargetDragOver)

#039      IPC_MESSAGE_HANDLER(ViewMsg_DragTargetDragLeave, OnDragTargetDragLeave)

#040      IPC_MESSAGE_HANDLER(ViewMsg_DragTargetDrop, OnDragTargetDrop)

#041      IPC_MESSAGE_HANDLER(ViewMsg_AllowDomAutomationBindings,

#042                         OnAllowDomAutomationBindings)

#043      IPC_MESSAGE_HANDLER(ViewMsg_AllowBindings, OnAllowBindings)

#044      IPC_MESSAGE_HANDLER(ViewMsg_SetDOMUIProperty, OnSetDOMUIProperty)

#045      IPC_MESSAGE_HANDLER(ViewMsg_DragSourceEndedOrMoved, OnDragSourceEndedOrMoved)

#046      IPC_MESSAGE_HANDLER(ViewMsg_DragSourceSystemDragEnded,

#047                         OnDragSourceSystemDragEnded)

#048      IPC_MESSAGE_HANDLER(ViewMsg_SetInitialFocus, OnSetInitialFocus)

#049      IPC_MESSAGE_HANDLER(ViewMsg_FindReplyACK, OnFindReplyAck)

#050      IPC_MESSAGE_HANDLER(ViewMsg_UpdateTargetURL_ACK, OnUpdateTargetURLAck)

#051      IPC_MESSAGE_HANDLER(ViewMsg_UpdateWebPreferences, OnUpdateWebPreferences)

#052      IPC_MESSAGE_HANDLER(ViewMsg_SetAltErrorPageURL, OnSetAltErrorPageURL)

#053      IPC_MESSAGE_HANDLER(ViewMsg_InstallMissingPlugin, OnInstallMissingPlugin)

#054      IPC_MESSAGE_HANDLER(ViewMsg_RunFileChooserResponse, OnFileChooserResponse)

#055      IPC_MESSAGE_HANDLER(ViewMsg_EnableViewSourceMode, OnEnableViewSourceMode)

#056      IPC_MESSAGE_HANDLER(ViewMsg_UpdateBackForwardListCount,

#057                         OnUpdateBackForwardListCount)

#058     IPC_MESSAGE_HANDLER(ViewMsg_GetAllSavableResourceLinksForCurrentPage,

#059                         OnGetAllSavableResourceLinksForCurrentPage)

#060     IPC_MESSAGE_HANDLER(ViewMsg_GetSerializedHtmlDataForCurrentPageWithLocalLinks,

#061                         OnGetSerializedHtmlDataForCurrentPageWithLocalLinks)

#062      IPC_MESSAGE_HANDLER(ViewMsg_GetApplicationInfo, OnGetApplicationInfo)

#063      IPC_MESSAGE_HANDLER(ViewMsg_ShouldClose, OnMsgShouldClose)

#064      IPC_MESSAGE_HANDLER(ViewMsg_ClosePage, OnClosePage)

#065      IPC_MESSAGE_HANDLER(ViewMsg_ThemeChanged, OnThemeChanged)

#066  #ifdef CHROME_PERSONALIZATION

#067      IPC_MESSAGE_HANDLER(ViewMsg_PersonalizationEvent, OnPersonalizationEvent)

#068  #endif

#069      IPC_MESSAGE_HANDLER(ViewMsg_HandleMessageFromExternalHost,

#070                          OnMessageFromExternalHost)

 

这里对于没有处理的消息进行提示。

#071      // Have the super handle all other messages.

#072      IPC_MESSAGE_UNHANDLED(RenderWidget::OnMessageReceived(message))

#073    IPC_END_MESSAGE_MAP()

#074  }

 

从上面这个函数可以看到,它的消息处理是非常多的,下面来分析一个浏览网络连接的消息,它就是ViewMsg_Navigate,可以看到这个消息后面响应函数是OnNavigate,也就是说,当你输入网络地址之后按回车,就会通过上说过的IPC机制把消息发送到这里,接着来看这个函数OnNavigate的代码,如下:

#001  void RenderView::OnNavigate(const ViewMsg_Navigate_Params& params) {

 

判断窗口是否关闭,如果关闭就不用去打开连接地址了。

#002    if (!webview())

#003      return;

#004 

 

处理一些about的连接处理,比如about:crash。

#005    AboutHandler::MaybeHandle(params.url);

#006 

 

保存是否重新加载网页。

#007    bool is_reload = params.reload;

#008 

 

获取WEB的显示框架。

#009    WebFrame* main_frame = webview()->GetMainFrame();

 

判断当是重新加载时,而当前又不是历史网页的情况。

#010    if (is_reload && !main_frame->HasCurrentState()) {

#011      // We cannot reload if we do not have any history state.  This happens, for

#012      // example, when recovering from a crash.  Our workaround here is a bit of

#013      // a hack since it means that reload after a crashed tab does not cause an

#014      // end-to-end cache validation.

#015      is_reload = false;

#016    }

#017 

 

下面设置缓冲策略。

#018    WebRequestCachePolicy cache_policy;

#019    if (is_reload) {

#020      cache_policy = WebRequestReloadIgnoringCacheData;

#021    } else if (params.page_id != -1 || main_frame->GetInViewSourceMode()) {

#022      cache_policy = WebRequestReturnCacheDataElseLoad;

#023    } else {

#024      cache_policy = WebRequestUseProtocolCachePolicy;

#025    }

#026 

 

下面创建一个下载请求,并把相关参数设置到请求里面。

#027    scoped_ptr<WebRequest> request(WebRequest::Create(params.url));

#028    request->SetCachePolicy(cache_policy);

#029    request->SetExtraData(new RenderViewExtraRequestData(

#030        params.page_id, params.transition, params.url));

#031 

 

设置WEBKIT的请求状态。

#032    // If we are reloading, then WebKit will use the state of the current page.

#033    // Otherwise, we give it the state to navigate to.

#034    if (!is_reload)

#035      request->SetHistoryState(params.state);

#036 

 

让主WEB显示框架去下载请求显示。

#037    main_frame->LoadRequest(request.get());

#038  }

 

分析这个函数,就可以知道处理浏览消息的过程,下一次来分析WebFrame里的接口函数LoadRequest处理过程,到底它是怎么样处理JavaScript脚本网页下载的呢?


继续上一次来分析LoadRequest的代码,在分析这个函数代码之前,先看看WebFrame类的继承层次关系,如下:

class WebFrame : public base::RefCounted<WebFrame> {

WebFrame是一个接口类,但它先继承引用计数类RefCounted,这样对于这个对象多次访问,就可以使用引用计数来判断对象的生命周期了。对于base::RefCounted<WebFrame>的语法,其实它是一种模板实现的多态特性,这种方案是最高效的实现方式,比使用虚函数更少占内存,并且运行的速度也更快。它就是解决如下的问题:

  void Release() {

    if (subtle::RefCountedBase::Release()) {

      delete static_cast<T*>(this);

    }

  }

上面的函数里static_cast<T*>(this),它就是一种多态的实现方法,由于base::RefCounted类并没有声明为虚析构函数,如下:

template <class T>

class RefCounted : public subtle::RefCountedBase {

 public:

  RefCounted() { }

  ~RefCounted() { }

 

既然没有把类RefCounted声明为虚析构函数,又想在基类里调用派生类的析构函数,只好使用static_cast和类型转换了,这是一种比较好的模板使用方法,在WTL里就大量使用这种技术。

接着可以看到:

class WebFrameImpl : public WebFrame {

 public:

  WebFrameImpl();

  ~WebFrameImpl();

类WebFrameImpl是继承接口类WebFrame,这里是使用接口与实现分析的设计模式,这样更方便代码灵活地复用。可见设计Chrome的设计师和写代码的程序员,都是顶尖的模板高手,大部的思想与WTL库的设计是一脉相承。也难怪Chrome的浏览器使用WTL库来设计界面。

 

#001  void WebFrameImpl::LoadRequest(WebRequest* request) {

#002    SubstituteData data;

#003    InternalLoadRequest(request, data, false);

#004  }

在WebFrame里调用函数LoadRequest,实际上是调用实现类WebFrameImpl函数LoadRequest,而在这个函数又是调用InternalLoadRequest来实现的,它的代码如下:

#001  void WebFrameImpl::InternalLoadRequest(const WebRequest* request,

#002                                        const SubstituteData& data,

#003                                        bool replace) {

 

//转换请求参数。

#004    const WebRequestImpl* request_impl =

#005        static_cast<const WebRequestImpl*>(request);

#006 

 

获取请求的资源。

#007    const ResourceRequest& resource_request =

#008        request_impl->frame_load_request().resourceRequest();

#009 

#010    // Special-case JavaScript URLs.  Do not interrupt the existing load when

#011    // asked to load a javascript URL unless the script generates a result.

#012    // We can't just use FrameLoader::executeIfJavaScriptURL because it doesn't

#013    // handle redirects properly.

 

获取需要下载网页的地址。

#014    const KURL& kurl = resource_request.url();

 

处理加载javascript的连接情况。

#015    if (!data.isValid() && kurl.protocol() == "javascript") {

#016      // Don't attempt to reload javascript URLs.

#017      if (resource_request.cachePolicy() == ReloadIgnoringCacheData)

#018        return;

#019 

#020      // We can't load a javascript: URL if there is no Document!

#021      if (!frame_->document())

#022        return;

#023 

#024      // TODO(darin): Is this the best API to use here?  It works and seems good,

#025      // but will it change out from under us?

#026      DeprecatedString script =

#027         KURL::decode_string(kurl.deprecatedString().mid(sizeof("javascript:")-1));

#028      bool succ = false;

 

加载执行脚本。

#029      WebCore::String value =

#030          frame_->loader()->executeScript(script, &succ, true);

#031      if (succ && !frame_->loader()->isScheduledLocationChangePending()) {

#032        // TODO(darin): We need to figure out how to represent this in session

#033        // history.  Hint: don't re-eval script when the user or script navigates

#034        // back-n-forth (instead store the script result somewhere).

#035        LoadDocumentData(kurl, value, String("text/html"), String());

#036      }

#037      return;

#038    }

#039 

 

停止上一次没有完成的加载情况。

#040    StopLoading();  // make sure existing activity stops

#041 

#042    // Keep track of the request temporarily.  This is effectively a way of

#043    // passing the request to callbacks that may need it.  See

#044    // WebFrameLoaderClient::createDocumentLoader.

 

保存当前的请求连接。

#045    currently_loading_request_ = request;

#046 

#047    // If we have a current datasource, save the request info on it immediately.

#048    // This is because WebCore may not actually initiate a load on the toplevel

#049    // frame for some subframe navigations, so we want to update its request.

 

获取当前数据源,如果已经存在就可以保存它。

#050    WebDataSourceImpl* datasource = GetDataSourceImpl();

#051    if (datasource)

#052      CacheCurrentRequestInfo(datasource);

#053 

 

如果数据有效就可以直接替换就行了。

#054    if (data.isValid()) {

#055      frame_->loader()->load(resource_request, data);

#056      if (replace) {

#057        // Do this to force WebKit to treat the load as replacing the currently

#058        // loaded page.

#059        frame_->loader()->setReplacing();

#060      }

 

如果是历史网页选择,就判断是否出错的加载处理。

#061    } else if (request_impl->history_item()) {

#062      // Use the history item if we have one, otherwise fall back to standard

#063      // load.

#064      RefPtr<HistoryItem> current_item = frame_->loader()->currentHistoryItem();

#065 

#066      // If there is no current_item, which happens when we are navigating in

#067      // session history after a crash, we need to manufacture one otherwise

#068      // WebKit hoarks. This is probably the wrong thing to do, but it seems to

#069      // work.

#070      if (!current_item) {

#071        current_item = new HistoryItem(KURL("about:blank"), "");

#072        frame_->loader()->setCurrentHistoryItem(current_item);

#073        frame_->page()->backForwardList()->setCurrentItem(current_item.get());

#074 

#075        // Mark the item as fake, so that we don't attempt to save its state and

#076        // end up with about:blank in the navigation history.

#077        frame_->page()->backForwardList()->setCurrentItemFake(true);

#078      }

#079 

#080      frame_->loader()->goToItem(request_impl->history_item().get(),

#081                                WebCore::FrameLoadTypeIndexedBackForward);

 

重新加载网页。

#082    } else if (resource_request.cachePolicy() == ReloadIgnoringCacheData) {

#083      frame_->loader()->reload();

 

 

下面开始调用load来加载新下载的网页资源。

#084    } else {

#085      frame_->loader()->load(resource_request);

#086    }

#087 

#088    currently_loading_request_ = NULL;

#089  }

 

上面通过几种情况来分别实现了加载javascript网页的处理,还有历史选项处理,还有重新加载网页和加载新网页的处理。下一次再来分析加载新网页的函数frame_->loader()->load的实现。







上一次说到类RenderThread和类RenderView把消息处理,那么这两个类是怎么样处理消息的呢?又是怎么样处理浏览的消息呢?现在就带着这两个问题去分析它的源码,理解它处理消息的方法。类RenderThread处理消息的代码如下:

#001  void RenderThread::OnMessageReceived(const IPC::Message& msg) {

#002    // NOTE: We could subclass router_ to intercept OnControlMessageReceived, but

#003    // it seems simpler to just process any control messages that we care about

#004    // up-front and then send the rest of the messages onto router_.

#005 

 

下面判断是控制消息,如果是控制消息就在本类里处理,否则就分发到别的地方处理,主要是转到类RenderView处理。

#006    if (msg.routing_id() == MSG_ROUTING_CONTROL) {

#007      IPC_BEGIN_MESSAGE_MAP(RenderThread, msg)

#008        IPC_MESSAGE_HANDLER(ViewMsg_VisitedLink_NewTable, OnUpdateVisitedLinks)

#009        IPC_MESSAGE_HANDLER(ViewMsg_SetNextPageID, OnSetNextPageID)

#010        IPC_MESSAGE_HANDLER(ViewMsg_New, OnCreateNewView)

#011        IPC_MESSAGE_HANDLER(ViewMsg_SetCacheCapacities, OnSetCacheCapacities)

#012        IPC_MESSAGE_HANDLER(ViewMsg_GetCacheResourceStats,

#013                           OnGetCacheResourceStats)

#014        // send the rest to the router

#015        IPC_MESSAGE_UNHANDLED(router_.OnMessageReceived(msg))

#016      IPC_END_MESSAGE_MAP()

#017    } else {

 

这里是分发消息到别的地方处理。

#018      router_.OnMessageReceived(msg);

#019    }

#020  }

 

在浏览器里,消息分为两大类:控制消息和路由消息。像使用IPC_MESSAGE_CONTROL宏定义的消息,就是控制消息;使用IPC_MESSAGE_ROUTED宏定义的消息,就是路由消息。

路由消息分发是由类MessageRouter来负责的,主要处理的代码如下:

#001 

#002  void MessageRouter::OnMessageReceived(const IPC::Message& msg) {

#003    if (msg.routing_id() == MSG_ROUTING_CONTROL) {

#004      OnControlMessageReceived(msg);

#005    } else {

#006      RouteMessage(msg);

#007    }

#008  }

在这里又分为MSG_ROUTING_CONTROL消息和其它路由消息,再一次通过函数RouteMessage分发之后,如下:

#001  bool MessageRouter::RouteMessage(const IPC::Message& msg) {

#002    IPC::Channel::Listener* listener = routes_.Lookup(msg.routing_id());

#003    if (!listener)

#004      return false;

#005 

#006    listener->OnMessageReceived(msg);

#007    return true;

#008  }

上面这个函数里又把消息通过发送到listener里去,其实listener是根据消息的目标routing_id来选择的,那么就是说它是选择发送到不同的窗口里去,因为每个TAB一个窗口。消息经过这样的处理之后,就到达了终点地--- RenderView::OnMessageReceived函数。下一次再来分析RenderView::OnMessageReceived函数的代码和后继处理。


上一次说到消息转发,并分析了RenderThread类里处理消息的函数,其实大部份的消息都是在RenderView类里的OnMessageReceived函数处理,比如浏览的消息也是在这里处理。它的代码如下:

#001  void RenderView::OnMessageReceived(const IPC::Message& message) {

#002    // Let the resource dispatcher intercept resource messages first.

 

如果是资源消息,就直接分发去处理,以便提高效率。

#003    if (resource_dispatcher_->OnMessageReceived(message))

#004      return;

 

下面开始处理RenderView类里所有的消息。

#005    IPC_BEGIN_MESSAGE_MAP(RenderView, message)

#006      IPC_MESSAGE_HANDLER(ViewMsg_CreatingNew_ACK, OnCreatingNewAck)

#007      IPC_MESSAGE_HANDLER(ViewMsg_CaptureThumbnail, SendThumbnail)

#008      IPC_MESSAGE_HANDLER(ViewMsg_GetPrintedPagesCount, OnGetPrintedPagesCount)

#009      IPC_MESSAGE_HANDLER(ViewMsg_PrintPages, OnPrintPages)

#010      IPC_MESSAGE_HANDLER(ViewMsg_Navigate, OnNavigate)

#011      IPC_MESSAGE_HANDLER(ViewMsg_Stop, OnStop)

#012      IPC_MESSAGE_HANDLER(ViewMsg_LoadAlternateHTMLText, OnLoadAlternateHTMLText)

#013      IPC_MESSAGE_HANDLER(ViewMsg_StopFinding, OnStopFinding)

#014      IPC_MESSAGE_HANDLER(ViewMsg_Undo, OnUndo)

#015      IPC_MESSAGE_HANDLER(ViewMsg_Redo, OnRedo)

#016      IPC_MESSAGE_HANDLER(ViewMsg_Cut, OnCut)

#017      IPC_MESSAGE_HANDLER(ViewMsg_Copy, OnCopy)

#018      IPC_MESSAGE_HANDLER(ViewMsg_Paste, OnPaste)

#019      IPC_MESSAGE_HANDLER(ViewMsg_Replace, OnReplace)

#020      IPC_MESSAGE_HANDLER(ViewMsg_Delete, OnDelete)

#021      IPC_MESSAGE_HANDLER(ViewMsg_SelectAll, OnSelectAll)

#022      IPC_MESSAGE_HANDLER(ViewMsg_CopyImageAt, OnCopyImageAt)

#023      IPC_MESSAGE_HANDLER(ViewMsg_Find, OnFind)

#024      IPC_MESSAGE_HANDLER(ViewMsg_AlterTextSize, OnAlterTextSize)

#025      IPC_MESSAGE_HANDLER(ViewMsg_SetPageEncoding, OnSetPageEncoding)

#026      IPC_MESSAGE_HANDLER(ViewMsg_InspectElement, OnInspectElement)

#027      IPC_MESSAGE_HANDLER(ViewMsg_ShowJavaScriptConsole, OnShowJavaScriptConsole)

#028      IPC_MESSAGE_HANDLER(ViewMsg_DownloadImage, OnDownloadImage)

#029      IPC_MESSAGE_HANDLER(ViewMsg_ScriptEvalRequest, OnScriptEvalRequest)

#030      IPC_MESSAGE_HANDLER(ViewMsg_AddMessageToConsole, OnAddMessageToConsole)

#031      IPC_MESSAGE_HANDLER(ViewMsg_DebugAttach, OnDebugAttach)

#032      IPC_MESSAGE_HANDLER(ViewMsg_DebugDetach, OnDebugDetach)

#033      IPC_MESSAGE_HANDLER(ViewMsg_ReservePageIDRange, OnReservePageIDRange)

#034      IPC_MESSAGE_HANDLER(ViewMsg_UploadFile, OnUploadFileRequest)

#035      IPC_MESSAGE_HANDLER(ViewMsg_FormFill, OnFormFill)

#036      IPC_MESSAGE_HANDLER(ViewMsg_FillPasswordForm, OnFillPasswordForm)

#037      IPC_MESSAGE_HANDLER(ViewMsg_DragTargetDragEnter, OnDragTargetDragEnter)

#038      IPC_MESSAGE_HANDLER(ViewMsg_DragTargetDragOver, OnDragTargetDragOver)

#039      IPC_MESSAGE_HANDLER(ViewMsg_DragTargetDragLeave, OnDragTargetDragLeave)

#040      IPC_MESSAGE_HANDLER(ViewMsg_DragTargetDrop, OnDragTargetDrop)

#041      IPC_MESSAGE_HANDLER(ViewMsg_AllowDomAutomationBindings,

#042                         OnAllowDomAutomationBindings)

#043      IPC_MESSAGE_HANDLER(ViewMsg_AllowBindings, OnAllowBindings)

#044      IPC_MESSAGE_HANDLER(ViewMsg_SetDOMUIProperty, OnSetDOMUIProperty)

#045      IPC_MESSAGE_HANDLER(ViewMsg_DragSourceEndedOrMoved, OnDragSourceEndedOrMoved)

#046      IPC_MESSAGE_HANDLER(ViewMsg_DragSourceSystemDragEnded,

#047                         OnDragSourceSystemDragEnded)

#048      IPC_MESSAGE_HANDLER(ViewMsg_SetInitialFocus, OnSetInitialFocus)

#049      IPC_MESSAGE_HANDLER(ViewMsg_FindReplyACK, OnFindReplyAck)

#050      IPC_MESSAGE_HANDLER(ViewMsg_UpdateTargetURL_ACK, OnUpdateTargetURLAck)

#051      IPC_MESSAGE_HANDLER(ViewMsg_UpdateWebPreferences, OnUpdateWebPreferences)

#052      IPC_MESSAGE_HANDLER(ViewMsg_SetAltErrorPageURL, OnSetAltErrorPageURL)

#053      IPC_MESSAGE_HANDLER(ViewMsg_InstallMissingPlugin, OnInstallMissingPlugin)

#054      IPC_MESSAGE_HANDLER(ViewMsg_RunFileChooserResponse, OnFileChooserResponse)

#055      IPC_MESSAGE_HANDLER(ViewMsg_EnableViewSourceMode, OnEnableViewSourceMode)

#056      IPC_MESSAGE_HANDLER(ViewMsg_UpdateBackForwardListCount,

#057                         OnUpdateBackForwardListCount)

#058     IPC_MESSAGE_HANDLER(ViewMsg_GetAllSavableResourceLinksForCurrentPage,

#059                         OnGetAllSavableResourceLinksForCurrentPage)

#060     IPC_MESSAGE_HANDLER(ViewMsg_GetSerializedHtmlDataForCurrentPageWithLocalLinks,

#061                         OnGetSerializedHtmlDataForCurrentPageWithLocalLinks)

#062      IPC_MESSAGE_HANDLER(ViewMsg_GetApplicationInfo, OnGetApplicationInfo)

#063      IPC_MESSAGE_HANDLER(ViewMsg_ShouldClose, OnMsgShouldClose)

#064      IPC_MESSAGE_HANDLER(ViewMsg_ClosePage, OnClosePage)

#065      IPC_MESSAGE_HANDLER(ViewMsg_ThemeChanged, OnThemeChanged)

#066  #ifdef CHROME_PERSONALIZATION

#067      IPC_MESSAGE_HANDLER(ViewMsg_PersonalizationEvent, OnPersonalizationEvent)

#068  #endif

#069      IPC_MESSAGE_HANDLER(ViewMsg_HandleMessageFromExternalHost,

#070                          OnMessageFromExternalHost)

 

这里对于没有处理的消息进行提示。

#071      // Have the super handle all other messages.

#072      IPC_MESSAGE_UNHANDLED(RenderWidget::OnMessageReceived(message))

#073    IPC_END_MESSAGE_MAP()

#074  }

 

从上面这个函数可以看到,它的消息处理是非常多的,下面来分析一个浏览网络连接的消息,它就是ViewMsg_Navigate,可以看到这个消息后面响应函数是OnNavigate,也就是说,当你输入网络地址之后按回车,就会通过上说过的IPC机制把消息发送到这里,接着来看这个函数OnNavigate的代码,如下:

#001  void RenderView::OnNavigate(const ViewMsg_Navigate_Params& params) {

 

判断窗口是否关闭,如果关闭就不用去打开连接地址了。

#002    if (!webview())

#003      return;

#004 

 

处理一些about的连接处理,比如about:crash。

#005    AboutHandler::MaybeHandle(params.url);

#006 

 

保存是否重新加载网页。

#007    bool is_reload = params.reload;

#008 

 

获取WEB的显示框架。

#009    WebFrame* main_frame = webview()->GetMainFrame();

 

判断当是重新加载时,而当前又不是历史网页的情况。

#010    if (is_reload && !main_frame->HasCurrentState()) {

#011      // We cannot reload if we do not have any history state.  This happens, for

#012      // example, when recovering from a crash.  Our workaround here is a bit of

#013      // a hack since it means that reload after a crashed tab does not cause an

#014      // end-to-end cache validation.

#015      is_reload = false;

#016    }

#017 

 

下面设置缓冲策略。

#018    WebRequestCachePolicy cache_policy;

#019    if (is_reload) {

#020      cache_policy = WebRequestReloadIgnoringCacheData;

#021    } else if (params.page_id != -1 || main_frame->GetInViewSourceMode()) {

#022      cache_policy = WebRequestReturnCacheDataElseLoad;

#023    } else {

#024      cache_policy = WebRequestUseProtocolCachePolicy;

#025    }

#026 

 

下面创建一个下载请求,并把相关参数设置到请求里面。

#027    scoped_ptr<WebRequest> request(WebRequest::Create(params.url));

#028    request->SetCachePolicy(cache_policy);

#029    request->SetExtraData(new RenderViewExtraRequestData(

#030        params.page_id, params.transition, params.url));

#031 

 

设置WEBKIT的请求状态。

#032    // If we are reloading, then WebKit will use the state of the current page.

#033    // Otherwise, we give it the state to navigate to.

#034    if (!is_reload)

#035      request->SetHistoryState(params.state);

#036 

 

让主WEB显示框架去下载请求显示。

#037    main_frame->LoadRequest(request.get());

#038  }

 

分析这个函数,就可以知道处理浏览消息的过程,下一次来分析WebFrame里的接口函数LoadRequest处理过程,到底它是怎么样处理JavaScript脚本网页下载的呢?


继续上一次的分析,这里开始把连接址和其它相关的信息传送frame_->loader()->load函数里面,那么在这个函数里面到底是怎么样处理的呢,只有去分析它的代码,我们才能找到它的答案,现在就来开始看吧,如下:

#001  void FrameLoader::load(const ResourceRequest& request)

#002  {

#003      load(request, SubstituteData());

#004  }

在这个函数也只是一个中间者,它又调用函数load函数的重载函数来实现了。

#001  void FrameLoader::load(const ResourceRequest& request, const SubstituteData& substituteData)

#002  {

#003      if (m_inStopAllLoaders)

#004          return;

#005         

#006      // FIXME: is this the right place to reset loadType? Perhaps this should be done after loading is finished or aborted.

#007      m_loadType = FrameLoadTypeStandard;

#008      load(m_client->createDocumentLoader(request, substituteData).get());

#009  }

#010 

在这个函数里,第一个参数request是连接相关的信息,第二个参数substituteData是一些状态数据。然后在第7行里设置加载的类型,第8行里调用WebFrameLoaderClient::createDocumentLoader函数来创建WebDocumentLoaderImpl对象,然后再通过get函数返回来,这样就知道load函数又调用那个重载函数了,原来它是调用这个函数,如下:

#001  void FrameLoader::load(DocumentLoader* newDocumentLoader)

#002  {

#003      ResourceRequest& r = newDocumentLoader->request();

#004      addExtraFieldsToRequest(r, true, false);

#005      FrameLoadType type;

#006 

#007      if (shouldTreatURLAsSameAsCurrent(newDocumentLoader->originalRequest().url())) {

#008          r.setCachePolicy(ReloadIgnoringCacheData);

#009          type = FrameLoadTypeSame;

#010      } else

#011          type = FrameLoadTypeStandard;

#012 

#013      // Do not use original encoding override since it is not loaded by user

#014      // selecting encoding.

#015      if (m_documentLoader)

#016          newDocumentLoader->setOverrideEncoding(String());

#017     

#018      // When we loading alternate content for an unreachable URL that we're

#019      // visiting in the b/f list, we treat it as a reload so the b/f list

#020      // is appropriately maintained.

#021      if (shouldReloadToHandleUnreachableURL(newDocumentLoader)) {

#022          ASSERT(type == FrameLoadTypeStandard);

#023          type = FrameLoadTypeReload;

#024      }

#025 

#026      load(newDocumentLoader, type, 0);

#027  }

上面只对newDocumentLoader做一些准备工作,并没有真正地去加载任何东西,接着又调用函数:

void FrameLoader::load(DocumentLoader* loader, FrameLoadType type, PassRefPtr<FormState> formState)

在上面这个函数进行安全策略的处理,然后再经过N个函数处理之后,就调用下面的函数:

void FrameLoader::continueLoadAfterWillSubmitForm(PolicyAction)

在这个函数开始使用类DocumentLoader来设置下载请求,主要通过函数

bool DocumentLoader::startLoadingMainResource(unsigned long identifier)

来实现的,紧跟后面调用加载函数:

bool MainResourceLoader::load(const ResourceRequest& r, const SubstituteData&  substituteData)

在这个函数里又开始分为两种情况处理,一种是延进加载数据,一种是立即加载数据,下面主要介绍立即加载数据函数:

bool MainResourceLoader::loadNow(ResourceRequest& r)

在类MainResourceLoader是主要资源下载的管理类,loadNow函数是把资源请求ResourceRequest变成一个IPC消息又发送给资源下载进程去处理。它的简略代码如下:

#001  bool MainResourceLoader::loadNow(ResourceRequest& r)

#002  {

......

#011      willSendRequest(r, ResourceResponse());

#012 

......

 

#015      if (!frameLoader())

#016          return false;

#017     

......

#023 

#024      if (m_substituteData.isValid())

#025          handleDataLoadSoon(r);

#026      else if (shouldLoadEmpty || frameLoader()->representationExistsForURLScheme(url.protocol()))

#027          handleEmptyLoad(url, !shouldLoadEmpty);

#028      else

#029          m_handle = ResourceHandle::create(r, this, m_frame.get(), false, true, true);

#030 

#031      return false;

#032  }

在这个函数的第29行里,就会通过ResourceHandle::create函数创建一个资源消息,并把这个消息发送出去,到底它是怎么样实现的呢?下一次再来分析它。





上一次说到类RenderThread和类RenderView把消息处理,那么这两个类是怎么样处理消息的呢?又是怎么样处理浏览的消息呢?现在就带着这两个问题去分析它的源码,理解它处理消息的方法。类RenderThread处理消息的代码如下:

#001  void RenderThread::OnMessageReceived(const IPC::Message& msg) {

#002    // NOTE: We could subclass router_ to intercept OnControlMessageReceived, but

#003    // it seems simpler to just process any control messages that we care about

#004    // up-front and then send the rest of the messages onto router_.

#005 

 

下面判断是控制消息,如果是控制消息就在本类里处理,否则就分发到别的地方处理,主要是转到类RenderView处理。

#006    if (msg.routing_id() == MSG_ROUTING_CONTROL) {

#007      IPC_BEGIN_MESSAGE_MAP(RenderThread, msg)

#008        IPC_MESSAGE_HANDLER(ViewMsg_VisitedLink_NewTable, OnUpdateVisitedLinks)

#009        IPC_MESSAGE_HANDLER(ViewMsg_SetNextPageID, OnSetNextPageID)

#010        IPC_MESSAGE_HANDLER(ViewMsg_New, OnCreateNewView)

#011        IPC_MESSAGE_HANDLER(ViewMsg_SetCacheCapacities, OnSetCacheCapacities)

#012        IPC_MESSAGE_HANDLER(ViewMsg_GetCacheResourceStats,

#013                           OnGetCacheResourceStats)

#014        // send the rest to the router

#015        IPC_MESSAGE_UNHANDLED(router_.OnMessageReceived(msg))

#016      IPC_END_MESSAGE_MAP()

#017    } else {

 

这里是分发消息到别的地方处理。

#018      router_.OnMessageReceived(msg);

#019    }

#020  }

 

在浏览器里,消息分为两大类:控制消息和路由消息。像使用IPC_MESSAGE_CONTROL宏定义的消息,就是控制消息;使用IPC_MESSAGE_ROUTED宏定义的消息,就是路由消息。

路由消息分发是由类MessageRouter来负责的,主要处理的代码如下:

#001 

#002  void MessageRouter::OnMessageReceived(const IPC::Message& msg) {

#003    if (msg.routing_id() == MSG_ROUTING_CONTROL) {

#004      OnControlMessageReceived(msg);

#005    } else {

#006      RouteMessage(msg);

#007    }

#008  }

在这里又分为MSG_ROUTING_CONTROL消息和其它路由消息,再一次通过函数RouteMessage分发之后,如下:

#001  bool MessageRouter::RouteMessage(const IPC::Message& msg) {

#002    IPC::Channel::Listener* listener = routes_.Lookup(msg.routing_id());

#003    if (!listener)

#004      return false;

#005 

#006    listener->OnMessageReceived(msg);

#007    return true;

#008  }

上面这个函数里又把消息通过发送到listener里去,其实listener是根据消息的目标routing_id来选择的,那么就是说它是选择发送到不同的窗口里去,因为每个TAB一个窗口。消息经过这样的处理之后,就到达了终点地--- RenderView::OnMessageReceived函数。下一次再来分析RenderView::OnMessageReceived函数的代码和后继处理。


上一次说到消息转发,并分析了RenderThread类里处理消息的函数,其实大部份的消息都是在RenderView类里的OnMessageReceived函数处理,比如浏览的消息也是在这里处理。它的代码如下:

#001  void RenderView::OnMessageReceived(const IPC::Message& message) {

#002    // Let the resource dispatcher intercept resource messages first.

 

如果是资源消息,就直接分发去处理,以便提高效率。

#003    if (resource_dispatcher_->OnMessageReceived(message))

#004      return;

 

下面开始处理RenderView类里所有的消息。

#005    IPC_BEGIN_MESSAGE_MAP(RenderView, message)

#006      IPC_MESSAGE_HANDLER(ViewMsg_CreatingNew_ACK, OnCreatingNewAck)

#007      IPC_MESSAGE_HANDLER(ViewMsg_CaptureThumbnail, SendThumbnail)

#008      IPC_MESSAGE_HANDLER(ViewMsg_GetPrintedPagesCount, OnGetPrintedPagesCount)

#009      IPC_MESSAGE_HANDLER(ViewMsg_PrintPages, OnPrintPages)

#010      IPC_MESSAGE_HANDLER(ViewMsg_Navigate, OnNavigate)

#011      IPC_MESSAGE_HANDLER(ViewMsg_Stop, OnStop)

#012      IPC_MESSAGE_HANDLER(ViewMsg_LoadAlternateHTMLText, OnLoadAlternateHTMLText)

#013      IPC_MESSAGE_HANDLER(ViewMsg_StopFinding, OnStopFinding)

#014      IPC_MESSAGE_HANDLER(ViewMsg_Undo, OnUndo)

#015      IPC_MESSAGE_HANDLER(ViewMsg_Redo, OnRedo)

#016      IPC_MESSAGE_HANDLER(ViewMsg_Cut, OnCut)

#017      IPC_MESSAGE_HANDLER(ViewMsg_Copy, OnCopy)

#018      IPC_MESSAGE_HANDLER(ViewMsg_Paste, OnPaste)

#019      IPC_MESSAGE_HANDLER(ViewMsg_Replace, OnReplace)

#020      IPC_MESSAGE_HANDLER(ViewMsg_Delete, OnDelete)

#021      IPC_MESSAGE_HANDLER(ViewMsg_SelectAll, OnSelectAll)

#022      IPC_MESSAGE_HANDLER(ViewMsg_CopyImageAt, OnCopyImageAt)

#023      IPC_MESSAGE_HANDLER(ViewMsg_Find, OnFind)

#024      IPC_MESSAGE_HANDLER(ViewMsg_AlterTextSize, OnAlterTextSize)

#025      IPC_MESSAGE_HANDLER(ViewMsg_SetPageEncoding, OnSetPageEncoding)

#026      IPC_MESSAGE_HANDLER(ViewMsg_InspectElement, OnInspectElement)

#027      IPC_MESSAGE_HANDLER(ViewMsg_ShowJavaScriptConsole, OnShowJavaScriptConsole)

#028      IPC_MESSAGE_HANDLER(ViewMsg_DownloadImage, OnDownloadImage)

#029      IPC_MESSAGE_HANDLER(ViewMsg_ScriptEvalRequest, OnScriptEvalRequest)

#030      IPC_MESSAGE_HANDLER(ViewMsg_AddMessageToConsole, OnAddMessageToConsole)

#031      IPC_MESSAGE_HANDLER(ViewMsg_DebugAttach, OnDebugAttach)

#032      IPC_MESSAGE_HANDLER(ViewMsg_DebugDetach, OnDebugDetach)

#033      IPC_MESSAGE_HANDLER(ViewMsg_ReservePageIDRange, OnReservePageIDRange)

#034      IPC_MESSAGE_HANDLER(ViewMsg_UploadFile, OnUploadFileRequest)

#035      IPC_MESSAGE_HANDLER(ViewMsg_FormFill, OnFormFill)

#036      IPC_MESSAGE_HANDLER(ViewMsg_FillPasswordForm, OnFillPasswordForm)

#037      IPC_MESSAGE_HANDLER(ViewMsg_DragTargetDragEnter, OnDragTargetDragEnter)

#038      IPC_MESSAGE_HANDLER(ViewMsg_DragTargetDragOver, OnDragTargetDragOver)

#039      IPC_MESSAGE_HANDLER(ViewMsg_DragTargetDragLeave, OnDragTargetDragLeave)

#040      IPC_MESSAGE_HANDLER(ViewMsg_DragTargetDrop, OnDragTargetDrop)

#041      IPC_MESSAGE_HANDLER(ViewMsg_AllowDomAutomationBindings,

#042                         OnAllowDomAutomationBindings)

#043      IPC_MESSAGE_HANDLER(ViewMsg_AllowBindings, OnAllowBindings)

#044      IPC_MESSAGE_HANDLER(ViewMsg_SetDOMUIProperty, OnSetDOMUIProperty)

#045      IPC_MESSAGE_HANDLER(ViewMsg_DragSourceEndedOrMoved, OnDragSourceEndedOrMoved)

#046      IPC_MESSAGE_HANDLER(ViewMsg_DragSourceSystemDragEnded,

#047                         OnDragSourceSystemDragEnded)

#048      IPC_MESSAGE_HANDLER(ViewMsg_SetInitialFocus, OnSetInitialFocus)

#049      IPC_MESSAGE_HANDLER(ViewMsg_FindReplyACK, OnFindReplyAck)

#050      IPC_MESSAGE_HANDLER(ViewMsg_UpdateTargetURL_ACK, OnUpdateTargetURLAck)

#051      IPC_MESSAGE_HANDLER(ViewMsg_UpdateWebPreferences, OnUpdateWebPreferences)

#052      IPC_MESSAGE_HANDLER(ViewMsg_SetAltErrorPageURL, OnSetAltErrorPageURL)

#053      IPC_MESSAGE_HANDLER(ViewMsg_InstallMissingPlugin, OnInstallMissingPlugin)

#054      IPC_MESSAGE_HANDLER(ViewMsg_RunFileChooserResponse, OnFileChooserResponse)

#055      IPC_MESSAGE_HANDLER(ViewMsg_EnableViewSourceMode, OnEnableViewSourceMode)

#056      IPC_MESSAGE_HANDLER(ViewMsg_UpdateBackForwardListCount,

#057                         OnUpdateBackForwardListCount)

#058     IPC_MESSAGE_HANDLER(ViewMsg_GetAllSavableResourceLinksForCurrentPage,

#059                         OnGetAllSavableResourceLinksForCurrentPage)

#060     IPC_MESSAGE_HANDLER(ViewMsg_GetSerializedHtmlDataForCurrentPageWithLocalLinks,

#061                         OnGetSerializedHtmlDataForCurrentPageWithLocalLinks)

#062      IPC_MESSAGE_HANDLER(ViewMsg_GetApplicationInfo, OnGetApplicationInfo)

#063      IPC_MESSAGE_HANDLER(ViewMsg_ShouldClose, OnMsgShouldClose)

#064      IPC_MESSAGE_HANDLER(ViewMsg_ClosePage, OnClosePage)

#065      IPC_MESSAGE_HANDLER(ViewMsg_ThemeChanged, OnThemeChanged)

#066  #ifdef CHROME_PERSONALIZATION

#067      IPC_MESSAGE_HANDLER(ViewMsg_PersonalizationEvent, OnPersonalizationEvent)

#068  #endif

#069      IPC_MESSAGE_HANDLER(ViewMsg_HandleMessageFromExternalHost,

#070                          OnMessageFromExternalHost)

 

这里对于没有处理的消息进行提示。

#071      // Have the super handle all other messages.

#072      IPC_MESSAGE_UNHANDLED(RenderWidget::OnMessageReceived(message))

#073    IPC_END_MESSAGE_MAP()

#074  }

 

从上面这个函数可以看到,它的消息处理是非常多的,下面来分析一个浏览网络连接的消息,它就是ViewMsg_Navigate,可以看到这个消息后面响应函数是OnNavigate,也就是说,当你输入网络地址之后按回车,就会通过上说过的IPC机制把消息发送到这里,接着来看这个函数OnNavigate的代码,如下:

#001  void RenderView::OnNavigate(const ViewMsg_Navigate_Params& params) {

 

判断窗口是否关闭,如果关闭就不用去打开连接地址了。

#002    if (!webview())

#003      return;

#004 

 

处理一些about的连接处理,比如about:crash。

#005    AboutHandler::MaybeHandle(params.url);

#006 

 

保存是否重新加载网页。

#007    bool is_reload = params.reload;

#008 

 

获取WEB的显示框架。

#009    WebFrame* main_frame = webview()->GetMainFrame();

 

判断当是重新加载时,而当前又不是历史网页的情况。

#010    if (is_reload && !main_frame->HasCurrentState()) {

#011      // We cannot reload if we do not have any history state.  This happens, for

#012      // example, when recovering from a crash.  Our workaround here is a bit of

#013      // a hack since it means that reload after a crashed tab does not cause an

#014      // end-to-end cache validation.

#015      is_reload = false;

#016    }

#017 

 

下面设置缓冲策略。

#018    WebRequestCachePolicy cache_policy;

#019    if (is_reload) {

#020      cache_policy = WebRequestReloadIgnoringCacheData;

#021    } else if (params.page_id != -1 || main_frame->GetInViewSourceMode()) {

#022      cache_policy = WebRequestReturnCacheDataElseLoad;

#023    } else {

#024      cache_policy = WebRequestUseProtocolCachePolicy;

#025    }

#026 

 

下面创建一个下载请求,并把相关参数设置到请求里面。

#027    scoped_ptr<WebRequest> request(WebRequest::Create(params.url));

#028    request->SetCachePolicy(cache_policy);

#029    request->SetExtraData(new RenderViewExtraRequestData(

#030        params.page_id, params.transition, params.url));

#031 

 

设置WEBKIT的请求状态。

#032    // If we are reloading, then WebKit will use the state of the current page.

#033    // Otherwise, we give it the state to navigate to.

#034    if (!is_reload)

#035      request->SetHistoryState(params.state);

#036 

 

让主WEB显示框架去下载请求显示。

#037    main_frame->LoadRequest(request.get());

#038  }

 

分析这个函数,就可以知道处理浏览消息的过程,下一次来分析WebFrame里的接口函数LoadRequest处理过程,到底它是怎么样处理JavaScript脚本网页下载的呢?


上一次说到需要把显示的网络连接地址变成一个资源的消息发送出去,它是通过函数ResourceHandle::create来实现的,但这个函数到底是怎么样实现的呢?现在就分析它的实现代码,了解它怎么样把资源变换成消息,并且通过IPC机制把消息发送到资源下载进程去。数ResourceHandle::create的代码如下:

#001  PassRefPtr<ResourceHandle> ResourceHandle::create(const ResourceRequest& request,

#002                                                   ResourceHandleClient* client,

#003                                                   Frame* deprecated,

#004                                                   bool defersLoading,

#005                                                   bool shouldContentSniff,

#006                                                   bool mightDownloadFromHandle) {

上面的参数request是把所有请求网络连接地址信息传进来了。

 

#007    RefPtr<ResourceHandle> newHandle(

#008        new ResourceHandle(request, client, defersLoading, shouldContentSniff,

#009                          mightDownloadFromHandle));

这里创建资源类ResourceHandle对象,通过它来生成一个消息发送出去。

 

#010 

#011    if (newHandle->start(NULL))

#012      return newHandle.release();

上面的代码里,调用函数start来处理资源请求下载。

 

#013 

#014    return NULL;

#015  }

 

在这个函数里调用newHandle->start函数来处理,其实它是调用下面的函数来工作的:

bool ResourceHandle::start(Frame* deprecated) {

  return d->Start(NULL);

}

那么这里的d实例是什么呢?可以通过ResourceHandle的构造函数来看到它的类,如下:

ResourceHandle::ResourceHandle(const ResourceRequest& request,

                               ResourceHandleClient* client,

                               bool defersLoading,

                               bool shouldContentSniff,

                               bool mightDownloadFromHandle)

#pragma warning(suppress: 4355)  // it's okay to pass |this| here!

      : d(new ResourceHandleInternal(this, request, client)) {

  // TODO(darin): figure out what to do with the two bool params

}               

可以看到d是类ResourceHandleInternal的实例,这就是说调用d->Start函数,其实就是调用下面的函数:

#001  bool ResourceHandleInternal::Start(

#002      ResourceLoaderBridge::SyncLoadResponse* sync_load_response) {

#003    DCHECK(!bridge_.get());

#004 

#005    // The WebFrame is the Frame's FrameWinClient

#006    WebFrameImpl* webframe =

#007        request_.frame() ? WebFrameImpl::FromFrame(request_.frame()) : NULL;

......

#154 

#155    if (sync_load_response) {

#156      bridge_->SyncLoad(sync_load_response);

#157      return true;

#158    }

#159 

 

通过上面的处理,然后就调用桥连接成员bridge_来创建消息。

#160    bool rv = bridge_->Start(this);

#161    if (rv) {

#162      pending_ = true;

#163      job_->ref();  // to be released when we get a OnCompletedRequest.

#164    } else {

#165      bridge_.reset();

#166    }

#167 

#168    return rv;

#169  }

在这里使用一个设计模式,叫桥连接模式。函数bridge_->Start的代码如下:

// Writes a footer on the message and sends it

bool IPCResourceLoaderBridge::Start(Peer* peer) {

  if (request_id_ != -1) {

    NOTREACHED() << "Starting a request twice";

    return false;

  }

 

  RESOURCE_LOG("Starting request for " << url_);

 

 

保存当前接收的连接端点。

  peer_ = peer;

 

 

生成请求ID,以便返回数据时可以找到相应的显示进程和窗口。

  // generate the request ID, and append it to the message

  request_id_ = dispatcher_->AddPendingRequest(peer_, request_.resource_type,

                                              request_.mixed_content);

 

 

找到IPC的消息发送对象,然后创建ViewHostMsg_RequestResource消息并发送出去。

  IPC::Message::Sender* sender = dispatcher_->message_sender();

  bool ret = false;

  if (sender)

    ret = sender->Send(new ViewHostMsg_RequestResource(MSG_ROUTING_NONE,

                                                      request_id_,

                                                      request_));

  return ret;

}

 

通过上面漫长的分析,总算搞清楚了这个过程:

从界面开始输入URL地址,然后界面把URL发送到渲染进程,渲染进程再进行处理,把这个URL连接请求再次发送到资源下载进程去处理。串起来是一个极其简单的过程,但在这个浏览器里比较复杂的,因为它是多进程的浏览器,进程之间相互消息传送,就比其它浏览器复杂,并且它还有很多安全策略的使用和优化处理,导致这个处理过程是比较复杂的。

OK,资源下载请求消息已经发送出去,那么这个消息又往何处而去呢?又怎么样通过网络连接下载回来呢?欲知后事如何,请继续看下一篇!



from: 

上一次说到类RenderThread和类RenderView把消息处理,那么这两个类是怎么样处理消息的呢?又是怎么样处理浏览的消息呢?现在就带着这两个问题去分析它的源码,理解它处理消息的方法。类RenderThread处理消息的代码如下:

#001  void RenderThread::OnMessageReceived(const IPC::Message& msg) {

#002    // NOTE: We could subclass router_ to intercept OnControlMessageReceived, but

#003    // it seems simpler to just process any control messages that we care about

#004    // up-front and then send the rest of the messages onto router_.

#005 

 

下面判断是控制消息,如果是控制消息就在本类里处理,否则就分发到别的地方处理,主要是转到类RenderView处理。

#006    if (msg.routing_id() == MSG_ROUTING_CONTROL) {

#007      IPC_BEGIN_MESSAGE_MAP(RenderThread, msg)

#008        IPC_MESSAGE_HANDLER(ViewMsg_VisitedLink_NewTable, OnUpdateVisitedLinks)

#009        IPC_MESSAGE_HANDLER(ViewMsg_SetNextPageID, OnSetNextPageID)

#010        IPC_MESSAGE_HANDLER(ViewMsg_New, OnCreateNewView)

#011        IPC_MESSAGE_HANDLER(ViewMsg_SetCacheCapacities, OnSetCacheCapacities)

#012        IPC_MESSAGE_HANDLER(ViewMsg_GetCacheResourceStats,

#013                           OnGetCacheResourceStats)

#014        // send the rest to the router

#015        IPC_MESSAGE_UNHANDLED(router_.OnMessageReceived(msg))

#016      IPC_END_MESSAGE_MAP()

#017    } else {

 

这里是分发消息到别的地方处理。

#018      router_.OnMessageReceived(msg);

#019    }

#020  }

 

在浏览器里,消息分为两大类:控制消息和路由消息。像使用IPC_MESSAGE_CONTROL宏定义的消息,就是控制消息;使用IPC_MESSAGE_ROUTED宏定义的消息,就是路由消息。

路由消息分发是由类MessageRouter来负责的,主要处理的代码如下:

#001 

#002  void MessageRouter::OnMessageReceived(const IPC::Message& msg) {

#003    if (msg.routing_id() == MSG_ROUTING_CONTROL) {

#004      OnControlMessageReceived(msg);

#005    } else {

#006      RouteMessage(msg);

#007    }

#008  }

在这里又分为MSG_ROUTING_CONTROL消息和其它路由消息,再一次通过函数RouteMessage分发之后,如下:

#001  bool MessageRouter::RouteMessage(const IPC::Message& msg) {

#002    IPC::Channel::Listener* listener = routes_.Lookup(msg.routing_id());

#003    if (!listener)

#004      return false;

#005 

#006    listener->OnMessageReceived(msg);

#007    return true;

#008  }

上面这个函数里又把消息通过发送到listener里去,其实listener是根据消息的目标routing_id来选择的,那么就是说它是选择发送到不同的窗口里去,因为每个TAB一个窗口。消息经过这样的处理之后,就到达了终点地--- RenderView::OnMessageReceived函数。下一次再来分析RenderView::OnMessageReceived函数的代码和后继处理。


上一次说到消息转发,并分析了RenderThread类里处理消息的函数,其实大部份的消息都是在RenderView类里的OnMessageReceived函数处理,比如浏览的消息也是在这里处理。它的代码如下:

#001  void RenderView::OnMessageReceived(const IPC::Message& message) {

#002    // Let the resource dispatcher intercept resource messages first.

 

如果是资源消息,就直接分发去处理,以便提高效率。

#003    if (resource_dispatcher_->OnMessageReceived(message))

#004      return;

 

下面开始处理RenderView类里所有的消息。

#005    IPC_BEGIN_MESSAGE_MAP(RenderView, message)

#006      IPC_MESSAGE_HANDLER(ViewMsg_CreatingNew_ACK, OnCreatingNewAck)

#007      IPC_MESSAGE_HANDLER(ViewMsg_CaptureThumbnail, SendThumbnail)

#008      IPC_MESSAGE_HANDLER(ViewMsg_GetPrintedPagesCount, OnGetPrintedPagesCount)

#009      IPC_MESSAGE_HANDLER(ViewMsg_PrintPages, OnPrintPages)

#010      IPC_MESSAGE_HANDLER(ViewMsg_Navigate, OnNavigate)

#011      IPC_MESSAGE_HANDLER(ViewMsg_Stop, OnStop)

#012      IPC_MESSAGE_HANDLER(ViewMsg_LoadAlternateHTMLText, OnLoadAlternateHTMLText)

#013      IPC_MESSAGE_HANDLER(ViewMsg_StopFinding, OnStopFinding)

#014      IPC_MESSAGE_HANDLER(ViewMsg_Undo, OnUndo)

#015      IPC_MESSAGE_HANDLER(ViewMsg_Redo, OnRedo)

#016      IPC_MESSAGE_HANDLER(ViewMsg_Cut, OnCut)

#017      IPC_MESSAGE_HANDLER(ViewMsg_Copy, OnCopy)

#018      IPC_MESSAGE_HANDLER(ViewMsg_Paste, OnPaste)

#019      IPC_MESSAGE_HANDLER(ViewMsg_Replace, OnReplace)

#020      IPC_MESSAGE_HANDLER(ViewMsg_Delete, OnDelete)

#021      IPC_MESSAGE_HANDLER(ViewMsg_SelectAll, OnSelectAll)

#022      IPC_MESSAGE_HANDLER(ViewMsg_CopyImageAt, OnCopyImageAt)

#023      IPC_MESSAGE_HANDLER(ViewMsg_Find, OnFind)

#024      IPC_MESSAGE_HANDLER(ViewMsg_AlterTextSize, OnAlterTextSize)

#025      IPC_MESSAGE_HANDLER(ViewMsg_SetPageEncoding, OnSetPageEncoding)

#026      IPC_MESSAGE_HANDLER(ViewMsg_InspectElement, OnInspectElement)

#027      IPC_MESSAGE_HANDLER(ViewMsg_ShowJavaScriptConsole, OnShowJavaScriptConsole)

#028      IPC_MESSAGE_HANDLER(ViewMsg_DownloadImage, OnDownloadImage)

#029      IPC_MESSAGE_HANDLER(ViewMsg_ScriptEvalRequest, OnScriptEvalRequest)

#030      IPC_MESSAGE_HANDLER(ViewMsg_AddMessageToConsole, OnAddMessageToConsole)

#031      IPC_MESSAGE_HANDLER(ViewMsg_DebugAttach, OnDebugAttach)

#032      IPC_MESSAGE_HANDLER(ViewMsg_DebugDetach, OnDebugDetach)

#033      IPC_MESSAGE_HANDLER(ViewMsg_ReservePageIDRange, OnReservePageIDRange)

#034      IPC_MESSAGE_HANDLER(ViewMsg_UploadFile, OnUploadFileRequest)

#035      IPC_MESSAGE_HANDLER(ViewMsg_FormFill, OnFormFill)

#036      IPC_MESSAGE_HANDLER(ViewMsg_FillPasswordForm, OnFillPasswordForm)

#037      IPC_MESSAGE_HANDLER(ViewMsg_DragTargetDragEnter, OnDragTargetDragEnter)

#038      IPC_MESSAGE_HANDLER(ViewMsg_DragTargetDragOver, OnDragTargetDragOver)

#039      IPC_MESSAGE_HANDLER(ViewMsg_DragTargetDragLeave, OnDragTargetDragLeave)

#040      IPC_MESSAGE_HANDLER(ViewMsg_DragTargetDrop, OnDragTargetDrop)

#041      IPC_MESSAGE_HANDLER(ViewMsg_AllowDomAutomationBindings,

#042                         OnAllowDomAutomationBindings)

#043      IPC_MESSAGE_HANDLER(ViewMsg_AllowBindings, OnAllowBindings)

#044      IPC_MESSAGE_HANDLER(ViewMsg_SetDOMUIProperty, OnSetDOMUIProperty)

#045      IPC_MESSAGE_HANDLER(ViewMsg_DragSourceEndedOrMoved, OnDragSourceEndedOrMoved)

#046      IPC_MESSAGE_HANDLER(ViewMsg_DragSourceSystemDragEnded,

#047                         OnDragSourceSystemDragEnded)

#048      IPC_MESSAGE_HANDLER(ViewMsg_SetInitialFocus, OnSetInitialFocus)

#049      IPC_MESSAGE_HANDLER(ViewMsg_FindReplyACK, OnFindReplyAck)

#050      IPC_MESSAGE_HANDLER(ViewMsg_UpdateTargetURL_ACK, OnUpdateTargetURLAck)

#051      IPC_MESSAGE_HANDLER(ViewMsg_UpdateWebPreferences, OnUpdateWebPreferences)

#052      IPC_MESSAGE_HANDLER(ViewMsg_SetAltErrorPageURL, OnSetAltErrorPageURL)

#053      IPC_MESSAGE_HANDLER(ViewMsg_InstallMissingPlugin, OnInstallMissingPlugin)

#054      IPC_MESSAGE_HANDLER(ViewMsg_RunFileChooserResponse, OnFileChooserResponse)

#055      IPC_MESSAGE_HANDLER(ViewMsg_EnableViewSourceMode, OnEnableViewSourceMode)

#056      IPC_MESSAGE_HANDLER(ViewMsg_UpdateBackForwardListCount,

#057                         OnUpdateBackForwardListCount)

#058     IPC_MESSAGE_HANDLER(ViewMsg_GetAllSavableResourceLinksForCurrentPage,

#059                         OnGetAllSavableResourceLinksForCurrentPage)

#060     IPC_MESSAGE_HANDLER(ViewMsg_GetSerializedHtmlDataForCurrentPageWithLocalLinks,

#061                         OnGetSerializedHtmlDataForCurrentPageWithLocalLinks)

#062      IPC_MESSAGE_HANDLER(ViewMsg_GetApplicationInfo, OnGetApplicationInfo)

#063      IPC_MESSAGE_HANDLER(ViewMsg_ShouldClose, OnMsgShouldClose)

#064      IPC_MESSAGE_HANDLER(ViewMsg_ClosePage, OnClosePage)

#065      IPC_MESSAGE_HANDLER(ViewMsg_ThemeChanged, OnThemeChanged)

#066  #ifdef CHROME_PERSONALIZATION

#067      IPC_MESSAGE_HANDLER(ViewMsg_PersonalizationEvent, OnPersonalizationEvent)

#068  #endif

#069      IPC_MESSAGE_HANDLER(ViewMsg_HandleMessageFromExternalHost,

#070                          OnMessageFromExternalHost)

 

这里对于没有处理的消息进行提示。

#071      // Have the super handle all other messages.

#072      IPC_MESSAGE_UNHANDLED(RenderWidget::OnMessageReceived(message))

#073    IPC_END_MESSAGE_MAP()

#074  }

 

从上面这个函数可以看到,它的消息处理是非常多的,下面来分析一个浏览网络连接的消息,它就是ViewMsg_Navigate,可以看到这个消息后面响应函数是OnNavigate,也就是说,当你输入网络地址之后按回车,就会通过上说过的IPC机制把消息发送到这里,接着来看这个函数OnNavigate的代码,如下:

#001  void RenderView::OnNavigate(const ViewMsg_Navigate_Params& params) {

 

判断窗口是否关闭,如果关闭就不用去打开连接地址了。

#002    if (!webview())

#003      return;

#004 

 

处理一些about的连接处理,比如about:crash。

#005    AboutHandler::MaybeHandle(params.url);

#006 

 

保存是否重新加载网页。

#007    bool is_reload = params.reload;

#008 

 

获取WEB的显示框架。

#009    WebFrame* main_frame = webview()->GetMainFrame();

 

判断当是重新加载时,而当前又不是历史网页的情况。

#010    if (is_reload && !main_frame->HasCurrentState()) {

#011      // We cannot reload if we do not have any history state.  This happens, for

#012      // example, when recovering from a crash.  Our workaround here is a bit of

#013      // a hack since it means that reload after a crashed tab does not cause an

#014      // end-to-end cache validation.

#015      is_reload = false;

#016    }

#017 

 

下面设置缓冲策略。

#018    WebRequestCachePolicy cache_policy;

#019    if (is_reload) {

#020      cache_policy = WebRequestReloadIgnoringCacheData;

#021    } else if (params.page_id != -1 || main_frame->GetInViewSourceMode()) {

#022      cache_policy = WebRequestReturnCacheDataElseLoad;

#023    } else {

#024      cache_policy = WebRequestUseProtocolCachePolicy;

#025    }

#026 

 

下面创建一个下载请求,并把相关参数设置到请求里面。

#027    scoped_ptr<WebRequest> request(WebRequest::Create(params.url));

#028    request->SetCachePolicy(cache_policy);

#029    request->SetExtraData(new RenderViewExtraRequestData(

#030        params.page_id, params.transition, params.url));

#031 

 

设置WEBKIT的请求状态。

#032    // If we are reloading, then WebKit will use the state of the current page.

#033    // Otherwise, we give it the state to navigate to.

#034    if (!is_reload)

#035      request->SetHistoryState(params.state);

#036 

 

让主WEB显示框架去下载请求显示。

#037    main_frame->LoadRequest(request.get());

#038  }

 

分析这个函数,就可以知道处理浏览消息的过程,下一次来分析WebFrame里的接口函数LoadRequest处理过程,到底它是怎么样处理JavaScript脚本网页下载的呢?


http://blog.csdn.net/caimouse/article/details/3071368

上一次说到类RenderThread和类RenderView把消息处理,那么这两个类是怎么样处理消息的呢?又是怎么样处理浏览的消息呢?现在就带着这两个问题去分析它的源码,理解它处理消息的方法。类RenderThread处理消息的代码如下:

#001  void RenderThread::OnMessageReceived(const IPC::Message& msg) {

#002    // NOTE: We could subclass router_ to intercept OnControlMessageReceived, but

#003    // it seems simpler to just process any control messages that we care about

#004    // up-front and then send the rest of the messages onto router_.

#005 

 

下面判断是控制消息,如果是控制消息就在本类里处理,否则就分发到别的地方处理,主要是转到类RenderView处理。

#006    if (msg.routing_id() == MSG_ROUTING_CONTROL) {

#007      IPC_BEGIN_MESSAGE_MAP(RenderThread, msg)

#008        IPC_MESSAGE_HANDLER(ViewMsg_VisitedLink_NewTable, OnUpdateVisitedLinks)

#009        IPC_MESSAGE_HANDLER(ViewMsg_SetNextPageID, OnSetNextPageID)

#010        IPC_MESSAGE_HANDLER(ViewMsg_New, OnCreateNewView)

#011        IPC_MESSAGE_HANDLER(ViewMsg_SetCacheCapacities, OnSetCacheCapacities)

#012        IPC_MESSAGE_HANDLER(ViewMsg_GetCacheResourceStats,

#013                           OnGetCacheResourceStats)

#014        // send the rest to the router

#015        IPC_MESSAGE_UNHANDLED(router_.OnMessageReceived(msg))

#016      IPC_END_MESSAGE_MAP()

#017    } else {

 

这里是分发消息到别的地方处理。

#018      router_.OnMessageReceived(msg);

#019    }

#020  }

 

在浏览器里,消息分为两大类:控制消息和路由消息。像使用IPC_MESSAGE_CONTROL宏定义的消息,就是控制消息;使用IPC_MESSAGE_ROUTED宏定义的消息,就是路由消息。

路由消息分发是由类MessageRouter来负责的,主要处理的代码如下:

#001 

#002  void MessageRouter::OnMessageReceived(const IPC::Message& msg) {

#003    if (msg.routing_id() == MSG_ROUTING_CONTROL) {

#004      OnControlMessageReceived(msg);

#005    } else {

#006      RouteMessage(msg);

#007    }

#008  }

在这里又分为MSG_ROUTING_CONTROL消息和其它路由消息,再一次通过函数RouteMessage分发之后,如下:

#001  bool MessageRouter::RouteMessage(const IPC::Message& msg) {

#002    IPC::Channel::Listener* listener = routes_.Lookup(msg.routing_id());

#003    if (!listener)

#004      return false;

#005 

#006    listener->OnMessageReceived(msg);

#007    return true;

#008  }

上面这个函数里又把消息通过发送到listener里去,其实listener是根据消息的目标routing_id来选择的,那么就是说它是选择发送到不同的窗口里去,因为每个TAB一个窗口。消息经过这样的处理之后,就到达了终点地--- RenderView::OnMessageReceived函数。下一次再来分析RenderView::OnMessageReceived函数的代码和后继处理。

上一次说到消息转发,并分析了RenderThread类里处理消息的函数,其实大部份的消息都是在RenderView类里的OnMessageReceived函数处理,比如浏览的消息也是在这里处理。它的代码如下:

#001  void RenderView::OnMessageReceived(const IPC::Message& message) {

#002    // Let the resource dispatcher intercept resource messages first.

 

如果是资源消息,就直接分发去处理,以便提高效率。

#003    if (resource_dispatcher_->OnMessageReceived(message))

#004      return;

 

下面开始处理RenderView类里所有的消息。

#005    IPC_BEGIN_MESSAGE_MAP(RenderView, message)

#006      IPC_MESSAGE_HANDLER(ViewMsg_CreatingNew_ACK, OnCreatingNewAck)

#007      IPC_MESSAGE_HANDLER(ViewMsg_CaptureThumbnail, SendThumbnail)

#008      IPC_MESSAGE_HANDLER(ViewMsg_GetPrintedPagesCount, OnGetPrintedPagesCount)

#009      IPC_MESSAGE_HANDLER(ViewMsg_PrintPages, OnPrintPages)

#010      IPC_MESSAGE_HANDLER(ViewMsg_Navigate, OnNavigate)

#011      IPC_MESSAGE_HANDLER(ViewMsg_Stop, OnStop)

#012      IPC_MESSAGE_HANDLER(ViewMsg_LoadAlternateHTMLText, OnLoadAlternateHTMLText)

#013      IPC_MESSAGE_HANDLER(ViewMsg_StopFinding, OnStopFinding)

#014      IPC_MESSAGE_HANDLER(ViewMsg_Undo, OnUndo)

#015      IPC_MESSAGE_HANDLER(ViewMsg_Redo, OnRedo)

#016      IPC_MESSAGE_HANDLER(ViewMsg_Cut, OnCut)

#017      IPC_MESSAGE_HANDLER(ViewMsg_Copy, OnCopy)

#018      IPC_MESSAGE_HANDLER(ViewMsg_Paste, OnPaste)

#019      IPC_MESSAGE_HANDLER(ViewMsg_Replace, OnReplace)

#020      IPC_MESSAGE_HANDLER(ViewMsg_Delete, OnDelete)

#021      IPC_MESSAGE_HANDLER(ViewMsg_SelectAll, OnSelectAll)

#022      IPC_MESSAGE_HANDLER(ViewMsg_CopyImageAt, OnCopyImageAt)

#023      IPC_MESSAGE_HANDLER(ViewMsg_Find, OnFind)

#024      IPC_MESSAGE_HANDLER(ViewMsg_AlterTextSize, OnAlterTextSize)

#025      IPC_MESSAGE_HANDLER(ViewMsg_SetPageEncoding, OnSetPageEncoding)

#026      IPC_MESSAGE_HANDLER(ViewMsg_InspectElement, OnInspectElement)

#027      IPC_MESSAGE_HANDLER(ViewMsg_ShowJavaScriptConsole, OnShowJavaScriptConsole)

#028      IPC_MESSAGE_HANDLER(ViewMsg_DownloadImage, OnDownloadImage)

#029      IPC_MESSAGE_HANDLER(ViewMsg_ScriptEvalRequest, OnScriptEvalRequest)

#030      IPC_MESSAGE_HANDLER(ViewMsg_AddMessageToConsole, OnAddMessageToConsole)

#031      IPC_MESSAGE_HANDLER(ViewMsg_DebugAttach, OnDebugAttach)

#032      IPC_MESSAGE_HANDLER(ViewMsg_DebugDetach, OnDebugDetach)

#033      IPC_MESSAGE_HANDLER(ViewMsg_ReservePageIDRange, OnReservePageIDRange)

#034      IPC_MESSAGE_HANDLER(ViewMsg_UploadFile, OnUploadFileRequest)

#035      IPC_MESSAGE_HANDLER(ViewMsg_FormFill, OnFormFill)

#036      IPC_MESSAGE_HANDLER(ViewMsg_FillPasswordForm, OnFillPasswordForm)

#037      IPC_MESSAGE_HANDLER(ViewMsg_DragTargetDragEnter, OnDragTargetDragEnter)

#038      IPC_MESSAGE_HANDLER(ViewMsg_DragTargetDragOver, OnDragTargetDragOver)

#039      IPC_MESSAGE_HANDLER(ViewMsg_DragTargetDragLeave, OnDragTargetDragLeave)

#040      IPC_MESSAGE_HANDLER(ViewMsg_DragTargetDrop, OnDragTargetDrop)

#041      IPC_MESSAGE_HANDLER(ViewMsg_AllowDomAutomationBindings,

#042                         OnAllowDomAutomationBindings)

#043      IPC_MESSAGE_HANDLER(ViewMsg_AllowBindings, OnAllowBindings)

#044      IPC_MESSAGE_HANDLER(ViewMsg_SetDOMUIProperty, OnSetDOMUIProperty)

#045      IPC_MESSAGE_HANDLER(ViewMsg_DragSourceEndedOrMoved, OnDragSourceEndedOrMoved)

#046      IPC_MESSAGE_HANDLER(ViewMsg_DragSourceSystemDragEnded,

#047                         OnDragSourceSystemDragEnded)

#048      IPC_MESSAGE_HANDLER(ViewMsg_SetInitialFocus, OnSetInitialFocus)

#049      IPC_MESSAGE_HANDLER(ViewMsg_FindReplyACK, OnFindReplyAck)

#050      IPC_MESSAGE_HANDLER(ViewMsg_UpdateTargetURL_ACK, OnUpdateTargetURLAck)

#051      IPC_MESSAGE_HANDLER(ViewMsg_UpdateWebPreferences, OnUpdateWebPreferences)

#052      IPC_MESSAGE_HANDLER(ViewMsg_SetAltErrorPageURL, OnSetAltErrorPageURL)

#053      IPC_MESSAGE_HANDLER(ViewMsg_InstallMissingPlugin, OnInstallMissingPlugin)

#054      IPC_MESSAGE_HANDLER(ViewMsg_RunFileChooserResponse, OnFileChooserResponse)

#055      IPC_MESSAGE_HANDLER(ViewMsg_EnableViewSourceMode, OnEnableViewSourceMode)

#056      IPC_MESSAGE_HANDLER(ViewMsg_UpdateBackForwardListCount,

#057                         OnUpdateBackForwardListCount)

#058     IPC_MESSAGE_HANDLER(ViewMsg_GetAllSavableResourceLinksForCurrentPage,

#059                         OnGetAllSavableResourceLinksForCurrentPage)

#060     IPC_MESSAGE_HANDLER(ViewMsg_GetSerializedHtmlDataForCurrentPageWithLocalLinks,

#061                         OnGetSerializedHtmlDataForCurrentPageWithLocalLinks)

#062      IPC_MESSAGE_HANDLER(ViewMsg_GetApplicationInfo, OnGetApplicationInfo)

#063      IPC_MESSAGE_HANDLER(ViewMsg_ShouldClose, OnMsgShouldClose)

#064      IPC_MESSAGE_HANDLER(ViewMsg_ClosePage, OnClosePage)

#065      IPC_MESSAGE_HANDLER(ViewMsg_ThemeChanged, OnThemeChanged)

#066  #ifdef CHROME_PERSONALIZATION

#067      IPC_MESSAGE_HANDLER(ViewMsg_PersonalizationEvent, OnPersonalizationEvent)

#068  #endif

#069      IPC_MESSAGE_HANDLER(ViewMsg_HandleMessageFromExternalHost,

#070                          OnMessageFromExternalHost)

 

这里对于没有处理的消息进行提示。

#071      // Have the super handle all other messages.

#072      IPC_MESSAGE_UNHANDLED(RenderWidget::OnMessageReceived(message))

#073    IPC_END_MESSAGE_MAP()

#074  }

 

从上面这个函数可以看到,它的消息处理是非常多的,下面来分析一个浏览网络连接的消息,它就是ViewMsg_Navigate,可以看到这个消息后面响应函数是OnNavigate,也就是说,当你输入网络地址之后按回车,就会通过上说过的IPC机制把消息发送到这里,接着来看这个函数OnNavigate的代码,如下:

#001  void RenderView::OnNavigate(const ViewMsg_Navigate_Params& params) {

 

判断窗口是否关闭,如果关闭就不用去打开连接地址了。

#002    if (!webview())

#003      return;

#004 

 

处理一些about的连接处理,比如about:crash

#005    AboutHandler::MaybeHandle(params.url);

#006 

 

保存是否重新加载网页。

#007    bool is_reload = params.reload;

#008 

 

获取WEB的显示框架。

#009    WebFrame* main_frame = webview()->GetMainFrame();

 

判断当是重新加载时,而当前又不是历史网页的情况。

#010    if (is_reload && !main_frame->HasCurrentState()) {

#011      // We cannot reload if we do not have any history state.  This happens, for

#012      // example, when recovering from a crash.  Our workaround here is a bit of

#013      // a hack since it means that reload after a crashed tab does not cause an

#014      // end-to-end cache validation.

#015      is_reload = false;

#016    }

#017 

 

下面设置缓冲策略。

#018    WebRequestCachePolicy cache_policy;

#019    if (is_reload) {

#020      cache_policy = WebRequestReloadIgnoringCacheData;

#021    } else if (params.page_id != -1 || main_frame->GetInViewSourceMode()) {

#022      cache_policy = WebRequestReturnCacheDataElseLoad;

#023    } else {

#024      cache_policy = WebRequestUseProtocolCachePolicy;

#025    }

#026 

 

下面创建一个下载请求,并把相关参数设置到请求里面。

#027    scoped_ptr<WebRequest> request(WebRequest::Create(params.url));

#028    request->SetCachePolicy(cache_policy);

#029    request->SetExtraData(new RenderViewExtraRequestData(

#030        params.page_id, params.transition, params.url));

#031 

 

设置WEBKIT的请求状态。

#032    // If we are reloading, then WebKit will use the state of the current page.

#033    // Otherwise, we give it the state to navigate to.

#034    if (!is_reload)

#035      request->SetHistoryState(params.state);

#036 

 

让主WEB显示框架去下载请求显示。

#037    main_frame->LoadRequest(request.get());

#038  }

 

分析这个函数,就可以知道处理浏览消息的过程,下一次来分析WebFrame里的接口函数LoadRequest处理过程,到底它是怎么样处理JavaScript脚本网页下载的呢?

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/神奇cpp/article/detail/882185
推荐阅读
  

闽ICP备14008679号