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