chromium网络资源加载分析(一) 主资源加载逻辑分析 ---chromium39

最近花了点时间看了看chromium加载网页的逻辑。由于这段内容较为复杂,现在只看了一部分。现将主资源的加载记录下来。


注:下面提到的文件,如果没有指明目录,则在third_party/WebKit目录下

1. ContentViewCore执行loadUrl之后,经过一些逻辑(这些逻辑比较简单,这里不做介绍),最终会走到:render_frame_impl.cc的方法:RenderFrameImpl::OnNavigate

   该方法中,有代码:frame->loadRequest(request);

2. 上面方法在thirdparty/WebKit目录下,WebLocalFrameImpl.cpp文件中:WebFrameImpl::loadRequest

3. 接着走到:FrameLoader.cpp文件中,FrameLoader::load

4. 接着走到:同文件中方法:FrameLoader::loadWithNavigationAction

    在该方法中,创建了DocumentLoader对象。且该对象的状态从:m_policyDocumentLoader变化为m_provisionalDocumentLoader

   注:DocumentLoader对象的状态的再次改变是在方法:FrameLoader::commitProvisionalLoad()中:

          m_documentLoader = m_provisionalDocumentLoader.release();

m_policyDocumentLoader = m_client->createDocumentLoader(m_frame, request, substituteData.isValid() ? substituteData : defaultSubstituteDataForURL(request.url()));

  之后该DocumentLoader对象状态发生变化:

 m_provisionalDocumentLoader = m_policyDocumentLoader.release();

5. 接着走到:DocumentLoader.cpp文件中方法: DocumentLoader::startLoadingMainResource()

     该方法中有代码:m_mainResource = m_fetcher->fetchMainResource(cachedResourceRequest, m_substituteData);

6. 该代码是文件ResourceFetcher.cpp文件中方法:ResourceFetcher::fetchMainResource

7. 接着走到:同文件中的方法:ResourceFetcher::requestResource

   该方法中有代码:resource = loadResource(type, request, request.charset()); 会创建Resouce对象。

  紧接着有代码:resource->load(this, request.options());

8.上面方法是在文件:Resource.cpp中,Resource::load。

    该方法中有代码:m_loader = ResourceLoader::create(fetcher, this, request, options);
                                    m_loader->start();

  创建了ResourceLoader对象。

9. 我们接着看 m_loader->start();。该代码是执行的ResourceLoader.cpp文件中方法:ResourceLoader::start()。

    在该方法中有代码:m_host->willStartLoadingResource(m_request);

    执行的是ResourceFetcher对象的方法:willStartLoadingResource

    上面方法会调用文件ApplicationCacheHost.cpp中方法:willStartLoadingResource。

    上面方法会调用content目录下文件:web_application_cache_host_impl.cc文件中方法:

    WebApplicationCacheHostImpl::willStartSubResourceRequest。

   继续看方法:ResourceLoader::start()。

该方法中有代码:m_loader = adoptPtr(blink::Platform::current()->createURLLoader());

这里创建了平台化的WebURLLoader对象。

createURLLoader()方法在文件content/下的blink_platform_impl.cc.

10. 是面创建的WebURLLoader对象是文件:  .../src/content/下的文件web_url_loader_impl.cc

      我们继续看该文件中的方法:loadAsynchronously

11. WebURLLoaderImpl::loadAsynchronously方法中有代码:context_->Start(request, NULL);

      该Start方法在同文件中:void WebURLLoaderImpl::Context::Start

      该方法中有代码:bridge_.reset(resource_dispatcher_->CreateBridge(request_info));


12. 上面方法会调用:content目录下:resource_dispatcher.cc文件中的方法:ResourceDispatcher::CreateBridge.

       该方法会创建对象:IPCResourceLoaderBridge

13. 我们继续看10中提到的方法:WebURLLoaderImpl::Context::Start。该方法中有代码:bridge_->Start(this)

14. 通过11-12的解释,我们来看content目录下:IPCResourceLoaderBridge对象的Start方法。该方法是在content目录下文件:resource_dispatcher.cc中:IPCResourceLoaderBridge::Start(RequestPeer* peer)

15. 上面方法会发送消息,该消息处理是在content目录下文件:resource_dispatcher_host_impl.cc中方法:ResourceDispatcherHostImpl::OnRequestResource

16. 上面方法会执行同文件的方法:ResourceDispatcherHostImpl::BeginRequest(方法。

17. 上面方法会执行同文件的方法:ResourceDispatcherHostImpl::BeginRequestInternal方法。

18. 上面方法会执行同文件的方法:ResourceDispatcherHostImpl::StartLoading方法

19. 上面方法会调用content目录下文件:resource_loader.cc中方法:ResourceLoader::StartRequest()

20. 上面方法会调用同文件的方法:ResourceLoader::StartRequestInternal()。该方法中有代码:request_->Start();

       该request_是.../src/net目录下文件url_request.cc对象。

21. 我们来看.../src/net目录下文件url_request.cc中方法: URLRequest::Start()

22. 上面方法会调用同文件中的方法:URLRequest::StartJob.该函数最后一行:job_->Start();

        该job_是.../src/content目录下url_request_job.cc对象。

23. 上面方法又会调用同文件的方法:  MaybeBeginDelivery();

24. 上面方法会调用同文件的方法:BeginDelivery

25. 上面方法会调用.../src/net/目录下文件:url_request_job.cc中的方法:URLRequestJob::NotifyRestartRequired

26. 上面方法调用.../src/net/目录下文件:url_request.cc中方法:URLRequest::Restart

27. 上面方法会调用同文件的方法:URLRequest::RestartWithJob

28. 上面方法调用同文件的方法:调用同文件方法:PrepareToRestart()将当前的job kill掉。

     之后会调用:URLRequest::StartJob()

       这次该文件中方法:job_->Start();

    这次创建的job是url_request_job.cc对象。

    关于这里,过程有些罗嗦。job创建和restart过程好几次。最后创建的是url_request_http_job.cc.我们这里看看其具体过程。

I/chromium( 2598): [url_request_job_manager.cc(50)] URLRequestJobManager::CreateJob
I/xxx    ( 2598): Tab.java @@@@@@@@@@@@@@@  onPageStarted url is  http://www.baidu.com/
I/chromium( 2598): [url_request_job_manager.cc(87)] vnbo URLRequestJobManager::CreateJob 000 job is 0x00485e60
I/chromium( 2598): [url_request_job.cc(506)]  URLRequestJob::NotifyRestartRequired()
I/chromium( 2598): [url_request.cc(715)]  URLRequest::Restart()  
I/chromium( 2598): [url_request_job_manager.cc(50)]  URLRequestJobManager::CreateJob
I/chromium( 2598): [url_request_job_manager.cc(96)] URLRequestJobManager::CreateJob job is 0x004977d8
I/chromium( 2598): [url_request_job.cc(53)]  URLRequestJob::Kill() and job is 0x00485e60
I/chromium( 2598): [service_worker_url_request_job.cc(59)]  ServiceWorkerURLRequestJob::Start()
I/chromium( 2598): [service_worker_url_request_job.cc(203)]  ServiceWorkerURLRequestJob::MaybeStartRequest()
I/chromium( 2598): [service_worker_url_request_job.cc(203)]  ServiceWorkerURLRequestJob::MaybeStartRequest()
I/chromium( 2598): [service_worker_url_request_job.cc(214)]  ServiceWorkerURLRequestJob::StartRequest()
I/chromium( 2598): [service_worker_url_request_job.cc(224)]  ServiceWorkerURLRequestJob::StartRequest() 1
I/chromium( 2598): [url_request_job.cc(506)]  URLRequestJob::NotifyRestartRequired()
I/chromium( 2598): [url_request.cc(715)]  URLRequest::Restart()  
I/chromium( 2598): [url_request_job_manager.cc(50)]  URLRequestJobManager::CreateJob
I/chromium( 2598): [url_request_job_manager.cc(87)]  URLRequestJobManager::CreateJob 000 job is 0x00497a00
I/chromium( 2598): [url_request_job.cc(53)]  URLRequestJob::Kill() and job is 0x004977d8
I/chromium( 2598): [url_request_job.cc(482)]  URLRequestJob::CompleteNotifyDone()
I/chromium( 2598): [url_request_job.cc(506)]  URLRequestJob::NotifyRestartRequired()
I/chromium( 2598): [url_request.cc(715)]  URLRequest::Restart()  
I/chromium( 2598): [url_request_job_manager.cc(50)]  URLRequestJobManager::CreateJob
I/chromium( 2598): [url_request_job_manager.cc(96)]  URLRequestJobManager::CreateJob job is 0x00000000
I/chromium( 2598): [url_request_http_job.cc(156)]  URLRequestJob* URLRequestHttpJob::Factory
I/chromium( 2598): [url_request_job_manager.cc(106)]  URLRequestJobManager::CreateJob job 2 is 0x00498848
I/chromium( 2598): [url_request_job.cc(53)]  URLRequestJob::Kill() and job is 0x00497a00

为了查看该创建Job的过程,将jobManager中CreateJob方法贴出来

URLRequestJob* URLRequestJobManager::CreateJob(
    URLRequest* request, NetworkDelegate* network_delegate) const {
  DCHECK(IsAllowedThread());
  LOG(INFO)<<" URLRequestJobManager::CreateJob";
  // If we are given an invalid URL, then don't even try to inspect the scheme.
  if (!request->url().is_valid()){
    URLRequestJob* job = new URLRequestErrorJob(request, network_delegate, ERR_INVALID_URL);
    LOG(INFO)<<" URLRequestJobManager::CreateJob 0 job is "<<job;
    return job;
  }
   // return new URLRequestErrorJob(request, network_delegate, ERR_INVALID_URL);

  // We do this here to avoid asking interceptors about unsupported schemes.
  const URLRequestJobFactory* job_factory = NULL;
  job_factory = request->context()->job_factory();

  const std::string& scheme = request->url().scheme();  // already lowercase
  if (!job_factory->IsHandledProtocol(scheme)) {
    URLRequestJob* job = new URLRequestErrorJob(
        request, network_delegate, ERR_UNKNOWN_URL_SCHEME);
    LOG(INFO)<<" URLRequestJobManager::CreateJob 00 job is "<<job;
    return job;
    //return new URLRequestErrorJob(
    //    request, network_delegate, ERR_UNKNOWN_URL_SCHEME);
  }

  // THREAD-SAFETY NOTICE:
  //   We do not need to acquire the lock here since we are only reading our
  //   data structures.  They should only be modified on the current thread.

  // See if the request should be intercepted.
  //

  // TODO(pauljensen): Remove this when AppCacheInterceptor is a
  // ProtocolHandler, see crbug.com/161547.
  if (!(request->load_flags() & LOAD_DISABLE_INTERCEPT)) {
    InterceptorList::const_iterator i;
    for (i = interceptors_.begin(); i != interceptors_.end(); ++i) {
      URLRequestJob* job = (*i)->MaybeIntercept(request, network_delegate);
      if (job){
        <strong><span style="color:#FF0000;">// note : the first job</span></strong>
        LOG(INFO)<<"vnbo URLRequestJobManager::CreateJob 000 job is "<<job;
        return job;
      }
        
    }
  }

  URLRequestJob* job = job_factory->MaybeCreateJobWithProtocolHandler(
      scheme, request, network_delegate);
  <span style="color:#FF0000;"><strong>// note : this second job</strong></span>
  LOG(INFO)<<" URLRequestJobManager::CreateJob job is "<<job;
  if (job)
    return job;

  // See if the request should be handled by a built-in protocol factory.
  for (size_t i = 0; i < arraysize(kBuiltinFactories); ++i) {
    if (scheme == kBuiltinFactories[i].scheme) {
      URLRequestJob* job = (kBuiltinFactories[i].factory)(
          request, network_delegate, scheme);
      DCHECK(job);  // The built-in factories are not expected to fail!
      <span style="color:#FF0000;"><strong>// note : the third job</strong></span>
       LOG(INFO)<<" URLRequestJobManager::CreateJob job 2 is "<<job;
      return job;
    }
  }

  // If we reached here, then it means that a registered protocol factory
  // wasn't interested in handling the URL.  That is fairly unexpected, and we
  // don't have a specific error to report here :-(
  LOG(WARNING) << "Failed to map: " << request->url().spec();
//  return new URLRequestErrorJob(request, network_delegate, ERR_FAILED);
  job = new URLRequestErrorJob(request, network_delegate, ERR_FAILED);
  LOG(INFO)<<"vnbo URLRequestJobManager::CreateJob job 3 is "<<job;
  return job;
}

29. 我们接着看:

        URLRequestHttpJob::AddCookieHeaderAndStart()

30. 上面方法调用同文件的方法:URLRequestHttpJob::CheckCookiePolicyAndLoad

31. 上面方法调用同文件的方法:URLRequestHttpJob::DoStartTransaction()

32.  上面方法调用同文件的方法:URLRequestHttpJob::StartTransaction()。

33 . 上面方法调用同文件的方法:URLRequestHttpJob::StartTransactionInternal()

        该方法中有代码:rv = transaction_->Start(

        这里创建的是HttpCache::Transaction::Transaction对象。

        注:在资源的加载的过程中,会有两类Transaction对象;一个是HttpCache::Transaction::Transaction对象,还有一个HttpNetworkTransaction::HttpNetworkTransaction对象。两者相互配合,才使的网页内容download下来。加载过程中,现将网页的header部分加载,然后再加载body部分。

         我们继续看:rv = transaction_->Start(,该代码执行的是:src/net目录下,http_cache_transaction.cc文件中方法:HttpCache::Transaction::Start

        在该方法中有代码:int rv = DoLoop(OK);

       在这里会执行一系列操作,这里先不进行分析,我们先去找到如何创建和启动HttpNetworkTransaction::HttpNetworkTransaction对象。因为这个对象才是真正去加载网页的Transaction。

 34. 在上面提到的方法HttpCache::Transaction::DoLoop中,有代码:

        case STATE_SEND_REQUEST:
        DCHECK_EQ(OK, rv);
        rv = DoSendRequest();
        break;

      我们继续看代码:DoSendRequest()。在该方法中,有代码:

        int rv = cache_->network_layer_->CreateTransaction(priority_,
                                                     &network_trans_);  这是创建HttpNetworkTransaction::HttpNetworkTransaction对象

      在该方法的后面有代码:  rv = network_trans_->Start(request_, io_callback_, net_log_);

      这是启动HttpNetworkTransaction::HttpNetworkTransaction对象

35. 在对象HttpNetworkTransaction::HttpNetworkTransaction中Start方法中,会调用同文件的方法:

     int HttpNetworkTransaction::DoLoop

     这里面,会进行一些列调用。 会创建HttpStreamRequest和HttpStreamBase对象。

     并调用方法DoReadHeaders、DoReadBody分别来下载网页的header部分和body部分。

36. 我们先看看DoReadHeaders方法:该方法中有代码:stream_->ReadResponseHeaders(io_callback_);

37. 该方法调用websocket_basic_handshake_stream.cc文件中方法:ReadResponseHeaders.

      该方法中有代码:int rv = parser()->ReadResponseHeaders   

38. 上面调用的是文件:http_stream_parser.cc中,方法:ReadResponseHeaders。这里有通过一些列调用,执行本文件中方法:

      DoReadHeaders()。通过Socket,将网页的header部分读取出来:

   connection_->socket()
      ->Read(read_buf_.get(), read_buf_->RemainingCapacity(), io_callback_);

 

      


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值