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 |