Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(312)

Side by Side Diff: content/browser/loader/resource_dispatcher_host_impl.cc

Issue 25772002: Allows prefetch requests to live beyond the renderer by delaying (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Possible AsyncResourceHandler support for detached resources. Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 14 matching lines...) Expand all
25 #include "content/browser/appcache/chrome_appcache_service.h" 25 #include "content/browser/appcache/chrome_appcache_service.h"
26 #include "content/browser/cert_store_impl.h" 26 #include "content/browser/cert_store_impl.h"
27 #include "content/browser/child_process_security_policy_impl.h" 27 #include "content/browser/child_process_security_policy_impl.h"
28 #include "content/browser/cross_site_request_manager.h" 28 #include "content/browser/cross_site_request_manager.h"
29 #include "content/browser/download/download_resource_handler.h" 29 #include "content/browser/download/download_resource_handler.h"
30 #include "content/browser/download/save_file_manager.h" 30 #include "content/browser/download/save_file_manager.h"
31 #include "content/browser/download/save_file_resource_handler.h" 31 #include "content/browser/download/save_file_resource_handler.h"
32 #include "content/browser/fileapi/chrome_blob_storage_context.h" 32 #include "content/browser/fileapi/chrome_blob_storage_context.h"
33 #include "content/browser/loader/async_resource_handler.h" 33 #include "content/browser/loader/async_resource_handler.h"
34 #include "content/browser/loader/buffered_resource_handler.h" 34 #include "content/browser/loader/buffered_resource_handler.h"
35 #include "content/browser/loader/detached_resource_handler.h"
mmenke 2013/10/17 18:33:48 Remove.
jkarlin2 2013/10/24 15:33:11 Done.
35 #include "content/browser/loader/cross_site_resource_handler.h" 36 #include "content/browser/loader/cross_site_resource_handler.h"
36 #include "content/browser/loader/power_save_block_resource_throttle.h" 37 #include "content/browser/loader/power_save_block_resource_throttle.h"
37 #include "content/browser/loader/redirect_to_file_resource_handler.h" 38 #include "content/browser/loader/redirect_to_file_resource_handler.h"
38 #include "content/browser/loader/resource_message_filter.h" 39 #include "content/browser/loader/resource_message_filter.h"
39 #include "content/browser/loader/resource_request_info_impl.h" 40 #include "content/browser/loader/resource_request_info_impl.h"
40 #include "content/browser/loader/stream_resource_handler.h" 41 #include "content/browser/loader/stream_resource_handler.h"
41 #include "content/browser/loader/sync_resource_handler.h" 42 #include "content/browser/loader/sync_resource_handler.h"
42 #include "content/browser/loader/throttling_resource_handler.h" 43 #include "content/browser/loader/throttling_resource_handler.h"
43 #include "content/browser/loader/upload_data_stream_builder.h" 44 #include "content/browser/loader/upload_data_stream_builder.h"
44 #include "content/browser/plugin_service_impl.h" 45 #include "content/browser/plugin_service_impl.h"
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
120 // net::LOAD_MAYBE_USER_GESTURE load flag. This is a fairly arbitrary 121 // 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 122 // 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, 123 // this should be OK as the load flag is a best-effort thing only,
123 // rather than being intended as fully accurate. 124 // rather than being intended as fully accurate.
124 const int kUserGestureWindowMs = 3500; 125 const int kUserGestureWindowMs = 3500;
125 126
126 // Ratio of |max_num_in_flight_requests_| that any one renderer is allowed to 127 // Ratio of |max_num_in_flight_requests_| that any one renderer is allowed to
127 // use. Arbitrarily chosen. 128 // use. Arbitrarily chosen.
128 const double kMaxRequestsPerProcessRatio = 0.45; 129 const double kMaxRequestsPerProcessRatio = 0.45;
129 130
131 bool IsDetachableResourceType(const ResourceType::Type type) {
132 switch (type) {
133 case ResourceType::PREFETCH:
134 return true;
135 default:
136 return false;
137 }
138 }
139
130 // Aborts a request before an URLRequest has actually been created. 140 // Aborts a request before an URLRequest has actually been created.
131 void AbortRequestBeforeItStarts(ResourceMessageFilter* filter, 141 void AbortRequestBeforeItStarts(ResourceMessageFilter* filter,
132 IPC::Message* sync_result, 142 IPC::Message* sync_result,
133 int request_id) { 143 int request_id) {
134 if (sync_result) { 144 if (sync_result) {
135 SyncLoadResult result; 145 SyncLoadResult result;
136 result.error_code = net::ERR_ABORTED; 146 result.error_code = net::ERR_ABORTED;
137 ResourceHostMsg_SyncLoad::WriteReplyParams(sync_result, result); 147 ResourceHostMsg_SyncLoad::WriteReplyParams(sync_result, result);
138 filter->Send(sync_result); 148 filter->Send(sync_result);
139 } else { 149 } else {
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after
399 delete loaders; 409 delete loaders;
400 } else { 410 } else {
401 ++i; 411 ++i;
402 } 412 }
403 } 413 }
404 414
405 #ifndef NDEBUG 415 #ifndef NDEBUG
406 for (LoaderList::iterator i = loaders_to_cancel.begin(); 416 for (LoaderList::iterator i = loaders_to_cancel.begin();
407 i != loaders_to_cancel.end(); ++i) { 417 i != loaders_to_cancel.end(); ++i) {
408 // There is no strict requirement that this be the case, but currently 418 // There is no strict requirement that this be the case, but currently
409 // downloads, streams and transferred requests are the only requests that 419 // downloads, streams, detachable requests, and transferred requests are the
410 // aren't cancelled when the associated processes go away. It may be OK for 420 // only requests that aren't cancelled when the associated processes go
411 // this invariant to change in the future, but if this assertion fires 421 // 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. 422 // this assertion fires without the invariant changing, then it's indicative
413 DCHECK((*i)->GetRequestInfo()->is_download() || 423 // of a leak.
414 (*i)->GetRequestInfo()->is_stream() || 424 DCHECK(
415 (*i)->is_transferring()); 425 (*i)->GetRequestInfo()->is_download() ||
426 (*i)->GetRequestInfo()->is_stream() ||
427 (*i)->GetRequestInfo()->is_detachable() ||
mmenke 2013/10/17 18:33:48 Wait...what's stopping us from putting detachable
jkarlin2 2013/10/24 15:33:11 I don't understand, they are in the list? On 2013
mmenke 2013/10/24 20:27:20 Sorry...What's stopping requests from being in the
jkarlin2 2013/10/25 14:10:21 At this point the renderers (and their attached re
mmenke 2013/10/25 14:57:51 Ah, right...I was misreading the code (I thought w
428 (*i)->is_transferring());
416 } 429 }
417 #endif 430 #endif
418 431
419 loaders_to_cancel.clear(); 432 loaders_to_cancel.clear();
420 433
421 // Validate that no more requests for this context were added. 434 // Validate that no more requests for this context were added.
422 for (LoaderMap::const_iterator i = pending_loaders_.begin(); 435 for (LoaderMap::const_iterator i = pending_loaders_.begin();
423 i != pending_loaders_.end(); ++i) { 436 i != pending_loaders_.end(); ++i) {
424 // http://crbug.com/90971 437 // http://crbug.com/90971
425 CHECK_NE(i->second->GetRequestInfo()->GetContext(), context); 438 CHECK_NE(i->second->GetRequestInfo()->GetContext(), context);
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after
687 new_url)); 700 new_url));
688 BrowserThread::PostTask( 701 BrowserThread::PostTask(
689 BrowserThread::UI, FROM_HERE, 702 BrowserThread::UI, FROM_HERE,
690 base::Bind( 703 base::Bind(
691 &NotifyRedirectOnUI, 704 &NotifyRedirectOnUI,
692 render_process_id, render_view_id, base::Passed(&detail))); 705 render_process_id, render_view_id, base::Passed(&detail)));
693 } 706 }
694 707
695 void ResourceDispatcherHostImpl::DidReceiveResponse(ResourceLoader* loader) { 708 void ResourceDispatcherHostImpl::DidReceiveResponse(ResourceLoader* loader) {
696 ResourceRequestInfoImpl* info = loader->GetRequestInfo(); 709 ResourceRequestInfoImpl* info = loader->GetRequestInfo();
710
697 // There should be an entry in the map created when we dispatched the 711 // There should be an entry in the map created when we dispatched the
698 // request. 712 // request unless it's been detached and the renderer has died.
699 OfflineMap::iterator policy_it( 713 OfflineMap::iterator policy_it(
700 offline_policy_map_.find(info->GetGlobalRoutingID())); 714 offline_policy_map_.find(info->GetGlobalRoutingID()));
701 if (offline_policy_map_.end() != policy_it) { 715 if (offline_policy_map_.end() != policy_it) {
702 policy_it->second->UpdateStateForSuccessfullyStartedRequest( 716 policy_it->second->UpdateStateForSuccessfullyStartedRequest(
703 loader->request()->response_info()); 717 loader->request()->response_info());
704 } else { 718 } else if (!info->is_detachable()) {
705 // We should always have an entry in offline_policy_map_ from when 719 // We should always have an entry in offline_policy_map_ from when
706 // this request traversed Begin{Download,SaveFile,Request}. 720 // this request traversed Begin{Download,SaveFile,Request}.
707 // TODO(rdsmith): This isn't currently true; see http://crbug.com/241176. 721 // TODO(rdsmith): This isn't currently true; see http://crbug.com/241176.
708 NOTREACHED(); 722 NOTREACHED();
709 } 723 }
710 724
711 int render_process_id, render_view_id; 725 int render_process_id, render_view_id;
712 if (!info->GetAssociatedRenderView(&render_process_id, &render_view_id)) 726 if (!info->GetAssociatedRenderView(&render_process_id, &render_view_id))
713 return; 727 return;
714 728
(...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after
1066 request_data.origin_pid, 1080 request_data.origin_pid,
1067 request_id, 1081 request_id,
1068 request_data.is_main_frame, 1082 request_data.is_main_frame,
1069 request_data.frame_id, 1083 request_data.frame_id,
1070 request_data.parent_is_main_frame, 1084 request_data.parent_is_main_frame,
1071 request_data.parent_frame_id, 1085 request_data.parent_frame_id,
1072 request_data.resource_type, 1086 request_data.resource_type,
1073 request_data.transition_type, 1087 request_data.transition_type,
1074 false, // is download 1088 false, // is download
1075 false, // is stream 1089 false, // is stream
1090 false, // is detachable
1076 allow_download, 1091 allow_download,
1077 request_data.has_user_gesture, 1092 request_data.has_user_gesture,
1078 request_data.referrer_policy, 1093 request_data.referrer_policy,
1079 resource_context, 1094 resource_context,
1080 filter_->GetWeakPtr(), 1095 filter_->GetWeakPtr(),
1081 !is_sync_load); 1096 !is_sync_load);
1082 extra_info->AssociateWithRequest(request); // Request takes ownership. 1097 extra_info->AssociateWithRequest(request); // Request takes ownership.
1083 1098
1084 if (request->url().SchemeIs(chrome::kBlobScheme)) { 1099 if (request->url().SchemeIs(chrome::kBlobScheme)) {
1085 // Hang on to a reference to ensure the blob is not released prior 1100 // Hang on to a reference to ensure the blob is not released prior
1086 // to the job being started. 1101 // to the job being started.
1087 webkit_blob::BlobProtocolHandler::SetRequestedBlobDataHandle( 1102 webkit_blob::BlobProtocolHandler::SetRequestedBlobDataHandle(
1088 request, 1103 request,
1089 filter_->blob_storage_context()->context()-> 1104 filter_->blob_storage_context()->context()->
1090 GetBlobDataFromPublicURL(request->url())); 1105 GetBlobDataFromPublicURL(request->url()));
1091 } 1106 }
1092 1107
1093 // Have the appcache associate its extra info with the request. 1108 // Have the appcache associate its extra info with the request.
1094 appcache::AppCacheInterceptor::SetExtraRequestInfo( 1109 appcache::AppCacheInterceptor::SetExtraRequestInfo(
1095 request, filter_->appcache_service(), child_id, 1110 request, filter_->appcache_service(), child_id,
1096 request_data.appcache_host_id, request_data.resource_type); 1111 request_data.appcache_host_id, request_data.resource_type);
1097 1112
1098 // Construct the IPC resource handler. 1113 // Construct the IPC resource handler.
1099 scoped_ptr<ResourceHandler> handler; 1114 scoped_ptr<ResourceHandler> handler;
1100 if (sync_result) { 1115 if (sync_result) {
1101 handler.reset(new SyncResourceHandler(request, sync_result, this)); 1116 handler.reset(new SyncResourceHandler(request, sync_result, this));
1102 } else { 1117 } else {
1103 handler.reset(new AsyncResourceHandler(request, this)); 1118 handler.reset(new AsyncResourceHandler(request, this));
1119 if (IsDetachableResourceType(request_data.resource_type))
1120 extra_info->set_is_detachable(true);
1104 } 1121 }
1105 1122
1123
mmenke 2013/10/17 18:33:48 nit: Remove extra line break.
jkarlin2 2013/10/24 15:33:11 Done.
1106 // The RedirectToFileResourceHandler depends on being next in the chain. 1124 // The RedirectToFileResourceHandler depends on being next in the chain.
1107 if (request_data.download_to_file) { 1125 if (request_data.download_to_file) {
1108 handler.reset( 1126 handler.reset(
1109 new RedirectToFileResourceHandler(handler.Pass(), request, this)); 1127 new RedirectToFileResourceHandler(handler.Pass(), request, this));
1110 } 1128 }
1111 1129
1112 // Install a CrossSiteResourceHandler for all main frame requests. This will 1130 // Install a CrossSiteResourceHandler for all main frame requests. This will
1113 // let us check whether a transfer is required and pause for the unload 1131 // let us check whether a transfer is required and pause for the unload
1114 // handler either if so or if a cross-process navigation is already under way. 1132 // handler either if so or if a cross-process navigation is already under way.
1115 if (request_data.resource_type == ResourceType::MAIN_FRAME && 1133 if (request_data.resource_type == ResourceType::MAIN_FRAME &&
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
1213 0, 1231 0,
1214 request_id_, 1232 request_id_,
1215 false, // is_main_frame 1233 false, // is_main_frame
1216 -1, // frame_id 1234 -1, // frame_id
1217 false, // parent_is_main_frame 1235 false, // parent_is_main_frame
1218 -1, // parent_frame_id 1236 -1, // parent_frame_id
1219 ResourceType::SUB_RESOURCE, 1237 ResourceType::SUB_RESOURCE,
1220 PAGE_TRANSITION_LINK, 1238 PAGE_TRANSITION_LINK,
1221 download, // is_download 1239 download, // is_download
1222 false, // is_stream 1240 false, // is_stream
1241 false, // is_detachable
1223 download, // allow_download 1242 download, // allow_download
1224 false, // has_user_gesture 1243 false, // has_user_gesture
1225 WebKit::WebReferrerPolicyDefault, 1244 WebKit::WebReferrerPolicyDefault,
1226 context, 1245 context,
1227 base::WeakPtr<ResourceMessageFilter>(), // filter 1246 base::WeakPtr<ResourceMessageFilter>(), // filter
1228 true); // is_async 1247 true); // is_async
1229 } 1248 }
1230 1249
1231 void ResourceDispatcherHostImpl::OnRenderViewHostCreated( 1250 void ResourceDispatcherHostImpl::OnRenderViewHostCreated(
1232 int child_id, 1251 int child_id,
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
1308 ResourceLoader* loader = GetLoader(id); 1327 ResourceLoader* loader = GetLoader(id);
1309 if (loader) { 1328 if (loader) {
1310 // The response we were meant to resume could have already been canceled. 1329 // The response we were meant to resume could have already been canceled.
1311 ResourceRequestInfoImpl* info = loader->GetRequestInfo(); 1330 ResourceRequestInfoImpl* info = loader->GetRequestInfo();
1312 if (info->cross_site_handler()) 1331 if (info->cross_site_handler())
1313 info->cross_site_handler()->ResumeResponse(); 1332 info->cross_site_handler()->ResumeResponse();
1314 } 1333 }
1315 } 1334 }
1316 1335
1317 // The object died, so cancel and detach all requests associated with it except 1336 // 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 1337 // for downloads and detachable resources, which belong to the browser process
1319 // renderer. 1338 // even if initiated via a renderer.
1320 void ResourceDispatcherHostImpl::CancelRequestsForProcess(int child_id) { 1339 void ResourceDispatcherHostImpl::CancelRequestsForProcess(int child_id) {
1321 CancelRequestsForRoute(child_id, -1 /* cancel all */); 1340 CancelRequestsForRoute(child_id, -1 /* cancel all */);
1322 registered_temp_files_.erase(child_id); 1341 registered_temp_files_.erase(child_id);
1323 } 1342 }
1324 1343
1325 void ResourceDispatcherHostImpl::CancelRequestsForRoute(int child_id, 1344 void ResourceDispatcherHostImpl::CancelRequestsForRoute(int child_id,
1326 int route_id) { 1345 int route_id) {
1327 // Since pending_requests_ is a map, we first build up a list of all of the 1346 // 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 1347 // 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 1348 // may be more than one request to cancel, we cannot simply hold onto the map
1330 // iterators found in the first loop. 1349 // iterators found in the first loop.
1331 1350
1332 // Find the global ID of all matching elements. 1351 // Find the global ID of all matching elements.
1333 bool any_requests_transferring = false; 1352 bool any_requests_transferring = false;
1334 std::vector<GlobalRequestID> matching_requests; 1353 std::vector<GlobalRequestID> matching_requests;
1335 for (LoaderMap::const_iterator i = pending_loaders_.begin(); 1354 for (LoaderMap::const_iterator i = pending_loaders_.begin();
1336 i != pending_loaders_.end(); ++i) { 1355 i != pending_loaders_.end(); ++i) {
1337 if (i->first.child_id != child_id) 1356 if (i->first.child_id != child_id)
1338 continue; 1357 continue;
1339 1358
1340 ResourceRequestInfoImpl* info = i->second->GetRequestInfo(); 1359 ResourceRequestInfoImpl* info = i->second->GetRequestInfo();
1341 1360
1342 GlobalRequestID id(child_id, i->first.request_id); 1361 GlobalRequestID id(child_id, i->first.request_id);
1343 DCHECK(id == i->first); 1362 DCHECK(id == i->first);
1344 1363 // Don't cancel navigations that are expected to live beyond this process.
1345 // Don't cancel navigations that are transferring to another process,
1346 // since they belong to another process now.
1347 if (IsTransferredNavigation(id)) 1364 if (IsTransferredNavigation(id))
1348 any_requests_transferring = true; 1365 any_requests_transferring = true;
1349 if (!info->is_download() && !info->is_stream() && 1366 if (!info->is_download() && !info->is_stream() && !info->is_detachable() &&
mmenke 2013/10/17 18:33:48 We aren't calling into DelayCancelForDetachable he
jkarlin2 2013/10/24 15:33:11 Done. Great catch. Fixed and tests added.
1350 !IsTransferredNavigation(id) && 1367 !IsTransferredNavigation(id) &&
1351 (route_id == -1 || route_id == info->GetRouteID())) { 1368 (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
(...skipping 552 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698