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/loader/resource_dispatcher_host_impl.h" | 7 #include "content/browser/loader/resource_dispatcher_host_impl.h" |
8 | 8 |
9 #include <set> | 9 #include <set> |
10 #include <vector> | 10 #include <vector> |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
120 // net::LOAD_MAYBE_USER_GESTURE load flag. This is a fairly arbitrary | 120 // net::LOAD_MAYBE_USER_GESTURE load flag. This is a fairly arbitrary |
121 // guess at how long to expect direct impact from a user gesture, but | 121 // guess at how long to expect direct impact from a user gesture, but |
122 // this should be OK as the load flag is a best-effort thing only, | 122 // this should be OK as the load flag is a best-effort thing only, |
123 // rather than being intended as fully accurate. | 123 // rather than being intended as fully accurate. |
124 const int kUserGestureWindowMs = 3500; | 124 const int kUserGestureWindowMs = 3500; |
125 | 125 |
126 // Ratio of |max_num_in_flight_requests_| that any one renderer is allowed to | 126 // Ratio of |max_num_in_flight_requests_| that any one renderer is allowed to |
127 // use. Arbitrarily chosen. | 127 // use. Arbitrarily chosen. |
128 const double kMaxRequestsPerProcessRatio = 0.45; | 128 const double kMaxRequestsPerProcessRatio = 0.45; |
129 | 129 |
130 bool IsDetachableResourceType(ResourceType::Type type) { | |
131 switch (type) { | |
132 case ResourceType::PREFETCH: | |
133 return true; | |
134 default: | |
135 return false; | |
136 } | |
137 } | |
138 | |
130 // Aborts a request before an URLRequest has actually been created. | 139 // Aborts a request before an URLRequest has actually been created. |
131 void AbortRequestBeforeItStarts(ResourceMessageFilter* filter, | 140 void AbortRequestBeforeItStarts(ResourceMessageFilter* filter, |
132 IPC::Message* sync_result, | 141 IPC::Message* sync_result, |
133 int request_id) { | 142 int request_id) { |
134 if (sync_result) { | 143 if (sync_result) { |
135 SyncLoadResult result; | 144 SyncLoadResult result; |
136 result.error_code = net::ERR_ABORTED; | 145 result.error_code = net::ERR_ABORTED; |
137 ResourceHostMsg_SyncLoad::WriteReplyParams(sync_result, result); | 146 ResourceHostMsg_SyncLoad::WriteReplyParams(sync_result, result); |
138 filter->Send(sync_result); | 147 filter->Send(sync_result); |
139 } else { | 148 } else { |
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
399 delete loaders; | 408 delete loaders; |
400 } else { | 409 } else { |
401 ++i; | 410 ++i; |
402 } | 411 } |
403 } | 412 } |
404 | 413 |
405 #ifndef NDEBUG | 414 #ifndef NDEBUG |
406 for (LoaderList::iterator i = loaders_to_cancel.begin(); | 415 for (LoaderList::iterator i = loaders_to_cancel.begin(); |
407 i != loaders_to_cancel.end(); ++i) { | 416 i != loaders_to_cancel.end(); ++i) { |
408 // There is no strict requirement that this be the case, but currently | 417 // There is no strict requirement that this be the case, but currently |
409 // downloads, streams and transferred requests are the only requests that | 418 // downloads, streams, detachable requests, and transferred requests are the |
410 // aren't cancelled when the associated processes go away. It may be OK for | 419 // only requests that aren't cancelled when the associated processes go |
411 // this invariant to change in the future, but if this assertion fires | 420 // away. It may be OK for this invariant to change in the future, but if |
412 // without the invariant changing, then it's indicative of a leak. | 421 // this assertion fires without the invariant changing, then it's indicative |
413 DCHECK((*i)->GetRequestInfo()->is_download() || | 422 // of a leak. |
414 (*i)->GetRequestInfo()->is_stream() || | 423 DCHECK( |
415 (*i)->is_transferring()); | 424 (*i)->GetRequestInfo()->is_download() || |
425 (*i)->GetRequestInfo()->is_stream() || | |
426 (*i)->GetRequestInfo()->is_detachable() || | |
427 (*i)->is_transferring()); | |
416 } | 428 } |
417 #endif | 429 #endif |
418 | 430 |
419 loaders_to_cancel.clear(); | 431 loaders_to_cancel.clear(); |
420 | 432 |
421 // Validate that no more requests for this context were added. | 433 // Validate that no more requests for this context were added. |
422 for (LoaderMap::const_iterator i = pending_loaders_.begin(); | 434 for (LoaderMap::const_iterator i = pending_loaders_.begin(); |
423 i != pending_loaders_.end(); ++i) { | 435 i != pending_loaders_.end(); ++i) { |
424 // http://crbug.com/90971 | 436 // http://crbug.com/90971 |
425 CHECK_NE(i->second->GetRequestInfo()->GetContext(), context); | 437 CHECK_NE(i->second->GetRequestInfo()->GetContext(), context); |
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
687 new_url)); | 699 new_url)); |
688 BrowserThread::PostTask( | 700 BrowserThread::PostTask( |
689 BrowserThread::UI, FROM_HERE, | 701 BrowserThread::UI, FROM_HERE, |
690 base::Bind( | 702 base::Bind( |
691 &NotifyRedirectOnUI, | 703 &NotifyRedirectOnUI, |
692 render_process_id, render_view_id, base::Passed(&detail))); | 704 render_process_id, render_view_id, base::Passed(&detail))); |
693 } | 705 } |
694 | 706 |
695 void ResourceDispatcherHostImpl::DidReceiveResponse(ResourceLoader* loader) { | 707 void ResourceDispatcherHostImpl::DidReceiveResponse(ResourceLoader* loader) { |
696 ResourceRequestInfoImpl* info = loader->GetRequestInfo(); | 708 ResourceRequestInfoImpl* info = loader->GetRequestInfo(); |
709 | |
697 // There should be an entry in the map created when we dispatched the | 710 // There should be an entry in the map created when we dispatched the |
698 // request. | 711 // request unless it's been detached and the renderer has died. |
699 OfflineMap::iterator policy_it( | 712 OfflineMap::iterator policy_it( |
700 offline_policy_map_.find(info->GetGlobalRoutingID())); | 713 offline_policy_map_.find(info->GetGlobalRoutingID())); |
701 if (offline_policy_map_.end() != policy_it) { | 714 if (offline_policy_map_.end() != policy_it) { |
702 policy_it->second->UpdateStateForSuccessfullyStartedRequest( | 715 policy_it->second->UpdateStateForSuccessfullyStartedRequest( |
703 loader->request()->response_info()); | 716 loader->request()->response_info()); |
704 } else { | 717 } else { |
705 // We should always have an entry in offline_policy_map_ from when | 718 // Unless detachable, we should have an entry in offline_policy_map_ from |
706 // this request traversed Begin{Download,SaveFile,Request}. | 719 // when this request traversed Begin{Download,SaveFile,Request}. |
707 // TODO(rdsmith): This isn't currently true; see http://crbug.com/241176. | 720 // TODO(rdsmith): This isn't currently true; see http://crbug.com/241176. |
708 NOTREACHED(); | 721 DCHECK(info->is_detachable()); |
709 } | 722 } |
710 | 723 |
711 int render_process_id, render_view_id; | 724 int render_process_id, render_view_id; |
712 if (!info->GetAssociatedRenderView(&render_process_id, &render_view_id)) | 725 if (!info->GetAssociatedRenderView(&render_process_id, &render_view_id)) |
713 return; | 726 return; |
714 | 727 |
715 // Notify the observers on the UI thread. | 728 // Notify the observers on the UI thread. |
716 scoped_ptr<ResourceRequestDetails> detail(new ResourceRequestDetails( | 729 scoped_ptr<ResourceRequestDetails> detail(new ResourceRequestDetails( |
717 loader->request(), | 730 loader->request(), |
718 GetCertID(loader->request(), info->GetChildID()))); | 731 GetCertID(loader->request(), info->GetChildID()))); |
(...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1066 request_data.origin_pid, | 1079 request_data.origin_pid, |
1067 request_id, | 1080 request_id, |
1068 request_data.is_main_frame, | 1081 request_data.is_main_frame, |
1069 request_data.frame_id, | 1082 request_data.frame_id, |
1070 request_data.parent_is_main_frame, | 1083 request_data.parent_is_main_frame, |
1071 request_data.parent_frame_id, | 1084 request_data.parent_frame_id, |
1072 request_data.resource_type, | 1085 request_data.resource_type, |
1073 request_data.transition_type, | 1086 request_data.transition_type, |
1074 false, // is download | 1087 false, // is download |
1075 false, // is stream | 1088 false, // is stream |
1089 false, // is detachable | |
1076 allow_download, | 1090 allow_download, |
1077 request_data.has_user_gesture, | 1091 request_data.has_user_gesture, |
1078 request_data.referrer_policy, | 1092 request_data.referrer_policy, |
1079 resource_context, | 1093 resource_context, |
1080 filter_->GetWeakPtr(), | 1094 filter_->GetWeakPtr(), |
1081 !is_sync_load); | 1095 !is_sync_load); |
1082 extra_info->AssociateWithRequest(request); // Request takes ownership. | 1096 extra_info->AssociateWithRequest(request); // Request takes ownership. |
1083 | 1097 |
1084 if (request->url().SchemeIs(chrome::kBlobScheme)) { | 1098 if (request->url().SchemeIs(chrome::kBlobScheme)) { |
1085 // Hang on to a reference to ensure the blob is not released prior | 1099 // Hang on to a reference to ensure the blob is not released prior |
1086 // to the job being started. | 1100 // to the job being started. |
1087 webkit_blob::BlobProtocolHandler::SetRequestedBlobDataHandle( | 1101 webkit_blob::BlobProtocolHandler::SetRequestedBlobDataHandle( |
1088 request, | 1102 request, |
1089 filter_->blob_storage_context()->context()-> | 1103 filter_->blob_storage_context()->context()-> |
1090 GetBlobDataFromPublicURL(request->url())); | 1104 GetBlobDataFromPublicURL(request->url())); |
1091 } | 1105 } |
1092 | 1106 |
1093 // Have the appcache associate its extra info with the request. | 1107 // Have the appcache associate its extra info with the request. |
1094 appcache::AppCacheInterceptor::SetExtraRequestInfo( | 1108 appcache::AppCacheInterceptor::SetExtraRequestInfo( |
1095 request, filter_->appcache_service(), child_id, | 1109 request, filter_->appcache_service(), child_id, |
1096 request_data.appcache_host_id, request_data.resource_type); | 1110 request_data.appcache_host_id, request_data.resource_type); |
1097 | 1111 |
1098 // Construct the IPC resource handler. | 1112 // Construct the IPC resource handler. |
1099 scoped_ptr<ResourceHandler> handler; | 1113 scoped_ptr<ResourceHandler> handler; |
1100 if (sync_result) { | 1114 if (sync_result) { |
1101 handler.reset(new SyncResourceHandler(request, sync_result, this)); | 1115 handler.reset(new SyncResourceHandler(request, sync_result, this)); |
1102 } else { | 1116 } else { |
1103 handler.reset(new AsyncResourceHandler(request, this)); | 1117 handler.reset(new AsyncResourceHandler(request, this)); |
1118 if (IsDetachableResourceType(request_data.resource_type)) | |
1119 extra_info->set_is_detachable(true); | |
1104 } | 1120 } |
1105 | 1121 |
1106 // The RedirectToFileResourceHandler depends on being next in the chain. | 1122 // The RedirectToFileResourceHandler depends on being next in the chain. |
1107 if (request_data.download_to_file) { | 1123 if (request_data.download_to_file) { |
1108 handler.reset( | 1124 handler.reset( |
1109 new RedirectToFileResourceHandler(handler.Pass(), request, this)); | 1125 new RedirectToFileResourceHandler(handler.Pass(), request, this)); |
1110 } | 1126 } |
1111 | 1127 |
1112 // Install a CrossSiteResourceHandler for all main frame requests. This will | 1128 // Install a CrossSiteResourceHandler for all main frame requests. This will |
1113 // let us check whether a transfer is required and pause for the unload | 1129 // let us check whether a transfer is required and pause for the unload |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1212 route_id, | 1228 route_id, |
1213 0, | 1229 0, |
1214 request_id_, | 1230 request_id_, |
1215 false, // is_main_frame | 1231 false, // is_main_frame |
1216 -1, // frame_id | 1232 -1, // frame_id |
1217 false, // parent_is_main_frame | 1233 false, // parent_is_main_frame |
1218 -1, // parent_frame_id | 1234 -1, // parent_frame_id |
1219 ResourceType::SUB_RESOURCE, | 1235 ResourceType::SUB_RESOURCE, |
1220 PAGE_TRANSITION_LINK, | 1236 PAGE_TRANSITION_LINK, |
1221 download, // is_download | 1237 download, // is_download |
1222 false, // is_stream | 1238 false, // is_stream |
1239 false, // is_detachable | |
1223 download, // allow_download | 1240 download, // allow_download |
1224 false, // has_user_gesture | 1241 false, // has_user_gesture |
1225 WebKit::WebReferrerPolicyDefault, | 1242 WebKit::WebReferrerPolicyDefault, |
1226 context, | 1243 context, |
1227 base::WeakPtr<ResourceMessageFilter>(), // filter | 1244 base::WeakPtr<ResourceMessageFilter>(), // filter |
1228 true); // is_async | 1245 true); // is_async |
1229 } | 1246 } |
1230 | 1247 |
1231 void ResourceDispatcherHostImpl::OnRenderViewHostCreated( | 1248 void ResourceDispatcherHostImpl::OnRenderViewHostCreated( |
1232 int child_id, | 1249 int child_id, |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1308 ResourceLoader* loader = GetLoader(id); | 1325 ResourceLoader* loader = GetLoader(id); |
1309 if (loader) { | 1326 if (loader) { |
1310 // The response we were meant to resume could have already been canceled. | 1327 // The response we were meant to resume could have already been canceled. |
1311 ResourceRequestInfoImpl* info = loader->GetRequestInfo(); | 1328 ResourceRequestInfoImpl* info = loader->GetRequestInfo(); |
1312 if (info->cross_site_handler()) | 1329 if (info->cross_site_handler()) |
1313 info->cross_site_handler()->ResumeResponse(); | 1330 info->cross_site_handler()->ResumeResponse(); |
1314 } | 1331 } |
1315 } | 1332 } |
1316 | 1333 |
1317 // The object died, so cancel and detach all requests associated with it except | 1334 // The object died, so cancel and detach all requests associated with it except |
1318 // for downloads, which belong to the browser process even if initiated via a | 1335 // for downloads and detachable resources, which belong to the browser process |
1319 // renderer. | 1336 // even if initiated via a renderer. |
1320 void ResourceDispatcherHostImpl::CancelRequestsForProcess(int child_id) { | 1337 void ResourceDispatcherHostImpl::CancelRequestsForProcess(int child_id) { |
1321 CancelRequestsForRoute(child_id, -1 /* cancel all */); | 1338 CancelRequestsForRoute(child_id, -1 /* cancel all */); |
1322 registered_temp_files_.erase(child_id); | 1339 registered_temp_files_.erase(child_id); |
1323 } | 1340 } |
1324 | 1341 |
1325 void ResourceDispatcherHostImpl::CancelRequestsForRoute(int child_id, | 1342 void ResourceDispatcherHostImpl::CancelRequestsForRoute(int child_id, |
1326 int route_id) { | 1343 int route_id) { |
1327 // Since pending_requests_ is a map, we first build up a list of all of the | 1344 // Since pending_requests_ is a map, we first build up a list of all of the |
1328 // matching requests to be cancelled, and then we cancel them. Since there | 1345 // matching requests to be cancelled, and then we cancel them. Since there |
1329 // may be more than one request to cancel, we cannot simply hold onto the map | 1346 // may be more than one request to cancel, we cannot simply hold onto the map |
1330 // iterators found in the first loop. | 1347 // iterators found in the first loop. |
1331 | 1348 |
1332 // Find the global ID of all matching elements. | 1349 // Find the global ID of all matching elements. |
1333 bool any_requests_transferring = false; | 1350 bool any_requests_transferring = false; |
1334 std::vector<GlobalRequestID> matching_requests; | 1351 std::vector<GlobalRequestID> matching_requests; |
1335 for (LoaderMap::const_iterator i = pending_loaders_.begin(); | 1352 for (LoaderMap::const_iterator i = pending_loaders_.begin(); |
1336 i != pending_loaders_.end(); ++i) { | 1353 i != pending_loaders_.end(); ++i) { |
1337 if (i->first.child_id != child_id) | 1354 if (i->first.child_id != child_id) |
1338 continue; | 1355 continue; |
1339 | 1356 |
1340 ResourceRequestInfoImpl* info = i->second->GetRequestInfo(); | 1357 ResourceRequestInfoImpl* info = i->second->GetRequestInfo(); |
1341 | 1358 |
1342 GlobalRequestID id(child_id, i->first.request_id); | 1359 GlobalRequestID id(child_id, i->first.request_id); |
1343 DCHECK(id == i->first); | 1360 DCHECK(id == i->first); |
1361 // Don't cancel navigations that are expected to live beyond this process. | |
1362 if (IsTransferredNavigation(id)) any_requests_transferring = true; | |
James Simonsen
2013/10/26 02:25:00
nit: Split this into 2 lines. This file doesn't us
jkarlin2
2013/10/28 19:25:41
Done.
| |
1344 | 1363 |
1345 // Don't cancel navigations that are transferring to another process, | 1364 if (info->is_detachable()) { |
1346 // since they belong to another process now. | 1365 i->second->CancelAfterTimeout(); |
1347 if (IsTransferredNavigation(id)) | 1366 } else if (!info->is_download() && !info->is_stream() && |
1348 any_requests_transferring = true; | 1367 !IsTransferredNavigation(id) && |
1349 if (!info->is_download() && !info->is_stream() && | 1368 (route_id == -1 || route_id == info->GetRouteID())) { |
1350 !IsTransferredNavigation(id) && | |
1351 (route_id == -1 || route_id == info->GetRouteID())) { | |
1352 matching_requests.push_back(id); | 1369 matching_requests.push_back(id); |
1353 } | 1370 } |
1354 } | 1371 } |
1355 | 1372 |
1356 // Remove matches. | 1373 // Remove matches. |
1357 for (size_t i = 0; i < matching_requests.size(); ++i) { | 1374 for (size_t i = 0; i < matching_requests.size(); ++i) { |
1358 LoaderMap::iterator iter = pending_loaders_.find(matching_requests[i]); | 1375 LoaderMap::iterator iter = pending_loaders_.find(matching_requests[i]); |
1359 // Although every matching request was in pending_requests_ when we built | 1376 // Although every matching request was in pending_requests_ when we built |
1360 // matching_requests, it is normal for a matching request to be not found | 1377 // matching_requests, it is normal for a matching request to be not found |
1361 // in pending_requests_ after we have removed some matching requests from | 1378 // in pending_requests_ after we have removed some matching requests from |
(...skipping 550 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1912 if ((load_flags & net::LOAD_REPORT_RAW_HEADERS) | 1929 if ((load_flags & net::LOAD_REPORT_RAW_HEADERS) |
1913 && !policy->CanReadRawCookies(child_id)) { | 1930 && !policy->CanReadRawCookies(child_id)) { |
1914 VLOG(1) << "Denied unauthorized request for raw headers"; | 1931 VLOG(1) << "Denied unauthorized request for raw headers"; |
1915 load_flags &= ~net::LOAD_REPORT_RAW_HEADERS; | 1932 load_flags &= ~net::LOAD_REPORT_RAW_HEADERS; |
1916 } | 1933 } |
1917 | 1934 |
1918 return load_flags; | 1935 return load_flags; |
1919 } | 1936 } |
1920 | 1937 |
1921 } // namespace content | 1938 } // namespace content |
OLD | NEW |