OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |