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

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

Issue 2496233003: Destroy the old RenderWidgetHostView when swapping out a main frame. (Closed)
Patch Set: fix unit tests, remove dcheck Created 4 years 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 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 <stddef.h> 7 #include <stddef.h>
8 8
9 #include <algorithm> 9 #include <algorithm>
10 #include <string> 10 #include <string>
(...skipping 681 matching lines...) Expand 10 before | Expand all | Expand 10 after
692 // Doing this is important in the case where the replacement proxy is created 692 // Doing this is important in the case where the replacement proxy is created
693 // above, as the RenderViewHost will continue to exist and should be 693 // above, as the RenderViewHost will continue to exist and should be
694 // considered swapped out if it is ever reused. When there's no replacement 694 // considered swapped out if it is ever reused. When there's no replacement
695 // proxy, this doesn't really matter, as the RenderViewHost will be destroyed 695 // proxy, this doesn't really matter, as the RenderViewHost will be destroyed
696 // shortly, since |render_frame_host| is its last active frame and will be 696 // shortly, since |render_frame_host| is its last active frame and will be
697 // deleted below. See https://crbug.com/627400. 697 // deleted below. See https://crbug.com/627400.
698 if (frame_tree_node_->IsMainFrame()) { 698 if (frame_tree_node_->IsMainFrame()) {
699 rvh->set_main_frame_routing_id(MSG_ROUTING_NONE); 699 rvh->set_main_frame_routing_id(MSG_ROUTING_NONE);
700 rvh->set_is_active(false); 700 rvh->set_is_active(false);
701 rvh->set_is_swapped_out(true); 701 rvh->set_is_swapped_out(true);
702
703 if (rvh->GetWidget()->GetView()) {
704 rvh->GetWidget()->GetView()->Destroy();
705 rvh->GetWidget()->SetView(nullptr);
706 }
702 } 707 }
703 708
704 render_frame_host.reset(); 709 render_frame_host.reset();
705 710
706 // If a new RenderFrameProxyHost was created above, or if the old proxy isn't 711 // If a new RenderFrameProxyHost was created above, or if the old proxy isn't
707 // live, create the RenderFrameProxy in the renderer, so that other frames 712 // live, create the RenderFrameProxy in the renderer, so that other frames
708 // can still communicate with this frame. See https://crbug.com/653746. 713 // can still communicate with this frame. See https://crbug.com/653746.
709 if (proxy && !proxy->is_render_frame_proxy_live()) 714 if (proxy && !proxy->is_render_frame_proxy_live())
710 proxy->InitRenderFrameProxy(); 715 proxy->InitRenderFrameProxy();
711 } 716 }
712 717
713 bool RenderFrameHostManager::DeleteFromPendingList( 718 bool RenderFrameHostManager::DeleteFromPendingList(
714 RenderFrameHostImpl* render_frame_host) { 719 RenderFrameHostImpl* render_frame_host) {
720 // If this is a main frame RFH that's about to be deleted, update its RVH's
721 // swapped-out state here. https://crbug.com/505887
722 if (frame_tree_node_->IsMainFrame()) {
723 RenderViewHostImpl* rvh = render_frame_host->render_view_host();
724
725 rvh->set_is_active(false);
lfg 2016/11/29 17:41:22 I had to change this back from the DCHECK, since t
Charlie Reis 2016/11/29 19:35:55 Ok. Please mention that in a comment.
alexmos 2016/11/29 19:47:37 I'm a bit confused by this actually. We start the
726 rvh->set_is_swapped_out(true);
727 }
728
715 for (RFHPendingDeleteList::iterator iter = pending_delete_hosts_.begin(); 729 for (RFHPendingDeleteList::iterator iter = pending_delete_hosts_.begin();
716 iter != pending_delete_hosts_.end(); 730 iter != pending_delete_hosts_.end();
717 iter++) { 731 iter++) {
718 if (iter->get() == render_frame_host) { 732 if (iter->get() == render_frame_host) {
719 pending_delete_hosts_.erase(iter); 733 pending_delete_hosts_.erase(iter);
720 return true; 734 return true;
721 } 735 }
722 } 736 }
723 return false; 737 return false;
724 } 738 }
(...skipping 1026 matching lines...) Expand 10 before | Expand all | Expand 10 after
1751 instance, MSG_ROUTING_NONE, MSG_ROUTING_NONE, widget_routing_id, hidden, 1765 instance, MSG_ROUTING_NONE, MSG_ROUTING_NONE, widget_routing_id, hidden,
1752 false); 1766 false);
1753 RenderViewHostImpl* render_view_host = 1767 RenderViewHostImpl* render_view_host =
1754 new_render_frame_host->render_view_host(); 1768 new_render_frame_host->render_view_host();
1755 1769
1756 // Prevent the process from exiting while we're trying to navigate in it. 1770 // Prevent the process from exiting while we're trying to navigate in it.
1757 new_render_frame_host->GetProcess()->AddPendingView(); 1771 new_render_frame_host->GetProcess()->AddPendingView();
1758 1772
1759 if (frame_tree_node_->IsMainFrame()) { 1773 if (frame_tree_node_->IsMainFrame()) {
1760 success = InitRenderView(render_view_host, proxy); 1774 success = InitRenderView(render_view_host, proxy);
1761
1762 // If we are reusing the RenderViewHost and it doesn't already have a
1763 // RenderWidgetHostView, we need to create one if this is the main frame.
1764 if (!render_view_host->GetWidget()->GetView())
1765 delegate_->CreateRenderWidgetHostViewForRenderManager(render_view_host);
1766 } else { 1775 } else {
1767 DCHECK(render_view_host->IsRenderViewLive()); 1776 DCHECK(render_view_host->IsRenderViewLive());
1768 } 1777 }
1769 1778
1770 if (success) { 1779 if (success) {
1771 if (frame_tree_node_->IsMainFrame()) { 1780 if (frame_tree_node_->IsMainFrame()) {
1772 // Don't show the main frame's view until we get a DidNavigate from it. 1781 // Don't show the main frame's view until we get a DidNavigate from it.
1773 // Only the RenderViewHost for the top-level RenderFrameHost has a 1782 // Only the RenderViewHost for the top-level RenderFrameHost has a
1774 // RenderWidgetHostView; RenderWidgetHosts for out-of-process iframes 1783 // RenderWidgetHostView; RenderWidgetHosts for out-of-process iframes
1775 // will be created later and hidden. 1784 // will be created later and hidden.
(...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after
2156 } else { 2165 } else {
2157 // PlzNavigate 2166 // PlzNavigate
2158 DCHECK(speculative_render_frame_host_); 2167 DCHECK(speculative_render_frame_host_);
2159 old_render_frame_host = 2168 old_render_frame_host =
2160 SetRenderFrameHost(std::move(speculative_render_frame_host_)); 2169 SetRenderFrameHost(std::move(speculative_render_frame_host_));
2161 } 2170 }
2162 2171
2163 // The process will no longer try to exit, so we can decrement the count. 2172 // The process will no longer try to exit, so we can decrement the count.
2164 render_frame_host_->GetProcess()->RemovePendingView(); 2173 render_frame_host_->GetProcess()->RemovePendingView();
2165 2174
2175 // The RenderViewHost keeps track of the main RenderFrameHost routing id.
2176 // If this is committing a main frame navigation, update it and set the
2177 // routing id in the RenderViewHost associated with the old RenderFrameHost
2178 // to MSG_ROUTING_NONE.
2179 if (is_main_frame) {
2180 RenderViewHostImpl* rvh = render_frame_host_->render_view_host();
2181 rvh->set_main_frame_routing_id(render_frame_host_->routing_id());
2182
2183 // If we are reusing the RenderViewHost, we need to create the
2184 // RenderWidgetHostView if this is the main frame.
2185 if (rvh->IsRenderViewLive() && !rvh->is_active())
2186 delegate_->CreateRenderWidgetHostViewForRenderManager(rvh);
2187
2188 // If the RenderViewHost is transitioning from swapped out to active state,
2189 // it was reused, so dispatch a RenderViewReady event. For example, this
2190 // is necessary to hide the sad tab if one is currently displayed. See
2191 // https://crbug.com/591984.
2192 //
2193 // TODO(alexmos): Remove this and move RenderViewReady consumers to use
2194 // the main frame's RenderFrameCreated instead.
2195 if (!rvh->is_active())
2196 rvh->PostRenderViewReady();
2197
2198 rvh->set_is_active(true);
2199 rvh->set_is_swapped_out(false);
2200
2201 // Tell the old RenderViewHost it is no longer active.
2202 RenderViewHostImpl* old_rvh = old_render_frame_host->render_view_host();
2203 old_rvh->set_main_frame_routing_id(MSG_ROUTING_NONE);
2204 old_rvh->set_is_active(false);
2205
2206 // Destroy the old RenderWidgetHostView.
2207 if (old_rvh->GetWidget()->GetView()) {
2208 old_rvh->GetWidget()->GetView()->Destroy();
2209 old_rvh->GetWidget()->SetView(nullptr);
2210 }
2211 }
2212
2166 // Show the new view (or a sad tab) if necessary. 2213 // Show the new view (or a sad tab) if necessary.
2167 bool new_rfh_has_view = !!render_frame_host_->GetView(); 2214 bool new_rfh_has_view = !!render_frame_host_->GetView();
2168 if (!delegate_->IsHidden() && new_rfh_has_view) { 2215 if (!delegate_->IsHidden() && new_rfh_has_view) {
2169 // In most cases, we need to show the new view. 2216 // In most cases, we need to show the new view.
2170 render_frame_host_->GetView()->Show(); 2217 render_frame_host_->GetView()->Show();
2171 } 2218 }
2172 if (!new_rfh_has_view) { 2219 if (!new_rfh_has_view) {
2173 // If the view is gone, then this RenderViewHost died while it was hidden. 2220 // If the view is gone, then this RenderViewHost died while it was hidden.
2174 // We ignored the RenderProcessGone call at the time, so we should send it 2221 // We ignored the RenderProcessGone call at the time, so we should send it
2175 // now to make sure the sad tab shows up, etc. 2222 // now to make sure the sad tab shows up, etc.
2176 DCHECK(!render_frame_host_->IsRenderFrameLive()); 2223 DCHECK(!render_frame_host_->IsRenderFrameLive());
2177 DCHECK(!render_frame_host_->render_view_host()->IsRenderViewLive()); 2224 DCHECK(!render_frame_host_->render_view_host()->IsRenderViewLive());
2178 render_frame_host_->ResetLoadingState(); 2225 render_frame_host_->ResetLoadingState();
2179 delegate_->RenderProcessGoneFromRenderManager( 2226 delegate_->RenderProcessGoneFromRenderManager(
2180 render_frame_host_->render_view_host()); 2227 render_frame_host_->render_view_host());
2181 } 2228 }
2182 2229
2183 // For top-level frames, also hide the old RenderViewHost's view.
2184 // TODO(creis): As long as show/hide are on RVH, we don't want to hide on
2185 // subframe navigations or we will interfere with the top-level frame.
2186 if (is_main_frame &&
2187 old_render_frame_host->render_view_host()->GetWidget()->GetView()) {
2188 old_render_frame_host->render_view_host()->GetWidget()->GetView()->Hide();
2189 }
2190
2191 // Make sure the size is up to date. (Fix for bug 1079768.) 2230 // Make sure the size is up to date. (Fix for bug 1079768.)
2192 delegate_->UpdateRenderViewSizeForRenderManager(); 2231 delegate_->UpdateRenderViewSizeForRenderManager();
2193 2232
2194 if (will_focus_location_bar) { 2233 if (will_focus_location_bar) {
2195 delegate_->SetFocusToLocationBar(false); 2234 delegate_->SetFocusToLocationBar(false);
2196 } else if (focus_render_view && render_frame_host_->GetView()) { 2235 } else if (focus_render_view && render_frame_host_->GetView()) {
2197 if (is_main_frame) { 2236 if (is_main_frame) {
2198 render_frame_host_->GetView()->Focus(); 2237 render_frame_host_->GetView()->Focus();
2199 } else { 2238 } else {
2200 // The main frame's view is already focused, but we need to set 2239 // The main frame's view is already focused, but we need to set
2201 // page-level focus in the subframe's renderer. 2240 // page-level focus in the subframe's renderer.
2202 frame_tree_node_->frame_tree()->SetPageFocus( 2241 frame_tree_node_->frame_tree()->SetPageFocus(
2203 render_frame_host_->GetSiteInstance(), true); 2242 render_frame_host_->GetSiteInstance(), true);
2204 } 2243 }
2205 } 2244 }
2206 2245
2207 // Notify that we've swapped RenderFrameHosts. We do this before shutting down 2246 // Notify that we've swapped RenderFrameHosts. We do this before shutting down
2208 // the RFH so that we can clean up RendererResources related to the RFH first. 2247 // the RFH so that we can clean up RendererResources related to the RFH first.
2209 delegate_->NotifySwappedFromRenderManager( 2248 delegate_->NotifySwappedFromRenderManager(
2210 old_render_frame_host.get(), render_frame_host_.get(), is_main_frame); 2249 old_render_frame_host.get(), render_frame_host_.get(), is_main_frame);
2211 2250
2212 // The RenderViewHost keeps track of the main RenderFrameHost routing id.
2213 // If this is committing a main frame navigation, update it and set the
2214 // routing id in the RenderViewHost associated with the old RenderFrameHost
2215 // to MSG_ROUTING_NONE.
2216 if (is_main_frame) {
2217 RenderViewHostImpl* rvh = render_frame_host_->render_view_host();
2218 rvh->set_main_frame_routing_id(render_frame_host_->routing_id());
2219
2220 // If the RenderViewHost is transitioning from swapped out to active state,
2221 // it was reused, so dispatch a RenderViewReady event. For example, this
2222 // is necessary to hide the sad tab if one is currently displayed. See
2223 // https://crbug.com/591984.
2224 //
2225 // TODO(alexmos): Remove this and move RenderViewReady consumers to use
2226 // the main frame's RenderFrameCreated instead.
2227 if (!rvh->is_active())
2228 rvh->PostRenderViewReady();
2229
2230 rvh->set_is_active(true);
2231 rvh->set_is_swapped_out(false);
2232 old_render_frame_host->render_view_host()->set_main_frame_routing_id(
2233 MSG_ROUTING_NONE);
2234 }
2235
2236 // Swap out the old frame now that the new one is visible. 2251 // Swap out the old frame now that the new one is visible.
2237 // This will swap it out and schedule it for deletion when the swap out ack 2252 // This will swap it out and schedule it for deletion when the swap out ack
2238 // arrives (or immediately if the process isn't live). 2253 // arrives (or immediately if the process isn't live).
2239 SwapOutOldFrame(std::move(old_render_frame_host)); 2254 SwapOutOldFrame(std::move(old_render_frame_host));
2240 2255
2241 // Since the new RenderFrameHost is now committed, there must be no proxies 2256 // Since the new RenderFrameHost is now committed, there must be no proxies
2242 // for its SiteInstance. Delete any existing ones. 2257 // for its SiteInstance. Delete any existing ones.
2243 DeleteRenderFrameProxyHost(render_frame_host_->GetSiteInstance()); 2258 DeleteRenderFrameProxyHost(render_frame_host_->GetSiteInstance());
2244 2259
2245 // If this is a subframe, it should have a CrossProcessFrameConnector 2260 // If this is a subframe, it should have a CrossProcessFrameConnector
(...skipping 489 matching lines...) Expand 10 before | Expand all | Expand 10 after
2735 resolved_url)) { 2750 resolved_url)) {
2736 DCHECK(!dest_instance || 2751 DCHECK(!dest_instance ||
2737 dest_instance == render_frame_host_->GetSiteInstance()); 2752 dest_instance == render_frame_host_->GetSiteInstance());
2738 return false; 2753 return false;
2739 } 2754 }
2740 2755
2741 return true; 2756 return true;
2742 } 2757 }
2743 2758
2744 } // namespace content 2759 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698