谷歌chrome浏览器的源码分析(六)
消息的流通過程,是一個不同類相互交流的過程,如果不了解這個過程,根本就不知道這些類是怎么樣相互協(xié)作的。由于上一次說到ViewHostMsg_RequestResource消息已經(jīng)發(fā)送出來,它的處理過徎其實就是一般資源的消息處理過程,下面就來看看這個消息的處理過程,如下:
1.???????base::MessagePumpWin::Run函數(shù)消息
2.???????base::MessagePumpWin::RunWithDispatcher
3.???????base::MessagePumpWin::DoRunLoop
4.???????base::MessagePumpWin::WaitForWork
5.???????base::MessagePumpWin::SignalWatcher
6.???????IPC::Channel::OnObjectSignaled?通道的消息處理。
7.???????IPC::Channel::ProcessIncomingMessages
8.???????IPC::SyncChannel::SyncContext::OnMessageReceived
9.???????IPC::ChannelProxy::Context::TryFilters
10.????ResourceMessageFilter::OnMessageReceived
11.????IPC::MessageWithTuple<Tuple2<int,ViewHostMsg_Resource_Request> >::Dispatch<ResourceMessageFilter,int,ViewHostMsg_Resource_Request const &>
12.????ResourceMessageFilter::OnRequestResource
13.????ResourceDispatcherHost::BeginRequest
?
消息通過上面12個函數(shù)的流轉(zhuǎn),到達到處理這個消息的函數(shù)ResourceDispatcherHost::BeginRequest,它在里面就會把消息變成一個網(wǎng)絡(luò)下載請求,函數(shù)代碼如下:
#001??void ResourceDispatcherHost::BeginRequest(
#002??????Receiver* receiver,
#003??????HANDLE render_process_handle,
#004??????int render_process_host_id,
#005??????int render_view_id,
#006??????int request_id,
#007??????const ViewHostMsg_Resource_Request& request_data,
#008??????URLRequestContext* request_context,
#009??????IPC::Message* sync_result) {
?
是否已經(jīng)傳送完成,或者關(guān)閉。
#010????if (is_shutdown_ ||
#011????????!ShouldServiceRequest(render_process_host_id, request_data)) {
#012??????// Tell the renderer that this request was disallowed.
#013??????receiver->Send(new ViewMsg_Resource_RequestComplete(
#014??????????render_view_id,
#015??????????request_id,
#016??????????URLRequestStatus(URLRequestStatus::FAILED, net::ERR_ABORTED)));
#017??????return;
#018????}
#019?
?
保證所有插件已經(jīng)加載。
#020????// Ensure the Chrome plugins are loaded, as they may intercept network
#021????// requests.??Does nothing if they are already loaded.
#022????// TODO(mpcomplete): This takes 200 ms!??Investigate parallelizing this by
#023????// starting the load earlier in a BG thread.
#024????plugin_service_->LoadChromePlugins(this);
#025?
?
構(gòu)造事件處理器。
#026????// Construct the event handler.
#027????scoped_refptr<EventHandler> handler;
#028????if (sync_result) {
#029??????handler = new SyncEventHandler(receiver, request_data.url, sync_result);
#030????} else {
#031??????handler = new AsyncEventHandler(receiver,
#032?????????????????????????????????????render_process_host_id,
#033?????????????????????????????????????render_view_id,
#034?????????????????????????????????????render_process_handle,
#035?????????????????????????????????????request_data.url,
#036?????????????????????????????????????this);
#037????}
#038?
#039????if (HandleExternalProtocol(request_id, render_process_host_id, render_view_id,
#040???????????????????????????????request_data.url, request_data.resource_type,
#041???????????????????????????????handler)) {
#042??????return;
#043????}
#044?
?
構(gòu)造下載請求。
#045????// Construct the request.
#046????URLRequest* request = new URLRequest(request_data.url, this);
#047????request->set_method(request_data.method);
#048????request->set_policy_url(request_data.policy_url);
#049????request->set_referrer(request_data.referrer.spec());
#050????request->SetExtraRequestHeaders(request_data.headers);
#051????request->set_load_flags(request_data.load_flags);
#052????request->set_context(request_context);
#053????request->set_origin_pid(request_data.origin_pid);
#054?
?
設(shè)置上傳數(shù)據(jù)。
#055????// Set upload data.
#056????uint64 upload_size = 0;
#057????if (!request_data.upload_content.empty()) {
#058??????scoped_refptr<net::UploadData> upload = new net::UploadData();
#059??????upload->set_elements(request_data.upload_content);??// Deep copy.
#060??????request->set_upload(upload);
#061??????upload_size = upload->GetContentLength();
#062????}
#063?
?
安裝一個CrossSiteEventHandler事件處理器。
#064????// Install a CrossSiteEventHandler if this request is coming from a
#065????// RenderViewHost with a pending cross-site request.??We only check this for
#066????// MAIN_FRAME requests.
#067????// TODO(mpcomplete): remove "render_process_host_id != -1"
#068????//???????????????????when http://b/viewIssue?id=1080959 is fixed.
#069????if (request_data.resource_type == ResourceType::MAIN_FRAME &&
#070????????render_process_host_id != -1 &&
#071????????Singleton<CrossSiteRequestManager>::get()->
#072????????????HasPendingCrossSiteRequest(render_process_host_id, render_view_id)) {
#073??????// Wrap the event handler to be sure the current page's onunload handler
#074??????// has a chance to run before we render the new page.
#075??????handler = new CrossSiteEventHandler(handler,
#076?????????????????????????????????????????render_process_host_id,
#077?????????????????????????????????????????render_view_id,
#078?????????????????????????????????????????this);
#079????}
#080?
#081????if (safe_browsing_->enabled() &&
#082????????safe_browsing_->CanCheckUrl(request_data.url)) {
#083??????handler = new SafeBrowsingEventHandler(handler,
#084????????????????????????????????????????????render_process_host_id,
#085????????????????????????????????????????????render_view_id,
#086????????????????????????????????????????????request_data.url,
#087????????????????????????????????????????????request_data.resource_type,
#088????????????????????????????????????????????safe_browsing_,
#089????????????????????????????????????????????this);
#090????}
#091?
?
創(chuàng)建一個緩沖區(qū)處理。
#092????// Insert a buffered event handler before the actual one.
#093????handler = new BufferedEventHandler(handler, this, request);
#094?
#095????// Make extra info and read footer (contains request ID).
#096????ExtraRequestInfo* extra_info =
#097????????new ExtraRequestInfo(handler,
#098?????????????????????????????request_id,
#099????????????????????????????render_process_host_id,
#100?????????????????????????????render_view_id,
#101????????????????????????????request_data.mixed_content,
#102????????????????????????????request_data.resource_type,
#103?????????????????????????????upload_size);
#104????extra_info->allow_download =
#105????????ResourceType::IsFrame(request_data.resource_type);
#106????request->set_user_data(extra_info);??// takes pointer ownership
#107?
?
開始調(diào)用內(nèi)部處理請求函數(shù)。
#108????BeginRequestInternal(request, request_data.mixed_content);
#109??}
?
通過上面的分析,已經(jīng)知道消息轉(zhuǎn)換為一個請求任務(wù)URLRequest,這個任務(wù)就需要交給后面的工作進程來處理了,它是通過函數(shù)BeginRequestInternal來把任務(wù)進一步發(fā)送出去。
上一次說到怎么樣開始把任務(wù)發(fā)送出去,也就是調(diào)用函數(shù)BeginRequestInternal來把URL請求發(fā)送,它的代碼如下:
#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?
?
啟動上傳狀態(tài)更新定時器。
#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??}
?
通過上面的函數(shù)可以看到主要調(diào)用URLRequest::Start()來處理下載的請求,它的代碼如下:
#001??void URLRequest::Start() {
#002????DCHECK(!is_pending_);
#003????DCHECK(!job_);
#004?
?
創(chuàng)建一個下載的工作任務(wù)。
#005????job_ = GetJobManager()->CreateJob(this);
#006????job_->SetExtraRequestHeaders(extra_request_headers_);
#007?
?
判斷是否有數(shù)據(jù)需要上傳。
#008????if (upload_.get())
#009??????job_->SetUpload(upload_.get());
#010?
?
設(shè)置請下開始下載的時間,以便后面檢查超時的狀態(tài)。
#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.
?
這里把工作任務(wù)啟動運行。
#018????job_->Start();
#019??}
?
由于這里是對URL的HTTP請求下載數(shù)據(jù),所以這里的job_是類URLRequestHttpJob的實例,也就是調(diào)用函數(shù)URLRequestHttpJob::Start(),在函數(shù)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個函數(shù)的調(diào)用處理,然后就會通過Windows的HTTP API進行發(fā)送請求和下載數(shù)據(jù)。我們來分析一下最后的函數(shù)WinHttpRequestThrottle::SendRequest,看看怎么樣調(diào)用Windows HTTP API函數(shù)來獲取數(shù)據(jù)的,它的代碼如下:
#001??BOOL WinHttpRequestThrottle::SendRequest(HINTERNET request_handle,
#002??????????????????????????????????????????DWORD total_size,
#003??????????????????????????????????????????DWORD_PTR context,
#004??????????????????????????????????????????bool report_async_error) {
?
下面就是調(diào)用Windows的API函數(shù)WinHttpSendRequest來發(fā)送請求,當(dāng)然在調(diào)用這個函數(shù)之前,需要調(diào)用函數(shù)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() };
?
出錯處理,就調(diào)用外面的回調(diào)函數(shù)。
#014??????HttpTransactionWinHttp::StatusCallback(
#015??????????request_handle, context,
#016??????????WINHTTP_CALLBACK_STATUS_REQUEST_ERROR,
#017??????????&async_result, sizeof(async_result));
#018????}
#019????return ok;
#020??}
?
通過前面一系列的分析學(xué)會chrome瀏覽器怎么樣輸入URL地址,以及怎么樣進行URL自動完成,然后把URL發(fā)送到渲染進程去處理,最后渲染進程又把資源下載請求發(fā)送到資源下載進程里處理,最后資源下載進程通過Windows HTTP API函數(shù)進行TCP連接,以及HTTP數(shù)據(jù)的上傳和下載。瀏覽器向網(wǎng)站發(fā)送請求的過程已經(jīng)分析完成了,那么HTTP API收到網(wǎng)頁的數(shù)據(jù)后,又是怎么樣處理的呢?下一次再來分析這個問題。
上一次說到使用WinHTTP函數(shù)來創(chuàng)建HTTP連接,并且使用它來發(fā)送請求,那么數(shù)據(jù)接收回來,當(dāng)然也是從它那里接收的,因此下面來分析它的接收數(shù)據(jù)的幾個函數(shù),然后再來看看chrome里收到數(shù)據(jù)后發(fā)送到那里處理。
在WinHTTP里使用WinHttpOpen函數(shù)來創(chuàng)建HTTP連接,然后使用WinHttpConnect連接需要下載數(shù)據(jù)的網(wǎng)站,接著調(diào)函數(shù)WinHttpOpenRequest來創(chuàng)建一個請求,使用函數(shù)WinHttpSendRequest發(fā)送HTTP請求,如果有數(shù)據(jù)發(fā)送到服務(wù)器,就通過WinHttpWriteData函數(shù)來發(fā)送,最后調(diào)用函數(shù)WinHttpReceiveResponse來查詢狀態(tài)碼,WinHttpQueryDataAvailable函數(shù)查詢可以接收到的數(shù)據(jù)大小,調(diào)用函數(shù)WinHttpQueryHeaders來查詢傳送回來的html頭的大小,調(diào)用函數(shù)WinHttpReadData來接收到WEB服務(wù)器發(fā)送回來的數(shù)據(jù)。
?
chrome就是通過下面的函數(shù)來實現(xiàn)數(shù)據(jù)接收的,如下:
#001??void HttpTransactionWinHttp::HandleStatusCallback(DWORD status,
#002???????????????????????????????????????????????????DWORD_PTR result,
#003???????????????????????????????????????????????????DWORD error,
#004???????????????????????????????????????????????????DWORD secure_failure) {
#005????int rv = ERR_FAILED;
#006?
#007????switch (status) {
#008??????case WINHTTP_CALLBACK_STATUS_REQUEST_ERROR:
#009????????rv = DidReceiveError(error, secure_failure);
#010????????break;
#011??????case WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE:
#012????????PopulateSSLInfo(secure_failure);
#013????????rv = DidSendRequest();
#014????????break;
#015??????case WINHTTP_CALLBACK_STATUS_WRITE_COMPLETE:
#016????????rv = DidWriteData(static_cast<DWORD>(result));
#017????????break;
?
接收到HTTP協(xié)議頭的數(shù)據(jù) 。
#018??????case WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE:
#019????????rv = DidReceiveHeaders();
#020????????break;
?
接收HTTP協(xié)議的數(shù)據(jù) 。
#021??????case WINHTTP_CALLBACK_STATUS_READ_COMPLETE:
#022????????rv = DidReadData(static_cast<DWORD>(result));
#023????????break;
#024??????default:
#025????????NOTREACHED() << "unexpected status code";
#026????}
#027?
#028????if (rv == ERR_IO_PENDING) {
#029??????session_callback_->AddRef();??// balanced when callback runs.
#030????} else if (callback_) {
#031??????DoCallback(rv);
#032????}
#033??}
?
通過上面的分析知道數(shù)據(jù)怎么樣從WinHTTP接收到,并且發(fā)送到下一個階段處理。
上一次說到通過WinHTTP來接收網(wǎng)絡(luò)數(shù)據(jù),但沒有具體介紹怎么樣接收,現(xiàn)在就來分析這方面的代碼。首先是通過函數(shù)WinHttpQueryHeaders來查詢HTTP協(xié)議頭的大小,接著還是通過函數(shù)WinHttpQueryHeaders把數(shù)據(jù)接收到緩沖區(qū)里。下面這段代碼,就是做這樣的事情:
#001??int HttpTransactionWinHttp::DidReceiveHeaders() {
#002????session_callback_->set_load_state(LOAD_STATE_IDLE);
#003?
?
第一次調(diào)用函數(shù)WinHttpQueryHeaders查看接收到協(xié)議頭的大小。
#004????DWORD size = 0;
#005????if (!WinHttpQueryHeaders(request_handle_,
#006????????????????????????????WINHTTP_QUERY_RAW_HEADERS,
#007????????????????????????????WINHTTP_HEADER_NAME_BY_INDEX,
#008?????????????????????????????NULL,
#009?????????????????????????????&size,
#010????????????????????????????WINHTTP_NO_HEADER_INDEX)) {
#011??????DWORD error = GetLastError();
#012??????if (error != ERROR_INSUFFICIENT_BUFFER) {
#013????????DLOG(ERROR) << "WinHttpQueryHeaders failed: " << GetLastError();
#014????????return TranslateLastOSError();
#015??????}
#016??????// OK, size should tell us how much to allocate...
#017??????DCHECK(size > 0);
#018????}
#019?
?
第二次調(diào)用函數(shù)WinHttpQueryHeaders來接收協(xié)議頭的數(shù)據(jù)。
#020????std::wstring raw_headers;
#021?
#022????// 'size' is the number of bytes rather than the number of characters.
#023????DCHECK(size % 2 == 0);
#024????if (!WinHttpQueryHeaders(request_handle_,
#025????????????????????????????WINHTTP_QUERY_RAW_HEADERS,
#026????????????????????????????WINHTTP_HEADER_NAME_BY_INDEX,
#027????????????????????????????WriteInto(&raw_headers, size/2 + 1),
#028?????????????????????????????&size,
#029????????????????????????????WINHTTP_NO_HEADER_INDEX)) {
#030??????DLOG(ERROR) << "WinHttpQueryHeaders failed: " << GetLastError();
#031??????return TranslateLastOSError();
#032????}
#033?
?
設(shè)置回應(yīng)的一些狀態(tài)。
#034????response_.response_time = Time::Now();
#035?
#036????// From experimentation, it appears that WinHttp translates non-ASCII bytes
#037????// found in the response headers to UTF-16 assuming that they are encoded
#038????// using the default system charset.??We attempt to undo that here.
#039????response_.headers =
#040????????new HttpResponseHeaders(base::SysWideToNativeMB(raw_headers));
#041?
#042????// WinHTTP truncates a response longer than 2GB.??Perhaps it stores the
#043????// response's content length in a signed 32-bit integer.??We fail rather
#044????// than reading a truncated response.
#045????if (response_.headers->GetContentLength() > 0x80000000)
#046??????return ERR_FILE_TOO_BIG;
#047?
#048????response_.vary_data.Init(*request_, *response_.headers);
#049????PopulateAuthChallenge();
#050?
#051????// Unfortunately, WinHttp does not close the connection when a non-keepalive
#052????// response is _not_ followed by the server closing the connection.?So, we
#053????// attempt to hack around this bug.
#054????if (!response_.headers->IsKeepAlive())
#055??????content_length_remaining_ = response_.headers->GetContentLength();
#056?
#057????return OK;
#058??}
?
通過上面的函數(shù)處理,就可以收到HTTP協(xié)議頭的數(shù)據(jù),這樣就可以進一步處理了。那么接著下來就是收到HTTP協(xié)議里的數(shù)據(jù),這個主要通過下面的函數(shù)來接收到的,如下:
#001??BOOL HttpTransactionWinHttp::SessionCallback::ReadData(
#002??????HINTERNET request_handle) {
#003????DCHECK(bytes_available_ >= 0);
#004????char* buf = read_buf_;
#005????read_buf_ = NULL;
#006????int bytes_to_read = std::min(bytes_available_, read_buf_len_);
#007????read_buf_len_ = 0;
#008????if (!bytes_to_read)
#009??????bytes_to_read = 1;
#010?
#011????// Because of how WinHTTP fills memory when used asynchronously, Purify isn't
#012????// able to detect that it's been initialized, so it scans for 0xcd in the
#013????// buffer and reports UMRs (uninitialized memory reads) for those individual
#014????// bytes. We override that to avoid the false error reports.
#015????// See http://b/issue?id=1173916.
#016????base::MemoryDebug::MarkAsInitialized(buf, bytes_to_read);
#017????return?WinHttpReadData(request_handle, buf, bytes_to_read, NULL);
#018??}
上面通過判斷可以接收到多少字節(jié),然后通過函數(shù)WinHttpReadData把數(shù)據(jù)保存到緩沖區(qū)read_buf_里,在這個緩沖區(qū)里保存了所有網(wǎng)絡(luò)接收到的數(shù)據(jù),那么這些數(shù)據(jù)又將要流向何方呢?下一次再來分析這個問題。
上次說到函數(shù)WinHttpReadData接收數(shù)據(jù)到緩沖區(qū)里,那么這些數(shù)據(jù)又是怎么樣傳送給下一步處理的呢?帶著這個問題,我們來分析下面這段代碼,如下:
#001??void HttpTransactionWinHttp::HandleStatusCallback(DWORD status,
#002???????????????????????????????????????????????????DWORD_PTR result,
#003???????????????????????????????????????????????????DWORD error,
#004???????????????????????????????????????????????????DWORD secure_failure) {
#005????int rv = ERR_FAILED;
#006?
#007????switch (status) {
#008??????case WINHTTP_CALLBACK_STATUS_REQUEST_ERROR:
#009????????rv = DidReceiveError(error, secure_failure);
#010????????break;
......
#027?
#028????if (rv == ERR_IO_PENDING) {
#029??????session_callback_->AddRef();??// balanced when callback runs.
#030????} else if (callback_) {
#031??????DoCallback(rv);
#032????}
#033??}
?
通過上面的函數(shù)可以看到,當(dāng)數(shù)據(jù)接收完成后,就會調(diào)用DoCallback函數(shù)處理接收到的數(shù)據(jù)。DoCallback函數(shù)的代碼如下:
?
#001??void HttpTransactionWinHttp::DoCallback(int rv) {
#002????DCHECK(rv != ERR_IO_PENDING);
#003????DCHECK(callback_);
#004?
#005????// since Run may result in Read being called, clear callback_ up front.
#006????CompletionCallback* c = callback_;
#007????callback_ = NULL;
#008????c->Run(rv);
#009??}
?
看到這里又是一個回調(diào)函數(shù)c->Run的通知,它是調(diào)用開始創(chuàng)建這個連接時設(shè)置的回調(diào)對象。如果是HTTP請求,那么這個請求回調(diào)函數(shù)是對象URLRequestHttpJob里的函數(shù),也就是調(diào)用URLRequestHttpJob::OnReadCompleted函數(shù),這個函數(shù)是當(dāng)數(shù)據(jù)接收完成,或接收失敗,或者接收還沒有完成時都會調(diào)用。這個函數(shù)代碼如下:
#001??void URLRequestHttpJob::OnReadCompleted(int result) {
#002????read_in_progress_ = false;
#003?
?
這里是接收數(shù)據(jù)完成。
#004????if (result == 0) {
#005??????NotifyDone(URLRequestStatus());
#006????} else if (result < 0) {
?
這里是接收數(shù)據(jù)出錯劃。
#007??????NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, result));
#008????} else {
?
這里是接收數(shù)據(jù)還沒有完成。
#009??????// Clear the IO_PENDING status
#010??????SetStatus(URLRequestStatus());
#011????}
#012?
#013????NotifyReadComplete(result);
#014??}
?
當(dāng)上面讀取數(shù)據(jù)完成時,就開始把接收到數(shù)據(jù)通過類ResourceDispatcherHost來發(fā)送出去,而類ResourceDispatcherHost發(fā)送數(shù)據(jù)的方式比較特別,它不是通過消息把整塊數(shù)據(jù)用命名管道發(fā)送的,而是通過共享內(nèi)存的方式讓另一個進程來讀取數(shù)據(jù),這樣達到速度快的特點,可見可多米處理處理考慮的都是速度,它的代碼如下:
#001??bool OnReadCompleted(int request_id, int* bytes_read) {
#002??????if (!*bytes_read)
#003????????return true;
#004??????DCHECK(read_buffer_.get());
#005?
#006??????if (!rdh_->WillSendData(render_process_host_id_, request_id)) {
#007????????// We should not send this data now, we have too many pending requests.
#008????????return true;
#009??????}
#010?
?
這里創(chuàng)建共享內(nèi)存。
#011??????SharedMemoryHandle handle;
#012??????if (!read_buffer_->GiveToProcess(render_process_, &handle)) {
#013????????// We wrongfully incremented the pending data count. Fake an ACK message
#014????????// to fix this. We can't move this call above the WillSendData because
#015????????// it's killing our read_buffer_, and we don't want that when we pause
#016????????// the request.
#017????????rdh_->OnDataReceivedACK(render_process_host_id_, request_id);
#018????????return false;
#019??????}
#020?
?
把共享內(nèi)存通過管道消息發(fā)送給渲染進程。
#021??????receiver_->Send(new ViewMsg_Resource_DataReceived(
#022??????????routing_id_, request_id, handle, *bytes_read));
#023?
#024??????return true;
#025????}
#026?
?
共享內(nèi)存是使用Windows API函數(shù)CreateFileMapping來創(chuàng)建內(nèi)存共享文件實現(xiàn)的,具體實現(xiàn)方法請參考類SharedMemory的實現(xiàn)。這里既然把消息通過管道發(fā)送出去了,那么在另一個線程里肯定就處理的這個消息,下一次再來分析那部份代碼。
from:?http://blog.csdn.net/caimouse/article/details/3230179
總結(jié)
以上是生活随笔為你收集整理的谷歌chrome浏览器的源码分析(六)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 谷歌chrome浏览器的源码分析(五)
- 下一篇: 谷歌chrome浏览器的源码分析(七)