谷歌浏览器的源码分析(25)

系统 1790 0
 

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

谷歌浏览器的源码分析(25)


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论