MasterofProject

Analysis of URL web page Chromium loading process

label AndroidChromiumURLdownload
3722 people read comment(5) Collection report
Classification:

Chromium in the Browser process for the web page to create a Tree Frame, the web page will be sent to the Render process to load URL. After receiving the Render process URL process to load the request, will do some of the necessary initialization work, and then request the Browser process to download the contents of the page. Browser process while downloading the content of the page, while the web content through shared memory will be passed to the Render process analysis, which is to create a Tree DOM. In this paper, we will analyze the loading process of web page URL.

Luo weibo:Http://weibo.com/shengyangluoWelcome attention!

Render process is to request the Browser process to download the contents of the web page, because the Render process does not have network access. For security reasons, Render will start the Chromium process in a restricted environment, so that the Render process does not have network access. So why not Browser process to download the active web content and then to the process of Render analysis?

This is because the Render process is through the WebKit to load the page WebKit, URL does not care about whether the process of its own network access rights, it through a specific interface to access the network. This particular interface is implemented by the WebKit user, which is the Content module in the Render process. Content module in the implementation of this interface, the IPC request through the Browser process to download the contents of the network. This design method makes the WebKit can be used flexibly. It can be used in the process of network access, and can not be used in the process of network access, and the use of the method is unified.

From the frontAnalysis of the process of creating Frame Tree ChromiumOne article can be known, Browser process to load the page to create a Tree Frame, the Render process will be sent to a type of IPC message FrameMsg_Navigate. After the Render process receives the IPC message, the processing flow is shown in figure 1:


Figure 1 web URL loading process

Render process after the implementation of some of the initial work on the Browser process to send a type of IPC message to the ResourceHostMsg_RequestResource. After receiving the Browser message, the IPC process will request the Web server to return the content of the web page to the HTTP server. Request to get the response, the Browser process will create a shared memory, and through a type of IPC ResourceMsg_SetDataBuffer message to the shared memory passed to the Render process.

After downloading to the new page content, the Browser process will be written to them to create the shared memory in front of the go, and send a Render process to send a type of IPC message to ResourceMsg_DataReceived. After the Render process receives the IPC message, it will read out the contents of the Browser process from shared memory, and to resolve, that is, to create a Tree DOM. This process continues until the web content downloads are completed.

Next, we begin to analyze the loading process of the web page URL from the IPC message of the Render process receiving type FrameMsg_Navigate. The Render process is a FrameMsg_Navigate message that is received by the member function OnMessageReceived class of the RenderFrameImpl class, as shown in the IPC message:

RenderFrameImpl: bool: OnMessageReceived (IPC: const: MSG Message&) {
......

Handled bool = true;
IPC_BEGIN_MESSAGE_MAP (RenderFrameImpl, MSG)
IPC_MESSAGE_HANDLER (FrameMsg_Navigate, OnNavigate)
......
IPC_END_MESSAGE_MAP ()

Handled return;
}
This function is defined in the file external/chromium_org/content/renderer/render_frame_impl.cc.

The member function RenderFrameImpl of the OnMessageReceived class will send the FrameMsg_Navigate message type IPC to another member function OnNavigate processing, the latter implementation is as follows:

RenderFrameImpl: void: OnNavigate (FrameMsg_Navigate_Params& params const) {
......

Is_reload bool = RenderViewImpl:: IsReload (params);
......

Frame WebFrame* = frame_;
......

If (is_reload) {
......
} if else (params.page_state.IsValid ()) {
......
} if params.base_url_for_data_url.is_empty (! Else ()) {
......
{else} {
To the given URL. / / Navigate
Request WebURLRequest (params.url);
......

Frame->loadRequest (request);

......
}

......
}
This function is defined in the file external/chromium_org/content/renderer/render_frame_impl.cc.

From the frontAnalysis of the process of creating Frame Tree ChromiumOne article can be known, RenderFrameImpl class member variable frame_ is pointing to a WebLocalFrameImpl object. Member function OnNavigate if currently being processed by RenderFrameImpl no loading a URL and the current to load the URL is not empty, the kind of RenderFrameImpl pointing to the invocation of a member variable frame WebLocalFrameImpl object member function loadRequest loading the specified URL.

The implementation of the member function loadRequest of the WebLocalFrameImpl class is shown below:

WebLocalFrameImpl: void: loadRequest (WebURLRequest& request const)
{
......
ResourceRequest& resourceRequest const = request.toResourceRequest ();

If (resourceRequest.url ().ProtocolIs ("JavaScript") {
LoadJavaScriptURL (resourceRequest.url ());
Return;
}

Frame () ->loader ().Load (FrameLoadRequest (0, resourceRequest));
}
This function is defined in the file external/chromium_org/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp.

If the parameter URL describes the request specified protocol is "JavaScript", then said to be loaded is a section of JavaScript. At this time WebLocalFrameImpl class member function loadRequest will call another member function loadJavaScriptURL load this section JavaScript.

Member function loadRequest in the other cases, the WebLocalFrameImpl first call a member function frame get member variable m frame description of a LocalFrame object, then member function loader calls the LocalFrame object for the member variable m loader described a FrameLoader object. With this FrameLoader object, call its member function load to load the parameter request description of the URL.

WebLocalFrameImpl class member variable m_frame description of the LocalFrame object and the LocalFrame class member variable m_loader description of the FrameLoader object creation process, you can refer to the previousAnalysis of the process of creating Frame Tree ChromiumOne article. Next we continue to analyze the implementation of the member function load of the FrameLoader class, as shown below:

FrameLoader: void: load (FrameLoadRequest& passedRequest const)
{
......
 
Request FrameLoadRequest (passedRequest);
......

NewLoadType FrameLoadType = determineFrameLoadType (request);
Action NavigationAction (request.resourceRequest (), newLoadType, request.formState (), request.triggeringEvent (), ();
......

LoadWithNavigationAction (action, newLoadType, request.formState (), request.substituteData (), request.clientRedirect (), (), ();
 
......
}
This function is defined in the file external/chromium_org/third_party/WebKit/Source/core/loader/FrameLoader.cpp.

FrameLoader class member function load is mainly called the other member function loadWithNavigationAction loading parameters URL description of the passedRequest.

The implementation of the member function loadWithNavigationAction of the FrameLoader class is shown below:

Void FrameLoader:: loadWithNavigationAction (const NavigationAction& action, the type FrameLoadType, PassRefPtrWillBeRawPtr<FormState> formState, const SubstituteData& substituteData, ClientRedirectPolicy clientRedirect, const AtomicString& overrideEncoding)
{
......
 
ResourceRequest& request const = action.resourceRequest ();
......

M_policyDocumentLoader = ->createDocumentLoader () client (m_frame, request, substituteData.isValid (), substituteData (): defaultSubstituteDataForURL (request.url ());
......

m_provisionaldocumentloader = m_policydocumentloader。release();
......

m_provisionaldocumentloader -> startloadingmainresource();
}
这个函数定义在文件外部/ chromium_org / third_party / WebKit /来源/核心/装载机/ frameloader CPP中。

frameloader类的成员函数loadwithnavigationaction首先调用成员函数客户端获得一个frameloaderclientimpl对象,接着再调用这个frameloaderclientimpl对象的成员函数createdocumentloader为参数行动描述的URL创建了一个webdatasourceimpl对象,并且保存在成员变量m_policydocumentloader中。关于frameloader类的成员函数客户端和frameloaderclientimpl类的成员函数createdocumentloader的实现,可以参考前面铬框架树创建过程分析一文。

frameloader类的成员函数loadwithnavigationaction接下来又将成员变量m_policydocumentloader描述的webdatasourceimpl对象转移到另外一个成员变量m_provisionaldocumentloader中,最后调用这个webdatasourceimpl对象的成员函数startloadingmainresource加载参数行动描述的URL。

webdatasourceimpl类的成员函数startloadingmainresource是从父类documentloader继承下来的,它的实现如下所示:

无效documentloader::startloadingmainresource()
{
......

fetchrequest cachedresourcerequest(请求,fetchinitiatortypenames::文件,mainresourceloadoptions);
m_mainresource = m_fetcher -> fetchmainresource(cachedresourcerequest,m_substitutedata);
......

m_mainresource -> addclient(本);

......
}
这个函数定义在文件外部/ chromium_org / third_party / WebKit /来源/核心/装载机/ documentloader CPP中。

从前面铬框架树创建过程分析一文可以知道,documentloader类的成员变量m_fetcher描述的是一个resourcefetcher对象,documentloader类的成员函数startloadingmainresource调用这个resourcefetcher对象的成员函数fetchmainresource请求加载本地变量cachedresourcerequest描述的资源这个资源描述的即为上一步指定要加载的URL。

resourcefetcher类的成员函数fetchmainresource执行结束后,会返回一个rawresource对象。这个rawresource对象保存在webdatasourceimpl类的成员变量m_mainresource中。这个rawresource对象描述的是一个异步加载的资源,documentloader类的成员startloadingmainresource调用它的成员函数addclient将当前正在处理的documentloader对象添加到它的内部去,用来获得异步加载的资源数据,也就是本地变量cachedresourcerequest描述的URL对应的网页内容。

rawresource类的成员函数addclient是从父类资源继承下来的,它的实现如下所示:

无效的资源::addclient(resourceclient *客户端)
{
如果(addclienttoset(客户端))
didaddclient(客户端);
}
这个函数定义在文件外部/ chromium_org / third_party / WebKit /来源/核心/取/ CPP中资源。

资源类的成员函数addclient调用另外一个成员函数addclienttoset将参数客户端描述的一个documentloader对象保存在内部,如下所示:

bool类型的资源::addclienttoset(resourceclient *客户端)
{
......

m_clients添加(客户端);
返回真;
}
这个函数定义在文件外部/ chromium_org / third_party / WebKit /来源/核心/取/ CPP中资源。

资源类的成员函数addclienttoset将参数客户端描述的一个documentloader保存在成员变量m_clients描述的一个散列集中,以便当前正在处理的资源对象描述的网页内容从Web服务器下载回来的时候,可以交给它处理。

接下来我们继续分析webdatasourceimpl类的成员函数startloadingmainresource调用成员变量m_fetcher描述的resourcefetcher对象的成员函数fetchmainresource加载本地变量cachedresourcerequest描述的URL的过程,如下所示:

resourceptr < rawresource > resourcefetcher::fetchmainresource(fetchrequest和请求,const substitutedata和substitutedata)
{
......
返回torawresource(requestresource(来源::主要源泉,要求));
}
这个函数定义在文件外部/ chromium_org / third_party / WebKit /来源/核心/取/ resourcefetcher CPP中。

resourcefetcher类的成员函数fetchmainresource调用另外一个成员函数requestresource加载参数描述的URL请求。resourcefetcher类的成员函数requestresource会返回一个rawresource对象给调用者,即resourcefetcher类的成员函数fetchmainresource后者又会将这个rawresource对象返回给它的调用者。

resourcefetcher类的成员函数requestresource的实现如下所示:

resourceptr <资源> resourcefetcher::requestresource(来源::类型,fetchrequest和要求)
{
......

kurl URL =请求。resourcerequest()。url();
......

const revalidationpolicy政策= determinerevalidationpolicy(类型、要求。mutableresourcerequest(),请求。forpreload(),资源。get(),请求。defer(),请求。options());
开关(策略){
......
箱载:
资源= createresourceforloading(类型、请求、要求。charset());
打破;
.....
}

......

如果(resourceneedsload(资源。get()、请求、政策)){
......
 
如果(!m_documentloader | |!m_documentloader -> schedulearchiveload(资源。get(),请求。resourcerequest()))
资源->负载(这个要求。options());
     
......
}

......

返回资源;
}
这个函数定义在文件外部/ chromium_org / third_party / WebKit /来源/核心/取/ resourcefetcher CPP中。

resourcefetcher类的成员函数requestresource首先调用成员函数createresourceforloading为参数请求描述的URL创建一个rawresource对象,如下所示:

resourceptr <资源> resourcefetcher::createresourceforloading(来源::类型,fetchrequest和请求,const string&字符集)
{
......

resourceptr <资源>资源= createresource(类型、要求。resourcerequest(),字符集);

......
返回资源;
}
这个函数定义在文件外部/ chromium_org / third_party / WebKit /来源/核心/取/ resourcefetcher CPP中。

resourcefetcher类的成员函数createresourceforloading调用函数createresource根据参数型和请求创建一个rawresource对象,如下所示:

静态资源* createresource(来源::类型,const resourcerequest和请求,const string&字符集)
{
开关(类型){
......
案例:致使资源:
案例资源:原料:
案例:texttrack资源:
案例资源:媒体:
返回新的rawresource(请求类型);
......
}

......
返回0;
}
这个函数定义在文件外部/ chromium_org / third_party / WebKit /来源/核心/取/ resourcefetcher CPP中。

从前面的调用过程可以知道,参数型的值等于资源::致使,因此函数createresource创建的是一个rawresource对象。

回到resourcefetcher类的成员函数requestresource中,它调用成员函数createresourceforloading为参数请求描述的URL创建了一个rawresource对象之后,接下来又调用成员函数resourceneedsload判断该URL是否需要进行加载。如果需要进行加载,那么resourcefetcher类的成员函数requestresource又会调用成员变量m_documentloader描述的一个documentloader对象的成员函数schedulearchiveload判断要加载的URL描述的是否是一个存档文件。如果不是,那么就会调用前面创建的rawresource对象的成员函数负荷从Web服务器下载对应的网页内容。

我们假设描述的URL请求需要进行加载,并且不是一个存档文件,因此接下来我们继续分析rawresource类的成员函数负荷的实现。rawresource类的成员函数负荷是从父类资源继承下来的,它的实现如下所示:

无效的资源::负载(resourcefetcher *提取,const resourceloaderoptions选项)
{
......

resourcerequest请求(m_resourcerequest);
......

m_loader = ResourceLoader::创造(获取,这要求,选择);
m_loader -> start();
}
这个函数定义在文件外部/ chromium_org / third_party / WebKit /来源/核心/取/ CPP中资源。

资源类的成员变量m_resourcerequest描述的是要加载的URL资源类的成员函数负荷首先调用ResourceLoader类的静态成员函数创建为其创建一个ResourceLoader对象,如下所示:

passrefptr ResourceLoader > < ResourceLoader::创造(resourceloaderhost *主机资源资源,建设resourcerequest和请求,const resourceloaderoptions选项)
{
refptr < ResourceLoader >装载机(adoptref(新的ResourceLoader(主机资源,选择)));
装载机-> init(请求);
release()返回装载机;
}
这个函数定义在文件外部/ chromium_org / third_party / WebKit /来源/核心/取/ CPP中ResourceLoader。

从这里可以看到ResourceLoader类的静态成员函数,创造创建的是一个ResourceLoader对象。这个ResourceLoader对象经过初始化之后,会返回给调用者。

回到资源类的成员函数负荷中,它为要加载的URL创建了一个ResourceLoader对象之后,会调用这个ResourceLoader对象的成员函数开始开始加载要加载的URL,如下所示:

无效:start() ResourceLoader:
{
......

m_loader = adoptptr(眨眼::::平台current() -> createurlloader());
......
眨眼::wrappedresourcerequest wrappedrequest(m_request);
m_loader -> loadasynchronously(wrappedrequest,这个);
}
这个函数定义在文件外部/ chromium_org / third_party / WebKit /来源/核心/取/ CPP中ResourceLoader。

类的成员函数ResourceLoader开始首先调用由铬的内容模块实现的一个眨眼::平台接口的成员函数createurlloader创建一个weburlloaderimpl对象,接着再调用这个weburlloaderimpl对象的成员函数loadasynchronously对象成员变量m_request描述的URL进行异步加载。

铬含量模块的的blinkplatformimpl类实现了眨眼::平台接口,它的成员函数createurlloader的实现如下所示:

weburlloader * blinkplatformimpl::createurlloader() {
返回新的weburlloaderimpl;
}
这个函数定义在文件外部/ chromium_org /内容/孩子/ blink_platform_impl CC中。

从这里可以看到,blinkplatformimpl类的成员函数createurlloader创建的是一个weburlloaderimpl对象这个weburlloaderimpl对象会返回给调用者。

接下来我们继续分析weburlloaderimpl类的成员函数loadasynchronously异步加载一个URL的过程,如下所示:

无效weburlloaderimpl::loadasynchronously(const weburlrequest和要求,
weburlloaderclient *客户端){
......

context_ -> set_client(客户端);
context_ ->启动(请求,null);
}
这个函数定义在文件外部/ chromium_org /内容/孩子/ web_url_loader_impl CC中。

从前面的调用过程可以知道,参数客户端描述的是一个ResourceLoader对象。这个ResourceLoader对象会保存在weburlloaderimpl类的成员变量content_描述的一个weburlloaderimpl::语境对象的内部。这是通过调用weburlloaderimpl::语境类的成员函数set_client实现的,如下所示:

类weburlloaderimpl::背景:公共基础::引用计数<背景>,
公共requestpeer {
公众:
......

无效set_client(weburlloaderclient *客户端){ client_ =客户;}

私人的:
......

weburlloaderclient * client_;
  
......
};
这个函数定义在文件外部/ chromium_org /内容/孩子/ web_url_loader_impl CC中。

weburlloaderimpl::语境类的成员函数set_client将参数客户端描述的ResourceLoader对象保存在成员变量client_中。

回到weburlloaderimpl类的成员函数loadasynchronously中,它接下来会继续调用成员变量content_描述的一个weburlloaderimpl::语境对象的成员函数开始描述的加载参数请求的URL,如下所示:

无效weburlloaderimpl::背景::开始(const weburlrequest和要求,
syncloadresponse * sync_load_response){
......

女孩url() URL =请求;
......

request_info请求的统计信息;
......
request_info.url =网址;
......
bridge_。复位(childthread::current() -> resource_dispatcher() -> createbridge(
request_info));

......

如果(bridge_ ->开始(这)){
addref();/ /平衡oncompletedrequest
{ }
bridge_。reset();
}
}
这个函数定义在文件外部/ chromium_org /内容/孩子/ web_url_loader_impl CC中。

weburlloaderimpl::语境类的成员函数开始首先调用当前渲染进程的一个childthread单例的成员函数resource_dispatcher获得一个resourcedispatcher对象,如下所示:

类content_export childthread
:::公共IPC监听器,
公共IPC::发件人,
公共non_exported_base(Mojo::服务提供者){
公众:
......

resourcedispatcher * resource_dispatcher() const {
resource_dispatcher_ get()返回;
}

......

私人的:
......

这个过程的资源负载。
scoped_ptr < resourcedispatcher > resource_dispatcher_;

......
};
这个函数定义在文件外部/ chromium_org /内容/孩子/ child_thread H中。

childthread类的成员函数resource_dispatcher返回的是成员变量resource_dispatcher_描述的一个resourcedispatcher对象。

回到weburlloaderimpl::语境类的成员函数开始中,它获得了一个resourcedispatcher对象之后,接着调用这个resourcedispatcher对象的成员函数createbridge创建一个ipcresourceloaderbridge对象,如下所示:

resourceloaderbridge * resourcedispatcher::createbridge(
const请求的统计信息和request_info){
返回新的ipcresourceloaderbridge(这request_info);
}
这个函数定义在文件外部/ chromium_org /内容/孩子/ resource_dispatcher CC中。

从这里可以看到,resourcedispatcher类的成员函数createbridge创建的是一个ipcresourceloaderbridge对象,并且会将这个ipcresourceloaderbridge对象返回给调用者。

回到weburlloaderimpl::语境类的成员函数开始中,它获得了一个ipcresourceloaderbridge对象之后,接着调用这个ipcresourceloaderbridge对象的成员函数开始描述的加载参数请求的URL,如下所示:

布尔ipcresourceloaderbridge::开始(requestpeer *点){
......

生成请求标识,并将其添加到消息中
request_id_ = dispatcher_ -> addpendingrequest(同行,
request_。resource_type,
request_。origin_pid,
frame_origin_,
request_。URL,
request_ download_to_file);

返回dispatcher_ -> message_sender() ->发送(
新的resourcehostmsg_requestresource(routing_id_,request_id_,request_));
}
这个函数定义在文件外部/ chromium_org /内容/孩子/ resource_dispatcher CC中。

ipcresourceloaderbridge类的成员变量dispatcher_描述的是一个resourcedispatcher对象,ipcresourceloaderbridge类的成员函数开始首先调用这个resourcedispatcher对象的成员函数addpendingrequest将参数同行描述的一个weburlloaderimpl::语境对象保存在内部,如下所示:

国际resourcedispatcher::addpendingrequest(requestpeer *回调,
resourcetype::型resource_type,
国际origin_pid,
女孩和frame_origin const,
女孩和request_url const,
布尔download_to_file){
//计算特有的request_id这个渲染过程。
int id = makerequestid();
pending_requests_ [ ] = pendingrequestinfo(回调,
resource_type,
origin_pid,
Frame_origin,
Request_url,
Download_to_file);
ID return;
}
This function is defined in the file external/chromium_org/content/child/resource_dispatcher.cc.

Member function AddPendingRequest ResourceDispatcher first call a member function MakeRequestID generate a request ID, then the callback parameter description of a WebURLLoaderImpl:: context object encapsulation in a PendingRequestInfo object, and the request ID key, will be the PendingRequestInfo object is saved in the pending requests for the member variable description of a hash map.

Back to the start member function of class IPCResourceLoaderBridge. It then calls the member variable dispatcher description object ResourceDispatcher members function message sender to obtain a IPC:: the sender object, and through the IPC:: the sender object to the browser process sends a type for IPC messages ResourceHostMsg_RequestResource ResourceHostMsg_RequestResource, used to request browser process of downloading request for the member variable to describe the corresponding to the URL of the web page content.

In the Browser process, the type IPC ResourceHostMsg_RequestResource message is received by the member function ResourceDispatcherHostImpl of the OnMessageReceived class, as shown below:

ResourceDispatcherHostImpl: OnMessageReceived: bool (
IPC: Message&: message const,
Filter ResourceMessageFilter*) {
......
Handled bool = true;
IPC_BEGIN_MESSAGE_MAP (ResourceDispatcherHostImpl, message)
IPC_MESSAGE_HANDLER (ResourceHostMsg_RequestResource, OnRequestResource)
......
IPC_MESSAGE_UNHANDLED (false = handled)
IPC_END_MESSAGE_MAP ()

......
}
This function is defined in the file external/chromium_org/content/browser/loader/resource_dispatcher_host_impl.cc.

Member function OnMessageReceived ResourceDispatcherHostImpl type of IPC message ResourceHostMsg_RequestResource ResourceHostMsg_RequestResource distributed another member function OnRequestResource processing, the latter implementation as shown below:

ResourceDispatcherHostImpl: OnRequestResource: void (
Routing_id int,
Request_id int,
ResourceHostMsg_Request& request_data const) {
BeginRequest (request_id, request_data, NULL, routing_id);
}
This function is defined in the file external/chromium_org/content/browser/loader/resource_dispatcher_host_impl.cc.

ResourceDispatcherHostImpl class member function OnRequestResource calls the other member function BeginRequest to start downloading the parameter request_data to describe the URL corresponding to the web page content, the latter implementation as follows:

ResourceDispatcherHostImpl: BeginRequest: void (
Request_id int,
ResourceHostMsg_Request& request_data const,
IPC:: Message* sync_result, valid for sync / / only
Route_id int) {
......

The request. / / Construct
Net:: cookie_store CookieStore* =
GetContentClient () ->browser () ->OverrideCookieStoreForRenderProcess () () ()
Child_id);
Scoped_ptr<net:: new_request URLRequest>;
New_request = request_context->CreateRequest (
Request_data.url, request_data.priority, NULL, cookie_store);
......

Handler scoped_ptr<ResourceHandler> (
CreateResourceHandler (
New_request.get (),
Request_data, sync_result, route_id, process_type, child_id,
Resource_context);

If (handler)
BeginRequestInternal (new_request.Pass (), handler.Pass ());
}
This function is defined in the file external/chromium_org/content/browser/loader/resource_dispatcher_host_impl.cc.

ResourceDispatcherHostImpl class member function request_data first remove from the parameter BeginRequest to download the URL content of the page, and then the URL is packaged in a URLRequest object.

ResourceDispatcherHostImpl class member function BeginRequest next call another member function CreateResourceHandler to create a AsyncResourceHandler object. The AsyncResourceHandler object is used to asynchronously receive and process the web content downloaded from the Web server.

The implementation of the member function CreateResourceHandler of the ResourceDispatcherHostImpl class is shown below:

scoped _ < >::resourcedispatcherhostimpl resourcehandler PTR(createresourcehandler
::* urlrequest request,网
resourcehostmsg _ const & _ request请求日期
::* _ IPC消息同步的结果,
_ int ID号,
_ int型的过程,
儿童_ int ID
resourcecontext *资源_ { context)
construct the IPC /资源的程序。
scoped resourcehandler > < _ PTR程序;
{ if(sync _ result)
…………………

handler.reset(New syncresourcehandler(request,sync _ result,this);
} else {
handler.reset(New asyncresourcehandler(request,this);

redirecttofileresourcehandler / the next in the chain有depends在线。
if(request to _ _ data.download _(文件)
(handler.reset
redirecttofileresourcehandler(纽约),handler.pass request());
}
}

…………………

在crosssiteresourcehandler for /安装在主框架的要求。this will
让美国/检查是否传输是在required for the加卸载和休息
或者,如果我知道/处理过程或if is already在跨下的导航方式。
_ bool是_插拔导航=
_ request type = data.resource _ resourcetype::主_帧;
我们是使用if / - A -帧的安装过程,它将为好。
if(!_插拔导航& _ is
::forcurrentprocess(命令行)→hasswitch(开关)::{ ksiteperprocess)
_插拔导航= _ is
_ request type = data.resource _ resourcetype:_:子帧;
}
if(is _插拔导航过程_ & _型型_渲染过程_ = =)
handler.reset(New crosssiteresourcehandler(handler.pass request),());

在事件处理程序中插入缓冲/ before the actual酮。
(handler.reset
新bufferedresourcehandler(request),handler.pass(this);,)

…………………

(handler.reset
纽约(handler.pass throttlingresourcehandler request(),(),throttles.pass));

handler.pass(回车);
}
这个函数定义在文件external /铬/内容/浏览器/ _ org /资源调度台主机_ _ _ impl.cc中.

从前面的调用过程可以知道,参数sync _ result的值等于null因此resourcedispatcherhostimpl类的成员函数createresourcehandler首先创建了一个asyncresourcehandler对象保存在本地变量handler中表示要通过异步方式下载参数request描述的url,,,。

接下来resourcedispatcherhostimpl类的成员函数createresourcehandler又会根据情况创建其它的handler对象.这些handler对象会依次连接在一起.其中,后面创建的handler对象位于前面创建的handler对象的前面.下载回来的网页内容将依次被这些handler对象处理.这意味着下载回来的网页内容最后会被最先创建的asyncresourcehandler对象进行处理.为了简单起见,后面我们只分析这个asyncresourcehandler对象处理下载回来的网页内容的过程,也就是假设resourcedispatcherhostimpl类的成员函数createresourcehandler返回给调用者的是一个asyncresourcehandler对象.

回到resourcedispatcherhostimpl类的成员函数beginrequest中,它最后调用另外一个成员函数beginrequestinternal下载本地变量new _ request描述的url对应的网页内容,如下所示:

::beginrequestinternal(resourcedispatcherhostimpl啊
scoped _ PTR:< >:urlrequest request,网
scoped resourcehandler > < _ PTR(程序)
…………………

resourcerequestinfoimpl*info=
resourcerequestinfoimpl forrequest(request.get(::));
…………………

联_ Loder(PTR resourceloader > <
纽约(request.pass resourceloader handler.pass(),(),this);

…..

(信息,开始装台);
}
这个函数定义在文件external /铬/内容/浏览器/ _ org /资源调度台主机_ _ _ impl.cc中.

resourcedispatcherhostimpl类的成员函数beginrequestinternal将参数request描述的url和参数handler描述的asyncresourcehandler对象封装在一个resourceloader对象后,调用另外一个成员函数startloading开始加载参数request描述的url。

resourcedispatcherhostimpl类的成员函数startloading的实现如下所示:

::(resourcedispatcherhostimpl开始装啊
resourcerequestinfoimpl *信息,
const linked_ptr < ResourceLoader >和装载){
......

装载机-> startrequest();
}
这个函数定义在文件外部/ chromium_org /内容/浏览器/装载机/ resource_dispatcher_host_impl CC中。

resourcedispatcherhostimpl类的成员函数开始装主要是调用参数装载机描述的ResourceLoader对象的成员函数startrequest开始加载其内部封装的URL。

类的成员函数startrequest的实现如下所示ResourceLoader:

无效的ResourceLoader::startrequest() {
......

/ /给处理机会延迟urlrequest被启动。
布尔defer_start = false;
如果(!handler_ -> onwillstart(request_ -> url(),与defer_start)){
cancel();
返回;
}

如果(defer_start){
deferred_stage_ = deferred_start;
{ }
startrequestinternal();
}
}
这个函数定义在外部/ chromium_org /内容/浏览器/装载机/ resource_loader CC中。

handler_ ResourceLoader类的成员变量描述的便是前面我们假设resourcedispatcherhostimpl类的成员函数createresourcehandler返回的asyncresourcehandler对象。ResourceLoader类的成员函数startrequest调用这个asyncresourcehandler对象的成员函数onwillstart询问是要取消、延迟、还是马上下载当前正在处理的ResourceLoader对象封装的URL对应的网页内容。

我们假设是第三种情况,这时候ResourceLoader类的成员函数startrequest就会马上调用另外一个成员函数startrequestinternal下载当前正在处理的ResourceLoader对象封装的URL对应的网页内容。

类的成员函数startrequestinternal的实现如下所示ResourceLoader:

无效的ResourceLoader::startrequestinternal() {
......

request_ -> start();

......
}
这个函数定义在外部/ chromium_org /内容/浏览器/装载机/ resource_loader CC中。

handler_ ResourceLoader类的成员变量描述的是前面在resourcedispatcherhostimpl类的成员函数BeginRequest中创建的一个urlrequest对象。这个urlrequest对象封装了要下载的URL。ResourceLoader类的成员函数startrequestinternal通过调用这个urlrequest对象的成员函数开始就可以启动下载网页的过程了。

urlrequest类是铬在净模块中提供的一个类,用来执行具体的网络操作,也就是根据约定的协议请求服务器返回指定对应的网页的内容这个过程我们留给读者自行分析Web URL。

Web服务器响应了请求之后,铬的净模块会调用ResourceLoader类的成员函数onresponsestarted会被调用,它的实现如下所示:

无效的ResourceLoader::onresponsestarted(网::urlrequest *未使用){
......

如果(request_ -> status()。is_success()){
阅读(假);//读第一块。
}

......
}
这个函数定义在外部/ chromium_org /内容/浏览器/装载机/ resource_loader CC中。

onresponsestarted ResourceLoader类的成员函数检查Web服务器的响应是否成功,例如Web服务器是否根据HTTP协议返回了200响应。如果成功的话,那么接下来就会调用另外一个成员函数阅读读出第一块数据。

类的成员函数阅读的实现如下所示ResourceLoader:

无效的ResourceLoader::阅读(bool is_continuation){
国际bytes_read = 0;
-(& bytes_read);

......

如果(!is_continuation | | bytes_read <= 0){
onreadcompleted(request_。get(),bytes_read);
{ }
/ /其他onreadcompleted来避免触发异步IO
/ /线程的情况下,urlrequest可以提供数据同步。
基地::::messageloop current() -> posttask(
from_here,
基地::::onreadcompleted ResourceLoader绑定(&,
weak_ptr_factory_。getweakptr(),
request_。get(),
bytes_read));
}
}
这个函数定义在外部/ chromium_org /内容/浏览器/装载机/ resource_loader CC中。

ResourceLoader class member function StartReading call member function ReadMore to read the Web server to return to the data, read out the data stored in the local variable bytes_read.

The implementation of the member function ReadMore of the ResourceLoader class is shown below:

ResourceLoader: void: ReadMore (bytes_read int*) {
......

Scoped_refptr<net:: buf IOBuffer>;
Buf_size int;
If (! Handler_->OnWillRead (&buf, &buf_size, -1)) {
Cancel ();
Return;
}

......

Request_->Read (buf.get (), buf_size, bytes_read);

......
}
This function is defined in external/chromium_org/content/browser/loader/resource_loader.cc.

ResourceLoader class member function ReadMore first call the member variable handler_ description of a AsyncResourceHandler object member function OnWillRead to get a Buffer. This Buffer is used to save the data returned from the Web server. These data can be obtained by calling a member function of the ResourceLoader class member variable reqeust_ described by the member function Read.

The implementation of the member function OnWillRead of the AsyncResourceHandler object is shown below:

AsyncResourceHandler: bool: OnWillRead (scoped_refptr<net:: buf IOBuffer>*,
Buf_size int*,
Min_size int) {
......

If (! EnsureResourceBufferIsInitialized) ()
False return;

......
Memory char* = buffer_->Allocate (&allocation_size_);
....

*buf = DependentIOBuffer new (buffer_.get (), memory);
*buf_size = allocation_size_;

......

True return;
}
This function is defined in the file external/chromium_org/content/browser/loader/async_resource_handler.cc.

Member function OnWillRead AsyncResourceHandler object first call a member function EnsureResourceBufferIsInitialized ensure member variables buffer points to a shared memory, and then from this shared memory allocation of a size equal allocation size for the member variable the value of the buffer, to return to the caller saved from the web server returns to the data.

The implementation of the member function EnsureResourceBufferIsInitialized of the AsyncResourceHandler class is shown below:

AsyncResourceHandler: bool: EnsureResourceBufferIsInitialized () {
If (buffer_.get) and buffer_->IsInitialized (())
True return;

......

Buffer_ = ResourceBuffer new ();
Buffer_->Initialize return (kBufferSize,
KMinAllocationSize,
KMaxAllocationSize);
}
This function is defined in the file external/chromium_org/content/browser/loader/async_resource_handler.cc.

Member function EnsureResourceBufferIsInitialized AsyncResourceHandler first check member variable buffer is pointed to the a ResourceBuffer object, and the ResourceBuffer object description shared memory is created.

If the member variable buffer AsyncResourceHandler also no point to a ResourceBuffer object, or point to a ResourceBuffer object but the ResourceBuffer object description sharing memory has not been created, then AsyncResourceHandler class members function EnsureResourceBufferIsInitialized will create a ResourceBuffer object stored in the buffer for the member variable, and initialize member function calls the ResourceBuffer object to create a block size is shared memory kBufferSize. This shared memory can be allocated to the buffer at a minimum value of kMinAllocationSize, the maximum value of kMaxAllocationSize.

On the Android platform, the ResourceBuffer class member function is called to create the shared memory, which is actually shared by Initialize. Anonymous shared memory can be shared between the two processes through the Binder mechanism. This point can refer to the frontAnalysis on the principle of (Anonymous Shared Memory Ashmem) sharing in the process of the anonymous shared memory Android systemOne article. So that the Browser process can be downloaded through this anonymous memory will be downloaded back to the content of the page to Render process.

This step completes execution, back to the member function StartReading resourceloader. If there is no read data (which indicates that the data has already been downloaded), or parameter is the continuation of the value is equal to false representation (read out is the first data block), then the resourceloader class member function StartReading will call the member function OnReadCompleted immediately to deal with the next step. In other cases, in order to avoid the data (Network) thread is blocked, the resourceloader class member functions StartReading does not immediately call a member function OnReadCompleted processing pronounce, but delayed a message processing, also is the resourceloader class of member function StartReading return to chromium net module for further processing.

Next we continue to analyze the implementation of the member function OnReadCompleted of the ResourceLoader class, as shown below:

ResourceLoader: void: OnReadCompleted (net:: unused URLRequest*, bytes_read int) {
......

CompleteRead (bytes_read);

......

If (bytes_read > 0) {
StartReading (true); / / Read the next chunk.
{else} {
Reported an EOF. Call ResponseCompleted. / / URLRequest
DCHECK_EQ (0, bytes_read);
ResponseCompleted ();
}
}
This function is defined in external/chromium_org/content/browser/loader/resource_loader.cc.

ResourceLoader class member function OnReadCompleted first call into the same function CompleteRead to deal with the current read out of the data, the size of the data described by the parameter bytes_read. If the current read out of the size of the data is greater than 0, then it means that the data has not finished, this time you need to call the front analysis of the member function StartReading continue to read. Note that this time passing member function StartReading parameters for the true, said it is not the first time to read the Web server to return to the data.

On the other hand, if the current read out the data size is less than or equal to 0, so that web server has put all of the data is returned to the, this time resourceloader class member functions OnReadCompleted will call also a member function ResponseCompleted end read access to data.

Next we continue to analyze the implementation of ResourceLoader class member function CompleteRead in order to understand the Browser process will be downloaded back to the web content to return to the process of processing the Render process, as shown below:

ResourceLoader: void: CompleteRead (bytes_read int) {
......

Defer bool = false;
If (! Handler_->OnReadCompleted (bytes_read, &defer)) {
Cancel ();
}

......
}
This function is defined in external/chromium_org/content/browser/loader/resource_loader.cc.

Handler for the member variable to describe a AsyncResourceHandler object with resourceloader class member function CompleteRead will read out the data, which is realized by calling the member function OnReadCompleted.

The implementation of the member function OnReadCompleted of the AsyncResourceHandler class is shown below:

AsyncResourceHandler: bool: OnReadCompleted (bytes_read int, defer bool*) {
......

If (! Sent_first_data_msg_) {
Base:: handle SharedMemoryHandle;
Size int;
If (! Buffer_->ShareToProcess (filter->PeerHandle (), &handle, &size)
False return;
Filter->Send (ResourceMsg_SetDataBuffer new (
GetRequestID (), handle, size, filter->peer_pid ());
Sent_first_data_msg_ = true;
}

Data_offset int = buffer_->GetLastAllocationOffset ();

Current_transfer_size int64_t = ->GetTotalReceivedBytes () request ();
Encoded_data_length int = reported_transfer_size_ - current_transfer_size;
Reported_transfer_size_ = current_transfer_size;

Filter->Send (ResourceMsg_DataReceived new (
GetRequestID (), data_offset, bytes_read, encoded_data_length);

......
}
This function is defined in the file external/chromium_org/content/browser/loader/async_resource_handler.cc.

When AsyncResourceHandler class member variables sent first data MSG value equals false, said the being processed object AsyncResourceHandler no to the render process returning from a web server to download back page content. At this time AsyncResourceHandler class member function OnReadCompleted first to the Render process to send a type of IPC message to the ResourceMsg_SetDataBuffer. The IPC message will describe the member variable buffer AsyncResourceHandler class of shared memory transfer to render process to render process next can through this shared memory reads from a web server to download back page content.

Finally, the member function AsyncResourceHandler of the OnReadCompleted class then sends a IPC message to the Render process for a type ResourceMsg_DataReceived. The IPC message tells the Render process how much data is being read at the beginning of the shared memory described in the front. With these data, the Render process can be built on the web Tree DOM.

Next we will continue to analyze the process of receiving and processing the Render process for ResourceMsg_SetDataBuffer and IPC ResourceMsg_DataReceived messages.

The Render process is a ResourceMsg_DataReceived message that is received by the member function DispatchMessage of the ResourceDispatcher class for the ResourceMsg_SetDataBuffer and IPC messages, as shown in the following:

ResourceDispatcher: void: DispatchMessage (IPC: const: message Message&) {
IPC_BEGIN_MESSAGE_MAP (ResourceDispatcher, message)
......
IPC_MESSAGE_HANDLER (ResourceMsg_SetDataBuffer, OnSetDataBuffer)
IPC_MESSAGE_HANDLER (ResourceMsg_DataReceived, OnReceivedData)
......
IPC_END_MESSAGE_MAP ()
}
This function is defined in the file external/chromium_org/content/child/resource_dispatcher.cc.

From here we can see, the dispatchmessage member function of class ResourceDispatcher the type of IPC message ResourceMsg_SetDataBuffer ResourceMsg_SetDataBuffer distributed to member functions OnSetDataBuffer processing, the IPC message ResourceMsg_DataReceived datareceived distribute to the members function OnReceivedData physical.

The implementation of the member function OnSetDataBuffer of the ResourceDispatcher class is shown below:

ResourceDispatcher: void: OnSetDataBuffer (request_id int,
Base:: shm_handle SharedMemoryHandle,
Shm_size int,
Base:: ProcessId: renderer_pid) {
......
Request_info PendingRequestInfo* = GetPendingRequestInfo (request_id);
......

Request_info->buffer.reset (
New base:: SharedMemory (shm_handle, true)); / / read only

OK bool = request_info->buffer->Map (shm_size);
......

Request_info->buffer_size = shm_size;
}

This function is defined in the file external/chromium_org/content/child/resource_dispatcher.cc.

From the previous analysis, it is known that the Render process creates a PendingRequestInfo object when the URL process is requested to download the page content specified by the Browser process. The PendingRequestInfo object to a Request ID as the key is stored inside the ResourceDispatcher class. This ID request_id that is the parameter Request describes the ID Request. Therefore, ResourceDispatcher class member function OnSetDataBuffer can get a PendingRequestInfo object through the parameter request_id. Member function OnSetDataBuffer with this PendingRequestInfo object after ResourceDispatcher class is according to the description parameter SHM handle handle to create a ShareMemory object and stored in the buffer variables of its members.

ResourceDispatcher class member functions OnSetDataBuffer finally call the ShareMemory object members function map can be the browser process transfer over shared memory mapped to the address space of the process, so the future can be directly from this shared memory read browser process of downloading back page content.

The implementation of the member function OnReceivedData of the ResourceDispatcher class is shown below:

ResourceDispatcher: void: OnReceivedData (request_id int,
Data_offset int,
Data_length int,
Encoded_data_length int) {
......
Request_info PendingRequestInfo* = GetPendingRequestInfo (request_id);
......
如果(request_info & data_length > 0){
......
linked_ptr <::共享内存> retain_buffer(request_info ->缓冲);
......

const char * data_start = static_cast <字符串>(request_info ->缓冲-> memory());
......
const char * data_ptr = data_start + data_offset;
......

/ / / /检查是否该响应数据是符合我们的跨站点
/ /文件拦截策略。我们只做了第一个数据包。
std::string alternative_data;
如果(request_info -> site_isolation_metadata。get()){
request_info -> blocked_response =
siteisolationpolicy::shouldblockresponse(
request_info -> site_isolation_metadata,data_ptr,data_length,
与alternative_data);
request_info -> site_isolation_metadata。reset();

当反应被阻断时,我们可以有任何替代数据
/ /发送到渲染器。当| alternative_data |大小是零,我们不
/ /或/或称之为对等的回调。
如果(request_info -> blocked_response &!alternative_data。empty()){
data_ptr = alternative_data。data();
data_length = alternative_data。size();
encoded_data_length = alternative_data。size();
}
}

如果(!request_info -> blocked_response | |!alternative_data。empty()){
如果(request_info -> threaded_data_provider){
request_info -> threaded_data_provider -> onreceiveddataonforegroundthread(
data_ptr,data_length,encoded_data_length);
/ /螺纹数据提供者会照顾它自己的信息,如
可在另一个线程上处理数据。
send_ack = false;
{ }
request_info ->点> onreceiveddata(
data_ptr,data_length,encoded_data_length);
}
}

......
}

......
}
这个函数定义在文件外部/ chromium_org /内容/孩子/ resource_dispatcher CC中。

resourcedispatcher类的成员函数onreceiveddata首先获得参数request_id对应的一个pendingrequestinfo对象,保存在本地变量request_info中。有了这个pendingrequestinfo对象之后,就可以根据参数data_offset和data_length从它的成员变量缓冲描述的共享内存中获得浏览器进程下载回来的网页内容。

如果这是一个跨站(跨站点)请求下载回来的内容,resourcedispatcher类的成员函数onreceiveddata会调用siteisolationpolicy类的静态成员函数shouldblockresponse根据跨站点文件决定是否需要阻止下载回来的内容在当前渲染进程中加载封锁政策。关于铬的跨站点文件封锁政策,可以参考站点隔离阻断站点隔离的跨站点文档这两篇文章。

如果siteisolationpolicy类的静态成员函数shouldblockresponse表明要阻止下载回来的内容在当前渲染进程中加载,那么本地变量request_info指向的pendingrequestinfo对象的成员变量blocked_response的值就会等于真实。这时候如果siteisolationpolicy类的静态成员函数shouldblockresponse还返回了替代数据,那么这个替代数据就会替换下载回来的网页内容交给WebKit处理。

如果siteisolationpolicy类的静态成员函数shouldblockresponse没有阻止下载回来的内容在当前渲染进程中加载,或者阻止的同时也提供了替代数据,那么resourcedispatcher类的成员函数onreceiveddata接下来继续判断本地变量request_info指向的pendingrequestinfo对象的成员变量threaded_data_provider是否指向了一个threadeddataprovider对象。如果指向了一个threadeddataprovider对象,那么resourcedispatcher类的成员函数onreceiveddata会将下载回来的网页内容交给这个threadeddataprovider对象的成员函数onreceiveddataonforegroundthread处理。否则的话,下载回来的网页内容将会交给本地变量request_info指向的pendingrequestinfo对象的成员变量同行描述的一个weburlloaderimpl::语境对象的成员函数onreceiveddata处理。

WebKit at the request of chromium content module downloads the specified corresponding to the URL of the web page content, will be downloaded back to the page content is specified to give a background thread receives and interprets, this time pointing to the local variable request info PendingRequestInfo object member variable threaded data provider will point to a ThreadedDataProvider object. The ThreadedDataProvider object will be downloaded back to the content of the page to a background thread to receive and parse. We do not consider this situation, so we continue to analyze the next WebURLLoaderImpl:: Context class member function OnReceivedData implementation, as shown below:

WebURLLoaderImpl: Context:: void: OnReceivedData (char* data const,
Data_length int,
Encoded_data_length int) {
......

If (ftp_listing_delegate_) {
The FTP listing delegate will make / the appropriate calls to
And client_->didReceiveResponse. / / client_->didReceiveData
Ftp_listing_delegate_->OnReceivedData (data, data_length);
} if else (multipart_delegate_) {
The multipart delegate will make the / appropriate calls to
And client_->didReceiveResponse. / / client_->didReceiveData
Multipart_delegate_->OnReceivedData (data, data_length, encoded_data_length);
{else} {
Client_->didReceiveData (loader_, data, data_length, encoded_data_length);
}
}

This function is defined in the file external/chromium_org/content/child/web_url_loader_impl.cc.

When text/vnd.chromium.ftp-dir the MIME type of the returned from the web server to the web content, WebURLLoaderImpl:: the context class member variables of FTP listing delegate point to a FtpDirectoryListingResponseDelegate object. This time from the web server to return to the page content is some FTP directory, the FtpDirectoryListingResponseDelegate object on the content of these pages are several typographic treatment, will then be submitted to the WebKit, description is resourceloader class member variables of a client of a resourceloader object.

When multipart/x-mixed-replace the MIME type of the returned from the web server to the web content, WebURLLoaderImpl:: the context class member variables of a multipart delegate pointing a MultipartResponseDelegate object This time from the Web server to return to the page content contains a number of data blocks, each data block has a separate MIME type, and they are through a String Boundary. The MultipartResponseDelegate object boundary string parsing out each data block according to the, and then to the WebKit, description is resourceloader class member variables of a client of a resourceloader object.

Member function OnReceivedData in the remaining cases, WebURLLoaderImpl:: context classes of directly to the web server returns to the contents of a web page to the WebKit, and member function didReceiveData is called resourceloader class member variables client described a resourceloader object processing.

At this point, we analyze the completion of the Chromium to download the specified URL corresponding to the web content of the process. Download the contents of the web page will be processed by WebKit, that is, by the ResourceLoader class member function didReceiveData for processing. This process is the process of analyzing the content of the web page, you will get an analysis of a Tree DOM. With Tree DOM, then you can download the contents of the web page to be returned to the rendering. In the next article, we detailed analysis of WebKit according to the page content generated Tree DOM process, please pay attention to! More information can also be concerned about the Sina Weibo luo:Http://weibo.com/shengyangluo.

top
Two
step on
Zero
Guess you're looking for
View comments
* the above user comments only represent their personal views, does not represent the views or position of the CSDN website
    personal data
    • visit6965339 times
    • Integral:Thirty-six thousand and twenty-six
    • Grade
    • Rank:Sixty-first name
    • original151
    • Reproduced:0
    • Translation:0
    • Comments:7097 article
    Blog post
    All articles of this blog are original, welcome to exchange, welcome to reprint; reprint please do not tamper with the content, and indicate the source, prohibit for commercial purposes, thank you!
    Sina Weibo
    Book information
    contact information
    Sina weibo:

    Http://weibo.com/shengyangluo

    QQ communication group:

    One hundred and thirty million one hundred and twelve thousand seven hundred and sixty

    Blog column
    Latest comments