Chromium Code Reviews| 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/browser/renderer_host/resource_dispatcher_host_impl.h" | 7 #include "content/browser/renderer_host/resource_dispatcher_host_impl.h" |
| 8 | 8 |
| 9 #include <set> | 9 #include <set> |
| 10 #include <vector> | 10 #include <vector> |
| 11 | 11 |
| 12 #include "base/bind.h" | 12 #include "base/bind.h" |
| 13 #include "base/bind_helpers.h" | 13 #include "base/bind_helpers.h" |
| 14 #include "base/command_line.h" | 14 #include "base/command_line.h" |
| 15 #include "base/compiler_specific.h" | 15 #include "base/compiler_specific.h" |
| 16 #include "base/debug/alias.h" | 16 #include "base/debug/alias.h" |
| 17 #include "base/logging.h" | 17 #include "base/logging.h" |
| 18 #include "base/memory/scoped_ptr.h" | 18 #include "base/memory/scoped_ptr.h" |
| 19 #include "base/message_loop.h" | 19 #include "base/message_loop.h" |
| 20 #include "base/metrics/histogram.h" | 20 #include "base/metrics/histogram.h" |
| 21 #include "base/shared_memory.h" | 21 #include "base/shared_memory.h" |
| 22 #include "base/stl_util.h" | 22 #include "base/stl_util.h" |
| 23 #include "base/third_party/dynamic_annotations/dynamic_annotations.h" | 23 #include "base/third_party/dynamic_annotations/dynamic_annotations.h" |
| 24 #include "base/threading/thread_restrictions.h" | |
| 25 #include "content/browser/appcache/chrome_appcache_service.h" | 24 #include "content/browser/appcache/chrome_appcache_service.h" |
| 26 #include "content/browser/cert_store_impl.h" | 25 #include "content/browser/cert_store_impl.h" |
| 27 #include "content/browser/child_process_security_policy_impl.h" | 26 #include "content/browser/child_process_security_policy_impl.h" |
| 28 #include "content/browser/cross_site_request_manager.h" | 27 #include "content/browser/cross_site_request_manager.h" |
| 29 #include "content/browser/download/download_file_manager.h" | 28 #include "content/browser/download/download_file_manager.h" |
| 30 #include "content/browser/download/download_resource_handler.h" | 29 #include "content/browser/download/download_resource_handler.h" |
| 31 #include "content/browser/download/save_file_manager.h" | 30 #include "content/browser/download/save_file_manager.h" |
| 32 #include "content/browser/download/save_file_resource_handler.h" | 31 #include "content/browser/download/save_file_resource_handler.h" |
| 33 #include "content/browser/fileapi/chrome_blob_storage_context.h" | 32 #include "content/browser/fileapi/chrome_blob_storage_context.h" |
| 34 #include "content/browser/plugin_service_impl.h" | 33 #include "content/browser/plugin_service_impl.h" |
| (...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 350 | 349 |
| 351 ResourceDispatcherHostImpl::ResourceDispatcherHostImpl() | 350 ResourceDispatcherHostImpl::ResourceDispatcherHostImpl() |
| 352 : download_file_manager_(new DownloadFileManager(NULL)), | 351 : download_file_manager_(new DownloadFileManager(NULL)), |
| 353 save_file_manager_(new SaveFileManager()), | 352 save_file_manager_(new SaveFileManager()), |
| 354 request_id_(-1), | 353 request_id_(-1), |
| 355 is_shutdown_(false), | 354 is_shutdown_(false), |
| 356 max_outstanding_requests_cost_per_process_( | 355 max_outstanding_requests_cost_per_process_( |
| 357 kMaxOutstandingRequestsCostPerProcess), | 356 kMaxOutstandingRequestsCostPerProcess), |
| 358 filter_(NULL), | 357 filter_(NULL), |
| 359 delegate_(NULL), | 358 delegate_(NULL), |
| 360 allow_cross_origin_auth_prompt_(false) { | 359 allow_cross_origin_auth_prompt_(false), |
| 360 weak_ptr_factory_(this) { | |
| 361 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 361 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 362 DCHECK(!g_resource_dispatcher_host); | 362 DCHECK(!g_resource_dispatcher_host); |
| 363 g_resource_dispatcher_host = this; | 363 g_resource_dispatcher_host = this; |
| 364 | 364 |
| 365 GetContentClient()->browser()->ResourceDispatcherHostCreated(); | 365 GetContentClient()->browser()->ResourceDispatcherHostCreated(); |
| 366 | 366 |
| 367 ANNOTATE_BENIGN_RACE( | 367 ANNOTATE_BENIGN_RACE( |
| 368 &last_user_gesture_time_, | 368 &last_user_gesture_time_, |
| 369 "We don't care about the precise value, see http://crbug.com/92889"); | 369 "We don't care about the precise value, see http://crbug.com/92889"); |
| 370 | 370 |
| (...skipping 425 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 796 iter != blocked_loaders_map_.end(); ++iter) { | 796 iter != blocked_loaders_map_.end(); ++iter) { |
| 797 std::pair<std::set<ProcessRouteIDs>::iterator, bool> result = | 797 std::pair<std::set<ProcessRouteIDs>::iterator, bool> result = |
| 798 ids.insert(iter->first); | 798 ids.insert(iter->first); |
| 799 // We should not have duplicates. | 799 // We should not have duplicates. |
| 800 DCHECK(result.second); | 800 DCHECK(result.second); |
| 801 } | 801 } |
| 802 for (std::set<ProcessRouteIDs>::const_iterator iter = ids.begin(); | 802 for (std::set<ProcessRouteIDs>::const_iterator iter = ids.begin(); |
| 803 iter != ids.end(); ++iter) { | 803 iter != ids.end(); ++iter) { |
| 804 CancelBlockedRequestsForRoute(iter->first, iter->second); | 804 CancelBlockedRequestsForRoute(iter->first, iter->second); |
| 805 } | 805 } |
| 806 | |
| 807 weak_ptr_factory_.InvalidateWeakPtrs(); | |
| 806 } | 808 } |
| 807 | 809 |
| 808 bool ResourceDispatcherHostImpl::OnMessageReceived( | 810 bool ResourceDispatcherHostImpl::OnMessageReceived( |
| 809 const IPC::Message& message, | 811 const IPC::Message& message, |
| 810 ResourceMessageFilter* filter, | 812 ResourceMessageFilter* filter, |
| 811 bool* message_was_ok) { | 813 bool* message_was_ok) { |
| 812 filter_ = filter; | 814 filter_ = filter; |
| 813 bool handled = true; | 815 bool handled = true; |
| 814 IPC_BEGIN_MESSAGE_MAP_EX(ResourceDispatcherHostImpl, message, *message_was_ok) | 816 IPC_BEGIN_MESSAGE_MAP_EX(ResourceDispatcherHostImpl, message, *message_was_ok) |
| 815 IPC_MESSAGE_HANDLER(ResourceHostMsg_RequestResource, OnRequestResource) | 817 IPC_MESSAGE_HANDLER(ResourceHostMsg_RequestResource, OnRequestResource) |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 834 } | 836 } |
| 835 | 837 |
| 836 filter_ = NULL; | 838 filter_ = NULL; |
| 837 return handled; | 839 return handled; |
| 838 } | 840 } |
| 839 | 841 |
| 840 void ResourceDispatcherHostImpl::OnRequestResource( | 842 void ResourceDispatcherHostImpl::OnRequestResource( |
| 841 const IPC::Message& message, | 843 const IPC::Message& message, |
| 842 int request_id, | 844 int request_id, |
| 843 const ResourceHostMsg_Request& request_data) { | 845 const ResourceHostMsg_Request& request_data) { |
| 844 BeginRequest(request_id, request_data, NULL, message.routing_id()); | 846 PrepareToBeginRequest(request_id, request_data, NULL, message.routing_id()); |
| 845 } | 847 } |
| 846 | 848 |
| 847 // Begins a resource request with the given params on behalf of the specified | 849 // Begins a resource request with the given params on behalf of the specified |
| 848 // child process. Responses will be dispatched through the given receiver. The | 850 // child process. Responses will be dispatched through the given receiver. The |
| 849 // process ID is used to lookup WebContentsImpl from routing_id's in the case of | 851 // process ID is used to lookup WebContentsImpl from routing_id's in the case of |
| 850 // a request from a renderer. request_context is the cookie/cache context to be | 852 // a request from a renderer. request_context is the cookie/cache context to be |
| 851 // used for this request. | 853 // used for this request. |
| 852 // | 854 // |
| 853 // If sync_result is non-null, then a SyncLoad reply will be generated, else | 855 // If sync_result is non-null, then a SyncLoad reply will be generated, else |
| 854 // a normal asynchronous set of response messages will be generated. | 856 // a normal asynchronous set of response messages will be generated. |
| 855 void ResourceDispatcherHostImpl::OnSyncLoad( | 857 void ResourceDispatcherHostImpl::OnSyncLoad( |
| 856 int request_id, | 858 int request_id, |
| 857 const ResourceHostMsg_Request& request_data, | 859 const ResourceHostMsg_Request& request_data, |
| 858 IPC::Message* sync_result) { | 860 IPC::Message* sync_result) { |
| 859 BeginRequest(request_id, request_data, sync_result, | 861 PrepareToBeginRequest(request_id, request_data, sync_result, |
| 860 sync_result->routing_id()); | 862 sync_result->routing_id()); |
| 863 } | |
| 864 | |
| 865 void ResourceDispatcherHostImpl::PrepareToBeginRequest( | |
| 866 int request_id, | |
| 867 const ResourceHostMsg_Request& request_data, | |
| 868 IPC::Message* sync_result, | |
| 869 int route_id) { | |
| 870 if (!is_shutdown_ && request_data.upload_data) { | |
| 871 ResourceContext* resource_context = filter_->resource_context(); | |
| 872 // http://crbug.com/90971 | |
| 873 CHECK(ContainsKey(active_resource_contexts_, resource_context)); | |
| 874 | |
| 875 // Might need to resolve the blob references in the upload data. | |
| 876 GetBlobStorageControllerForResourceContext(resource_context)-> | |
| 877 ResolveBlobReferencesInUploadData(request_data.upload_data.get()); | |
| 878 | |
| 879 // BeginRequest() will be called later with upload_size. | |
| 880 request_data.upload_data->GetContentLength( | |
| 881 base::Bind(&ResourceDispatcherHostImpl::BeginRequest, | |
|
darin (slow to review)
2012/07/31 19:29:46
note: The ResourceDispatcherHostImpl out-lives the
| |
| 882 weak_ptr_factory_.GetWeakPtr(), | |
| 883 scoped_refptr<ResourceMessageFilter>(filter_), | |
| 884 request_id, | |
| 885 request_data, | |
| 886 sync_result, | |
| 887 route_id)); | |
| 888 } else { // There is no upload data. | |
| 889 const uint64 upload_size = 0; | |
| 890 BeginRequest( | |
| 891 filter_, request_id, request_data, sync_result, route_id, upload_size); | |
| 892 } | |
| 861 } | 893 } |
| 862 | 894 |
| 863 void ResourceDispatcherHostImpl::BeginRequest( | 895 void ResourceDispatcherHostImpl::BeginRequest( |
| 896 scoped_refptr<ResourceMessageFilter> filter, | |
| 864 int request_id, | 897 int request_id, |
| 865 const ResourceHostMsg_Request& request_data, | 898 const ResourceHostMsg_Request& request_data, |
| 866 IPC::Message* sync_result, // only valid for sync | 899 IPC::Message* sync_result, // only valid for sync |
| 867 int route_id) { | 900 int route_id, |
| 868 ProcessType process_type = filter_->process_type(); | 901 uint64 upload_size) { |
| 869 int child_id = filter_->child_id(); | 902 ProcessType process_type = filter->process_type(); |
| 903 int child_id = filter->child_id(); | |
| 870 | 904 |
| 871 // If we crash here, figure out what URL the renderer was requesting. | 905 // If we crash here, figure out what URL the renderer was requesting. |
| 872 // http://crbug.com/91398 | 906 // http://crbug.com/91398 |
| 873 char url_buf[128]; | 907 char url_buf[128]; |
| 874 base::strlcpy(url_buf, request_data.url.spec().c_str(), arraysize(url_buf)); | 908 base::strlcpy(url_buf, request_data.url.spec().c_str(), arraysize(url_buf)); |
| 875 base::debug::Alias(url_buf); | 909 base::debug::Alias(url_buf); |
| 876 | 910 |
| 877 // If the request that's coming in is being transferred from another process, | 911 // If the request that's coming in is being transferred from another process, |
| 878 // we want to reuse and resume the old loader rather than start a new one. | 912 // we want to reuse and resume the old loader rather than start a new one. |
| 879 linked_ptr<ResourceLoader> deferred_loader; | 913 linked_ptr<ResourceLoader> deferred_loader; |
| 880 { | 914 { |
| 881 LoaderMap::iterator it = pending_loaders_.find( | 915 LoaderMap::iterator it = pending_loaders_.find( |
| 882 GlobalRequestID(request_data.transferred_request_child_id, | 916 GlobalRequestID(request_data.transferred_request_child_id, |
| 883 request_data.transferred_request_request_id)); | 917 request_data.transferred_request_request_id)); |
| 884 if (it != pending_loaders_.end()) { | 918 if (it != pending_loaders_.end()) { |
| 885 if (it->second->is_transferring()) { | 919 if (it->second->is_transferring()) { |
| 886 deferred_loader = it->second; | 920 deferred_loader = it->second; |
| 887 pending_loaders_.erase(it); | 921 pending_loaders_.erase(it); |
| 888 } else { | 922 } else { |
| 889 RecordAction(UserMetricsAction("BadMessageTerminate_RDH")); | 923 RecordAction(UserMetricsAction("BadMessageTerminate_RDH")); |
| 890 filter_->BadMessageReceived(); | 924 filter->BadMessageReceived(); |
| 891 return; | 925 return; |
| 892 } | 926 } |
| 893 } | 927 } |
| 894 } | 928 } |
| 895 | 929 |
| 896 ResourceContext* resource_context = filter_->resource_context(); | 930 ResourceContext* resource_context = filter->resource_context(); |
| 897 // http://crbug.com/90971 | 931 // http://crbug.com/90971 |
| 898 CHECK(ContainsKey(active_resource_contexts_, resource_context)); | 932 CHECK(ContainsKey(active_resource_contexts_, resource_context)); |
| 899 | 933 |
| 900 // Might need to resolve the blob references in the upload data. | |
| 901 if (request_data.upload_data) { | |
| 902 GetBlobStorageControllerForResourceContext(resource_context)-> | |
| 903 ResolveBlobReferencesInUploadData(request_data.upload_data.get()); | |
| 904 } | |
| 905 | |
| 906 if (is_shutdown_ || | 934 if (is_shutdown_ || |
| 907 !ShouldServiceRequest(process_type, child_id, request_data)) { | 935 !ShouldServiceRequest(process_type, child_id, request_data)) { |
| 908 AbortRequestBeforeItStarts(filter_, sync_result, route_id, request_id); | 936 AbortRequestBeforeItStarts(filter, sync_result, route_id, request_id); |
| 909 return; | 937 return; |
| 910 } | 938 } |
| 911 | 939 |
| 912 const Referrer referrer(MaybeStripReferrer(request_data.referrer), | 940 const Referrer referrer(MaybeStripReferrer(request_data.referrer), |
| 913 request_data.referrer_policy); | 941 request_data.referrer_policy); |
| 914 | 942 |
| 915 // Allow the observer to block/handle the request. | 943 // Allow the observer to block/handle the request. |
| 916 if (delegate_ && !delegate_->ShouldBeginRequest(child_id, | 944 if (delegate_ && !delegate_->ShouldBeginRequest(child_id, |
| 917 route_id, | 945 route_id, |
| 918 request_data.method, | 946 request_data.method, |
| 919 request_data.url, | 947 request_data.url, |
| 920 request_data.resource_type, | 948 request_data.resource_type, |
| 921 resource_context, | 949 resource_context, |
| 922 referrer)) { | 950 referrer)) { |
| 923 AbortRequestBeforeItStarts(filter_, sync_result, route_id, request_id); | 951 AbortRequestBeforeItStarts(filter, sync_result, route_id, request_id); |
| 924 return; | 952 return; |
| 925 } | 953 } |
| 926 | 954 |
| 927 int load_flags = | 955 int load_flags = |
| 928 BuildLoadFlagsForRequest(request_data, child_id, sync_result != NULL); | 956 BuildLoadFlagsForRequest(request_data, child_id, sync_result != NULL); |
| 929 | 957 |
| 930 // Construct the request. | 958 // Construct the request. |
| 931 scoped_ptr<net::URLRequest> new_request; | 959 scoped_ptr<net::URLRequest> new_request; |
| 932 net::URLRequest* request; | 960 net::URLRequest* request; |
| 933 if (deferred_loader.get()) { | 961 if (deferred_loader.get()) { |
| 934 request = deferred_loader->request(); | 962 request = deferred_loader->request(); |
| 935 | 963 |
| 936 // Give the ResourceLoader (or any of the ResourceHandlers held by it) a | 964 // Give the ResourceLoader (or any of the ResourceHandlers held by it) a |
| 937 // chance to reset some state before we complete the transfer. | 965 // chance to reset some state before we complete the transfer. |
| 938 deferred_loader->WillCompleteTransfer(); | 966 deferred_loader->WillCompleteTransfer(); |
| 939 } else { | 967 } else { |
| 940 new_request.reset(new net::URLRequest( | 968 new_request.reset(new net::URLRequest( |
| 941 request_data.url, | 969 request_data.url, |
| 942 NULL, | 970 NULL, |
| 943 filter_->GetURLRequestContext(request_data.resource_type))); | 971 filter->GetURLRequestContext(request_data.resource_type))); |
| 944 request = new_request.get(); | 972 request = new_request.get(); |
| 945 | 973 |
| 946 request->set_method(request_data.method); | 974 request->set_method(request_data.method); |
| 947 request->set_first_party_for_cookies(request_data.first_party_for_cookies); | 975 request->set_first_party_for_cookies(request_data.first_party_for_cookies); |
| 948 request->set_referrer(referrer.url.spec()); | 976 request->set_referrer(referrer.url.spec()); |
| 949 webkit_glue::ConfigureURLRequestForReferrerPolicy(request, | 977 webkit_glue::ConfigureURLRequestForReferrerPolicy(request, |
| 950 referrer.policy); | 978 referrer.policy); |
| 951 net::HttpRequestHeaders headers; | 979 net::HttpRequestHeaders headers; |
| 952 headers.AddHeadersFromString(request_data.headers); | 980 headers.AddHeadersFromString(request_data.headers); |
| 953 request->SetExtraRequestHeaders(headers); | 981 request->SetExtraRequestHeaders(headers); |
| 954 } | 982 } |
| 955 | 983 |
| 956 // TODO(darin): Do we really need all of these URLRequest setters in the | 984 // TODO(darin): Do we really need all of these URLRequest setters in the |
| 957 // transferred navigation case? | 985 // transferred navigation case? |
| 958 | 986 |
| 959 request->set_load_flags(load_flags); | 987 request->set_load_flags(load_flags); |
| 960 | 988 |
| 961 request->set_priority(DetermineRequestPriority(request_data.resource_type)); | 989 request->set_priority(DetermineRequestPriority(request_data.resource_type)); |
| 962 | 990 |
| 963 // Set upload data. | 991 // Set upload data. |
| 964 uint64 upload_size = 0; | 992 if (request_data.upload_data) |
| 965 if (request_data.upload_data) { | |
| 966 request->set_upload(request_data.upload_data); | 993 request->set_upload(request_data.upload_data); |
| 967 // This results in performing file IO. crbug.com/112607. | |
| 968 base::ThreadRestrictions::ScopedAllowIO allow_io; | |
| 969 upload_size = request_data.upload_data->GetContentLengthSync(); | |
| 970 } | |
| 971 | 994 |
| 972 bool allow_download = request_data.allow_download && | 995 bool allow_download = request_data.allow_download && |
| 973 ResourceType::IsFrame(request_data.resource_type); | 996 ResourceType::IsFrame(request_data.resource_type); |
| 974 | 997 |
| 975 // Make extra info and read footer (contains request ID). | 998 // Make extra info and read footer (contains request ID). |
| 976 ResourceRequestInfoImpl* extra_info = | 999 ResourceRequestInfoImpl* extra_info = |
| 977 new ResourceRequestInfoImpl( | 1000 new ResourceRequestInfoImpl( |
| 978 process_type, | 1001 process_type, |
| 979 child_id, | 1002 child_id, |
| 980 route_id, | 1003 route_id, |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 1005 | 1028 |
| 1006 // Have the appcache associate its extra info with the request. | 1029 // Have the appcache associate its extra info with the request. |
| 1007 appcache::AppCacheInterceptor::SetExtraRequestInfo( | 1030 appcache::AppCacheInterceptor::SetExtraRequestInfo( |
| 1008 request, ResourceContext::GetAppCacheService(resource_context), child_id, | 1031 request, ResourceContext::GetAppCacheService(resource_context), child_id, |
| 1009 request_data.appcache_host_id, request_data.resource_type); | 1032 request_data.appcache_host_id, request_data.resource_type); |
| 1010 | 1033 |
| 1011 // Construct the IPC resource handler. | 1034 // Construct the IPC resource handler. |
| 1012 scoped_ptr<ResourceHandler> handler; | 1035 scoped_ptr<ResourceHandler> handler; |
| 1013 if (sync_result) { | 1036 if (sync_result) { |
| 1014 handler.reset(new SyncResourceHandler( | 1037 handler.reset(new SyncResourceHandler( |
| 1015 filter_, request, sync_result, this)); | 1038 filter, request, sync_result, this)); |
| 1016 } else { | 1039 } else { |
| 1017 handler.reset(new AsyncResourceHandler( | 1040 handler.reset(new AsyncResourceHandler( |
| 1018 filter_, route_id, request, this)); | 1041 filter, route_id, request, this)); |
| 1019 } | 1042 } |
| 1020 | 1043 |
| 1021 // The RedirectToFileResourceHandler depends on being next in the chain. | 1044 // The RedirectToFileResourceHandler depends on being next in the chain. |
| 1022 if (request_data.download_to_file) { | 1045 if (request_data.download_to_file) { |
| 1023 handler.reset( | 1046 handler.reset( |
| 1024 new RedirectToFileResourceHandler(handler.Pass(), child_id, this)); | 1047 new RedirectToFileResourceHandler(handler.Pass(), child_id, this)); |
| 1025 } | 1048 } |
| 1026 | 1049 |
| 1027 // Install a CrossSiteResourceHandler if this request is coming from a | 1050 // Install a CrossSiteResourceHandler if this request is coming from a |
| 1028 // RenderViewHost with a pending cross-site request. We only check this for | 1051 // RenderViewHost with a pending cross-site request. We only check this for |
| (...skipping 690 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1719 | 1742 |
| 1720 return i->second.get(); | 1743 return i->second.get(); |
| 1721 } | 1744 } |
| 1722 | 1745 |
| 1723 ResourceLoader* ResourceDispatcherHostImpl::GetLoader(int child_id, | 1746 ResourceLoader* ResourceDispatcherHostImpl::GetLoader(int child_id, |
| 1724 int request_id) const { | 1747 int request_id) const { |
| 1725 return GetLoader(GlobalRequestID(child_id, request_id)); | 1748 return GetLoader(GlobalRequestID(child_id, request_id)); |
| 1726 } | 1749 } |
| 1727 | 1750 |
| 1728 } // namespace content | 1751 } // namespace content |
| OLD | NEW |