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

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

Issue 1408743005: Properly recreate swapped out RenderView. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: A different approach. Created 5 years, 2 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
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 <algorithm> 7 #include <algorithm>
8 #include <utility> 8 #include <utility>
9 9
10 #include "base/command_line.h" 10 #include "base/command_line.h"
(...skipping 400 matching lines...) Expand 10 before | Expand all | Expand 10 after
411 // occur before initializing the RenderView; the flow of creating the 411 // occur before initializing the RenderView; the flow of creating the
412 // RenderView can cause browser-side code to execute that expects the this 412 // RenderView can cause browser-side code to execute that expects the this
413 // RFH's ServiceRegistry to be initialized (e.g., if the site is a WebUI 413 // RFH's ServiceRegistry to be initialized (e.g., if the site is a WebUI
414 // site that is handled via Mojo, then Mojo WebUI code in //chrome will 414 // site that is handled via Mojo, then Mojo WebUI code in //chrome will
415 // add a service to this RFH's ServiceRegistry). 415 // add a service to this RFH's ServiceRegistry).
416 dest_render_frame_host->SetUpMojoIfNeeded(); 416 dest_render_frame_host->SetUpMojoIfNeeded();
417 417
418 // Recreate the opener chain. 418 // Recreate the opener chain.
419 CreateOpenerProxies(dest_render_frame_host->GetSiteInstance(), 419 CreateOpenerProxies(dest_render_frame_host->GetSiteInstance(),
420 frame_tree_node_); 420 frame_tree_node_);
421 if (!InitRenderView(dest_render_frame_host->render_view_host(), 421 if (!InitRenderView(dest_render_frame_host->render_view_host(), nullptr))
422 MSG_ROUTING_NONE))
423 return nullptr; 422 return nullptr;
424 423
425 // Now that we've created a new renderer, be sure to hide it if it isn't 424 // Now that we've created a new renderer, be sure to hide it if it isn't
426 // our primary one. Otherwise, we might crash if we try to call Show() 425 // our primary one. Otherwise, we might crash if we try to call Show()
427 // on it later. 426 // on it later.
428 if (dest_render_frame_host != render_frame_host_) { 427 if (dest_render_frame_host != render_frame_host_) {
429 if (dest_render_frame_host->GetView()) 428 if (dest_render_frame_host->GetView())
430 dest_render_frame_host->GetView()->Hide(); 429 dest_render_frame_host->GetView()->Hide();
431 } else { 430 } else {
432 // After a renderer crash we'd have marked the host as invisible, so we 431 // After a renderer crash we'd have marked the host as invisible, so we
(...skipping 637 matching lines...) Expand 10 before | Expand all | Expand 10 after
1070 } 1069 }
1071 DCHECK(navigation_rfh && 1070 DCHECK(navigation_rfh &&
1072 (navigation_rfh == render_frame_host_.get() || 1071 (navigation_rfh == render_frame_host_.get() ||
1073 navigation_rfh == speculative_render_frame_host_.get())); 1072 navigation_rfh == speculative_render_frame_host_.get()));
1074 1073
1075 // If the RenderFrame that needs to navigate is not live (its process was just 1074 // If the RenderFrame that needs to navigate is not live (its process was just
1076 // created or has crashed), initialize it. 1075 // created or has crashed), initialize it.
1077 if (!navigation_rfh->IsRenderFrameLive()) { 1076 if (!navigation_rfh->IsRenderFrameLive()) {
1078 // Recreate the opener chain. 1077 // Recreate the opener chain.
1079 CreateOpenerProxies(navigation_rfh->GetSiteInstance(), frame_tree_node_); 1078 CreateOpenerProxies(navigation_rfh->GetSiteInstance(), frame_tree_node_);
1080 if (!InitRenderView(navigation_rfh->render_view_host(), MSG_ROUTING_NONE)) { 1079 if (!InitRenderView(navigation_rfh->render_view_host(), nullptr)) {
1081 return nullptr; 1080 return nullptr;
1082 } 1081 }
1083 1082
1084 if (navigation_rfh == render_frame_host_) { 1083 if (navigation_rfh == render_frame_host_) {
1085 // TODO(nasko): This is a very ugly hack. The Chrome extensions process 1084 // TODO(nasko): This is a very ugly hack. The Chrome extensions process
1086 // manager still uses NotificationService and expects to see a 1085 // manager still uses NotificationService and expects to see a
1087 // RenderViewHost changed notification after WebContents and 1086 // RenderViewHost changed notification after WebContents and
1088 // RenderFrameHostManager are completely initialized. This should be 1087 // RenderFrameHostManager are completely initialized. This should be
1089 // removed once the process manager moves away from NotificationService. 1088 // removed once the process manager moves away from NotificationService.
1090 // See https://crbug.com/462682. 1089 // See https://crbug.com/462682.
(...skipping 696 matching lines...) Expand 10 before | Expand all | Expand 10 after
1787 // Prevent the process from exiting while we're trying to use it. 1786 // Prevent the process from exiting while we're trying to use it.
1788 if (!swapped_out) { 1787 if (!swapped_out) {
1789 new_render_frame_host = proxy->PassFrameHostOwnership(); 1788 new_render_frame_host = proxy->PassFrameHostOwnership();
1790 new_render_frame_host->GetProcess()->AddPendingView(); 1789 new_render_frame_host->GetProcess()->AddPendingView();
1791 1790
1792 proxy_hosts_->Remove(instance->GetId()); 1791 proxy_hosts_->Remove(instance->GetId());
1793 // NB |proxy| is deleted at this point. 1792 // NB |proxy| is deleted at this point.
1794 1793
1795 // If we are reusing the RenderViewHost and it doesn't already have a 1794 // If we are reusing the RenderViewHost and it doesn't already have a
1796 // RenderWidgetHostView, we need to create one if this is the main frame. 1795 // RenderWidgetHostView, we need to create one if this is the main frame.
1797 if (!render_view_host->GetWidget()->GetView() && 1796 if (render_view_host->IsRenderViewLive() &&
1797 !render_view_host->GetWidget()->GetView() &&
1798 frame_tree_node_->IsMainFrame()) { 1798 frame_tree_node_->IsMainFrame()) {
1799 delegate_->CreateRenderWidgetHostViewForRenderManager(render_view_host); 1799 delegate_->CreateRenderWidgetHostViewForRenderManager(render_view_host);
1800 } 1800 }
1801 } 1801 }
1802 } else { 1802 } else {
1803 // Create a new RenderFrameHost if we don't find an existing one. 1803 // Create a new RenderFrameHost if we don't find an existing one.
1804 1804
1805 int32 widget_routing_id = MSG_ROUTING_NONE; 1805 int32 widget_routing_id = MSG_ROUTING_NONE;
1806 // A RenderFrame in a different process from its parent RenderFrame 1806 // A RenderFrame in a different process from its parent RenderFrame
1807 // requires a RenderWidget for input/layout/painting. 1807 // requires a RenderWidget for input/layout/painting.
1808 if (frame_tree_node_->parent() && 1808 if (frame_tree_node_->parent() &&
1809 frame_tree_node_->parent()->current_frame_host()->GetSiteInstance() != 1809 frame_tree_node_->parent()->current_frame_host()->GetSiteInstance() !=
1810 instance) { 1810 instance) {
1811 CHECK(SiteIsolationPolicy::AreCrossProcessFramesPossible()); 1811 CHECK(SiteIsolationPolicy::AreCrossProcessFramesPossible());
1812 widget_routing_id = instance->GetProcess()->GetNextRoutingID(); 1812 widget_routing_id = instance->GetProcess()->GetNextRoutingID();
1813 } 1813 }
1814 1814
1815 new_render_frame_host = CreateRenderFrameHost( 1815 new_render_frame_host = CreateRenderFrameHost(
1816 instance, MSG_ROUTING_NONE, MSG_ROUTING_NONE, widget_routing_id, flags); 1816 instance, MSG_ROUTING_NONE, MSG_ROUTING_NONE, widget_routing_id, flags);
1817 RenderViewHostImpl* render_view_host = 1817 RenderViewHostImpl* render_view_host =
1818 new_render_frame_host->render_view_host(); 1818 new_render_frame_host->render_view_host();
1819 int proxy_routing_id = MSG_ROUTING_NONE;
1820 1819
1821 // Prevent the process from exiting while we're trying to navigate in it. 1820 // Prevent the process from exiting while we're trying to navigate in it.
1822 // Otherwise, if the new RFH is swapped out already, store it. 1821 // Otherwise, if the new RFH is swapped out already, store it.
1823 if (!swapped_out) { 1822 if (!swapped_out) {
1824 new_render_frame_host->GetProcess()->AddPendingView(); 1823 new_render_frame_host->GetProcess()->AddPendingView();
1825 } else { 1824 } else {
1826 proxy = new RenderFrameProxyHost( 1825 proxy = new RenderFrameProxyHost(
1827 new_render_frame_host->GetSiteInstance(), 1826 new_render_frame_host->GetSiteInstance(),
1828 new_render_frame_host->render_view_host(), frame_tree_node_); 1827 new_render_frame_host->render_view_host(), frame_tree_node_);
1829 proxy_hosts_->Add(instance->GetId(), make_scoped_ptr(proxy)); 1828 proxy_hosts_->Add(instance->GetId(), make_scoped_ptr(proxy));
1830 proxy_routing_id = proxy->GetRoutingID();
Charlie Reis 2015/10/16 23:09:57 For posterity: this is the key part of the fix. W
1831 proxy->TakeFrameHostOwnership(new_render_frame_host.Pass()); 1829 proxy->TakeFrameHostOwnership(new_render_frame_host.Pass());
1832 } 1830 }
1833 1831
1834 if (frame_tree_node_->IsMainFrame()) { 1832 if (frame_tree_node_->IsMainFrame()) {
1835 success = InitRenderView(render_view_host, proxy_routing_id); 1833 success = InitRenderView(render_view_host, proxy);
1836 1834
1837 // If we are reusing the RenderViewHost and it doesn't already have a 1835 // If we are reusing the RenderViewHost and it doesn't already have a
1838 // RenderWidgetHostView, we need to create one if this is the main frame. 1836 // RenderWidgetHostView, we need to create one if this is the main frame.
1839 if (!swapped_out && !render_view_host->GetWidget()->GetView()) 1837 if (!swapped_out && !render_view_host->GetWidget()->GetView())
1840 delegate_->CreateRenderWidgetHostViewForRenderManager(render_view_host); 1838 delegate_->CreateRenderWidgetHostViewForRenderManager(render_view_host);
1841 } else { 1839 } else {
1842 DCHECK(render_view_host->IsRenderViewLive()); 1840 DCHECK(render_view_host->IsRenderViewLive());
1843 } 1841 }
1844 1842
1845 if (success) { 1843 if (success) {
1846 // Remember that InitRenderView also created the RenderFrameProxy.
1847 if (swapped_out)
1848 proxy->set_render_frame_proxy_created(true);
1849 if (frame_tree_node_->IsMainFrame()) { 1844 if (frame_tree_node_->IsMainFrame()) {
1850 // Don't show the main frame's view until we get a DidNavigate from it. 1845 // Don't show the main frame's view until we get a DidNavigate from it.
1851 // Only the RenderViewHost for the top-level RenderFrameHost has a 1846 // Only the RenderViewHost for the top-level RenderFrameHost has a
1852 // RenderWidgetHostView; RenderWidgetHosts for out-of-process iframes 1847 // RenderWidgetHostView; RenderWidgetHosts for out-of-process iframes
1853 // will be created later and hidden. 1848 // will be created later and hidden.
1854 if (render_view_host->GetWidget()->GetView()) 1849 if (render_view_host->GetWidget()->GetView())
1855 render_view_host->GetWidget()->GetView()->Hide(); 1850 render_view_host->GetWidget()->GetView()->Hide();
1856 } 1851 }
1857 // RenderViewHost for |instance| might exist prior to calling 1852 // RenderViewHost for |instance| might exist prior to calling
1858 // CreateRenderFrame. In such a case, InitRenderView will not create the 1853 // CreateRenderFrame. In such a case, InitRenderView will not create the
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
1919 return proxy->GetRoutingID(); 1914 return proxy->GetRoutingID();
1920 1915
1921 if (!proxy) { 1916 if (!proxy) {
1922 proxy = 1917 proxy =
1923 new RenderFrameProxyHost(instance, render_view_host, frame_tree_node_); 1918 new RenderFrameProxyHost(instance, render_view_host, frame_tree_node_);
1924 proxy_hosts_->Add(instance->GetId(), make_scoped_ptr(proxy)); 1919 proxy_hosts_->Add(instance->GetId(), make_scoped_ptr(proxy));
1925 } 1920 }
1926 1921
1927 if (SiteIsolationPolicy::IsSwappedOutStateForbidden() && 1922 if (SiteIsolationPolicy::IsSwappedOutStateForbidden() &&
1928 frame_tree_node_->IsMainFrame()) { 1923 frame_tree_node_->IsMainFrame()) {
1929 InitRenderView(render_view_host, proxy->GetRoutingID()); 1924 InitRenderView(render_view_host, proxy);
1930 proxy->set_render_frame_proxy_created(true);
1931 } else { 1925 } else {
1932 proxy->InitRenderFrameProxy(); 1926 proxy->InitRenderFrameProxy();
1933 } 1927 }
1934 1928
1935 return proxy->GetRoutingID(); 1929 return proxy->GetRoutingID();
1936 } 1930 }
1937 1931
1938 void RenderFrameHostManager::CreateProxiesForChildFrame(FrameTreeNode* child) { 1932 void RenderFrameHostManager::CreateProxiesForChildFrame(FrameTreeNode* child) {
1939 for (const auto& pair : *proxy_hosts_) { 1933 for (const auto& pair : *proxy_hosts_) {
1940 // Do not create proxies for subframes in the outer delegate's process, 1934 // Do not create proxies for subframes in the outer delegate's process,
(...skipping 13 matching lines...) Expand all
1954 1948
1955 if (render_view_host->IsRenderViewLive()) 1949 if (render_view_host->IsRenderViewLive())
1956 return; 1950 return;
1957 1951
1958 // If the proxy in |instance| doesn't exist, this RenderView is not swapped 1952 // If the proxy in |instance| doesn't exist, this RenderView is not swapped
1959 // out and shouldn't be reinitialized here. 1953 // out and shouldn't be reinitialized here.
1960 RenderFrameProxyHost* proxy = GetRenderFrameProxyHost(instance); 1954 RenderFrameProxyHost* proxy = GetRenderFrameProxyHost(instance);
1961 if (!proxy) 1955 if (!proxy)
1962 return; 1956 return;
1963 1957
1964 InitRenderView(render_view_host, proxy->GetRoutingID()); 1958 InitRenderView(render_view_host, proxy);
1965 proxy->set_render_frame_proxy_created(true);
1966 } 1959 }
1967 1960
1968 void RenderFrameHostManager::CreateOuterDelegateProxy( 1961 void RenderFrameHostManager::CreateOuterDelegateProxy(
1969 SiteInstance* outer_contents_site_instance, 1962 SiteInstance* outer_contents_site_instance,
1970 RenderFrameHostImpl* render_frame_host) { 1963 RenderFrameHostImpl* render_frame_host) {
1971 CHECK(BrowserPluginGuestMode::UseCrossProcessFramesForGuests()); 1964 CHECK(BrowserPluginGuestMode::UseCrossProcessFramesForGuests());
1972 RenderFrameProxyHost* proxy = new RenderFrameProxyHost( 1965 RenderFrameProxyHost* proxy = new RenderFrameProxyHost(
1973 outer_contents_site_instance, nullptr, frame_tree_node_); 1966 outer_contents_site_instance, nullptr, frame_tree_node_);
1974 proxy_hosts_->Add(outer_contents_site_instance->GetId(), 1967 proxy_hosts_->Add(outer_contents_site_instance->GetId(),
1975 make_scoped_ptr(proxy)); 1968 make_scoped_ptr(proxy));
(...skipping 13 matching lines...) Expand all
1989 } 1982 }
1990 1983
1991 void RenderFrameHostManager::SetRWHViewForInnerContents( 1984 void RenderFrameHostManager::SetRWHViewForInnerContents(
1992 RenderWidgetHostView* child_rwhv) { 1985 RenderWidgetHostView* child_rwhv) {
1993 DCHECK(ForInnerDelegate() && frame_tree_node_->IsMainFrame()); 1986 DCHECK(ForInnerDelegate() && frame_tree_node_->IsMainFrame());
1994 GetProxyToOuterDelegate()->SetChildRWHView(child_rwhv); 1987 GetProxyToOuterDelegate()->SetChildRWHView(child_rwhv);
1995 } 1988 }
1996 1989
1997 bool RenderFrameHostManager::InitRenderView( 1990 bool RenderFrameHostManager::InitRenderView(
1998 RenderViewHostImpl* render_view_host, 1991 RenderViewHostImpl* render_view_host,
1999 int proxy_routing_id) { 1992 RenderFrameProxyHost* proxy) {
2000 // Ensure the renderer process is initialized before creating the 1993 // Ensure the renderer process is initialized before creating the
2001 // RenderView. 1994 // RenderView.
2002 if (!render_view_host->GetProcess()->Init()) 1995 if (!render_view_host->GetProcess()->Init())
2003 return false; 1996 return false;
2004 1997
2005 // We may have initialized this RenderViewHost for another RenderFrameHost. 1998 // We may have initialized this RenderViewHost for another RenderFrameHost.
2006 if (render_view_host->IsRenderViewLive()) 1999 if (render_view_host->IsRenderViewLive())
2007 return true; 2000 return true;
2008 2001
2009 // If |render_view_host| is not for a proxy and the navigation is to a WebUI, 2002 // If |render_view_host| is not for a proxy and the navigation is to a WebUI,
2010 // and if the RenderView is not in a guest process, tell |render_view_host| 2003 // and if the RenderView is not in a guest process, tell |render_view_host|
2011 // about any bindings it will need enabled. 2004 // about any bindings it will need enabled.
2012 // TODO(carlosk): Move WebUI to RenderFrameHost in https://crbug.com/508850. 2005 // TODO(carlosk): Move WebUI to RenderFrameHost in https://crbug.com/508850.
2013 WebUIImpl* dest_web_ui = nullptr; 2006 WebUIImpl* dest_web_ui = nullptr;
2014 DCHECK_EQ(render_view_host->is_active(), 2007 DCHECK_EQ(render_view_host->is_active(), !proxy);
Charlie Reis 2015/10/16 23:09:57 These are no longer equal, as your test shows. Su
nasko 2015/10/16 23:42:09 I think this is correct. I've removed the DCHECK.
2015 proxy_routing_id == MSG_ROUTING_NONE); 2008 if (!proxy) {
2016 if (proxy_routing_id == MSG_ROUTING_NONE) {
2017 if (base::CommandLine::ForCurrentProcess()->HasSwitch( 2009 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2018 switches::kEnableBrowserSideNavigation)) { 2010 switches::kEnableBrowserSideNavigation)) {
2019 dest_web_ui = 2011 dest_web_ui =
2020 should_reuse_web_ui_ ? web_ui_.get() : speculative_web_ui_.get(); 2012 should_reuse_web_ui_ ? web_ui_.get() : speculative_web_ui_.get();
2021 } else { 2013 } else {
2022 dest_web_ui = pending_web_ui(); 2014 dest_web_ui = pending_web_ui();
2023 } 2015 }
2024 } 2016 }
2025 if (dest_web_ui && !render_view_host->GetProcess()->IsForGuestsOnly()) { 2017 if (dest_web_ui && !render_view_host->GetProcess()->IsForGuestsOnly()) {
2026 render_view_host->AllowBindings(dest_web_ui->GetBindings()); 2018 render_view_host->AllowBindings(dest_web_ui->GetBindings());
2027 } else { 2019 } else {
2028 // Ensure that we don't create an unprivileged RenderView in a WebUI-enabled 2020 // Ensure that we don't create an unprivileged RenderView in a WebUI-enabled
2029 // process unless it's swapped out. 2021 // process unless it's swapped out.
2030 if (render_view_host->is_active()) { 2022 if (render_view_host->is_active()) {
2031 CHECK(!ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings( 2023 CHECK(!ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
2032 render_view_host->GetProcess()->GetID())); 2024 render_view_host->GetProcess()->GetID()));
2033 } 2025 }
2034 } 2026 }
2035 2027
2036 int opener_frame_routing_id = 2028 int opener_frame_routing_id =
2037 GetOpenerRoutingID(render_view_host->GetSiteInstance()); 2029 GetOpenerRoutingID(render_view_host->GetSiteInstance());
2038 2030
2039 return delegate_->CreateRenderViewForRenderManager( 2031 bool created = delegate_->CreateRenderViewForRenderManager(
2040 render_view_host, opener_frame_routing_id, proxy_routing_id, 2032 render_view_host, opener_frame_routing_id,
2033 proxy ? proxy->GetRoutingID() : MSG_ROUTING_NONE,
2041 frame_tree_node_->current_replication_state()); 2034 frame_tree_node_->current_replication_state());
2035
2036 if (proxy)
nasko 2015/10/16 23:42:09 I also noticed that the bool is set unconditionall
alexmos 2015/10/16 23:54:17 Acknowledged.
2037 proxy->set_render_frame_proxy_created(true);
2038
2039 return created;
2042 } 2040 }
2043 2041
2044 bool RenderFrameHostManager::InitRenderFrame( 2042 bool RenderFrameHostManager::InitRenderFrame(
2045 RenderFrameHostImpl* render_frame_host) { 2043 RenderFrameHostImpl* render_frame_host) {
2046 if (render_frame_host->IsRenderFrameLive()) 2044 if (render_frame_host->IsRenderFrameLive())
2047 return true; 2045 return true;
2048 2046
2049 SiteInstance* site_instance = render_frame_host->GetSiteInstance(); 2047 SiteInstance* site_instance = render_frame_host->GetSiteInstance();
2050 2048
2051 int opener_routing_id = MSG_ROUTING_NONE; 2049 int opener_routing_id = MSG_ROUTING_NONE;
(...skipping 598 matching lines...) Expand 10 before | Expand all | Expand 10 after
2650 int RenderFrameHostManager::GetOpenerRoutingID(SiteInstance* instance) { 2648 int RenderFrameHostManager::GetOpenerRoutingID(SiteInstance* instance) {
2651 if (!frame_tree_node_->opener()) 2649 if (!frame_tree_node_->opener())
2652 return MSG_ROUTING_NONE; 2650 return MSG_ROUTING_NONE;
2653 2651
2654 return frame_tree_node_->opener() 2652 return frame_tree_node_->opener()
2655 ->render_manager() 2653 ->render_manager()
2656 ->GetRoutingIdForSiteInstance(instance); 2654 ->GetRoutingIdForSiteInstance(instance);
2657 } 2655 }
2658 2656
2659 } // namespace content 2657 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698