谷歌chrome浏览器的源码分析(五)
上一次說到類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腳本網頁下載的呢?
總結
以上是生活随笔為你收集整理的谷歌chrome浏览器的源码分析(五)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 谷歌chrome浏览器的源码分析(四)
- 下一篇: 谷歌chrome浏览器的源码分析(六)