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

Side by Side Diff: content/browser/frame_host/render_frame_host_manager.cc

Issue 88503002: Have the unload event execute in background on cross-site navigations (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Addressed Charlie's comments Created 6 years, 10 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 | Annotate | Revision Log
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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 #include "content/browser/frame_host/render_frame_host_manager.h" 5 #include "content/browser/frame_host/render_frame_host_manager.h"
6 6
7 #include <utility> 7 #include <utility>
8 8
9 #include "base/command_line.h" 9 #include "base/command_line.h"
10 #include "base/debug/trace_event.h" 10 #include "base/debug/trace_event.h"
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
68 Delegate* delegate) 68 Delegate* delegate)
69 : frame_tree_node_(frame_tree_node), 69 : frame_tree_node_(frame_tree_node),
70 delegate_(delegate), 70 delegate_(delegate),
71 cross_navigation_pending_(false), 71 cross_navigation_pending_(false),
72 render_frame_delegate_(render_frame_delegate), 72 render_frame_delegate_(render_frame_delegate),
73 render_view_delegate_(render_view_delegate), 73 render_view_delegate_(render_view_delegate),
74 render_widget_delegate_(render_widget_delegate), 74 render_widget_delegate_(render_widget_delegate),
75 render_frame_host_(NULL), 75 render_frame_host_(NULL),
76 pending_render_frame_host_(NULL), 76 pending_render_frame_host_(NULL),
77 interstitial_page_(NULL), 77 interstitial_page_(NULL),
78 cross_process_frame_connector_(NULL) {} 78 cross_process_frame_connector_(NULL),
79 weak_factory_(this) {}
79 80
80 RenderFrameHostManager::~RenderFrameHostManager() { 81 RenderFrameHostManager::~RenderFrameHostManager() {
81 if (pending_render_frame_host_) 82 if (pending_render_frame_host_)
82 CancelPending(); 83 CancelPending();
83 84
84 if (cross_process_frame_connector_) 85 if (cross_process_frame_connector_)
85 delete cross_process_frame_connector_; 86 delete cross_process_frame_connector_;
86 87
87 // We should always have a current RenderFrameHost except in some tests. 88 // We should always have a current RenderFrameHost except in some tests.
88 // TODO(creis): Now that we aren't using Shutdown, make render_frame_host_ and 89 // TODO(creis): Now that we aren't using Shutdown, make render_frame_host_ and
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
230 if (!cross_navigation_pending_) 231 if (!cross_navigation_pending_)
231 return true; 232 return true;
232 233
233 // We should always have a pending RFH when there's a cross-process navigation 234 // We should always have a pending RFH when there's a cross-process navigation
234 // in progress. Sanity check this for http://crbug.com/276333. 235 // in progress. Sanity check this for http://crbug.com/276333.
235 CHECK(pending_render_frame_host_); 236 CHECK(pending_render_frame_host_);
236 237
237 // If the tab becomes unresponsive during {before}unload while doing a 238 // If the tab becomes unresponsive during {before}unload while doing a
238 // cross-site navigation, proceed with the navigation. (This assumes that 239 // cross-site navigation, proceed with the navigation. (This assumes that
239 // the pending RenderFrameHost is still responsive.) 240 // the pending RenderFrameHost is still responsive.)
240 if (render_frame_host_->render_view_host()->is_waiting_for_unload_ack()) { 241 if (render_frame_host_->render_view_host()->IsWaitingForUnloadACK()) {
241 // The request has been started and paused while we're waiting for the 242 // The request has been started and paused while we're waiting for the
242 // unload handler to finish. We'll pretend that it did. The pending 243 // unload handler to finish. We'll pretend that it did. The pending
243 // renderer will then be swapped in as part of the usual DidNavigate logic. 244 // renderer will then be swapped in as part of the usual DidNavigate logic.
244 // (If the unload handler later finishes, this call will be ignored because 245 // (If the unload handler later finishes, this call will be ignored because
245 // the pending_nav_params_ state will already be cleaned up.) 246 // the pending_nav_params_ state will already be cleaned up.)
246 current_host()->OnSwappedOut(true); 247 current_host()->OnSwappedOut(true);
247 } else if (render_frame_host_->render_view_host()-> 248 } else if (render_frame_host_->render_view_host()->
248 is_waiting_for_beforeunload_ack()) { 249 is_waiting_for_beforeunload_ack()) {
249 // Haven't gotten around to starting the request, because we're still 250 // Haven't gotten around to starting the request, because we're still
250 // waiting for the beforeunload handler to finish. We'll pretend that it 251 // waiting for the beforeunload handler to finish. We'll pretend that it
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after
533 // ResourceDispatcherHost has told us to run the onunload handler, which 534 // ResourceDispatcherHost has told us to run the onunload handler, which
534 // means it is not a download or unsafe page, and we are going to perform the 535 // means it is not a download or unsafe page, and we are going to perform the
535 // navigation. Thus, we no longer need to remember that the RenderFrameHost 536 // navigation. Thus, we no longer need to remember that the RenderFrameHost
536 // is part of a pending cross-site request. 537 // is part of a pending cross-site request.
537 if (pending_render_frame_host_) { 538 if (pending_render_frame_host_) {
538 pending_render_frame_host_->render_view_host()-> 539 pending_render_frame_host_->render_view_host()->
539 SetHasPendingCrossSiteRequest(false); 540 SetHasPendingCrossSiteRequest(false);
540 } 541 }
541 } 542 }
542 543
544 void RenderFrameHostManager::ClearPendingShutdownRFHForSiteInstance(
545 int32 site_instance_id,
546 RenderFrameHostImpl* rfh) {
547 RFHPendingDeleteMap::iterator iter =
548 pending_delete_hosts_.find(site_instance_id);
549 if (iter != pending_delete_hosts_.end() && iter->second.get() == rfh)
550 pending_delete_hosts_.erase(site_instance_id);
551 }
552
543 void RenderFrameHostManager::Observe( 553 void RenderFrameHostManager::Observe(
544 int type, 554 int type,
545 const NotificationSource& source, 555 const NotificationSource& source,
546 const NotificationDetails& details) { 556 const NotificationDetails& details) {
547 switch (type) { 557 switch (type) {
548 case NOTIFICATION_RENDERER_PROCESS_CLOSED: 558 case NOTIFICATION_RENDERER_PROCESS_CLOSED:
549 case NOTIFICATION_RENDERER_PROCESS_CLOSING: 559 case NOTIFICATION_RENDERER_PROCESS_CLOSING:
550 RendererProcessClosing( 560 RendererProcessClosing(
551 Source<RenderProcessHost>(source).ptr()); 561 Source<RenderProcessHost>(source).ptr());
552 break; 562 break;
553 563
554 default: 564 default:
555 NOTREACHED(); 565 NOTREACHED();
556 } 566 }
557 } 567 }
558 568
559 bool RenderFrameHostManager::ClearSwappedOutRFHsInSiteInstance( 569 bool RenderFrameHostManager::ClearSwappedOutRFHsInSiteInstance(
560 int32 site_instance_id, 570 int32 site_instance_id,
561 FrameTreeNode* node) { 571 FrameTreeNode* node) {
562 RenderFrameHostMap::iterator iter = 572 RenderFrameHostMap::iterator iter =
563 node->render_manager()->swapped_out_hosts_.find(site_instance_id); 573 node->render_manager()->swapped_out_hosts_.find(site_instance_id);
564 if (iter != node->render_manager()->swapped_out_hosts_.end()) 574 if (iter != node->render_manager()->swapped_out_hosts_.end()) {
565 delete iter->second; 575 RenderFrameHostImpl* swapped_out_rfh = iter->second;
576 // If the RVH is pending swap out, it needs to switch state to
577 // pending shutdown. Otherwise it is deleted.
578 if (swapped_out_rfh->render_view_host()->rvh_state() ==
579 RenderViewHostImpl::STATE_PENDING_SWAP_OUT) {
580 swapped_out_rfh->SetPendingShutdown(base::Bind(
581 &RenderFrameHostManager::ClearPendingShutdownRFHForSiteInstance,
582 node->render_manager()->weak_factory_.GetWeakPtr(),
583 site_instance_id,
584 swapped_out_rfh));
585 RFHPendingDeleteMap::iterator pending_delete_iter =
586 node->render_manager()->pending_delete_hosts_.find(site_instance_id);
587 if (pending_delete_iter ==
588 node->render_manager()->pending_delete_hosts_.end() ||
589 pending_delete_iter->second.get() != iter->second) {
590 node->render_manager()->pending_delete_hosts_[site_instance_id] =
591 linked_ptr<RenderFrameHostImpl>(swapped_out_rfh);
592 }
593 } else {
594 delete swapped_out_rfh;
595 }
596 node->render_manager()->swapped_out_hosts_.erase(site_instance_id);
597 }
566 598
567 return true; 599 return true;
568 } 600 }
569 601
570 bool RenderFrameHostManager::ShouldTransitionCrossSite() { 602 bool RenderFrameHostManager::ShouldTransitionCrossSite() {
571 // False in the single-process mode, as it makes RVHs to accumulate 603 // False in the single-process mode, as it makes RVHs to accumulate
572 // in swapped_out_hosts_. 604 // in swapped_out_hosts_.
573 // True if we are using process-per-site-instance (default) or 605 // True if we are using process-per-site-instance (default) or
574 // process-per-site (kProcessPerSite). 606 // process-per-site (kProcessPerSite).
575 return 607 return
(...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after
946 // If the pending navigation is to a WebUI and the RenderView is not in a 978 // If the pending navigation is to a WebUI and the RenderView is not in a
947 // guest process, tell the RenderViewHost about any bindings it will need 979 // guest process, tell the RenderViewHost about any bindings it will need
948 // enabled. 980 // enabled.
949 if (pending_web_ui() && !render_view_host->GetProcess()->IsGuest()) { 981 if (pending_web_ui() && !render_view_host->GetProcess()->IsGuest()) {
950 render_view_host->AllowBindings(pending_web_ui()->GetBindings()); 982 render_view_host->AllowBindings(pending_web_ui()->GetBindings());
951 } else { 983 } else {
952 // Ensure that we don't create an unprivileged RenderView in a WebUI-enabled 984 // Ensure that we don't create an unprivileged RenderView in a WebUI-enabled
953 // process unless it's swapped out. 985 // process unless it's swapped out.
954 RenderViewHostImpl* rvh_impl = 986 RenderViewHostImpl* rvh_impl =
955 static_cast<RenderViewHostImpl*>(render_view_host); 987 static_cast<RenderViewHostImpl*>(render_view_host);
956 if (!rvh_impl->is_swapped_out()) { 988 if (!rvh_impl->IsSwappedOut()) {
957 CHECK(!ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings( 989 CHECK(!ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
958 render_view_host->GetProcess()->GetID())); 990 render_view_host->GetProcess()->GetID()));
959 } 991 }
960 } 992 }
961 993
962 return delegate_->CreateRenderViewForRenderManager( 994 return delegate_->CreateRenderViewForRenderManager(
963 render_view_host, opener_route_id, cross_process_frame_connector_); 995 render_view_host, opener_route_id, cross_process_frame_connector_);
964 } 996 }
965 997
966 void RenderFrameHostManager::CommitPending() { 998 void RenderFrameHostManager::CommitPending() {
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
1021 // to make sure the sad tab shows up, etc. 1053 // to make sure the sad tab shows up, etc.
1022 if (!render_frame_host_->render_view_host()->GetView()) { 1054 if (!render_frame_host_->render_view_host()->GetView()) {
1023 delegate_->RenderProcessGoneFromRenderManager( 1055 delegate_->RenderProcessGoneFromRenderManager(
1024 render_frame_host_->render_view_host()); 1056 render_frame_host_->render_view_host());
1025 } else if (!delegate_->IsHidden()) { 1057 } else if (!delegate_->IsHidden()) {
1026 render_frame_host_->render_view_host()->GetView()->Show(); 1058 render_frame_host_->render_view_host()->GetView()->Show();
1027 } 1059 }
1028 1060
1029 // If the old view is live and top-level, hide it now that the new one is 1061 // If the old view is live and top-level, hide it now that the new one is
1030 // visible. 1062 // visible.
1063 int32 old_site_instance_id =
1064 old_render_frame_host->render_view_host()->GetSiteInstance()->GetId();
1031 if (old_render_frame_host->render_view_host()->GetView()) { 1065 if (old_render_frame_host->render_view_host()->GetView()) {
1032 if (is_main_frame) { 1066 if (is_main_frame) {
1033 old_render_frame_host->render_view_host()->GetView()->Hide(); 1067 old_render_frame_host->render_view_host()->GetView()->Hide();
1034 old_render_frame_host->render_view_host()->WasSwappedOut(); 1068 old_render_frame_host->render_view_host()->WasSwappedOut(base::Bind(
1069 &RenderFrameHostManager::ClearPendingShutdownRFHForSiteInstance,
1070 weak_factory_.GetWeakPtr(),
1071 old_site_instance_id,
1072 old_render_frame_host));
1035 } else { 1073 } else {
1036 // TODO(creis): We'll need to set this back to false if we navigate back. 1074 // TODO(creis): We'll need to set this back to false if we navigate back.
1037 old_render_frame_host->set_swapped_out(true); 1075 old_render_frame_host->set_swapped_out(true);
1038 } 1076 }
1039 } 1077 }
1040 1078
1041 // Make sure the size is up to date. (Fix for bug 1079768.) 1079 // Make sure the size is up to date. (Fix for bug 1079768.)
1042 delegate_->UpdateRenderViewSizeForRenderManager(); 1080 delegate_->UpdateRenderViewSizeForRenderManager();
1043 1081
1044 if (will_focus_location_bar) { 1082 if (will_focus_location_bar) {
(...skipping 13 matching lines...) Expand all
1058 old_render_frame_host->render_view_host(), 1096 old_render_frame_host->render_view_host(),
1059 render_frame_host_->render_view_host()); 1097 render_frame_host_->render_view_host());
1060 } 1098 }
1061 1099
1062 // If the pending frame was on the swapped out list, we can remove it. 1100 // If the pending frame was on the swapped out list, we can remove it.
1063 swapped_out_hosts_.erase(render_frame_host_->render_view_host()-> 1101 swapped_out_hosts_.erase(render_frame_host_->render_view_host()->
1064 GetSiteInstance()->GetId()); 1102 GetSiteInstance()->GetId());
1065 1103
1066 if (old_render_frame_host->render_view_host()->IsRenderViewLive()) { 1104 if (old_render_frame_host->render_view_host()->IsRenderViewLive()) {
1067 // If the old RFH is live, we are swapping it out and should keep track of 1105 // If the old RFH is live, we are swapping it out and should keep track of
1068 // it in case we navigate back to it. 1106 // it in case we navigate back to it, or it is waiting for the unload event
1107 // to execute in the background.
1069 // TODO(creis): Swap out the subframe in --site-per-process. 1108 // TODO(creis): Swap out the subframe in --site-per-process.
1070 if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess)) 1109 if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess))
1071 DCHECK(old_render_frame_host->is_swapped_out() || 1110 DCHECK(old_render_frame_host->is_swapped_out() ||
1072 old_render_frame_host->render_view_host()->is_swapped_out()); 1111 !RenderViewHostImpl::IsRVHStateActive(
1073 1112 old_render_frame_host->render_view_host()->rvh_state()));
1074 // Temp fix for http://crbug.com/90867 until we do a better cleanup to make 1113 // Temp fix for http://crbug.com/90867 until we do a better cleanup to make
1075 // sure we don't get different rvh instances for the same site instance 1114 // sure we don't get different rvh instances for the same site instance
1076 // in the same rvhmgr. 1115 // in the same rvhmgr.
1077 // TODO(creis): Clean this up. 1116 // TODO(creis): Clean this up.
1078 int32 old_site_instance_id =
1079 old_render_frame_host->render_view_host()->GetSiteInstance()->GetId();
1080 RenderFrameHostMap::iterator iter = 1117 RenderFrameHostMap::iterator iter =
1081 swapped_out_hosts_.find(old_site_instance_id); 1118 swapped_out_hosts_.find(old_site_instance_id);
1082 if (iter != swapped_out_hosts_.end() && 1119 if (iter != swapped_out_hosts_.end() &&
1083 iter->second != old_render_frame_host) { 1120 iter->second != old_render_frame_host) {
1084 // Delete the RFH that will be replaced in the map to avoid a leak. 1121 // Delete the RFH that will be replaced in the map to avoid a leak.
1085 delete iter->second; 1122 delete iter->second;
1086 } 1123 }
1087 swapped_out_hosts_[old_site_instance_id] = old_render_frame_host; 1124 // If the RenderViewHost backing the RenderFrameHost is pending shutdown,
1125 // the RenderFrameHost should be put in the map of RenderFrameHosts pending
1126 // shutdown. Otherwise, it is stored in the map of swapped out
1127 // RenderFrameHosts.
1128 if (old_render_frame_host->render_view_host()->rvh_state() ==
1129 RenderViewHostImpl::STATE_PENDING_SHUTDOWN) {
1130 swapped_out_hosts_.erase(old_site_instance_id);
1131 RFHPendingDeleteMap::iterator pending_delete_iter =
1132 pending_delete_hosts_.find(old_site_instance_id);
1133 if (pending_delete_iter == pending_delete_hosts_.end() ||
1134 pending_delete_iter->second.get() != old_render_frame_host) {
1135 pending_delete_hosts_[old_site_instance_id] =
1136 linked_ptr<RenderFrameHostImpl>(old_render_frame_host);
1137 }
1138 } else {
1139 swapped_out_hosts_[old_site_instance_id] = old_render_frame_host;
1140 }
1088 1141
1089 // If there are no active views in this SiteInstance, it means that 1142 // If there are no active views in this SiteInstance, it means that
1090 // this RFH was the last active one in the SiteInstance. Now that we 1143 // this RFH was the last active one in the SiteInstance. Now that we
1091 // know that all RFHs are swapped out, we can delete all the RFHs and RVHs 1144 // know that all RFHs are swapped out, we can delete all the RFHs and RVHs
1092 // in this SiteInstance. We do this after ensuring the RFH is on the 1145 // in this SiteInstance. We do this after ensuring the RFH is on the
1093 // swapped out list to simplify the deletion. 1146 // swapped out list to simplify the deletion.
1094 if (!static_cast<SiteInstanceImpl*>( 1147 if (!static_cast<SiteInstanceImpl*>(
1095 old_render_frame_host->render_view_host()->GetSiteInstance())-> 1148 old_render_frame_host->render_view_host()->GetSiteInstance())->
1096 active_view_count()) { 1149 active_view_count()) {
1097 ShutdownRenderFrameHostsInSiteInstance(old_site_instance_id); 1150 ShutdownRenderFrameHostsInSiteInstance(old_site_instance_id);
(...skipping 22 matching lines...) Expand all
1120 continue; 1173 continue;
1121 RenderViewHostImpl* rvh = 1174 RenderViewHostImpl* rvh =
1122 static_cast<RenderViewHostImpl*>(RenderViewHost::From(widget)); 1175 static_cast<RenderViewHostImpl*>(RenderViewHost::From(widget));
1123 if (site_instance_id == rvh->GetSiteInstance()->GetId()) { 1176 if (site_instance_id == rvh->GetSiteInstance()->GetId()) {
1124 // This deletes all RenderFrameHosts using the |rvh|, which then causes 1177 // This deletes all RenderFrameHosts using the |rvh|, which then causes
1125 // |rvh| to Shutdown. 1178 // |rvh| to Shutdown.
1126 FrameTree* tree = rvh->GetDelegate()->GetFrameTree(); 1179 FrameTree* tree = rvh->GetDelegate()->GetFrameTree();
1127 tree->ForEach(base::Bind( 1180 tree->ForEach(base::Bind(
1128 &RenderFrameHostManager::ClearSwappedOutRFHsInSiteInstance, 1181 &RenderFrameHostManager::ClearSwappedOutRFHsInSiteInstance,
1129 site_instance_id)); 1182 site_instance_id));
1130 // rvh is now deleted.
1131 } 1183 }
1132 } 1184 }
1133 } 1185 }
1134 1186
1135 RenderFrameHostImpl* RenderFrameHostManager::UpdateRendererStateForNavigate( 1187 RenderFrameHostImpl* RenderFrameHostManager::UpdateRendererStateForNavigate(
1136 const NavigationEntryImpl& entry) { 1188 const NavigationEntryImpl& entry) {
1137 // If we are currently navigating cross-process, we want to get back to normal 1189 // If we are currently navigating cross-process, we want to get back to normal
1138 // and then navigate as usual. 1190 // and then navigate as usual.
1139 if (cross_navigation_pending_) { 1191 if (cross_navigation_pending_) {
1140 if (pending_render_frame_host_) 1192 if (pending_render_frame_host_)
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after
1389 SiteInstance* instance) const { 1441 SiteInstance* instance) const {
1390 RenderFrameHostMap::const_iterator iter = 1442 RenderFrameHostMap::const_iterator iter =
1391 swapped_out_hosts_.find(instance->GetId()); 1443 swapped_out_hosts_.find(instance->GetId());
1392 if (iter != swapped_out_hosts_.end()) 1444 if (iter != swapped_out_hosts_.end())
1393 return iter->second; 1445 return iter->second;
1394 1446
1395 return NULL; 1447 return NULL;
1396 } 1448 }
1397 1449
1398 } // namespace content 1450 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698