1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "base/path_service.h" 6 #include "base/strings/utf_string_conversions.h" 7 #include "base/time/time.h" 8 #include "base/values.h" 9 #include "content/browser/frame_host/render_frame_host_impl.h" 10 #include "content/browser/renderer_host/render_view_host_impl.h" 11 #include "content/browser/web_contents/web_contents_impl.h" 12 #include "content/common/view_messages.h" 13 #include "content/public/browser/notification_types.h" 14 #include "content/public/browser/web_contents_observer.h" 15 #include "content/public/common/content_paths.h" 16 #include "content/public/common/frame_navigate_params.h" 17 #include "content/public/test/browser_test_utils.h" 18 #include "content/public/test/content_browser_test.h" 19 #include "content/public/test/content_browser_test_utils.h" 20 #include "content/shell/browser/shell.h" 21 #include "net/base/filename_util.h" 22 #include "net/base/host_port_pair.h" 23 #include "net/test/embedded_test_server/embedded_test_server.h" 24 25 namespace content { 26 27 class RenderViewHostTest : public ContentBrowserTest { 28 public: 29 RenderViewHostTest() {} 30 }; 31 32 class RenderViewHostTestWebContentsObserver : public WebContentsObserver { 33 public: 34 explicit RenderViewHostTestWebContentsObserver(WebContents* web_contents) 35 : WebContentsObserver(web_contents), 36 navigation_count_(0) {} 37 virtual ~RenderViewHostTestWebContentsObserver() {} 38 39 virtual void DidNavigateMainFrame( 40 const LoadCommittedDetails& details, 41 const FrameNavigateParams& params) OVERRIDE { 42 observed_socket_address_ = params.socket_address; 43 base_url_ = params.base_url; 44 ++navigation_count_; 45 } 46 47 const net::HostPortPair& observed_socket_address() const { 48 return observed_socket_address_; 49 } 50 51 GURL base_url() const { 52 return base_url_; 53 } 54 55 int navigation_count() const { return navigation_count_; } 56 57 private: 58 net::HostPortPair observed_socket_address_; 59 GURL base_url_; 60 int navigation_count_; 61 62 DISALLOW_COPY_AND_ASSIGN(RenderViewHostTestWebContentsObserver); 63 }; 64 65 IN_PROC_BROWSER_TEST_F(RenderViewHostTest, FrameNavigateSocketAddress) { 66 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); 67 RenderViewHostTestWebContentsObserver observer(shell()->web_contents()); 68 69 GURL test_url = embedded_test_server()->GetURL("/simple_page.html"); 70 NavigateToURL(shell(), test_url); 71 72 EXPECT_EQ(net::HostPortPair::FromURL( 73 embedded_test_server()->base_url()).ToString(), 74 observer.observed_socket_address().ToString()); 75 EXPECT_EQ(1, observer.navigation_count()); 76 } 77 78 IN_PROC_BROWSER_TEST_F(RenderViewHostTest, BaseURLParam) { 79 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); 80 RenderViewHostTestWebContentsObserver observer(shell()->web_contents()); 81 82 // Base URL is not set if it is the same as the URL. 83 GURL test_url = embedded_test_server()->GetURL("/simple_page.html"); 84 NavigateToURL(shell(), test_url); 85 EXPECT_TRUE(observer.base_url().is_empty()); 86 EXPECT_EQ(1, observer.navigation_count()); 87 88 // But should be set to the original page when reading MHTML. 89 base::FilePath content_test_data_dir; 90 ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &content_test_data_dir)); 91 test_url = net::FilePathToFileURL( 92 content_test_data_dir.AppendASCII("google.mht")); 93 NavigateToURL(shell(), test_url); 94 EXPECT_EQ("http://www.google.com/", observer.base_url().spec()); 95 } 96 97 // This test ensures a RenderFrameHost object is created for the top level frame 98 // in each RenderViewHost. 99 IN_PROC_BROWSER_TEST_F(RenderViewHostTest, BasicRenderFrameHost) { 100 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); 101 102 GURL test_url = embedded_test_server()->GetURL("/simple_page.html"); 103 NavigateToURL(shell(), test_url); 104 105 FrameTreeNode* old_root = static_cast<WebContentsImpl*>( 106 shell()->web_contents())->GetFrameTree()->root(); 107 EXPECT_TRUE(old_root->current_frame_host()); 108 109 ShellAddedObserver new_shell_observer; 110 EXPECT_TRUE(ExecuteScript(shell()->web_contents(), "window.open();")); 111 Shell* new_shell = new_shell_observer.GetShell(); 112 FrameTreeNode* new_root = static_cast<WebContentsImpl*>( 113 new_shell->web_contents())->GetFrameTree()->root(); 114 115 EXPECT_TRUE(new_root->current_frame_host()); 116 EXPECT_NE(old_root->current_frame_host()->routing_id(), 117 new_root->current_frame_host()->routing_id()); 118 } 119 120 IN_PROC_BROWSER_TEST_F(RenderViewHostTest, IsFocusedElementEditable) { 121 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); 122 123 GURL test_url = embedded_test_server()->GetURL("/touch_selection.html"); 124 NavigateToURL(shell(), test_url); 125 126 RenderViewHost* rvh = shell()->web_contents()->GetRenderViewHost(); 127 EXPECT_FALSE(rvh->IsFocusedElementEditable()); 128 EXPECT_TRUE(ExecuteScript(shell()->web_contents(), "focus_textfield();")); 129 EXPECT_TRUE(rvh->IsFocusedElementEditable()); 130 } 131 132 IN_PROC_BROWSER_TEST_F(RenderViewHostTest, ReleaseSessionOnCloseACK) { 133 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); 134 GURL test_url = embedded_test_server()->GetURL( 135 "/access-session-storage.html"); 136 NavigateToURL(shell(), test_url); 137 138 // Make a new Shell, a seperate tab with it's own session namespace and 139 // have it start loading a url but still be in progress. 140 ShellAddedObserver new_shell_observer; 141 EXPECT_TRUE(ExecuteScript(shell()->web_contents(), "window.open();")); 142 Shell* new_shell = new_shell_observer.GetShell(); 143 new_shell->LoadURL(test_url); 144 RenderViewHost* rvh = new_shell->web_contents()->GetRenderViewHost(); 145 SiteInstance* site_instance = rvh->GetSiteInstance(); 146 scoped_refptr<SessionStorageNamespace> session_namespace = 147 rvh->GetDelegate()->GetSessionStorageNamespace(site_instance); 148 EXPECT_FALSE(session_namespace->HasOneRef()); 149 150 // Close it, or rather start the close operation. The session namespace 151 // should remain until RPH gets an ACK from the renderer about having 152 // closed the view. 153 new_shell->Close(); 154 EXPECT_FALSE(session_namespace->HasOneRef()); 155 156 // Do something that causes ipc queues to flush and tasks in 157 // flight to complete such that we should have received the ACK. 158 NavigateToURL(shell(), test_url); 159 160 // Verify we have the only remaining reference to the namespace. 161 EXPECT_TRUE(session_namespace->HasOneRef()); 162 } 163 164 } // namespace content 165