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

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

Issue 2041993002: WebUI: Fix lifecycle-bug when RenderFrameHost is swapped out (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 6 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 <stddef.h> 5 #include <stddef.h>
6 #include <stdint.h> 6 #include <stdint.h>
7 7
8 #include <set> 8 #include <set>
9 9
10 #include "base/command_line.h" 10 #include "base/command_line.h"
(...skipping 16 matching lines...) Expand all
27 #include "content/browser/webui/web_ui_impl.h" 27 #include "content/browser/webui/web_ui_impl.h"
28 #include "content/common/content_constants_internal.h" 28 #include "content/common/content_constants_internal.h"
29 #include "content/common/input_messages.h" 29 #include "content/common/input_messages.h"
30 #include "content/common/site_isolation_policy.h" 30 #include "content/common/site_isolation_policy.h"
31 #include "content/public/browser/navigation_controller.h" 31 #include "content/public/browser/navigation_controller.h"
32 #include "content/public/browser/navigation_entry.h" 32 #include "content/public/browser/navigation_entry.h"
33 #include "content/public/browser/render_process_host.h" 33 #include "content/public/browser/render_process_host.h"
34 #include "content/public/browser/resource_dispatcher_host.h" 34 #include "content/public/browser/resource_dispatcher_host.h"
35 #include "content/public/browser/web_contents.h" 35 #include "content/public/browser/web_contents.h"
36 #include "content/public/browser/web_contents_observer.h" 36 #include "content/public/browser/web_contents_observer.h"
37 #include "content/public/browser/web_ui_message_handler.h"
37 #include "content/public/common/bindings_policy.h" 38 #include "content/public/common/bindings_policy.h"
38 #include "content/public/common/browser_side_navigation_policy.h" 39 #include "content/public/common/browser_side_navigation_policy.h"
39 #include "content/public/common/content_switches.h" 40 #include "content/public/common/content_switches.h"
40 #include "content/public/common/file_chooser_file_info.h" 41 #include "content/public/common/file_chooser_file_info.h"
41 #include "content/public/common/file_chooser_params.h" 42 #include "content/public/common/file_chooser_params.h"
42 #include "content/public/common/page_state.h" 43 #include "content/public/common/page_state.h"
43 #include "content/public/common/url_constants.h" 44 #include "content/public/common/url_constants.h"
44 #include "content/public/test/browser_test_utils.h" 45 #include "content/public/test/browser_test_utils.h"
45 #include "content/public/test/content_browser_test.h" 46 #include "content/public/test/content_browser_test.h"
46 #include "content/public/test/content_browser_test_utils.h" 47 #include "content/public/test/content_browser_test_utils.h"
(...skipping 21 matching lines...) Expand all
68 " document.body.appendChild(lnk);\n" 69 " document.body.appendChild(lnk);\n"
69 " lnk.click();\n" 70 " lnk.click();\n"
70 "})"; 71 "})";
71 72
72 // Adds a link with given url and target=_blank, and clicks on it. 73 // Adds a link with given url and target=_blank, and clicks on it.
73 void OpenUrlViaClickTarget(const ToRenderFrameHost& adapter, const GURL& url) { 74 void OpenUrlViaClickTarget(const ToRenderFrameHost& adapter, const GURL& url) {
74 EXPECT_TRUE(ExecuteScript(adapter, 75 EXPECT_TRUE(ExecuteScript(adapter,
75 std::string(kOpenUrlViaClickTargetFunc) + "(\"" + url.spec() + "\");")); 76 std::string(kOpenUrlViaClickTargetFunc) + "(\"" + url.spec() + "\");"));
76 } 77 }
77 78
79 class TestWebUIMessageHandler : public WebUIMessageHandler {
80 public:
81 using WebUIMessageHandler::AllowJavascript;
82 using WebUIMessageHandler::IsJavascriptAllowed;
83
84 protected:
85 void RegisterMessages() override {}
86 };
87
88 // This class implements waiting for RenderFrameHost destruction. It relies on
89 // the fact that RenderFrameDeleted event is fired when RenderFrameHost is
90 // destroyed.
91 // Note: RenderFrameDeleted is also fired when the process associated with the
92 // RenderFrameHost crashes, so this cannot be used in cases where process dying
93 // is expected.
94 class RenderFrameHostDestructionObserver : public WebContentsObserver {
95 public:
96 explicit RenderFrameHostDestructionObserver(RenderFrameHost* rfh)
97 : WebContentsObserver(WebContents::FromRenderFrameHost(rfh)),
98 message_loop_runner_(new MessageLoopRunner),
99 deleted_(false),
100 render_frame_host_(rfh) {}
101 ~RenderFrameHostDestructionObserver() override {}
102
103 bool deleted() const { return deleted_; }
104
105 void Wait() {
106 if (deleted_)
107 return;
108
109 message_loop_runner_->Run();
110 }
111
112 // WebContentsObserver implementation:
113 void RenderFrameDeleted(RenderFrameHost* rfh) override {
114 if (rfh == render_frame_host_) {
115 CHECK(!deleted_);
116 deleted_ = true;
117 }
118
119 if (deleted_ && message_loop_runner_->loop_running()) {
120 base::ThreadTaskRunnerHandle::Get()->PostTask(
121 FROM_HERE, message_loop_runner_->QuitClosure());
122 }
123 }
124
125 private:
126 scoped_refptr<MessageLoopRunner> message_loop_runner_;
127 bool deleted_;
128 RenderFrameHost* render_frame_host_;
129 };
130
78 } // anonymous namespace 131 } // anonymous namespace
79 132
80 class RenderFrameHostManagerTest : public ContentBrowserTest { 133 class RenderFrameHostManagerTest : public ContentBrowserTest {
81 public: 134 public:
82 RenderFrameHostManagerTest() : foo_com_("foo.com") { 135 RenderFrameHostManagerTest() : foo_com_("foo.com") {
83 replace_host_.SetHostStr(foo_com_); 136 replace_host_.SetHostStr(foo_com_);
84 } 137 }
85 138
86 static void GetFilePathWithHostAndPortReplacement( 139 static void GetFilePathWithHostAndPortReplacement(
87 const std::string& original_file_path, 140 const std::string& original_file_path,
(...skipping 1722 matching lines...) Expand 10 before | Expand all | Expand 10 after
1810 1863
1811 EXPECT_TRUE(NavigateToURL(shell(), GURL(url::kAboutBlankURL))); 1864 EXPECT_TRUE(NavigateToURL(shell(), GURL(url::kAboutBlankURL)));
1812 EXPECT_NE(orig_site_instance, shell()->web_contents()->GetSiteInstance()); 1865 EXPECT_NE(orig_site_instance, shell()->web_contents()->GetSiteInstance());
1813 1866
1814 GURL regular_page_url(embedded_test_server()->GetURL("/title2.html")); 1867 GURL regular_page_url(embedded_test_server()->GetURL("/title2.html"));
1815 EXPECT_TRUE(NavigateToURL(shell(), regular_page_url)); 1868 EXPECT_TRUE(NavigateToURL(shell(), regular_page_url));
1816 EXPECT_FALSE(ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings( 1869 EXPECT_FALSE(ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
1817 shell()->web_contents()->GetRenderProcessHost()->GetID())); 1870 shell()->web_contents()->GetRenderProcessHost()->GetID()));
1818 } 1871 }
1819 1872
1873 // crbug.com/615274
1874 // This test ensures that after an RFH is swapped out, the associated WebUI
1875 // instance is no longer allowed to send JavaScript messages. This is necessary
1876 // because WebUI currently (and unusually) always sends JavaScript messages to
1877 // the current main frame, rather than the RFH that owns the WebUI.
1878 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
1879 WebUIJavascriptDisallowedAfterSwapOut) {
1880 StartEmbeddedServer();
1881
1882 const GURL web_ui_url(std::string(kChromeUIScheme) + "://" +
1883 std::string(kChromeUIGpuHost));
1884 EXPECT_TRUE(NavigateToURL(shell(), web_ui_url));
1885
1886 RenderFrameHostImpl* rfh =
1887 static_cast<WebContentsImpl*>(shell()->web_contents())->GetMainFrame();
1888
1889 // Set up a slow unload handler to force the RFH to linger in the swapped
1890 // out but not-yet-deleted state.
1891 EXPECT_TRUE(
1892 ExecuteScript(rfh, "window.onunload=function(e){ while(1); };\n"));
1893
1894 WebUIImpl* web_ui = rfh->web_ui();
1895
1896 EXPECT_TRUE(web_ui->CanCallJavascript());
1897 TestWebUIMessageHandler* handler = new TestWebUIMessageHandler();
1898
1899 web_ui->AddMessageHandler(handler);
1900 EXPECT_FALSE(handler->IsJavascriptAllowed());
1901
1902 handler->AllowJavascript();
1903 EXPECT_TRUE(handler->IsJavascriptAllowed());
1904
1905 rfh->DisableSwapOutTimerForTesting();
1906 RenderFrameHostDestructionObserver rfh_observer(rfh);
1907
1908 // Navigate, but wait for commit, not the actual load to finish.
1909 SiteInstanceImpl* web_ui_site_instance = rfh->GetSiteInstance();
1910 FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
1911 ->GetFrameTree()
1912 ->root();
1913 TestFrameNavigationObserver commit_observer(root);
1914 shell()->LoadURL(GURL(url::kAboutBlankURL));
1915 commit_observer.WaitForCommit();
1916 EXPECT_NE(web_ui_site_instance, shell()->web_contents()->GetSiteInstance());
1917 EXPECT_TRUE(
1918 root->render_manager()->GetRenderFrameProxyHost(web_ui_site_instance));
1919
1920 // The previous RFH should still be pending deletion, as we wait for either
1921 // the SwapOut ACK or a timeout.
1922 ASSERT_TRUE(rfh->IsRenderFrameLive());
1923 ASSERT_FALSE(rfh->is_active());
1924
1925 // We specifically want verify behavior between swap-out and RFH destruction.
1926 ASSERT_FALSE(rfh_observer.deleted());
1927
1928 EXPECT_FALSE(handler->IsJavascriptAllowed());
1929 }
1930
1820 class FileChooserDelegate : public WebContentsDelegate { 1931 class FileChooserDelegate : public WebContentsDelegate {
1821 public: 1932 public:
1822 FileChooserDelegate(const base::FilePath& file) 1933 FileChooserDelegate(const base::FilePath& file)
1823 : file_(file), file_chosen_(false) {} 1934 : file_(file), file_chosen_(false) {}
1824 1935
1825 void RunFileChooser(WebContents* web_contents, 1936 void RunFileChooser(WebContents* web_contents,
1826 const FileChooserParams& params) override { 1937 const FileChooserParams& params) override {
1827 // Send the selected file to the renderer process. 1938 // Send the selected file to the renderer process.
1828 FileChooserFileInfo file_info; 1939 FileChooserFileInfo file_info;
1829 file_info.file_path = file_; 1940 file_info.file_path = file_;
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
1952 shell()->web_contents()->GetController().GoBack(); 2063 shell()->web_contents()->GetController().GoBack();
1953 back_nav_load_observer.Wait(); 2064 back_nav_load_observer.Wait();
1954 EXPECT_NE(process_id, 2065 EXPECT_NE(process_id,
1955 shell()->web_contents()->GetRenderProcessHost()->GetID()); 2066 shell()->web_contents()->GetRenderProcessHost()->GetID());
1956 2067
1957 // Ensure that the file access still exists in the new process ID. 2068 // Ensure that the file access still exists in the new process ID.
1958 EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile( 2069 EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile(
1959 shell()->web_contents()->GetRenderProcessHost()->GetID(), file)); 2070 shell()->web_contents()->GetRenderProcessHost()->GetID(), file));
1960 } 2071 }
1961 2072
1962 // This class implements waiting for RenderFrameHost destruction. It relies on
1963 // the fact that RenderFrameDeleted event is fired when RenderFrameHost is
1964 // destroyed.
1965 // Note: RenderFrameDeleted is also fired when the process associated with the
1966 // RenderFrameHost crashes, so this cannot be used in cases where process dying
1967 // is expected.
1968 class RenderFrameHostDestructionObserver : public WebContentsObserver {
1969 public:
1970 explicit RenderFrameHostDestructionObserver(RenderFrameHost* rfh)
1971 : WebContentsObserver(WebContents::FromRenderFrameHost(rfh)),
1972 message_loop_runner_(new MessageLoopRunner),
1973 deleted_(false),
1974 render_frame_host_(rfh) {}
1975 ~RenderFrameHostDestructionObserver() override {}
1976
1977 void Wait() {
1978 if (deleted_)
1979 return;
1980
1981 message_loop_runner_->Run();
1982 }
1983
1984 // WebContentsObserver implementation:
1985 void RenderFrameDeleted(RenderFrameHost* rfh) override {
1986 if (rfh == render_frame_host_) {
1987 CHECK(!deleted_);
1988 deleted_ = true;
1989 }
1990
1991 if (deleted_ && message_loop_runner_->loop_running()) {
1992 base::ThreadTaskRunnerHandle::Get()->PostTask(
1993 FROM_HERE, message_loop_runner_->QuitClosure());
1994 }
1995 }
1996
1997 private:
1998 scoped_refptr<MessageLoopRunner> message_loop_runner_;
1999 bool deleted_;
2000 RenderFrameHost* render_frame_host_;
2001 };
2002
2003 // Ensures that no RenderFrameHost/RenderViewHost objects are leaked when 2073 // Ensures that no RenderFrameHost/RenderViewHost objects are leaked when
2004 // doing a simple cross-process navigation. 2074 // doing a simple cross-process navigation.
2005 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, 2075 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
2006 CleanupOnCrossProcessNavigation) { 2076 CleanupOnCrossProcessNavigation) {
2007 StartEmbeddedServer(); 2077 StartEmbeddedServer();
2008 2078
2009 // Do an initial navigation and capture objects we expect to be cleaned up 2079 // Do an initial navigation and capture objects we expect to be cleaned up
2010 // on cross-process navigation. 2080 // on cross-process navigation.
2011 GURL start_url = embedded_test_server()->GetURL("/title1.html"); 2081 GURL start_url = embedded_test_server()->GetURL("/title1.html");
2012 NavigateToURL(shell(), start_url); 2082 NavigateToURL(shell(), start_url);
(...skipping 737 matching lines...) Expand 10 before | Expand all | Expand 10 after
2750 TestNavigationObserver commit_observer(web_contents); 2820 TestNavigationObserver commit_observer(web_contents);
2751 shell()->LoadURL(embedded_test_server()->GetURL("b.com", "/title1.html")); 2821 shell()->LoadURL(embedded_test_server()->GetURL("b.com", "/title1.html"));
2752 commit_observer.Wait(); 2822 commit_observer.Wait();
2753 exit_observer.Wait(); 2823 exit_observer.Wait();
2754 2824
2755 // Ensure the entry's title hasn't changed after the ignored commit. 2825 // Ensure the entry's title hasn't changed after the ignored commit.
2756 EXPECT_EQ(title, entry->GetTitle()); 2826 EXPECT_EQ(title, entry->GetTitle());
2757 } 2827 }
2758 2828
2759 } // namespace content 2829 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/frame_host/render_frame_host_impl.cc ('k') | content/browser/webui/web_ui_impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698