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

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: Rebase + addressed some of Nasko's comments Created 6 years, 11 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 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
67 Delegate* delegate) 67 Delegate* delegate)
68 : frame_tree_node_(frame_tree_node), 68 : frame_tree_node_(frame_tree_node),
69 delegate_(delegate), 69 delegate_(delegate),
70 cross_navigation_pending_(false), 70 cross_navigation_pending_(false),
71 render_frame_delegate_(render_frame_delegate), 71 render_frame_delegate_(render_frame_delegate),
72 render_view_delegate_(render_view_delegate), 72 render_view_delegate_(render_view_delegate),
73 render_widget_delegate_(render_widget_delegate), 73 render_widget_delegate_(render_widget_delegate),
74 render_frame_host_(NULL), 74 render_frame_host_(NULL),
75 pending_render_frame_host_(NULL), 75 pending_render_frame_host_(NULL),
76 interstitial_page_(NULL), 76 interstitial_page_(NULL),
77 cross_process_frame_connector_(NULL) {} 77 cross_process_frame_connector_(NULL),
78 weak_factory_(this) {}
78 79
79 RenderFrameHostManager::~RenderFrameHostManager() { 80 RenderFrameHostManager::~RenderFrameHostManager() {
80 if (pending_render_frame_host_) 81 if (pending_render_frame_host_)
81 CancelPending(); 82 CancelPending();
82 83
83 if (cross_process_frame_connector_) 84 if (cross_process_frame_connector_)
84 delete cross_process_frame_connector_; 85 delete cross_process_frame_connector_;
85 86
86 // We should always have a current RenderFrameHost except in some tests. 87 // We should always have a current RenderFrameHost except in some tests.
87 // TODO(creis): Now that we aren't using Shutdown, make render_frame_host_ and 88 // 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
229 if (!cross_navigation_pending_) 230 if (!cross_navigation_pending_)
230 return true; 231 return true;
231 232
232 // We should always have a pending RFH when there's a cross-process navigation 233 // We should always have a pending RFH when there's a cross-process navigation
233 // in progress. Sanity check this for http://crbug.com/276333. 234 // in progress. Sanity check this for http://crbug.com/276333.
234 CHECK(pending_render_frame_host_); 235 CHECK(pending_render_frame_host_);
235 236
236 // If the tab becomes unresponsive during {before}unload while doing a 237 // If the tab becomes unresponsive during {before}unload while doing a
237 // cross-site navigation, proceed with the navigation. (This assumes that 238 // cross-site navigation, proceed with the navigation. (This assumes that
238 // the pending RenderFrameHost is still responsive.) 239 // the pending RenderFrameHost is still responsive.)
239 if (render_frame_host_->render_view_host()->is_waiting_for_unload_ack()) { 240 if (render_frame_host_->render_view_host()->IsWaitingForUnloadACK()) {
240 // The request has been started and paused while we're waiting for the 241 // The request has been started and paused while we're waiting for the
241 // unload handler to finish. We'll pretend that it did. The pending 242 // unload handler to finish. We'll pretend that it did. The pending
242 // renderer will then be swapped in as part of the usual DidNavigate logic. 243 // renderer will then be swapped in as part of the usual DidNavigate logic.
243 // (If the unload handler later finishes, this call will be ignored because 244 // (If the unload handler later finishes, this call will be ignored because
244 // the pending_nav_params_ state will already be cleaned up.) 245 // the pending_nav_params_ state will already be cleaned up.)
245 current_host()->OnSwappedOut(true); 246 current_host()->OnSwappedOut(true);
246 } else if (render_frame_host_->render_view_host()-> 247 } else if (render_frame_host_->render_view_host()->
247 is_waiting_for_beforeunload_ack()) { 248 is_waiting_for_beforeunload_ack()) {
248 // Haven't gotten around to starting the request, because we're still 249 // Haven't gotten around to starting the request, because we're still
249 // waiting for the beforeunload handler to finish. We'll pretend that it 250 // waiting for the beforeunload handler to finish. We'll pretend that it
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after
532 // ResourceDispatcherHost has told us to run the onunload handler, which 533 // ResourceDispatcherHost has told us to run the onunload handler, which
533 // means it is not a download or unsafe page, and we are going to perform the 534 // means it is not a download or unsafe page, and we are going to perform the
534 // navigation. Thus, we no longer need to remember that the RenderFrameHost 535 // navigation. Thus, we no longer need to remember that the RenderFrameHost
535 // is part of a pending cross-site request. 536 // is part of a pending cross-site request.
536 if (pending_render_frame_host_) { 537 if (pending_render_frame_host_) {
537 pending_render_frame_host_->render_view_host()-> 538 pending_render_frame_host_->render_view_host()->
538 SetHasPendingCrossSiteRequest(false); 539 SetHasPendingCrossSiteRequest(false);
539 } 540 }
540 } 541 }
541 542
543 void RenderFrameHostManager::ClearPendingShutdownRFHForSiteInstance(
544 int32 site_instance_id,
545 RenderFrameHostImpl* rfh) {
546 base::hash_map<int32, linked_ptr<RenderFrameHostImpl> >::iterator iter =
547 pending_delete_hosts_.find(site_instance_id);
548 if (iter != pending_delete_hosts_.end() && iter->second.get() == rfh)
549 pending_delete_hosts_.erase(site_instance_id);
550 }
551
542 void RenderFrameHostManager::Observe( 552 void RenderFrameHostManager::Observe(
543 int type, 553 int type,
544 const NotificationSource& source, 554 const NotificationSource& source,
545 const NotificationDetails& details) { 555 const NotificationDetails& details) {
546 switch (type) { 556 switch (type) {
547 case NOTIFICATION_RENDERER_PROCESS_CLOSED: 557 case NOTIFICATION_RENDERER_PROCESS_CLOSED:
548 case NOTIFICATION_RENDERER_PROCESS_CLOSING: 558 case NOTIFICATION_RENDERER_PROCESS_CLOSING:
549 RendererProcessClosing( 559 RendererProcessClosing(
550 Source<RenderProcessHost>(source).ptr()); 560 Source<RenderProcessHost>(source).ptr());
551 break; 561 break;
552 562
553 default: 563 default:
554 NOTREACHED(); 564 NOTREACHED();
555 } 565 }
556 } 566 }
557 567
558 bool RenderFrameHostManager::ClearSwappedOutRFHsInSiteInstance( 568 bool RenderFrameHostManager::ClearSwappedOutRFHsInSiteInstance(
559 int32 site_instance_id, 569 int32 site_instance_id,
560 FrameTreeNode* node) { 570 FrameTreeNode* node) {
561 RenderFrameHostMap::iterator iter = 571 RenderFrameHostMap::iterator iter =
562 node->render_manager()->swapped_out_hosts_.find(site_instance_id); 572 node->render_manager()->swapped_out_hosts_.find(site_instance_id);
563 if (iter != node->render_manager()->swapped_out_hosts_.end()) 573 if (iter != node->render_manager()->swapped_out_hosts_.end()) {
564 delete iter->second; 574 RenderFrameHostImpl* swapped_out_rfh = iter->second;
575 // If the RVH is pending swap out, it needs to switch state to
576 // pending shutdown. Otherwise it is deleted.
577 if (swapped_out_rfh->render_view_host()->rvh_state() ==
578 RenderViewHostImpl::STATE_PENDING_SWAP_OUT) {
579 swapped_out_rfh->SetPendingShutdown(base::Bind(
580 &RenderFrameHostManager::ClearPendingShutdownRFHForSiteInstance,
581 node->render_manager()->weak_factory_.GetWeakPtr(),
582 site_instance_id,
583 swapped_out_rfh));
584 RFHPendingDeleteMap::iterator pending_delete_iter =
585 node->render_manager()->pending_delete_hosts_.find(site_instance_id);
586 if (pending_delete_iter ==
587 node->render_manager()->pending_delete_hosts_.end() ||
588 pending_delete_iter->second.get() != iter->second) {
589 node->render_manager()->pending_delete_hosts_[site_instance_id] =
590 linked_ptr<RenderFrameHostImpl>(swapped_out_rfh);
591 }
592 } else {
593 delete swapped_out_rfh;
594 }
595 node->render_manager()->swapped_out_hosts_.erase(site_instance_id);
596 }
565 597
566 return true; 598 return true;
567 } 599 }
568 600
569 bool RenderFrameHostManager::ShouldTransitionCrossSite() { 601 bool RenderFrameHostManager::ShouldTransitionCrossSite() {
570 // False in the single-process mode, as it makes RVHs to accumulate 602 // False in the single-process mode, as it makes RVHs to accumulate
571 // in swapped_out_hosts_. 603 // in swapped_out_hosts_.
572 // True if we are using process-per-site-instance (default) or 604 // True if we are using process-per-site-instance (default) or
573 // process-per-site (kProcessPerSite). 605 // process-per-site (kProcessPerSite).
574 return 606 return
(...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after
937 // If the pending navigation is to a WebUI and the RenderView is not in a 969 // If the pending navigation is to a WebUI and the RenderView is not in a
938 // guest process, tell the RenderViewHost about any bindings it will need 970 // guest process, tell the RenderViewHost about any bindings it will need
939 // enabled. 971 // enabled.
940 if (pending_web_ui() && !render_view_host->GetProcess()->IsGuest()) { 972 if (pending_web_ui() && !render_view_host->GetProcess()->IsGuest()) {
941 render_view_host->AllowBindings(pending_web_ui()->GetBindings()); 973 render_view_host->AllowBindings(pending_web_ui()->GetBindings());
942 } else { 974 } else {
943 // Ensure that we don't create an unprivileged RenderView in a WebUI-enabled 975 // Ensure that we don't create an unprivileged RenderView in a WebUI-enabled
944 // process unless it's swapped out. 976 // process unless it's swapped out.
945 RenderViewHostImpl* rvh_impl = 977 RenderViewHostImpl* rvh_impl =
946 static_cast<RenderViewHostImpl*>(render_view_host); 978 static_cast<RenderViewHostImpl*>(render_view_host);
947 if (!rvh_impl->is_swapped_out()) { 979 if (rvh_impl->rvh_state() != RenderViewHostImpl::STATE_SWAPPED_OUT) {
948 CHECK(!ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings( 980 CHECK(!ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
949 render_view_host->GetProcess()->GetID())); 981 render_view_host->GetProcess()->GetID()));
950 } 982 }
951 } 983 }
952 984
953 return delegate_->CreateRenderViewForRenderManager( 985 return delegate_->CreateRenderViewForRenderManager(
954 render_view_host, opener_route_id, cross_process_frame_connector_); 986 render_view_host, opener_route_id, cross_process_frame_connector_);
955 } 987 }
956 988
957 void RenderFrameHostManager::CommitPending() { 989 void RenderFrameHostManager::CommitPending() {
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
1012 // to make sure the sad tab shows up, etc. 1044 // to make sure the sad tab shows up, etc.
1013 if (!render_frame_host_->render_view_host()->GetView()) { 1045 if (!render_frame_host_->render_view_host()->GetView()) {
1014 delegate_->RenderProcessGoneFromRenderManager( 1046 delegate_->RenderProcessGoneFromRenderManager(
1015 render_frame_host_->render_view_host()); 1047 render_frame_host_->render_view_host());
1016 } else if (!delegate_->IsHidden()) { 1048 } else if (!delegate_->IsHidden()) {
1017 render_frame_host_->render_view_host()->GetView()->Show(); 1049 render_frame_host_->render_view_host()->GetView()->Show();
1018 } 1050 }
1019 1051
1020 // If the old view is live and top-level, hide it now that the new one is 1052 // If the old view is live and top-level, hide it now that the new one is
1021 // visible. 1053 // visible.
1054 int32 old_site_instance_id =
1055 old_render_frame_host->render_view_host()->GetSiteInstance()->GetId();
1022 if (old_render_frame_host->render_view_host()->GetView()) { 1056 if (old_render_frame_host->render_view_host()->GetView()) {
1023 if (is_main_frame) { 1057 if (is_main_frame) {
1024 old_render_frame_host->render_view_host()->GetView()->Hide(); 1058 old_render_frame_host->render_view_host()->GetView()->Hide();
1025 old_render_frame_host->render_view_host()->WasSwappedOut(); 1059 old_render_frame_host->render_view_host()->WasSwappedOut(base::Bind(
1060 &RenderFrameHostManager::ClearPendingShutdownRFHForSiteInstance,
1061 weak_factory_.GetWeakPtr(),
1062 old_site_instance_id,
1063 old_render_frame_host));
1026 } else { 1064 } else {
1027 // TODO(creis): We'll need to set this back to false if we navigate back. 1065 // TODO(creis): We'll need to set this back to false if we navigate back.
1028 old_render_frame_host->set_swapped_out(true); 1066 old_render_frame_host->set_swapped_out(true);
1029 } 1067 }
1030 } 1068 }
1031 1069
1032 // Make sure the size is up to date. (Fix for bug 1079768.) 1070 // Make sure the size is up to date. (Fix for bug 1079768.)
1033 delegate_->UpdateRenderViewSizeForRenderManager(); 1071 delegate_->UpdateRenderViewSizeForRenderManager();
1034 1072
1035 if (will_focus_location_bar) { 1073 if (will_focus_location_bar) {
(...skipping 13 matching lines...) Expand all
1049 old_render_frame_host->render_view_host(), 1087 old_render_frame_host->render_view_host(),
1050 render_frame_host_->render_view_host()); 1088 render_frame_host_->render_view_host());
1051 } 1089 }
1052 1090
1053 // If the pending frame was on the swapped out list, we can remove it. 1091 // If the pending frame was on the swapped out list, we can remove it.
1054 swapped_out_hosts_.erase(render_frame_host_->render_view_host()-> 1092 swapped_out_hosts_.erase(render_frame_host_->render_view_host()->
1055 GetSiteInstance()->GetId()); 1093 GetSiteInstance()->GetId());
1056 1094
1057 if (old_render_frame_host->render_view_host()->IsRenderViewLive()) { 1095 if (old_render_frame_host->render_view_host()->IsRenderViewLive()) {
1058 // If the old RFH is live, we are swapping it out and should keep track of 1096 // If the old RFH is live, we are swapping it out and should keep track of
1059 // it in case we navigate back to it. 1097 // it in case we navigate back to it, or it is waiting for the unload event
1098 // to execute in the background.
1060 // TODO(creis): Swap out the subframe in --site-per-process. 1099 // TODO(creis): Swap out the subframe in --site-per-process.
1061 if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess)) 1100 if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess))
1062 DCHECK(old_render_frame_host->is_swapped_out() || 1101 DCHECK(old_render_frame_host->is_swapped_out() ||
1063 old_render_frame_host->render_view_host()->is_swapped_out()); 1102 !RenderViewHostImpl::IsRVHStateActive(
1064 1103 old_render_frame_host->render_view_host()->rvh_state()));
1065 // Temp fix for http://crbug.com/90867 until we do a better cleanup to make 1104 // Temp fix for http://crbug.com/90867 until we do a better cleanup to make
1066 // sure we don't get different rvh instances for the same site instance 1105 // sure we don't get different rvh instances for the same site instance
1067 // in the same rvhmgr. 1106 // in the same rvhmgr.
1068 // TODO(creis): Clean this up. 1107 // TODO(creis): Clean this up.
1069 int32 old_site_instance_id =
1070 old_render_frame_host->render_view_host()->GetSiteInstance()->GetId();
1071 RenderFrameHostMap::iterator iter = 1108 RenderFrameHostMap::iterator iter =
1072 swapped_out_hosts_.find(old_site_instance_id); 1109 swapped_out_hosts_.find(old_site_instance_id);
1073 if (iter != swapped_out_hosts_.end() && 1110 if (iter != swapped_out_hosts_.end() &&
1074 iter->second != old_render_frame_host) { 1111 iter->second != old_render_frame_host) {
1075 // Delete the RFH that will be replaced in the map to avoid a leak. 1112 // Delete the RFH that will be replaced in the map to avoid a leak.
1076 delete iter->second; 1113 delete iter->second;
1077 } 1114 }
1078 swapped_out_hosts_[old_site_instance_id] = old_render_frame_host; 1115 // If the RenderViewHost backing the RenderFrameHost is pending shutdown,
1116 // the RenderFrameHost should be put in the map of RenderFrameHost pending
1117 // shutdown. Otherwise, it is stored in the map of swapped out
1118 // RenderFrameHosts.
1119 if (old_render_frame_host->render_view_host()->rvh_state() ==
1120 RenderViewHostImpl::STATE_PENDING_SHUTDOWN) {
1121 swapped_out_hosts_.erase(old_site_instance_id);
1122 RFHPendingDeleteMap::iterator pending_delete_iter =
1123 pending_delete_hosts_.find(old_site_instance_id);
1124 if (pending_delete_iter == pending_delete_hosts_.end() ||
1125 pending_delete_iter->second.get() != old_render_frame_host) {
1126 pending_delete_hosts_[old_site_instance_id] =
1127 linked_ptr<RenderFrameHostImpl>(old_render_frame_host);
1128 }
1129 } else {
1130 swapped_out_hosts_[old_site_instance_id] = old_render_frame_host;
1131 }
1079 1132
1080 // If there are no active views in this SiteInstance, it means that 1133 // If there are no active views in this SiteInstance, it means that
1081 // this RFH was the last active one in the SiteInstance. Now that we 1134 // this RFH was the last active one in the SiteInstance. Now that we
1082 // know that all RFHs are swapped out, we can delete all the RFHs and RVHs 1135 // know that all RFHs are swapped out, we can delete all the RFHs and RVHs
1083 // in this SiteInstance. We do this after ensuring the RFH is on the 1136 // in this SiteInstance. We do this after ensuring the RFH is on the
1084 // swapped out list to simplify the deletion. 1137 // swapped out list to simplify the deletion.
1085 if (!static_cast<SiteInstanceImpl*>( 1138 if (!static_cast<SiteInstanceImpl*>(
1086 old_render_frame_host->render_view_host()->GetSiteInstance())-> 1139 old_render_frame_host->render_view_host()->GetSiteInstance())->
1087 active_view_count()) { 1140 active_view_count()) {
1088 ShutdownRenderFrameHostsInSiteInstance(old_site_instance_id); 1141 ShutdownRenderFrameHostsInSiteInstance(old_site_instance_id);
(...skipping 22 matching lines...) Expand all
1111 continue; 1164 continue;
1112 RenderViewHostImpl* rvh = 1165 RenderViewHostImpl* rvh =
1113 static_cast<RenderViewHostImpl*>(RenderViewHost::From(widget)); 1166 static_cast<RenderViewHostImpl*>(RenderViewHost::From(widget));
1114 if (site_instance_id == rvh->GetSiteInstance()->GetId()) { 1167 if (site_instance_id == rvh->GetSiteInstance()->GetId()) {
1115 // This deletes all RenderFrameHosts using the |rvh|, which then causes 1168 // This deletes all RenderFrameHosts using the |rvh|, which then causes
1116 // |rvh| to Shutdown. 1169 // |rvh| to Shutdown.
1117 FrameTree* tree = rvh->GetDelegate()->GetFrameTree(); 1170 FrameTree* tree = rvh->GetDelegate()->GetFrameTree();
1118 tree->ForEach(base::Bind( 1171 tree->ForEach(base::Bind(
1119 &RenderFrameHostManager::ClearSwappedOutRFHsInSiteInstance, 1172 &RenderFrameHostManager::ClearSwappedOutRFHsInSiteInstance,
1120 site_instance_id)); 1173 site_instance_id));
1121 // rvh is now deleted.
1122 } 1174 }
1123 } 1175 }
1124 } 1176 }
1125 1177
1126 RenderFrameHostImpl* RenderFrameHostManager::UpdateRendererStateForNavigate( 1178 RenderFrameHostImpl* RenderFrameHostManager::UpdateRendererStateForNavigate(
1127 const NavigationEntryImpl& entry) { 1179 const NavigationEntryImpl& entry) {
1128 // If we are currently navigating cross-process, we want to get back to normal 1180 // If we are currently navigating cross-process, we want to get back to normal
1129 // and then navigate as usual. 1181 // and then navigate as usual.
1130 if (cross_navigation_pending_) { 1182 if (cross_navigation_pending_) {
1131 if (pending_render_frame_host_) 1183 if (pending_render_frame_host_)
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after
1380 SiteInstance* instance) const { 1432 SiteInstance* instance) const {
1381 RenderFrameHostMap::const_iterator iter = 1433 RenderFrameHostMap::const_iterator iter =
1382 swapped_out_hosts_.find(instance->GetId()); 1434 swapped_out_hosts_.find(instance->GetId());
1383 if (iter != swapped_out_hosts_.end()) 1435 if (iter != swapped_out_hosts_.end())
1384 return iter->second; 1436 return iter->second;
1385 1437
1386 return NULL; 1438 return NULL;
1387 } 1439 }
1388 1440
1389 } // namespace content 1441 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698