| 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 |