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 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |