blob: 599f3cc5b71d1fa5b408dcb9c36c35c8a32e0010 [file] [log] [blame]
clamyf1ccb4d2015-01-28 17:40:381// Copyright 2014 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
avib7348942015-12-25 20:57:105#include <stdint.h>
6
clamyf1ccb4d2015-01-28 17:40:387#include "base/command_line.h"
8#include "base/strings/stringprintf.h"
clamyb39c17ca2016-02-29 13:33:269#include "base/strings/utf_string_conversions.h"
clamyf1ccb4d2015-01-28 17:40:3810#include "content/browser/web_contents/web_contents_impl.h"
clamy61dfb232016-02-26 18:08:4911#include "content/common/site_isolation_policy.h"
clamyf1ccb4d2015-01-28 17:40:3812#include "content/public/browser/web_contents.h"
13#include "content/public/common/content_switches.h"
14#include "content/public/test/browser_test_utils.h"
15#include "content/public/test/content_browser_test.h"
16#include "content/public/test/content_browser_test_utils.h"
17#include "content/public/test/test_navigation_observer.h"
18#include "content/shell/browser/shell.h"
19#include "net/dns/mock_host_resolver.h"
20#include "net/test/embedded_test_server/embedded_test_server.h"
clamy62b271d2015-04-16 11:54:5721#include "net/test/url_request/url_request_failed_job.h"
clamyf1ccb4d2015-01-28 17:40:3822#include "url/gurl.h"
23
24namespace content {
25
26class BrowserSideNavigationBrowserTest : public ContentBrowserTest {
27 public:
28 BrowserSideNavigationBrowserTest() {}
29
30 protected:
31 void SetUpCommandLine(base::CommandLine* command_line) override {
32 command_line->AppendSwitch(switches::kEnableBrowserSideNavigation);
33 }
34
35 void SetUpOnMainThread() override {
36 host_resolver()->AddRule("*", "127.0.0.1");
svaldezc3a9a172015-11-03 22:01:3337 ASSERT_TRUE(embedded_test_server()->Start());
clamyf1ccb4d2015-01-28 17:40:3838 }
39};
40
41// Ensure that browser initiated basic navigations work with browser side
42// navigation.
43IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBrowserTest,
44 BrowserInitiatedNavigations) {
45 // Perform a navigation with no live renderer.
46 {
47 TestNavigationObserver observer(shell()->web_contents());
48 GURL url(embedded_test_server()->GetURL("/title1.html"));
49 NavigateToURL(shell(), url);
50 EXPECT_EQ(url, observer.last_navigation_url());
51 EXPECT_TRUE(observer.last_navigation_succeeded());
52 }
53
54 RenderFrameHost* initial_rfh =
55 static_cast<WebContentsImpl*>(shell()->web_contents())
56 ->GetFrameTree()->root()->current_frame_host();
57
58 // Perform a same site navigation.
59 {
60 TestNavigationObserver observer(shell()->web_contents());
61 GURL url(embedded_test_server()->GetURL("/title2.html"));
62 NavigateToURL(shell(), url);
63 EXPECT_EQ(url, observer.last_navigation_url());
64 EXPECT_TRUE(observer.last_navigation_succeeded());
65 }
66
67 // The RenderFrameHost should not have changed.
68 EXPECT_EQ(initial_rfh, static_cast<WebContentsImpl*>(shell()->web_contents())
69 ->GetFrameTree()->root()->current_frame_host());
70
71 // Perform a cross-site navigation.
72 {
73 TestNavigationObserver observer(shell()->web_contents());
74 GURL url = embedded_test_server()->GetURL("foo.com", "/title3.html");
75 NavigateToURL(shell(), url);
76 EXPECT_EQ(url, observer.last_navigation_url());
77 EXPECT_TRUE(observer.last_navigation_succeeded());
78 }
79
80 // The RenderFrameHost should have changed.
81 EXPECT_NE(initial_rfh, static_cast<WebContentsImpl*>(shell()->web_contents())
82 ->GetFrameTree()->root()->current_frame_host());
83}
84
85// Ensure that renderer initiated same-site navigations work with browser side
86// navigation.
87IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBrowserTest,
88 RendererInitiatedSameSiteNavigation) {
89 // Perform a navigation with no live renderer.
90 {
91 TestNavigationObserver observer(shell()->web_contents());
92 GURL url(embedded_test_server()->GetURL("/simple_links.html"));
93 NavigateToURL(shell(), url);
94 EXPECT_EQ(url, observer.last_navigation_url());
95 EXPECT_TRUE(observer.last_navigation_succeeded());
96 }
97
98 RenderFrameHost* initial_rfh =
99 static_cast<WebContentsImpl*>(shell()->web_contents())
100 ->GetFrameTree()->root()->current_frame_host();
101
102 // Simulate clicking on a same-site link.
103 {
104 TestNavigationObserver observer(shell()->web_contents());
105 GURL url(embedded_test_server()->GetURL("/title2.html"));
106 bool success = false;
107 EXPECT_TRUE(ExecuteScriptAndExtractBool(
108 shell()->web_contents(),
109 "window.domAutomationController.send(clickSameSiteLink());", &success));
110 EXPECT_TRUE(success);
111 EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
112 EXPECT_EQ(url, observer.last_navigation_url());
113 EXPECT_TRUE(observer.last_navigation_succeeded());
114 }
115
116 // The RenderFrameHost should not have changed.
117 EXPECT_EQ(initial_rfh, static_cast<WebContentsImpl*>(shell()->web_contents())
118 ->GetFrameTree()->root()->current_frame_host());
119}
120
121// Ensure that renderer initiated cross-site navigations work with browser side
122// navigation.
123IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBrowserTest,
124 RendererInitiatedCrossSiteNavigation) {
125 // Perform a navigation with no live renderer.
126 {
127 TestNavigationObserver observer(shell()->web_contents());
128 GURL url(embedded_test_server()->GetURL("/simple_links.html"));
129 NavigateToURL(shell(), url);
130 EXPECT_EQ(url, observer.last_navigation_url());
131 EXPECT_TRUE(observer.last_navigation_succeeded());
132 }
133
134 RenderFrameHost* initial_rfh =
135 static_cast<WebContentsImpl*>(shell()->web_contents())
136 ->GetFrameTree()->root()->current_frame_host();
137
138 // Simulate clicking on a cross-site link.
139 {
140 TestNavigationObserver observer(shell()->web_contents());
141 const char kReplacePortNumber[] =
142 "window.domAutomationController.send(setPortNumber(%d));";
avib7348942015-12-25 20:57:10143 uint16_t port_number = embedded_test_server()->port();
clamyf1ccb4d2015-01-28 17:40:38144 GURL url = embedded_test_server()->GetURL("foo.com", "/title2.html");
145 bool success = false;
146 EXPECT_TRUE(ExecuteScriptAndExtractBool(
147 shell()->web_contents(),
148 base::StringPrintf(kReplacePortNumber, port_number),
149 &success));
150 success = false;
151 EXPECT_TRUE(ExecuteScriptAndExtractBool(
152 shell()->web_contents(),
153 "window.domAutomationController.send(clickCrossSiteLink());",
154 &success));
155 EXPECT_TRUE(success);
156 EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
157 EXPECT_EQ(url, observer.last_navigation_url());
158 EXPECT_TRUE(observer.last_navigation_succeeded());
159 }
160
clamy61dfb232016-02-26 18:08:49161 // The RenderFrameHost should not have changed unless site-per-process is
162 // enabled.
163 if (SiteIsolationPolicy::AreCrossProcessFramesPossible()) {
164 EXPECT_NE(initial_rfh,
165 static_cast<WebContentsImpl*>(shell()->web_contents())
166 ->GetFrameTree()
167 ->root()
168 ->current_frame_host());
169 } else {
170 EXPECT_EQ(initial_rfh,
171 static_cast<WebContentsImpl*>(shell()->web_contents())
172 ->GetFrameTree()
173 ->root()
174 ->current_frame_host());
175 }
clamyf1ccb4d2015-01-28 17:40:38176}
177
clamy62b271d2015-04-16 11:54:57178// Ensure that browser side navigation handles navigation failures.
179IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBrowserTest, FailedNavigation) {
180 // Perform a navigation with no live renderer.
181 {
182 TestNavigationObserver observer(shell()->web_contents());
183 GURL url(embedded_test_server()->GetURL("/title1.html"));
184 NavigateToURL(shell(), url);
185 EXPECT_EQ(url, observer.last_navigation_url());
186 EXPECT_TRUE(observer.last_navigation_succeeded());
187 }
188
189 // Now navigate to an unreachable url.
190 {
191 TestNavigationObserver observer(shell()->web_contents());
192 GURL error_url(
193 net::URLRequestFailedJob::GetMockHttpUrl(net::ERR_CONNECTION_RESET));
pauljensen4c845092015-08-28 17:04:54194 BrowserThread::PostTask(
195 BrowserThread::IO, FROM_HERE,
196 base::Bind(&net::URLRequestFailedJob::AddUrlHandler));
clamy62b271d2015-04-16 11:54:57197 NavigateToURL(shell(), error_url);
198 EXPECT_EQ(error_url, observer.last_navigation_url());
199 NavigationEntry* entry =
200 shell()->web_contents()->GetController().GetLastCommittedEntry();
201 EXPECT_EQ(PAGE_TYPE_ERROR, entry->GetPageType());
202 }
203}
204
clamyb39c17ca2016-02-29 13:33:26205// Ensure that browser side navigation handles POST navigations correctly.
206IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBrowserTest, POSTNavigation) {
207 GURL url(embedded_test_server()->GetURL("/session_history/form.html"));
208 GURL post_url = embedded_test_server()->GetURL("/echotitle");
209
210 // Navigate to a page with a form.
211 TestNavigationObserver observer(shell()->web_contents());
212 NavigateToURL(shell(), url);
213 EXPECT_EQ(url, observer.last_navigation_url());
214 EXPECT_TRUE(observer.last_navigation_succeeded());
215
216 // Submit the form.
217 GURL submit_url("javascript:submitForm('isubmit')");
218 NavigateToURL(shell(), submit_url);
219
220 // Check that a proper POST navigation was done.
221 EXPECT_EQ("text=&select=a",
222 base::UTF16ToASCII(shell()->web_contents()->GetTitle()));
223 EXPECT_EQ(post_url, shell()->web_contents()->GetLastCommittedURL());
224 EXPECT_TRUE(shell()
225 ->web_contents()
226 ->GetController()
227 .GetActiveEntry()
228 ->GetHasPostData());
229}
230
clamyf1ccb4d2015-01-28 17:40:38231} // namespace content