上一次说到怎么样开始把任务发送出去,也就是调用函数BeginRequestInternal来把URL请求发送,它的代码如下:
#001 void ResourceDispatcherHost::BeginRequestInternal(URLRequest* request,
#002 bool mixed_content) {
获取请求信息。
#003 ExtraRequestInfo* info = ExtraInfoForRequest(request);
生成全局ID,然后保存到正在下载请求队列里。
#004 GlobalRequestID global_id(info->render_process_host_id, info->request_id);
#005 pending_requests_[global_id] = request;
#006 if (mixed_content) {
#007 // We don't start the request in that case. The SSLManager will potentially
#008 // change the request (potentially to indicate its content should be
#009 // filtered) and start it itself.
#010 SSLManager::OnMixedContentRequest(this, request, ui_loop_);
#011 return;
#012 }
这里开始处理请求。
#013 request->Start();
#014
启动上传状态更新定时器。
#015 // Make sure we have the load state monitor running
#016 if (!update_load_states_timer_.IsRunning()) {
#017 update_load_states_timer_.Start(
#018 TimeDelta::FromMilliseconds(kUpdateLoadStatesIntervalMsec),
#019 this, &ResourceDispatcherHost::UpdateLoadStates);
#020 }
#021 }
通过上面的函数可以看到主要调用URLRequest::Start()来处理下载的请求,它的代码如下:
#001 void URLRequest::Start() {
#002 DCHECK(!is_pending_);
#003 DCHECK(!job_);
#004
创建一个下载的工作任务。
#005 job_ = GetJobManager()->CreateJob(this);
#006 job_->SetExtraRequestHeaders(extra_request_headers_);
#007
判断是否有数据需要上传。
#008 if (upload_.get())
#009 job_->SetUpload(upload_.get());
#010
设置请下开始下载的时间,以便后面检查超时的状态。
#011 is_pending_ = true;
#012 response_info_.request_time = Time::Now();
#013
#014 // Don't allow errors to be sent from within Start().
#015 // TODO(brettw) this may cause NotifyDone to be sent synchronously,
#016 // we probably don't want this: they should be sent asynchronously so
#017 // the caller does not get reentered.
这里把工作任务启动运行。
#018 job_->Start();
#019 }
由于这里是对URL的HTTP请求下载数据,所以这里的job_是类URLRequestHttpJob的实例,也就是调用函数URLRequestHttpJob::Start(),在函数URLRequestHttpJob::Start()的处理过程序如下:
1. URLRequestHttpJob::StartTransaction()
2. net::HttpCache::Transaction::Start
3. net::HttpCache::Transaction::BeginNetworkRequest()
4. net::HttpTransactionWinHttp::Start
5. net::HttpTransactionWinHttp::DidResolveProxy()
6. net::HttpTransactionWinHttp::OpenRequest
7. net::HttpTransactionWinHttp::SendRequest()
8. net::WinHttpRequestThrottle::SubmitRequest
9. net::WinHttpRequestThrottle::SendRequest
通过上面9个函数的调用处理,然后就会通过Windows的HTTP API进行发送请求和下载数据。我们来分析一下最后的函数WinHttpRequestThrottle::SendRequest,看看怎么样调用Windows HTTP API函数来获取数据的,它的代码如下:
#001 BOOL WinHttpRequestThrottle::SendRequest(HINTERNET request_handle,
#002 DWORD total_size,
#003 DWORD_PTR context,
#004 bool report_async_error) {
下面就是调用Windows的API函数WinHttpSendRequest来发送请求,当然在调用这个函数之前,需要调用函数WinHttpOpenRequest先打开一个TCP连接。
#005 BOOL ok = WinHttpSendRequest(request_handle,
#006 WINHTTP_NO_ADDITIONAL_HEADERS,
#007 0,
#008 WINHTTP_NO_REQUEST_DATA,
#009 0,
#010 total_size,
#011 context);
#012 if (!ok && report_async_error) {
#013 WINHTTP_ASYNC_RESULT async_result = { API_SEND_REQUEST, GetLastError() };
出错处理,就调用外面的回调函数。
#014 HttpTransactionWinHttp::StatusCallback(
#015 request_handle, context,
#016 WINHTTP_CALLBACK_STATUS_REQUEST_ERROR,
#017 &async_result, sizeof(async_result));
#018 }
#019 return ok;
#020 }
通过前面一系列的分析学会chrome浏览器怎么样输入URL地址,以及怎么样进行URL自动完成,然后把URL发送到渲染进程去处理,最后渲染进程又把资源下载请求发送到资源下载进程里处理,最后资源下载进程通过Windows HTTP API函数进行TCP连接,以及HTTP数据的上传和下载。浏览器向网站发送请求的过程已经分析完成了,那么HTTP API收到网页的数据后,又是怎么样处理的呢?下一次再来分析这个问题。