| 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> |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 92 | 92 |
| 93 namespace content { | 93 namespace content { |
| 94 | 94 |
| 95 namespace { | 95 namespace { |
| 96 | 96 |
| 97 static ResourceDispatcherHostImpl* g_resource_dispatcher_host; | 97 static ResourceDispatcherHostImpl* g_resource_dispatcher_host; |
| 98 | 98 |
| 99 // The interval for calls to ResourceDispatcherHostImpl::UpdateLoadStates | 99 // The interval for calls to ResourceDispatcherHostImpl::UpdateLoadStates |
| 100 const int kUpdateLoadStatesIntervalMsec = 100; | 100 const int kUpdateLoadStatesIntervalMsec = 100; |
| 101 | 101 |
| 102 // Maximum number of pending data messages sent to the renderer at any | |
| 103 // given time for a given request. | |
| 104 const int kMaxPendingDataMessages = 20; | |
| 105 | |
| 106 // Maximum byte "cost" of all the outstanding requests for a renderer. | 102 // Maximum byte "cost" of all the outstanding requests for a renderer. |
| 107 // See delcaration of |max_outstanding_requests_cost_per_process_| for details. | 103 // See delcaration of |max_outstanding_requests_cost_per_process_| for details. |
| 108 // This bound is 25MB, which allows for around 6000 outstanding requests. | 104 // This bound is 25MB, which allows for around 6000 outstanding requests. |
| 109 const int kMaxOutstandingRequestsCostPerProcess = 26214400; | 105 const int kMaxOutstandingRequestsCostPerProcess = 26214400; |
| 110 | 106 |
| 111 // The number of milliseconds after noting a user gesture that we will | 107 // The number of milliseconds after noting a user gesture that we will |
| 112 // tag newly-created URLRequest objects with the | 108 // tag newly-created URLRequest objects with the |
| 113 // net::LOAD_MAYBE_USER_GESTURE load flag. This is a fairly arbitrary | 109 // net::LOAD_MAYBE_USER_GESTURE load flag. This is a fairly arbitrary |
| 114 // guess at how long to expect direct impact from a user gesture, but | 110 // guess at how long to expect direct impact from a user gesture, but |
| 115 // this should be OK as the load flag is a best-effort thing only, | 111 // this should be OK as the load flag is a best-effort thing only, |
| (...skipping 810 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 926 route_id, | 922 route_id, |
| 927 request_data.method, | 923 request_data.method, |
| 928 request_data.url, | 924 request_data.url, |
| 929 request_data.resource_type, | 925 request_data.resource_type, |
| 930 resource_context, | 926 resource_context, |
| 931 referrer)) { | 927 referrer)) { |
| 932 AbortRequestBeforeItStarts(filter_, sync_result, route_id, request_id); | 928 AbortRequestBeforeItStarts(filter_, sync_result, route_id, request_id); |
| 933 return; | 929 return; |
| 934 } | 930 } |
| 935 | 931 |
| 936 // Construct the event handler. | |
| 937 scoped_ptr<ResourceHandler> handler; | |
| 938 if (sync_result) { | |
| 939 handler.reset(new SyncResourceHandler( | |
| 940 filter_, request_data.url, sync_result, this)); | |
| 941 } else { | |
| 942 handler.reset(new AsyncResourceHandler( | |
| 943 filter_, route_id, request_data.url, this)); | |
| 944 } | |
| 945 | |
| 946 // The RedirectToFileResourceHandler depends on being next in the chain. | |
| 947 if (request_data.download_to_file) { | |
| 948 handler.reset( | |
| 949 new RedirectToFileResourceHandler(handler.Pass(), child_id, this)); | |
| 950 } | |
| 951 | |
| 952 int load_flags = | 932 int load_flags = |
| 953 BuildLoadFlagsForRequest(request_data, child_id, sync_result != NULL); | 933 BuildLoadFlagsForRequest(request_data, child_id, sync_result != NULL); |
| 954 | 934 |
| 955 // Construct the request. | 935 // Construct the request. |
| 956 scoped_ptr<net::URLRequest> new_request; | 936 scoped_ptr<net::URLRequest> new_request; |
| 957 net::URLRequest* request; | 937 net::URLRequest* request; |
| 958 if (deferred_loader.get()) { | 938 if (deferred_loader.get()) { |
| 959 request = deferred_loader->request(); | 939 request = deferred_loader->request(); |
| 960 } else { | 940 } else { |
| 961 new_request.reset(new net::URLRequest(request_data.url, NULL)); | 941 new_request.reset(new net::URLRequest(request_data.url, NULL)); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 982 | 962 |
| 983 // Set upload data. | 963 // Set upload data. |
| 984 uint64 upload_size = 0; | 964 uint64 upload_size = 0; |
| 985 if (request_data.upload_data) { | 965 if (request_data.upload_data) { |
| 986 request->set_upload(request_data.upload_data); | 966 request->set_upload(request_data.upload_data); |
| 987 // This results in performing file IO. crbug.com/112607. | 967 // This results in performing file IO. crbug.com/112607. |
| 988 base::ThreadRestrictions::ScopedAllowIO allow_io; | 968 base::ThreadRestrictions::ScopedAllowIO allow_io; |
| 989 upload_size = request_data.upload_data->GetContentLengthSync(); | 969 upload_size = request_data.upload_data->GetContentLengthSync(); |
| 990 } | 970 } |
| 991 | 971 |
| 972 // Construct the IPC resource handler. |
| 973 scoped_ptr<ResourceHandler> handler; |
| 974 if (sync_result) { |
| 975 handler.reset(new SyncResourceHandler( |
| 976 filter_, request, sync_result, this)); |
| 977 } else { |
| 978 handler.reset(new AsyncResourceHandler( |
| 979 filter_, route_id, request, this)); |
| 980 } |
| 981 |
| 982 // The RedirectToFileResourceHandler depends on being next in the chain. |
| 983 if (request_data.download_to_file) { |
| 984 handler.reset( |
| 985 new RedirectToFileResourceHandler(handler.Pass(), child_id, this)); |
| 986 } |
| 987 |
| 992 // Install a CrossSiteResourceHandler if this request is coming from a | 988 // Install a CrossSiteResourceHandler if this request is coming from a |
| 993 // RenderViewHost with a pending cross-site request. We only check this for | 989 // RenderViewHost with a pending cross-site request. We only check this for |
| 994 // MAIN_FRAME requests. Unblock requests only come from a blocked page, do | 990 // MAIN_FRAME requests. Unblock requests only come from a blocked page, do |
| 995 // not count as cross-site, otherwise it gets blocked indefinitely. | 991 // not count as cross-site, otherwise it gets blocked indefinitely. |
| 996 if (request_data.resource_type == ResourceType::MAIN_FRAME && | 992 if (request_data.resource_type == ResourceType::MAIN_FRAME && |
| 997 process_type == PROCESS_TYPE_RENDERER && | 993 process_type == PROCESS_TYPE_RENDERER && |
| 998 CrossSiteRequestManager::GetInstance()-> | 994 CrossSiteRequestManager::GetInstance()-> |
| 999 HasPendingCrossSiteRequest(child_id, route_id)) { | 995 HasPendingCrossSiteRequest(child_id, route_id)) { |
| 1000 // Wrap the event handler to be sure the current page's onunload handler | 996 // Wrap the event handler to be sure the current page's onunload handler |
| 1001 // has a chance to run before we render the new page. | 997 // has a chance to run before we render the new page. |
| 1002 handler.reset( | 998 handler.reset(new CrossSiteResourceHandler(handler.Pass(), child_id, |
| 1003 new CrossSiteResourceHandler(handler.Pass(), child_id, route_id, this)); | 999 route_id, request)); |
| 1004 } | 1000 } |
| 1005 | 1001 |
| 1006 // Insert a buffered event handler before the actual one. | 1002 // Insert a buffered event handler before the actual one. |
| 1007 handler.reset( | 1003 handler.reset( |
| 1008 new BufferedResourceHandler(handler.Pass(), this, request)); | 1004 new BufferedResourceHandler(handler.Pass(), this, request)); |
| 1009 | 1005 |
| 1010 ScopedVector<ResourceThrottle> throttles; | 1006 ScopedVector<ResourceThrottle> throttles; |
| 1011 if (delegate_) { | 1007 if (delegate_) { |
| 1012 bool is_continuation_of_transferred_request = | 1008 bool is_continuation_of_transferred_request = |
| 1013 (deferred_loader.get() != NULL); | 1009 (deferred_loader.get() != NULL); |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1077 } else { | 1073 } else { |
| 1078 BeginRequestInternal(new_request.Pass(), handler.Pass()); | 1074 BeginRequestInternal(new_request.Pass(), handler.Pass()); |
| 1079 } | 1075 } |
| 1080 } | 1076 } |
| 1081 | 1077 |
| 1082 void ResourceDispatcherHostImpl::OnReleaseDownloadedFile(int request_id) { | 1078 void ResourceDispatcherHostImpl::OnReleaseDownloadedFile(int request_id) { |
| 1083 UnregisterDownloadedTempFile(filter_->child_id(), request_id); | 1079 UnregisterDownloadedTempFile(filter_->child_id(), request_id); |
| 1084 } | 1080 } |
| 1085 | 1081 |
| 1086 void ResourceDispatcherHostImpl::OnDataReceivedACK(int request_id) { | 1082 void ResourceDispatcherHostImpl::OnDataReceivedACK(int request_id) { |
| 1087 DataReceivedACK(filter_->child_id(), request_id); | 1083 ResourceLoader* loader = GetLoader(filter_->child_id(), request_id); |
| 1088 } | |
| 1089 | |
| 1090 void ResourceDispatcherHostImpl::DataReceivedACK(int child_id, | |
| 1091 int request_id) { | |
| 1092 ResourceLoader* loader = GetLoader(child_id, request_id); | |
| 1093 if (!loader) | 1084 if (!loader) |
| 1094 return; | 1085 return; |
| 1095 | 1086 |
| 1096 ResourceRequestInfoImpl* info = loader->GetRequestInfo(); | 1087 ResourceRequestInfoImpl* info = loader->GetRequestInfo(); |
| 1097 | 1088 if (info->async_handler()) |
| 1098 // Decrement the number of pending data messages. | 1089 info->async_handler()->OnDataReceivedACK(); |
| 1099 info->DecrementPendingDataCount(); | |
| 1100 | |
| 1101 // If the pending data count was higher than the max, resume the request. | |
| 1102 if (info->pending_data_count() == kMaxPendingDataMessages) { | |
| 1103 // Decrement the pending data count one more time because we also | |
| 1104 // incremented it before pausing the request. | |
| 1105 info->DecrementPendingDataCount(); | |
| 1106 | |
| 1107 // Resume the request. | |
| 1108 // | |
| 1109 // TODO(darin): Make the AsyncResourceHandler be responsible for resuming | |
| 1110 // via its controller(). This static_cast is here as a temporary measure. | |
| 1111 // | |
| 1112 static_cast<ResourceController*>(loader)->Resume(); | |
| 1113 } | |
| 1114 } | 1090 } |
| 1115 | 1091 |
| 1116 void ResourceDispatcherHostImpl::OnDataDownloadedACK(int request_id) { | 1092 void ResourceDispatcherHostImpl::OnDataDownloadedACK(int request_id) { |
| 1117 // TODO(michaeln): maybe throttle DataDownloaded messages | 1093 // TODO(michaeln): maybe throttle DataDownloaded messages |
| 1118 } | 1094 } |
| 1119 | 1095 |
| 1120 void ResourceDispatcherHostImpl::RegisterDownloadedTempFile( | 1096 void ResourceDispatcherHostImpl::RegisterDownloadedTempFile( |
| 1121 int child_id, int request_id, ShareableFileReference* reference) { | 1097 int child_id, int request_id, ShareableFileReference* reference) { |
| 1122 registered_temp_files_[child_id][request_id] = reference; | 1098 registered_temp_files_[child_id][request_id] = reference; |
| 1123 ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFile( | 1099 ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFile( |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1167 void ResourceDispatcherHostImpl::OnFollowRedirect( | 1143 void ResourceDispatcherHostImpl::OnFollowRedirect( |
| 1168 int request_id, | 1144 int request_id, |
| 1169 bool has_new_first_party_for_cookies, | 1145 bool has_new_first_party_for_cookies, |
| 1170 const GURL& new_first_party_for_cookies) { | 1146 const GURL& new_first_party_for_cookies) { |
| 1171 ResourceLoader* loader = GetLoader(filter_->child_id(), request_id); | 1147 ResourceLoader* loader = GetLoader(filter_->child_id(), request_id); |
| 1172 if (!loader) { | 1148 if (!loader) { |
| 1173 DVLOG(1) << "OnFollowRedirect for invalid request"; | 1149 DVLOG(1) << "OnFollowRedirect for invalid request"; |
| 1174 return; | 1150 return; |
| 1175 } | 1151 } |
| 1176 | 1152 |
| 1177 loader->OnFollowRedirect(has_new_first_party_for_cookies, | 1153 ResourceRequestInfoImpl* info = loader->GetRequestInfo(); |
| 1178 new_first_party_for_cookies); | 1154 if (info->async_handler()) { |
| 1155 info->async_handler()->OnFollowRedirect( |
| 1156 has_new_first_party_for_cookies, |
| 1157 new_first_party_for_cookies); |
| 1158 } |
| 1179 } | 1159 } |
| 1180 | 1160 |
| 1181 ResourceRequestInfoImpl* ResourceDispatcherHostImpl::CreateRequestInfo( | 1161 ResourceRequestInfoImpl* ResourceDispatcherHostImpl::CreateRequestInfo( |
| 1182 int child_id, | 1162 int child_id, |
| 1183 int route_id, | 1163 int route_id, |
| 1184 bool download, | 1164 bool download, |
| 1185 ResourceContext* context) { | 1165 ResourceContext* context) { |
| 1186 return new ResourceRequestInfoImpl( | 1166 return new ResourceRequestInfoImpl( |
| 1187 PROCESS_TYPE_RENDERER, | 1167 PROCESS_TYPE_RENDERER, |
| 1188 child_id, | 1168 child_id, |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1283 request->set_context(context->GetRequestContext()); | 1263 request->set_context(context->GetRequestContext()); |
| 1284 | 1264 |
| 1285 // Since we're just saving some resources we need, disallow downloading. | 1265 // Since we're just saving some resources we need, disallow downloading. |
| 1286 ResourceRequestInfoImpl* extra_info = | 1266 ResourceRequestInfoImpl* extra_info = |
| 1287 CreateRequestInfo(child_id, route_id, false, context); | 1267 CreateRequestInfo(child_id, route_id, false, context); |
| 1288 extra_info->AssociateWithRequest(request.get()); // Request takes ownership. | 1268 extra_info->AssociateWithRequest(request.get()); // Request takes ownership. |
| 1289 | 1269 |
| 1290 BeginRequestInternal(request.Pass(), handler.Pass()); | 1270 BeginRequestInternal(request.Pass(), handler.Pass()); |
| 1291 } | 1271 } |
| 1292 | 1272 |
| 1293 bool ResourceDispatcherHostImpl::WillSendData(int child_id, int request_id, | |
| 1294 bool* defer) { | |
| 1295 ResourceLoader* loader = GetLoader(child_id, request_id); | |
| 1296 if (!loader) { | |
| 1297 NOTREACHED() << "WillSendData for invalid request"; | |
| 1298 return false; | |
| 1299 } | |
| 1300 | |
| 1301 ResourceRequestInfoImpl* info = loader->GetRequestInfo(); | |
| 1302 | |
| 1303 info->IncrementPendingDataCount(); | |
| 1304 if (info->pending_data_count() > kMaxPendingDataMessages) { | |
| 1305 // We reached the max number of data messages that can be sent to | |
| 1306 // the renderer for a given request. Pause the request and wait for | |
| 1307 // the renderer to start processing them before resuming it. | |
| 1308 *defer = true; | |
| 1309 return false; | |
| 1310 } | |
| 1311 | |
| 1312 return true; | |
| 1313 } | |
| 1314 | |
| 1315 void ResourceDispatcherHostImpl::MarkAsTransferredNavigation( | 1273 void ResourceDispatcherHostImpl::MarkAsTransferredNavigation( |
| 1316 const GlobalRequestID& id) { | 1274 const GlobalRequestID& id) { |
| 1317 GetLoader(id)->MarkAsTransferring(); | 1275 GetLoader(id)->MarkAsTransferring(); |
| 1318 } | 1276 } |
| 1319 | 1277 |
| 1320 int ResourceDispatcherHostImpl::GetOutstandingRequestsMemoryCost( | 1278 int ResourceDispatcherHostImpl::GetOutstandingRequestsMemoryCost( |
| 1321 int child_id) const { | 1279 int child_id) const { |
| 1322 OutstandingRequestsMemoryCostMap::const_iterator entry = | 1280 OutstandingRequestsMemoryCostMap::const_iterator entry = |
| 1323 outstanding_requests_memory_cost_map_.find(child_id); | 1281 outstanding_requests_memory_cost_map_.find(child_id); |
| 1324 return (entry == outstanding_requests_memory_cost_map_.end()) ? | 1282 return (entry == outstanding_requests_memory_cost_map_.end()) ? |
| (...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1756 | 1714 |
| 1757 return i->second.get(); | 1715 return i->second.get(); |
| 1758 } | 1716 } |
| 1759 | 1717 |
| 1760 ResourceLoader* ResourceDispatcherHostImpl::GetLoader(int child_id, | 1718 ResourceLoader* ResourceDispatcherHostImpl::GetLoader(int child_id, |
| 1761 int request_id) const { | 1719 int request_id) const { |
| 1762 return GetLoader(GlobalRequestID(child_id, request_id)); | 1720 return GetLoader(GlobalRequestID(child_id, request_id)); |
| 1763 } | 1721 } |
| 1764 | 1722 |
| 1765 } // namespace content | 1723 } // namespace content |
| OLD | NEW |