| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 "chrome/browser/renderer_host/resource_dispatcher_host.h" | 7 #include "chrome/browser/renderer_host/resource_dispatcher_host.h" |
| 8 | 8 |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 64 #include "net/base/net_errors.h" | 64 #include "net/base/net_errors.h" |
| 65 #include "net/base/request_priority.h" | 65 #include "net/base/request_priority.h" |
| 66 #include "net/base/ssl_cert_request_info.h" | 66 #include "net/base/ssl_cert_request_info.h" |
| 67 #include "net/base/upload_data.h" | 67 #include "net/base/upload_data.h" |
| 68 #include "net/http/http_response_headers.h" | 68 #include "net/http/http_response_headers.h" |
| 69 #include "net/url_request/url_request.h" | 69 #include "net/url_request/url_request.h" |
| 70 #include "net/url_request/url_request_context.h" | 70 #include "net/url_request/url_request_context.h" |
| 71 #include "webkit/appcache/appcache_interceptor.h" | 71 #include "webkit/appcache/appcache_interceptor.h" |
| 72 #include "webkit/appcache/appcache_interfaces.h" | 72 #include "webkit/appcache/appcache_interfaces.h" |
| 73 #include "webkit/blob/blob_storage_controller.h" | 73 #include "webkit/blob/blob_storage_controller.h" |
| 74 #include "webkit/blob/deletable_file_reference.h" | |
| 75 | 74 |
| 76 // TODO(oshima): Enable this for other platforms. | 75 // TODO(oshima): Enable this for other platforms. |
| 77 #if defined(OS_CHROMEOS) | 76 #if defined(OS_CHROMEOS) |
| 78 #include "chrome/browser/renderer_host/offline_resource_handler.h" | 77 #include "chrome/browser/renderer_host/offline_resource_handler.h" |
| 79 #endif | 78 #endif |
| 80 | 79 |
| 81 // Uncomment to enable logging of request traffic. | 80 // Uncomment to enable logging of request traffic. |
| 82 // #define LOG_RESOURCE_DISPATCHER_REQUESTS | 81 // #define LOG_RESOURCE_DISPATCHER_REQUESTS |
| 83 | 82 |
| 84 #ifdef LOG_RESOURCE_DISPATCHER_REQUESTS | 83 #ifdef LOG_RESOURCE_DISPATCHER_REQUESTS |
| 85 # define RESOURCE_LOG(stuff) LOG(INFO) << stuff | 84 # define RESOURCE_LOG(stuff) LOG(INFO) << stuff |
| 86 #else | 85 #else |
| 87 # define RESOURCE_LOG(stuff) | 86 # define RESOURCE_LOG(stuff) |
| 88 #endif | 87 #endif |
| 89 | 88 |
| 90 using base::Time; | 89 using base::Time; |
| 91 using base::TimeDelta; | 90 using base::TimeDelta; |
| 92 using base::TimeTicks; | 91 using base::TimeTicks; |
| 93 using webkit_blob::DeletableFileReference; | |
| 94 | 92 |
| 95 // ---------------------------------------------------------------------------- | 93 // ---------------------------------------------------------------------------- |
| 96 | 94 |
| 97 // A ShutdownTask proxies a shutdown task from the UI thread to the IO thread. | 95 // A ShutdownTask proxies a shutdown task from the UI thread to the IO thread. |
| 98 // It should be constructed on the UI thread and run in the IO thread. | 96 // It should be constructed on the UI thread and run in the IO thread. |
| 99 class ResourceDispatcherHost::ShutdownTask : public Task { | 97 class ResourceDispatcherHost::ShutdownTask : public Task { |
| 100 public: | 98 public: |
| 101 explicit ShutdownTask(ResourceDispatcherHost* resource_dispatcher_host) | 99 explicit ShutdownTask(ResourceDispatcherHost* resource_dispatcher_host) |
| 102 : rdh_(resource_dispatcher_host) { | 100 : rdh_(resource_dispatcher_host) { |
| 103 } | 101 } |
| (...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 316 return socket_stream_dispatcher_host_->OnMessageReceived( | 314 return socket_stream_dispatcher_host_->OnMessageReceived( |
| 317 message, receiver, message_was_ok); | 315 message, receiver, message_was_ok); |
| 318 } | 316 } |
| 319 | 317 |
| 320 *message_was_ok = true; | 318 *message_was_ok = true; |
| 321 receiver_ = receiver; | 319 receiver_ = receiver; |
| 322 | 320 |
| 323 IPC_BEGIN_MESSAGE_MAP_EX(ResourceDispatcherHost, message, *message_was_ok) | 321 IPC_BEGIN_MESSAGE_MAP_EX(ResourceDispatcherHost, message, *message_was_ok) |
| 324 IPC_MESSAGE_HANDLER(ViewHostMsg_RequestResource, OnRequestResource) | 322 IPC_MESSAGE_HANDLER(ViewHostMsg_RequestResource, OnRequestResource) |
| 325 IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_SyncLoad, OnSyncLoad) | 323 IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_SyncLoad, OnSyncLoad) |
| 326 IPC_MESSAGE_HANDLER(ViewHostMsg_ResourceLoaderDeleted, | |
| 327 OnResourceLoaderDeleted) | |
| 328 IPC_MESSAGE_HANDLER(ViewHostMsg_DataReceived_ACK, OnDataReceivedACK) | 324 IPC_MESSAGE_HANDLER(ViewHostMsg_DataReceived_ACK, OnDataReceivedACK) |
| 329 IPC_MESSAGE_HANDLER(ViewHostMsg_DataDownloaded_ACK, OnDataDownloadedACK) | |
| 330 IPC_MESSAGE_HANDLER(ViewHostMsg_UploadProgress_ACK, OnUploadProgressACK) | 325 IPC_MESSAGE_HANDLER(ViewHostMsg_UploadProgress_ACK, OnUploadProgressACK) |
| 331 IPC_MESSAGE_HANDLER(ViewHostMsg_CancelRequest, OnCancelRequest) | 326 IPC_MESSAGE_HANDLER(ViewHostMsg_CancelRequest, OnCancelRequest) |
| 332 IPC_MESSAGE_HANDLER(ViewHostMsg_FollowRedirect, OnFollowRedirect) | 327 IPC_MESSAGE_HANDLER(ViewHostMsg_FollowRedirect, OnFollowRedirect) |
| 333 IPC_MESSAGE_HANDLER(ViewHostMsg_ClosePage_ACK, OnClosePageACK) | 328 IPC_MESSAGE_HANDLER(ViewHostMsg_ClosePage_ACK, OnClosePageACK) |
| 334 IPC_END_MESSAGE_MAP_EX() | 329 IPC_END_MESSAGE_MAP_EX() |
| 335 | 330 |
| 336 receiver_ = NULL; | 331 receiver_ = NULL; |
| 337 | 332 |
| 338 return true; | 333 return true; |
| 339 } | 334 } |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 373 if (!context) { | 368 if (!context) { |
| 374 URLRequestContextGetter* context_getter = | 369 URLRequestContextGetter* context_getter = |
| 375 Profile::GetDefaultRequestContext(); | 370 Profile::GetDefaultRequestContext(); |
| 376 if (context_getter) { | 371 if (context_getter) { |
| 377 context = static_cast<ChromeURLRequestContext*>( | 372 context = static_cast<ChromeURLRequestContext*>( |
| 378 context_getter->GetURLRequestContext()); | 373 context_getter->GetURLRequestContext()); |
| 379 } | 374 } |
| 380 } | 375 } |
| 381 | 376 |
| 382 // Might need to resolve the blob references in the upload data. | 377 // Might need to resolve the blob references in the upload data. |
| 383 if (request_data.upload_data && context) { | 378 if (request_data.upload_data) { |
| 384 context->blob_storage_context()->controller()-> | 379 context->blob_storage_context()->controller()-> |
| 385 ResolveBlobReferencesInUploadData(request_data.upload_data.get()); | 380 ResolveBlobReferencesInUploadData(request_data.upload_data.get()); |
| 386 } | 381 } |
| 387 | 382 |
| 388 if (is_shutdown_ || | 383 if (is_shutdown_ || |
| 389 !ShouldServiceRequest(process_type, child_id, request_data)) { | 384 !ShouldServiceRequest(process_type, child_id, request_data)) { |
| 390 URLRequestStatus status(URLRequestStatus::FAILED, net::ERR_ABORTED); | 385 URLRequestStatus status(URLRequestStatus::FAILED, net::ERR_ABORTED); |
| 391 if (sync_result) { | 386 if (sync_result) { |
| 392 SyncLoadResult result; | 387 SyncLoadResult result; |
| 393 result.status = status; | 388 result.status = status; |
| (...skipping 27 matching lines...) Expand all Loading... |
| 421 this); | 416 this); |
| 422 } else { | 417 } else { |
| 423 handler = new AsyncResourceHandler(receiver_, | 418 handler = new AsyncResourceHandler(receiver_, |
| 424 child_id, | 419 child_id, |
| 425 route_id, | 420 route_id, |
| 426 receiver_->handle(), | 421 receiver_->handle(), |
| 427 request_data.url, | 422 request_data.url, |
| 428 this); | 423 this); |
| 429 } | 424 } |
| 430 | 425 |
| 431 // The RedirectToFileResourceHandler depends on being next in the chain. | |
| 432 if (request_data.download_to_file) | 426 if (request_data.download_to_file) |
| 433 handler = new RedirectToFileResourceHandler(handler, child_id, this); | 427 handler = new RedirectToFileResourceHandler(handler, child_id, this); |
| 434 | 428 |
| 435 if (HandleExternalProtocol(request_id, child_id, route_id, | 429 if (HandleExternalProtocol(request_id, child_id, route_id, |
| 436 request_data.url, request_data.resource_type, | 430 request_data.url, request_data.resource_type, |
| 437 handler)) { | 431 handler)) { |
| 438 return; | 432 return; |
| 439 } | 433 } |
| 440 | 434 |
| 441 // Construct the request. | 435 // Construct the request. |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 516 false, // is download | 510 false, // is download |
| 517 ResourceType::IsFrame(request_data.resource_type), // allow_download | 511 ResourceType::IsFrame(request_data.resource_type), // allow_download |
| 518 request_data.host_renderer_id, | 512 request_data.host_renderer_id, |
| 519 request_data.host_render_view_id); | 513 request_data.host_render_view_id); |
| 520 ApplyExtensionLocalizationFilter(request_data.url, request_data.resource_type, | 514 ApplyExtensionLocalizationFilter(request_data.url, request_data.resource_type, |
| 521 extra_info); | 515 extra_info); |
| 522 SetRequestInfo(request, extra_info); // Request takes ownership. | 516 SetRequestInfo(request, extra_info); // Request takes ownership. |
| 523 chrome_browser_net::SetOriginProcessUniqueIDForRequest( | 517 chrome_browser_net::SetOriginProcessUniqueIDForRequest( |
| 524 request_data.origin_child_id, request); | 518 request_data.origin_child_id, request); |
| 525 | 519 |
| 526 if (request->url().SchemeIs(chrome::kBlobScheme) && context) { | |
| 527 // Hang on to a reference to ensure the blob is not released prior | |
| 528 // to the job being started. | |
| 529 webkit_blob::BlobStorageController* controller = | |
| 530 context->blob_storage_context()->controller(); | |
| 531 extra_info->set_requested_blob_data( | |
| 532 controller->GetBlobDataFromUrl(request->url())); | |
| 533 } | |
| 534 | |
| 535 // Have the appcache associate its extra info with the request. | 520 // Have the appcache associate its extra info with the request. |
| 536 appcache::AppCacheInterceptor::SetExtraRequestInfo( | 521 appcache::AppCacheInterceptor::SetExtraRequestInfo( |
| 537 request, context ? context->appcache_service() : NULL, child_id, | 522 request, context ? context->appcache_service() : NULL, child_id, |
| 538 request_data.appcache_host_id, request_data.resource_type); | 523 request_data.appcache_host_id, request_data.resource_type); |
| 539 | 524 |
| 540 BeginRequestInternal(request); | 525 BeginRequestInternal(request); |
| 541 } | 526 } |
| 542 | 527 |
| 543 void ResourceDispatcherHost::OnResourceLoaderDeleted(int request_id) { | |
| 544 DCHECK(pending_requests_.end() == | |
| 545 pending_requests_.find(GlobalRequestID(receiver_->id(), request_id))); | |
| 546 UnregisterDownloadedTempFile(receiver_->id(), request_id); | |
| 547 } | |
| 548 | |
| 549 void ResourceDispatcherHost::OnDataReceivedACK(int request_id) { | 528 void ResourceDispatcherHost::OnDataReceivedACK(int request_id) { |
| 550 DataReceivedACK(receiver_->id(), request_id); | 529 DataReceivedACK(receiver_->id(), request_id); |
| 551 } | 530 } |
| 552 | 531 |
| 553 void ResourceDispatcherHost::DataReceivedACK(int child_id, | 532 void ResourceDispatcherHost::DataReceivedACK(int child_id, |
| 554 int request_id) { | 533 int request_id) { |
| 555 PendingRequestList::iterator i = pending_requests_.find( | 534 PendingRequestList::iterator i = pending_requests_.find( |
| 556 GlobalRequestID(child_id, request_id)); | 535 GlobalRequestID(child_id, request_id)); |
| 557 if (i == pending_requests_.end()) | 536 if (i == pending_requests_.end()) |
| 558 return; | 537 return; |
| 559 | 538 |
| 560 ResourceDispatcherHostRequestInfo* info = InfoForRequest(i->second); | 539 ResourceDispatcherHostRequestInfo* info = InfoForRequest(i->second); |
| 561 | 540 |
| 562 // Decrement the number of pending data messages. | 541 // Decrement the number of pending data messages. |
| 563 info->DecrementPendingDataCount(); | 542 info->DecrementPendingDataCount(); |
| 564 | 543 |
| 565 // If the pending data count was higher than the max, resume the request. | 544 // If the pending data count was higher than the max, resume the request. |
| 566 if (info->pending_data_count() == kMaxPendingDataMessages) { | 545 if (info->pending_data_count() == kMaxPendingDataMessages) { |
| 567 // Decrement the pending data count one more time because we also | 546 // Decrement the pending data count one more time because we also |
| 568 // incremented it before pausing the request. | 547 // incremented it before pausing the request. |
| 569 info->DecrementPendingDataCount(); | 548 info->DecrementPendingDataCount(); |
| 570 | 549 |
| 571 // Resume the request. | 550 // Resume the request. |
| 572 PauseRequest(child_id, request_id, false); | 551 PauseRequest(child_id, request_id, false); |
| 573 } | 552 } |
| 574 } | 553 } |
| 575 | 554 |
| 576 void ResourceDispatcherHost::OnDataDownloadedACK(int request_id) { | |
| 577 // TODO(michaeln): maybe throttle DataDownloaded messages | |
| 578 } | |
| 579 | |
| 580 void ResourceDispatcherHost::RegisterDownloadedTempFile( | |
| 581 int receiver_id, int request_id, DeletableFileReference* reference) { | |
| 582 // Note: receiver_id is the child_id is the render_process_id... | |
| 583 registered_temp_files_[receiver_id][request_id] = reference; | |
| 584 ChildProcessSecurityPolicy::GetInstance()->GrantUploadFile( | |
| 585 receiver_id, reference->path()); | |
| 586 } | |
| 587 | |
| 588 void ResourceDispatcherHost::UnregisterDownloadedTempFile( | |
| 589 int receiver_id, int request_id) { | |
| 590 DeletableFilesMap& map = registered_temp_files_[receiver_id]; | |
| 591 DeletableFilesMap::iterator found = map.find(request_id); | |
| 592 if (found == map.end()) | |
| 593 return; | |
| 594 map.erase(found); | |
| 595 // TODO(michaeln): revoke access to this file upon the file's deletion. | |
| 596 } | |
| 597 | |
| 598 | |
| 599 bool ResourceDispatcherHost::Send(IPC::Message* message) { | 555 bool ResourceDispatcherHost::Send(IPC::Message* message) { |
| 600 delete message; | 556 delete message; |
| 601 return false; | 557 return false; |
| 602 } | 558 } |
| 603 | 559 |
| 604 void ResourceDispatcherHost::OnUploadProgressACK(int request_id) { | 560 void ResourceDispatcherHost::OnUploadProgressACK(int request_id) { |
| 605 int child_id = receiver_->id(); | 561 int child_id = receiver_->id(); |
| 606 PendingRequestList::iterator i = pending_requests_.find( | 562 PendingRequestList::iterator i = pending_requests_.find( |
| 607 GlobalRequestID(child_id, request_id)); | 563 GlobalRequestID(child_id, request_id)); |
| 608 if (i == pending_requests_.end()) | 564 if (i == pending_requests_.end()) |
| (...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 884 return (entry == outstanding_requests_memory_cost_map_.end()) ? | 840 return (entry == outstanding_requests_memory_cost_map_.end()) ? |
| 885 0 : entry->second; | 841 0 : entry->second; |
| 886 } | 842 } |
| 887 | 843 |
| 888 // The object died, so cancel and detach all requests associated with it except | 844 // The object died, so cancel and detach all requests associated with it except |
| 889 // for downloads, which belong to the browser process even if initiated via a | 845 // for downloads, which belong to the browser process even if initiated via a |
| 890 // renderer. | 846 // renderer. |
| 891 void ResourceDispatcherHost::CancelRequestsForProcess(int child_id) { | 847 void ResourceDispatcherHost::CancelRequestsForProcess(int child_id) { |
| 892 socket_stream_dispatcher_host_->CancelRequestsForProcess(child_id); | 848 socket_stream_dispatcher_host_->CancelRequestsForProcess(child_id); |
| 893 CancelRequestsForRoute(child_id, -1 /* cancel all */); | 849 CancelRequestsForRoute(child_id, -1 /* cancel all */); |
| 894 registered_temp_files_.erase(child_id); | |
| 895 } | 850 } |
| 896 | 851 |
| 897 void ResourceDispatcherHost::CancelRequestsForRoute(int child_id, | 852 void ResourceDispatcherHost::CancelRequestsForRoute(int child_id, |
| 898 int route_id) { | 853 int route_id) { |
| 899 // Since pending_requests_ is a map, we first build up a list of all of the | 854 // Since pending_requests_ is a map, we first build up a list of all of the |
| 900 // matching requests to be cancelled, and then we cancel them. Since there | 855 // matching requests to be cancelled, and then we cancel them. Since there |
| 901 // may be more than one request to cancel, we cannot simply hold onto the map | 856 // may be more than one request to cancel, we cannot simply hold onto the map |
| 902 // iterators found in the first loop. | 857 // iterators found in the first loop. |
| 903 | 858 |
| 904 // Find the global ID of all matching elements. | 859 // Find the global ID of all matching elements. |
| (...skipping 931 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1836 } | 1791 } |
| 1837 | 1792 |
| 1838 // static | 1793 // static |
| 1839 bool ResourceDispatcherHost::IsResourceDispatcherHostMessage( | 1794 bool ResourceDispatcherHost::IsResourceDispatcherHostMessage( |
| 1840 const IPC::Message& message) { | 1795 const IPC::Message& message) { |
| 1841 switch (message.type()) { | 1796 switch (message.type()) { |
| 1842 case ViewHostMsg_RequestResource::ID: | 1797 case ViewHostMsg_RequestResource::ID: |
| 1843 case ViewHostMsg_CancelRequest::ID: | 1798 case ViewHostMsg_CancelRequest::ID: |
| 1844 case ViewHostMsg_FollowRedirect::ID: | 1799 case ViewHostMsg_FollowRedirect::ID: |
| 1845 case ViewHostMsg_ClosePage_ACK::ID: | 1800 case ViewHostMsg_ClosePage_ACK::ID: |
| 1846 case ViewHostMsg_ResourceLoaderDeleted::ID: | |
| 1847 case ViewHostMsg_DataReceived_ACK::ID: | 1801 case ViewHostMsg_DataReceived_ACK::ID: |
| 1848 case ViewHostMsg_DataDownloaded_ACK::ID: | 1802 case ViewHostMsg_DownloadProgress_ACK::ID: |
| 1849 case ViewHostMsg_UploadProgress_ACK::ID: | 1803 case ViewHostMsg_UploadProgress_ACK::ID: |
| 1850 case ViewHostMsg_SyncLoad::ID: | 1804 case ViewHostMsg_SyncLoad::ID: |
| 1851 return true; | 1805 return true; |
| 1852 | 1806 |
| 1853 default: | 1807 default: |
| 1854 break; | 1808 break; |
| 1855 } | 1809 } |
| 1856 | 1810 |
| 1857 return false; | 1811 return false; |
| 1858 } | 1812 } |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1927 return is_prefetch_enabled_; | 1881 return is_prefetch_enabled_; |
| 1928 } | 1882 } |
| 1929 | 1883 |
| 1930 // static | 1884 // static |
| 1931 void ResourceDispatcherHost::set_is_prefetch_enabled(bool value) { | 1885 void ResourceDispatcherHost::set_is_prefetch_enabled(bool value) { |
| 1932 is_prefetch_enabled_ = value; | 1886 is_prefetch_enabled_ = value; |
| 1933 } | 1887 } |
| 1934 | 1888 |
| 1935 // static | 1889 // static |
| 1936 bool ResourceDispatcherHost::is_prefetch_enabled_ = false; | 1890 bool ResourceDispatcherHost::is_prefetch_enabled_ = false; |
| OLD | NEW |