OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // See http://dev.chromium.org/developers/design-documents/multi-process-resourc
e-loading | 5 // See http://dev.chromium.org/developers/design-documents/multi-process-resourc
e-loading |
6 | 6 |
7 #include "content/child/resource_dispatcher.h" | 7 #include "content/child/resource_dispatcher.h" |
8 | 8 |
9 #include "base/basictypes.h" | 9 #include "base/basictypes.h" |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
193 new ResourceHostMsg_RequestResource(routing_id_, request_id_, request_)); | 193 new ResourceHostMsg_RequestResource(routing_id_, request_id_, request_)); |
194 } | 194 } |
195 | 195 |
196 void IPCResourceLoaderBridge::Cancel() { | 196 void IPCResourceLoaderBridge::Cancel() { |
197 if (request_id_ < 0) { | 197 if (request_id_ < 0) { |
198 NOTREACHED() << "Trying to cancel an unstarted request"; | 198 NOTREACHED() << "Trying to cancel an unstarted request"; |
199 return; | 199 return; |
200 } | 200 } |
201 | 201 |
202 if (!is_synchronous_request_) | 202 if (!is_synchronous_request_) |
203 dispatcher_->CancelPendingRequest(routing_id_, request_id_); | 203 dispatcher_->CancelPendingRequest(request_id_); |
204 | 204 |
205 // We can't remove the request ID from the resource dispatcher because more | 205 // We can't remove the request ID from the resource dispatcher because more |
206 // data might be pending. Sending the cancel message may cause more data | 206 // data might be pending. Sending the cancel message may cause more data |
207 // to be flushed, and will then cause a complete message to be sent. | 207 // to be flushed, and will then cause a complete message to be sent. |
208 } | 208 } |
209 | 209 |
210 void IPCResourceLoaderBridge::SetDefersLoading(bool value) { | 210 void IPCResourceLoaderBridge::SetDefersLoading(bool value) { |
211 if (request_id_ < 0) { | 211 if (request_id_ < 0) { |
212 NOTREACHED() << "Trying to (un)defer an unstarted request"; | 212 NOTREACHED() << "Trying to (un)defer an unstarted request"; |
213 return; | 213 return; |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
317 ResourceDispatcher::PendingRequestInfo* | 317 ResourceDispatcher::PendingRequestInfo* |
318 ResourceDispatcher::GetPendingRequestInfo(int request_id) { | 318 ResourceDispatcher::GetPendingRequestInfo(int request_id) { |
319 PendingRequestList::iterator it = pending_requests_.find(request_id); | 319 PendingRequestList::iterator it = pending_requests_.find(request_id); |
320 if (it == pending_requests_.end()) { | 320 if (it == pending_requests_.end()) { |
321 // This might happen for kill()ed requests on the webkit end. | 321 // This might happen for kill()ed requests on the webkit end. |
322 return NULL; | 322 return NULL; |
323 } | 323 } |
324 return &(it->second); | 324 return &(it->second); |
325 } | 325 } |
326 | 326 |
327 void ResourceDispatcher::OnUploadProgress( | 327 void ResourceDispatcher::OnUploadProgress(int request_id, int64 position, |
328 const IPC::Message& message, int request_id, int64 position, int64 size) { | 328 int64 size) { |
329 PendingRequestInfo* request_info = GetPendingRequestInfo(request_id); | 329 PendingRequestInfo* request_info = GetPendingRequestInfo(request_id); |
330 if (!request_info) | 330 if (!request_info) |
331 return; | 331 return; |
332 | 332 |
333 request_info->peer->OnUploadProgress(position, size); | 333 request_info->peer->OnUploadProgress(position, size); |
334 | 334 |
335 // Acknowledge receipt | 335 // Acknowledge receipt |
336 message_sender()->Send( | 336 message_sender()->Send(new ResourceHostMsg_UploadProgress_ACK(request_id)); |
337 new ResourceHostMsg_UploadProgress_ACK(message.routing_id(), request_id)); | |
338 } | 337 } |
339 | 338 |
340 void ResourceDispatcher::OnReceivedResponse( | 339 void ResourceDispatcher::OnReceivedResponse( |
341 int request_id, const ResourceResponseHead& response_head) { | 340 int request_id, const ResourceResponseHead& response_head) { |
342 PendingRequestInfo* request_info = GetPendingRequestInfo(request_id); | 341 PendingRequestInfo* request_info = GetPendingRequestInfo(request_id); |
343 if (!request_info) | 342 if (!request_info) |
344 return; | 343 return; |
345 request_info->response_start = ConsumeIOTimestamp(); | 344 request_info->response_start = ConsumeIOTimestamp(); |
346 | 345 |
347 if (delegate_) { | 346 if (delegate_) { |
(...skipping 18 matching lines...) Expand all Loading... |
366 void ResourceDispatcher::OnReceivedCachedMetadata( | 365 void ResourceDispatcher::OnReceivedCachedMetadata( |
367 int request_id, const std::vector<char>& data) { | 366 int request_id, const std::vector<char>& data) { |
368 PendingRequestInfo* request_info = GetPendingRequestInfo(request_id); | 367 PendingRequestInfo* request_info = GetPendingRequestInfo(request_id); |
369 if (!request_info) | 368 if (!request_info) |
370 return; | 369 return; |
371 | 370 |
372 if (data.size()) | 371 if (data.size()) |
373 request_info->peer->OnReceivedCachedMetadata(&data.front(), data.size()); | 372 request_info->peer->OnReceivedCachedMetadata(&data.front(), data.size()); |
374 } | 373 } |
375 | 374 |
376 void ResourceDispatcher::OnSetDataBuffer(const IPC::Message& message, | 375 void ResourceDispatcher::OnSetDataBuffer(int request_id, |
377 int request_id, | |
378 base::SharedMemoryHandle shm_handle, | 376 base::SharedMemoryHandle shm_handle, |
379 int shm_size, | 377 int shm_size, |
380 base::ProcessId renderer_pid) { | 378 base::ProcessId renderer_pid) { |
381 PendingRequestInfo* request_info = GetPendingRequestInfo(request_id); | 379 PendingRequestInfo* request_info = GetPendingRequestInfo(request_id); |
382 if (!request_info) | 380 if (!request_info) |
383 return; | 381 return; |
384 | 382 |
385 bool shm_valid = base::SharedMemory::IsHandleValid(shm_handle); | 383 bool shm_valid = base::SharedMemory::IsHandleValid(shm_handle); |
386 CHECK((shm_valid && shm_size > 0) || (!shm_valid && !shm_size)); | 384 CHECK((shm_valid && shm_size > 0) || (!shm_valid && !shm_size)); |
387 | 385 |
388 request_info->buffer.reset( | 386 request_info->buffer.reset( |
389 new base::SharedMemory(shm_handle, true)); // read only | 387 new base::SharedMemory(shm_handle, true)); // read only |
390 | 388 |
391 bool ok = request_info->buffer->Map(shm_size); | 389 bool ok = request_info->buffer->Map(shm_size); |
392 if (!ok) { | 390 if (!ok) { |
393 // Added to help debug crbug/160401. | 391 // Added to help debug crbug/160401. |
394 base::ProcessId renderer_pid_copy = renderer_pid; | 392 base::ProcessId renderer_pid_copy = renderer_pid; |
395 base::debug::Alias(&renderer_pid_copy); | 393 base::debug::Alias(&renderer_pid_copy); |
396 | 394 |
397 base::SharedMemoryHandle shm_handle_copy = shm_handle; | 395 base::SharedMemoryHandle shm_handle_copy = shm_handle; |
398 base::debug::Alias(&shm_handle_copy); | 396 base::debug::Alias(&shm_handle_copy); |
399 | 397 |
400 CrashOnMapFailure(); | 398 CrashOnMapFailure(); |
401 return; | 399 return; |
402 } | 400 } |
403 | 401 |
404 request_info->buffer_size = shm_size; | 402 request_info->buffer_size = shm_size; |
405 } | 403 } |
406 | 404 |
407 void ResourceDispatcher::OnReceivedData(const IPC::Message& message, | 405 void ResourceDispatcher::OnReceivedData(int request_id, |
408 int request_id, | |
409 int data_offset, | 406 int data_offset, |
410 int data_length, | 407 int data_length, |
411 int encoded_data_length) { | 408 int encoded_data_length) { |
412 PendingRequestInfo* request_info = GetPendingRequestInfo(request_id); | 409 PendingRequestInfo* request_info = GetPendingRequestInfo(request_id); |
413 if (request_info && data_length > 0) { | 410 if (request_info && data_length > 0) { |
414 CHECK(base::SharedMemory::IsHandleValid(request_info->buffer->handle())); | 411 CHECK(base::SharedMemory::IsHandleValid(request_info->buffer->handle())); |
415 CHECK_GE(request_info->buffer_size, data_offset + data_length); | 412 CHECK_GE(request_info->buffer_size, data_offset + data_length); |
416 | 413 |
417 // Ensure that the SHM buffer remains valid for the duration of this scope. | 414 // Ensure that the SHM buffer remains valid for the duration of this scope. |
418 // It is possible for CancelPendingRequest() to be called before we exit | 415 // It is possible for CancelPendingRequest() to be called before we exit |
(...skipping 23 matching lines...) Expand all Loading... |
442 request_info->peer->OnReceivedData(alternative_data.data(), | 439 request_info->peer->OnReceivedData(alternative_data.data(), |
443 alternative_data.size(), | 440 alternative_data.size(), |
444 alternative_data.size()); | 441 alternative_data.size()); |
445 } | 442 } |
446 | 443 |
447 UMA_HISTOGRAM_TIMES("ResourceDispatcher.OnReceivedDataTime", | 444 UMA_HISTOGRAM_TIMES("ResourceDispatcher.OnReceivedDataTime", |
448 base::TimeTicks::Now() - time_start); | 445 base::TimeTicks::Now() - time_start); |
449 } | 446 } |
450 | 447 |
451 // Acknowledge the reception of this data. | 448 // Acknowledge the reception of this data. |
452 message_sender()->Send( | 449 message_sender()->Send(new ResourceHostMsg_DataReceived_ACK(request_id)); |
453 new ResourceHostMsg_DataReceived_ACK(message.routing_id(), request_id)); | |
454 } | 450 } |
455 | 451 |
456 void ResourceDispatcher::OnDownloadedData(const IPC::Message& message, | 452 void ResourceDispatcher::OnDownloadedData(int request_id, |
457 int request_id, | |
458 int data_len, | 453 int data_len, |
459 int encoded_data_length) { | 454 int encoded_data_length) { |
460 // Acknowledge the reception of this message. | 455 // Acknowledge the reception of this message. |
461 message_sender()->Send( | 456 message_sender()->Send( |
462 new ResourceHostMsg_DataDownloaded_ACK(message.routing_id(), request_id)); | 457 new ResourceHostMsg_DataDownloaded_ACK(request_id)); |
463 | 458 |
464 PendingRequestInfo* request_info = GetPendingRequestInfo(request_id); | 459 PendingRequestInfo* request_info = GetPendingRequestInfo(request_id); |
465 if (!request_info) | 460 if (!request_info) |
466 return; | 461 return; |
467 | 462 |
468 request_info->peer->OnDownloadedData(data_len, encoded_data_length); | 463 request_info->peer->OnDownloadedData(data_len, encoded_data_length); |
469 } | 464 } |
470 | 465 |
471 void ResourceDispatcher::OnReceivedRedirect( | 466 void ResourceDispatcher::OnReceivedRedirect( |
472 const IPC::Message& message, | |
473 int request_id, | 467 int request_id, |
474 const GURL& new_url, | 468 const GURL& new_url, |
475 const ResourceResponseHead& response_head) { | 469 const ResourceResponseHead& response_head) { |
476 PendingRequestInfo* request_info = GetPendingRequestInfo(request_id); | 470 PendingRequestInfo* request_info = GetPendingRequestInfo(request_id); |
477 if (!request_info) | 471 if (!request_info) |
478 return; | 472 return; |
479 request_info->response_start = ConsumeIOTimestamp(); | 473 request_info->response_start = ConsumeIOTimestamp(); |
480 | 474 |
481 int32 routing_id = message.routing_id(); | |
482 bool has_new_first_party_for_cookies = false; | 475 bool has_new_first_party_for_cookies = false; |
483 GURL new_first_party_for_cookies; | 476 GURL new_first_party_for_cookies; |
484 ResourceResponseInfo renderer_response_info; | 477 ResourceResponseInfo renderer_response_info; |
485 ToResourceResponseInfo(*request_info, response_head, &renderer_response_info); | 478 ToResourceResponseInfo(*request_info, response_head, &renderer_response_info); |
486 if (request_info->peer->OnReceivedRedirect(new_url, renderer_response_info, | 479 if (request_info->peer->OnReceivedRedirect(new_url, renderer_response_info, |
487 &has_new_first_party_for_cookies, | 480 &has_new_first_party_for_cookies, |
488 &new_first_party_for_cookies)) { | 481 &new_first_party_for_cookies)) { |
489 // Double-check if the request is still around. The call above could | 482 // Double-check if the request is still around. The call above could |
490 // potentially remove it. | 483 // potentially remove it. |
491 request_info = GetPendingRequestInfo(request_id); | 484 request_info = GetPendingRequestInfo(request_id); |
492 if (!request_info) | 485 if (!request_info) |
493 return; | 486 return; |
494 // We update the response_url here so that we can send it to | 487 // We update the response_url here so that we can send it to |
495 // SiteIsolationPolicy later when OnReceivedResponse is called. | 488 // SiteIsolationPolicy later when OnReceivedResponse is called. |
496 request_info->response_url = new_url; | 489 request_info->response_url = new_url; |
497 request_info->pending_redirect_message.reset( | 490 request_info->pending_redirect_message.reset( |
498 new ResourceHostMsg_FollowRedirect(routing_id, request_id, | 491 new ResourceHostMsg_FollowRedirect(request_id, |
499 has_new_first_party_for_cookies, | 492 has_new_first_party_for_cookies, |
500 new_first_party_for_cookies)); | 493 new_first_party_for_cookies)); |
501 if (!request_info->is_deferred) { | 494 if (!request_info->is_deferred) { |
502 FollowPendingRedirect(request_id, *request_info); | 495 FollowPendingRedirect(request_id, *request_info); |
503 } | 496 } |
504 } else { | 497 } else { |
505 CancelPendingRequest(routing_id, request_id); | 498 CancelPendingRequest(request_id); |
506 } | 499 } |
507 } | 500 } |
508 | 501 |
509 void ResourceDispatcher::FollowPendingRedirect( | 502 void ResourceDispatcher::FollowPendingRedirect( |
510 int request_id, | 503 int request_id, |
511 PendingRequestInfo& request_info) { | 504 PendingRequestInfo& request_info) { |
512 IPC::Message* msg = request_info.pending_redirect_message.release(); | 505 IPC::Message* msg = request_info.pending_redirect_message.release(); |
513 if (msg) | 506 if (msg) |
514 message_sender()->Send(msg); | 507 message_sender()->Send(msg); |
515 } | 508 } |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
567 return false; | 560 return false; |
568 | 561 |
569 SiteIsolationPolicy::OnRequestComplete(request_id); | 562 SiteIsolationPolicy::OnRequestComplete(request_id); |
570 PendingRequestInfo& request_info = it->second; | 563 PendingRequestInfo& request_info = it->second; |
571 ReleaseResourcesInMessageQueue(&request_info.deferred_message_queue); | 564 ReleaseResourcesInMessageQueue(&request_info.deferred_message_queue); |
572 pending_requests_.erase(it); | 565 pending_requests_.erase(it); |
573 | 566 |
574 return true; | 567 return true; |
575 } | 568 } |
576 | 569 |
577 void ResourceDispatcher::CancelPendingRequest(int routing_id, | 570 void ResourceDispatcher::CancelPendingRequest(int request_id) { |
578 int request_id) { | |
579 PendingRequestList::iterator it = pending_requests_.find(request_id); | 571 PendingRequestList::iterator it = pending_requests_.find(request_id); |
580 if (it == pending_requests_.end()) { | 572 if (it == pending_requests_.end()) { |
581 DVLOG(1) << "unknown request"; | 573 DVLOG(1) << "unknown request"; |
582 return; | 574 return; |
583 } | 575 } |
584 | 576 |
585 SiteIsolationPolicy::OnRequestComplete(request_id); | 577 SiteIsolationPolicy::OnRequestComplete(request_id); |
586 PendingRequestInfo& request_info = it->second; | 578 PendingRequestInfo& request_info = it->second; |
587 ReleaseResourcesInMessageQueue(&request_info.deferred_message_queue); | 579 ReleaseResourcesInMessageQueue(&request_info.deferred_message_queue); |
588 pending_requests_.erase(it); | 580 pending_requests_.erase(it); |
589 | 581 |
590 message_sender()->Send( | 582 message_sender()->Send(new ResourceHostMsg_CancelRequest(request_id)); |
591 new ResourceHostMsg_CancelRequest(routing_id, request_id)); | |
592 } | 583 } |
593 | 584 |
594 void ResourceDispatcher::SetDefersLoading(int request_id, bool value) { | 585 void ResourceDispatcher::SetDefersLoading(int request_id, bool value) { |
595 PendingRequestList::iterator it = pending_requests_.find(request_id); | 586 PendingRequestList::iterator it = pending_requests_.find(request_id); |
596 if (it == pending_requests_.end()) { | 587 if (it == pending_requests_.end()) { |
597 DLOG(ERROR) << "unknown request"; | 588 DLOG(ERROR) << "unknown request"; |
598 return; | 589 return; |
599 } | 590 } |
600 PendingRequestInfo& request_info = it->second; | 591 PendingRequestInfo& request_info = it->second; |
601 if (value) { | 592 if (value) { |
602 request_info.is_deferred = value; | 593 request_info.is_deferred = value; |
603 } else if (request_info.is_deferred) { | 594 } else if (request_info.is_deferred) { |
604 request_info.is_deferred = false; | 595 request_info.is_deferred = false; |
605 | 596 |
606 FollowPendingRedirect(request_id, request_info); | 597 FollowPendingRedirect(request_id, request_info); |
607 | 598 |
608 base::MessageLoop::current()->PostTask( | 599 base::MessageLoop::current()->PostTask( |
609 FROM_HERE, | 600 FROM_HERE, |
610 base::Bind(&ResourceDispatcher::FlushDeferredMessages, | 601 base::Bind(&ResourceDispatcher::FlushDeferredMessages, |
611 weak_factory_.GetWeakPtr(), | 602 weak_factory_.GetWeakPtr(), |
612 request_id)); | 603 request_id)); |
613 } | 604 } |
614 } | 605 } |
615 | 606 |
616 void ResourceDispatcher::DidChangePriority( | 607 void ResourceDispatcher::DidChangePriority( |
617 int routing_id, int request_id, net::RequestPriority new_priority) { | 608 int routing_id, int request_id, net::RequestPriority new_priority) { |
618 DCHECK(ContainsKey(pending_requests_, request_id)); | 609 DCHECK(ContainsKey(pending_requests_, request_id)); |
619 message_sender()->Send(new ResourceHostMsg_DidChangePriority( | 610 message_sender()->Send(new ResourceHostMsg_DidChangePriority( |
620 routing_id, request_id, new_priority)); | 611 request_id, new_priority)); |
621 } | 612 } |
622 | 613 |
623 ResourceDispatcher::PendingRequestInfo::PendingRequestInfo() | 614 ResourceDispatcher::PendingRequestInfo::PendingRequestInfo() |
624 : peer(NULL), | 615 : peer(NULL), |
625 resource_type(ResourceType::SUB_RESOURCE), | 616 resource_type(ResourceType::SUB_RESOURCE), |
626 is_deferred(false), | 617 is_deferred(false), |
627 buffer_size(0) { | 618 buffer_size(0) { |
628 } | 619 } |
629 | 620 |
630 ResourceDispatcher::PendingRequestInfo::PendingRequestInfo( | 621 ResourceDispatcher::PendingRequestInfo::PendingRequestInfo( |
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
801 void ResourceDispatcher::ReleaseResourcesInMessageQueue(MessageQueue* queue) { | 792 void ResourceDispatcher::ReleaseResourcesInMessageQueue(MessageQueue* queue) { |
802 while (!queue->empty()) { | 793 while (!queue->empty()) { |
803 IPC::Message* message = queue->front(); | 794 IPC::Message* message = queue->front(); |
804 ReleaseResourcesInDataMessage(*message); | 795 ReleaseResourcesInDataMessage(*message); |
805 queue->pop_front(); | 796 queue->pop_front(); |
806 delete message; | 797 delete message; |
807 } | 798 } |
808 } | 799 } |
809 | 800 |
810 } // namespace content | 801 } // namespace content |
OLD | NEW |