上一次说到需要把显示的网络连接地址变成一个资源的消息发送出去,它是通过函数
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
,资源下载请求消息已经发送出去,那么这个消息又往何处而去呢?又怎么样通过网络连接下载回来呢?欲知后事如何,请继续看下一篇!