blob: e8c933d5a2e043b52f3ac0a7444c04a405cb70be [file] [log] [blame]
naskob2f82b82016-04-15 07:09:071// Copyright 2016 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
naskoe4ebe0782016-10-27 16:52:175#include "base/command_line.h"
Gabriel Charette078e3662017-08-28 22:59:046#include "base/run_loop.h"
Alex Moshchukd252c192017-07-17 22:03:487#include "base/test/scoped_feature_list.h"
Alex Moshchuk71f485592017-08-16 16:20:008#include "base/test/test_timeouts.h"
naskoe4ebe0782016-10-27 16:52:179#include "chrome/app/chrome_command_ids.h"
naskob2f82b82016-04-15 07:09:0710#include "chrome/browser/chrome_notification_types.h"
naskoe4ebe0782016-10-27 16:52:1711#include "chrome/browser/renderer_context_menu/render_view_context_menu_test_util.h"
naskob2f82b82016-04-15 07:09:0712#include "chrome/browser/ui/browser.h"
afakhry4d116bd2016-11-29 17:25:2513#include "chrome/browser/ui/browser_commands.h"
naskob2f82b82016-04-15 07:09:0714#include "chrome/browser/ui/tabs/tab_strip_model.h"
clamyb4f02242017-09-19 12:58:2715#include "chrome/common/url_constants.h"
naskob2f82b82016-04-15 07:09:0716#include "chrome/test/base/in_process_browser_test.h"
17#include "chrome/test/base/ui_test_utils.h"
Alex Moshchukd252c192017-07-17 22:03:4818#include "components/network_session_configurator/common/network_switches.h"
afakhry4d116bd2016-11-29 17:25:2519#include "components/url_formatter/url_formatter.h"
Alex Moshchuk95e8906d2017-07-21 01:06:2320#include "components/variations/active_field_trials.h"
21#include "components/variations/metrics_util.h"
Alex Moshchuk9cf0ac12017-10-25 21:26:1922#include "components/variations/variations_switches.h"
afakhry4d116bd2016-11-29 17:25:2523#include "content/public/browser/navigation_entry.h"
naskob2f82b82016-04-15 07:09:0724#include "content/public/browser/navigation_handle.h"
25#include "content/public/browser/notification_service.h"
afakhry4d116bd2016-11-29 17:25:2526#include "content/public/browser/render_frame_host.h"
clamyb4f02242017-09-19 12:58:2727#include "content/public/browser/render_process_host.h"
naskob2f82b82016-04-15 07:09:0728#include "content/public/browser/web_contents_observer.h"
Alex Moshchuk71f485592017-08-16 16:20:0029#include "content/public/common/browser_side_navigation_policy.h"
Alex Moshchukd252c192017-07-17 22:03:4830#include "content/public/common/content_features.h"
lgreycb827f612017-01-13 01:32:2431#include "content/public/common/content_switches.h"
naskoe4ebe0782016-10-27 16:52:1732#include "content/public/common/context_menu_params.h"
afakhry4d116bd2016-11-29 17:25:2533#include "content/public/common/url_constants.h"
naskob2f82b82016-04-15 07:09:0734#include "content/public/test/browser_test_utils.h"
Alex Moshchuk71f485592017-08-16 16:20:0035#include "content/public/test/navigation_handle_observer.h"
naskob2f82b82016-04-15 07:09:0736#include "content/public/test/test_navigation_observer.h"
Alex Moshchukd252c192017-07-17 22:03:4837#include "google_apis/gaia/gaia_switches.h"
naskoe4ebe0782016-10-27 16:52:1738#include "net/dns/mock_host_resolver.h"
naskob2f82b82016-04-15 07:09:0739
40class ChromeNavigationBrowserTest : public InProcessBrowserTest {
41 public:
42 ChromeNavigationBrowserTest() {}
43 ~ChromeNavigationBrowserTest() override {}
44
45 void SetUpCommandLine(base::CommandLine* command_line) override {
lgreycb827f612017-01-13 01:32:2446 // Backgrounded renderer processes run at a lower priority, causing the
47 // tests to take more time to complete. Disable backgrounding so that the
48 // tests don't time out.
49 command_line->AppendSwitch(switches::kDisableRendererBackgrounding);
50
naskob2f82b82016-04-15 07:09:0751 ASSERT_TRUE(embedded_test_server()->Start());
52 }
53
54 void StartServerWithExpiredCert() {
55 expired_https_server_.reset(
56 new net::EmbeddedTestServer(net::EmbeddedTestServer::TYPE_HTTPS));
57 expired_https_server_->SetSSLConfig(net::EmbeddedTestServer::CERT_EXPIRED);
58 expired_https_server_->AddDefaultHandlers(
59 base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
60 ASSERT_TRUE(expired_https_server_->Start());
61 }
62
63 net::EmbeddedTestServer* expired_https_server() {
64 return expired_https_server_.get();
65 }
66
67 private:
68 std::unique_ptr<net::EmbeddedTestServer> expired_https_server_;
69
70 DISALLOW_COPY_AND_ASSIGN(ChromeNavigationBrowserTest);
71};
72
73// Helper class to track and allow waiting for navigation start events.
74class DidStartNavigationObserver : public content::WebContentsObserver {
75 public:
76 explicit DidStartNavigationObserver(content::WebContents* web_contents)
77 : content::WebContentsObserver(web_contents),
78 message_loop_runner_(new content::MessageLoopRunner) {}
79 ~DidStartNavigationObserver() override {}
80
gab2998ee72017-05-05 16:23:5081 // Runs a nested run loop and blocks until the full load has
naskob2f82b82016-04-15 07:09:0782 // completed.
83 void Wait() { message_loop_runner_->Run(); }
84
85 private:
86 // WebContentsObserver
87 void DidStartNavigation(content::NavigationHandle* handle) override {
88 if (message_loop_runner_->loop_running())
89 message_loop_runner_->Quit();
90 }
91
92 // The MessageLoopRunner used to spin the message loop.
93 scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
94
95 DISALLOW_COPY_AND_ASSIGN(DidStartNavigationObserver);
96};
97
98// Test to verify that navigations are not deleting the transient
99// NavigationEntry when showing an interstitial page and the old renderer
100// process is trying to navigate. See https://crbug.com/600046.
101IN_PROC_BROWSER_TEST_F(
102 ChromeNavigationBrowserTest,
103 TransientEntryPreservedOnMultipleNavigationsDuringInterstitial) {
104 StartServerWithExpiredCert();
105
106 GURL setup_url =
107 embedded_test_server()->GetURL("/window_open_and_navigate.html");
108 GURL initial_url = embedded_test_server()->GetURL("/title1.html");
109 GURL error_url(expired_https_server()->GetURL("/ssl/blank_page.html"));
110
111 ui_test_utils::NavigateToURL(browser(), setup_url);
112 content::WebContents* main_web_contents =
113 browser()->tab_strip_model()->GetActiveWebContents();
114
115 // Call the JavaScript method in the test page, which opens a new window
116 // and stores a handle to it.
117 content::WindowedNotificationObserver tab_added_observer(
118 chrome::NOTIFICATION_TAB_ADDED,
119 content::NotificationService::AllSources());
120 EXPECT_TRUE(content::ExecuteScript(main_web_contents, "openWin();"));
121 tab_added_observer.Wait();
122 content::WebContents* new_web_contents =
123 browser()->tab_strip_model()->GetActiveWebContents();
124
125 // Navigate the opened window to a page that will successfully commit and
126 // create a NavigationEntry.
127 {
128 content::TestNavigationObserver observer(new_web_contents);
129 EXPECT_TRUE(content::ExecuteScript(
130 main_web_contents, "navigate('" + initial_url.spec() + "');"));
131 observer.Wait();
132 EXPECT_EQ(initial_url, new_web_contents->GetLastCommittedURL());
133 }
134
135 // Navigate the opened window to a page which will trigger an
136 // interstitial.
137 {
138 content::TestNavigationObserver observer(new_web_contents);
139 EXPECT_TRUE(content::ExecuteScript(
140 main_web_contents, "navigate('" + error_url.spec() + "');"));
141 observer.Wait();
142 EXPECT_EQ(initial_url, new_web_contents->GetLastCommittedURL());
143 EXPECT_EQ(error_url, new_web_contents->GetVisibleURL());
144 }
145
146 // Navigate again the opened window to the same page. It should not cause
147 // WebContents::GetVisibleURL to return the last committed one.
148 {
149 DidStartNavigationObserver nav_observer(new_web_contents);
150 EXPECT_TRUE(content::ExecuteScript(
151 main_web_contents, "navigate('" + error_url.spec() + "');"));
152 nav_observer.Wait();
153 EXPECT_EQ(error_url, new_web_contents->GetVisibleURL());
154 EXPECT_TRUE(new_web_contents->GetController().GetTransientEntry());
155 EXPECT_FALSE(new_web_contents->IsLoading());
156 }
157}
naskoe4ebe0782016-10-27 16:52:17158
afakhry4d116bd2016-11-29 17:25:25159// Tests that viewing frame source on a local file:// page with an iframe
160// with a remote URL shows the correct tab title.
161IN_PROC_BROWSER_TEST_F(ChromeNavigationBrowserTest, TestViewFrameSource) {
162 // The local page file:// URL.
163 GURL local_page_with_iframe_url = ui_test_utils::GetTestUrl(
164 base::FilePath(base::FilePath::kCurrentDirectory),
165 base::FilePath(FILE_PATH_LITERAL("iframe.html")));
166
167 // The non-file:// URL of the page to load in the iframe.
168 GURL iframe_target_url = embedded_test_server()->GetURL("/title1.html");
169 ui_test_utils::NavigateToURL(browser(), local_page_with_iframe_url);
170 content::WebContents* web_contents =
171 browser()->tab_strip_model()->GetActiveWebContents();
172
173 content::TestNavigationObserver observer(web_contents);
174 ASSERT_TRUE(content::ExecuteScript(
175 web_contents->GetMainFrame(),
176 base::StringPrintf("var iframe = document.getElementById('test');\n"
177 "iframe.setAttribute('src', '%s');\n",
178 iframe_target_url.spec().c_str())));
179 observer.Wait();
180
181 content::RenderFrameHost* frame =
182 content::ChildFrameAt(web_contents->GetMainFrame(), 0);
183 ASSERT_TRUE(frame);
184 ASSERT_NE(frame, web_contents->GetMainFrame());
185
186 content::ContextMenuParams params;
187 params.page_url = local_page_with_iframe_url;
188 params.frame_url = frame->GetLastCommittedURL();
afakhry4d116bd2016-11-29 17:25:25189 TestRenderViewContextMenu menu(frame, params);
190 menu.Init();
191 menu.ExecuteCommand(IDC_CONTENT_CONTEXT_VIEWFRAMESOURCE, 0);
192 ASSERT_EQ(browser()->tab_strip_model()->count(), 2);
193 content::WebContents* new_web_contents =
194 browser()->tab_strip_model()->GetWebContentsAt(1);
195 ASSERT_NE(new_web_contents, web_contents);
196 WaitForLoadStop(new_web_contents);
197
198 GURL view_frame_source_url(content::kViewSourceScheme + std::string(":") +
199 iframe_target_url.spec());
200 EXPECT_EQ(url_formatter::FormatUrl(view_frame_source_url),
201 new_web_contents->GetTitle());
202}
203
Nasko Oskovdeb6c7ea2017-11-30 18:18:11204// Base class for ctrl+click tests, which contains all the common functionality
205// independent from which process the navigation happens in. Each subclass
206// defines its own expectations depending on the conditions of the test.
207class CtrlClickProcessTest : public ChromeNavigationBrowserTest {
lukaszaf206da92017-04-20 23:26:51208 protected:
Nasko Oskovdeb6c7ea2017-11-30 18:18:11209 virtual void VerifyProcessExpectations(
210 content::WebContents* main_contents,
211 content::WebContents* new_contents) = 0;
Nasko Oskovdeb6c7ea2017-11-30 18:18:11212
lukaszaf206da92017-04-20 23:26:51213 // Simulates ctrl-clicking an anchor with the given id in |main_contents|.
Nasko Oskovdeb6c7ea2017-11-30 18:18:11214 // Verifies that the new contents are in the correct process and separate
215 // BrowsingInstance from |main_contents|. Returns contents of the newly
lukaszaf206da92017-04-20 23:26:51216 // opened tab.
217 content::WebContents* SimulateCtrlClick(content::WebContents* main_contents,
218 const char* id_of_anchor_to_click) {
219 // Ctrl-click the anchor/link in the page.
220 content::WebContents* new_contents = nullptr;
221 {
222 content::WebContentsAddedObserver new_tab_observer;
223#if defined(OS_MACOSX)
224 const char* new_tab_click_script_template =
225 "simulateClick(\"%s\", { metaKey: true });";
226#else
227 const char* new_tab_click_script_template =
228 "simulateClick(\"%s\", { ctrlKey: true });";
229#endif
230 std::string new_tab_click_script = base::StringPrintf(
231 new_tab_click_script_template, id_of_anchor_to_click);
232 EXPECT_TRUE(ExecuteScript(main_contents, new_tab_click_script));
233
234 // Wait for a new tab to appear (the whole point of this test).
235 new_contents = new_tab_observer.GetWebContents();
236 }
237
Nasko Oskovdeb6c7ea2017-11-30 18:18:11238 // Verify that the new tab has the right contents and is in the tab strip.
lukaszaf206da92017-04-20 23:26:51239 EXPECT_TRUE(WaitForLoadStop(new_contents));
lukaszaf206da92017-04-20 23:26:51240 EXPECT_LT(1, browser()->tab_strip_model()->count()); // More than 1 tab?
Nasko Oskovdeb6c7ea2017-11-30 18:18:11241 CHECK_NE(TabStripModel::kNoTab,
242 browser()->tab_strip_model()->GetIndexOfWebContents(new_contents));
lukaszaf206da92017-04-20 23:26:51243 GURL expected_url(embedded_test_server()->GetURL("/title1.html"));
244 EXPECT_EQ(expected_url, new_contents->GetLastCommittedURL());
245
Nasko Oskovdeb6c7ea2017-11-30 18:18:11246 VerifyProcessExpectations(main_contents, new_contents);
lukaszaf206da92017-04-20 23:26:51247
lukaszaf206da92017-04-20 23:26:51248 {
249 // Double-check that main_contents has expected window.name set.
250 // This is a sanity check of test setup; this is not a product test.
251 std::string name_of_main_contents_window;
252 EXPECT_TRUE(ExecuteScriptAndExtractString(
253 main_contents, "window.domAutomationController.send(window.name)",
254 &name_of_main_contents_window));
255 EXPECT_EQ("main_contents", name_of_main_contents_window);
256
257 // Verify that the new contents doesn't have a window.opener set.
lukaszabe2f0da2017-04-25 00:43:00258 bool window_opener_cast_to_bool = true;
lukaszaf206da92017-04-20 23:26:51259 EXPECT_TRUE(ExecuteScriptAndExtractBool(
260 new_contents, "window.domAutomationController.send(!!window.opener)",
261 &window_opener_cast_to_bool));
262 EXPECT_FALSE(window_opener_cast_to_bool);
263
Nasko Oskovdeb6c7ea2017-11-30 18:18:11264 VerifyBrowsingInstanceExpectations(main_contents, new_contents);
lukaszaf206da92017-04-20 23:26:51265 }
266
267 return new_contents;
268 }
lukaszabe2f0da2017-04-25 00:43:00269
270 void TestCtrlClick(const char* id_of_anchor_to_click) {
271 // Navigate to the test page.
272 GURL main_url(embedded_test_server()->GetURL(
273 "/frame_tree/anchor_to_same_site_location.html"));
274 ui_test_utils::NavigateToURL(browser(), main_url);
275
276 // Verify that there is only 1 active tab (with the right contents
277 // committed).
278 EXPECT_EQ(0, browser()->tab_strip_model()->active_index());
279 content::WebContents* main_contents =
280 browser()->tab_strip_model()->GetWebContentsAt(0);
281 EXPECT_EQ(main_url, main_contents->GetLastCommittedURL());
282
283 // Test what happens after ctrl-click. SimulateCtrlClick will verify
Nasko Oskovdeb6c7ea2017-11-30 18:18:11284 // that |new_contents1| is in the correct process and separate
285 // BrowsingInstance from |main_contents|.
lukaszabe2f0da2017-04-25 00:43:00286 content::WebContents* new_contents1 =
287 SimulateCtrlClick(main_contents, id_of_anchor_to_click);
288
Nasko Oskovdeb6c7ea2017-11-30 18:18:11289 // Test that each subsequent ctrl-click also gets the correct process.
lukaszabe2f0da2017-04-25 00:43:00290 content::WebContents* new_contents2 =
291 SimulateCtrlClick(main_contents, id_of_anchor_to_click);
lukaszabe2f0da2017-04-25 00:43:00292 EXPECT_FALSE(new_contents1->GetSiteInstance()->IsRelatedSiteInstance(
293 new_contents2->GetSiteInstance()));
Nasko Oskovdeb6c7ea2017-11-30 18:18:11294 VerifyProcessExpectations(new_contents1, new_contents2);
295 }
Lukasz Anforowicz1c9509062017-12-06 00:38:17296
297 private:
298 void VerifyBrowsingInstanceExpectations(content::WebContents* main_contents,
299 content::WebContents* new_contents) {
300 // Verify that the new contents cannot find the old contents via
301 // window.open. (i.e. window.open should open a new window, rather than
302 // returning a reference to main_contents / old window).
303 std::string location_of_opened_window;
304 EXPECT_TRUE(ExecuteScriptAndExtractString(
305 new_contents,
306 "w = window.open('', 'main_contents');"
307 "window.domAutomationController.send(w.location.href);",
308 &location_of_opened_window));
309 EXPECT_EQ(url::kAboutBlankURL, location_of_opened_window);
310 }
Nasko Oskovdeb6c7ea2017-11-30 18:18:11311};
312
313// Tests that verify that ctrl-click results 1) open up in a new renderer
314// process (https://crbug.com/23815) and 2) are in a new BrowsingInstance (e.g.
315// cannot find the opener's window by name - https://crbug.com/658386).
316class CtrlClickShouldEndUpInNewProcessTest : public CtrlClickProcessTest {
317 protected:
318 void VerifyProcessExpectations(content::WebContents* main_contents,
319 content::WebContents* new_contents) override {
320 // Verify that the two WebContents are in a different process, SiteInstance
321 // and BrowsingInstance from the old contents.
322 EXPECT_NE(main_contents->GetMainFrame()->GetProcess(),
323 new_contents->GetMainFrame()->GetProcess());
324 EXPECT_NE(main_contents->GetMainFrame()->GetSiteInstance(),
325 new_contents->GetMainFrame()->GetSiteInstance());
326 EXPECT_FALSE(main_contents->GetSiteInstance()->IsRelatedSiteInstance(
327 new_contents->GetSiteInstance()));
328 }
lukaszaf206da92017-04-20 23:26:51329};
330
331IN_PROC_BROWSER_TEST_F(CtrlClickShouldEndUpInNewProcessTest, NoTarget) {
lukaszabe2f0da2017-04-25 00:43:00332 TestCtrlClick("test-anchor-no-target");
333}
lukaszaf206da92017-04-20 23:26:51334
lukaszabe2f0da2017-04-25 00:43:00335IN_PROC_BROWSER_TEST_F(CtrlClickShouldEndUpInNewProcessTest, BlankTarget) {
336 TestCtrlClick("test-anchor-with-blank-target");
337}
lukaszaf206da92017-04-20 23:26:51338
lukaszabe2f0da2017-04-25 00:43:00339IN_PROC_BROWSER_TEST_F(CtrlClickShouldEndUpInNewProcessTest, SubframeTarget) {
340 TestCtrlClick("test-anchor-with-subframe-target");
lukaszaf206da92017-04-20 23:26:51341}
342
Nasko Oskovdeb6c7ea2017-11-30 18:18:11343// Similar to the tests above, but verifies that the new WebContents ends up in
344// the same process as the opener when it is exceeding the process limit.
345// See https://crbug.com/774723.
346class CtrlClickShouldEndUpInSameProcessTest : public CtrlClickProcessTest {
347 public:
348 void SetUpCommandLine(base::CommandLine* command_line) override {
349 CtrlClickProcessTest::SetUpCommandLine(command_line);
350 content::IsolateAllSitesForTesting(command_line);
351 content::RenderProcessHost::SetMaxRendererProcessCount(1);
352 }
353
354 void SetUpOnMainThread() override {
355 CtrlClickProcessTest::SetUpOnMainThread();
356 host_resolver()->AddRule("*", "127.0.0.1");
357 }
358
359 protected:
360 void VerifyProcessExpectations(content::WebContents* contents1,
361 content::WebContents* contents2) override {
362 // Verify that the two WebContents are in the same process, though different
363 // SiteInstance and BrowsingInstance from the old contents.
364 EXPECT_EQ(contents1->GetMainFrame()->GetProcess(),
365 contents2->GetMainFrame()->GetProcess());
366 EXPECT_EQ(contents1->GetMainFrame()->GetSiteInstance()->GetSiteURL(),
367 contents2->GetMainFrame()->GetSiteInstance()->GetSiteURL());
368 EXPECT_FALSE(contents1->GetSiteInstance()->IsRelatedSiteInstance(
369 contents2->GetSiteInstance()));
370 }
Nasko Oskovdeb6c7ea2017-11-30 18:18:11371};
372
373IN_PROC_BROWSER_TEST_F(CtrlClickShouldEndUpInSameProcessTest, NoTarget) {
374 TestCtrlClick("test-anchor-no-target");
375}
376
377IN_PROC_BROWSER_TEST_F(CtrlClickShouldEndUpInSameProcessTest, BlankTarget) {
378 TestCtrlClick("test-anchor-with-blank-target");
379}
380
381IN_PROC_BROWSER_TEST_F(CtrlClickShouldEndUpInSameProcessTest, SubframeTarget) {
382 TestCtrlClick("test-anchor-with-subframe-target");
383}
384
naskoe4ebe0782016-10-27 16:52:17385class ChromeNavigationPortMappedBrowserTest : public InProcessBrowserTest {
386 public:
387 ChromeNavigationPortMappedBrowserTest() {}
388 ~ChromeNavigationPortMappedBrowserTest() override {}
389
390 void SetUpCommandLine(base::CommandLine* command_line) override {
391 ASSERT_TRUE(embedded_test_server()->Start());
392
393 // Use the command line parameter for the host resolver, so URLs without
394 // explicit port numbers can be mapped under the hood to the port number
395 // the |embedded_test_server| uses. It is required to test with potentially
396 // malformed URLs.
397 std::string port =
398 base::IntToString(embedded_test_server()->host_port_pair().port());
399 command_line->AppendSwitchASCII(
400 "host-resolver-rules",
401 "MAP * 127.0.0.1:" + port + ", EXCLUDE 127.0.0.1*");
402 }
403
404 private:
405 DISALLOW_COPY_AND_ASSIGN(ChromeNavigationPortMappedBrowserTest);
406};
407
408// Test to verify that a malformed URL set as the virtual URL of a
409// NavigationEntry will result in the navigation being dropped.
410// See https://crbug.com/657720.
411IN_PROC_BROWSER_TEST_F(ChromeNavigationPortMappedBrowserTest,
412 ContextMenuNavigationToInvalidUrl) {
413 GURL initial_url = embedded_test_server()->GetURL("/title1.html");
414 GURL new_tab_url(
415 "www.foo.com::/server-redirect?https%3A%2F%2Fptop.only.wip.la%3A443%2Fhttp%2Fbar.com%2Ftitle2.html");
416
417 // Navigate to an initial page, to ensure we have a committed document
418 // from which to perform a context menu initiated navigation.
419 ui_test_utils::NavigateToURL(browser(), initial_url);
420 content::WebContents* web_contents =
421 browser()->tab_strip_model()->GetActiveWebContents();
422
423 // This corresponds to "Open link in new tab".
424 content::ContextMenuParams params;
425 params.is_editable = false;
Blink Reformat1c4d759e2017-04-09 16:34:54426 params.media_type = blink::WebContextMenuData::kMediaTypeNone;
naskoe4ebe0782016-10-27 16:52:17427 params.page_url = initial_url;
428 params.link_url = new_tab_url;
429
430 content::WindowedNotificationObserver tab_added_observer(
431 chrome::NOTIFICATION_TAB_ADDED,
432 content::NotificationService::AllSources());
433
434 TestRenderViewContextMenu menu(web_contents->GetMainFrame(), params);
435 menu.Init();
436 menu.ExecuteCommand(IDC_CONTENT_CONTEXT_OPENLINKNEWTAB, 0);
437
438 // Wait for the new tab to be created and for loading to stop. The
439 // navigation should not be allowed, therefore there should not be a last
440 // committed URL in the new tab.
441 tab_added_observer.Wait();
442 content::WebContents* new_web_contents =
443 browser()->tab_strip_model()->GetWebContentsAt(
444 browser()->tab_strip_model()->count() - 1);
445 WaitForLoadStop(new_web_contents);
446
447 // If the test is unsuccessful, the return value from GetLastCommittedURL
448 // will be the virtual URL for the created NavigationEntry.
449 // Note: Before the bug was fixed, the URL was the new_tab_url with a scheme
450 // prepended and one less ":" character after the host.
451 EXPECT_EQ(GURL(), new_web_contents->GetLastCommittedURL());
452}
nasko7058e5de2017-04-18 23:05:30453
454// A test performing two simultaneous navigations, to ensure code in chrome/,
455// such as tab helpers, can handle those cases.
456// This test starts a browser-initiated cross-process navigation, which is
457// delayed. At the same time, the renderer does a synchronous navigation
458// through pushState, which will create a separate navigation and associated
459// NavigationHandle. Afterwards, the original cross-process navigation is
460// resumed and confirmed to properly commit.
461IN_PROC_BROWSER_TEST_F(ChromeNavigationBrowserTest,
462 SlowCrossProcessNavigationWithPushState) {
463 const GURL kURL1 = embedded_test_server()->GetURL("/title1.html");
464 const GURL kPushStateURL =
465 embedded_test_server()->GetURL("/title1.html#fragment");
466 const GURL kURL2 = embedded_test_server()->GetURL("/title2.html");
467
468 content::WebContents* web_contents =
469 browser()->tab_strip_model()->GetActiveWebContents();
470
471 // Navigate to the initial page.
472 ui_test_utils::NavigateToURL(browser(), kURL1);
473
474 // Start navigating to the second page.
475 content::TestNavigationManager manager(web_contents, kURL2);
476 content::NavigationHandleCommitObserver navigation_observer(web_contents,
477 kURL2);
478 web_contents->GetController().LoadURL(
479 kURL2, content::Referrer(), ui::PAGE_TRANSITION_LINK, std::string());
480 EXPECT_TRUE(manager.WaitForRequestStart());
481
482 // The current page does a PushState.
483 content::NavigationHandleCommitObserver push_state_observer(web_contents,
484 kPushStateURL);
485 std::string push_state =
486 "history.pushState({}, \"title 1\", \"" + kPushStateURL.spec() + "\");";
487 EXPECT_TRUE(ExecuteScript(web_contents, push_state));
488 content::NavigationEntry* last_committed =
489 web_contents->GetController().GetLastCommittedEntry();
490 EXPECT_TRUE(last_committed);
491 EXPECT_EQ(kPushStateURL, last_committed->GetURL());
492
493 EXPECT_TRUE(push_state_observer.has_committed());
494 EXPECT_TRUE(push_state_observer.was_same_document());
495 EXPECT_TRUE(push_state_observer.was_renderer_initiated());
496
497 // Let the navigation finish. It should commit successfully.
498 manager.WaitForNavigationFinished();
499 last_committed = web_contents->GetController().GetLastCommittedEntry();
500 EXPECT_TRUE(last_committed);
501 EXPECT_EQ(kURL2, last_committed->GetURL());
502
503 EXPECT_TRUE(navigation_observer.has_committed());
504 EXPECT_FALSE(navigation_observer.was_same_document());
505 EXPECT_FALSE(navigation_observer.was_renderer_initiated());
506}
Alex Moshchukd252c192017-07-17 22:03:48507
Alex Moshchuk71f485592017-08-16 16:20:00508// Check that if a page has an iframe that loads an error page, that error page
509// does not inherit the Content Security Policy from the parent frame. See
510// https://crbug.com/703801. This test is in chrome/ because error page
511// behavior is only fully defined in chrome/.
512IN_PROC_BROWSER_TEST_F(ChromeNavigationBrowserTest,
513 ErrorPageDoesNotInheritCSP) {
514 GURL url(
515 embedded_test_server()->GetURL("/page_with_csp_and_error_iframe.html"));
516 content::WebContents* web_contents =
517 browser()->tab_strip_model()->GetActiveWebContents();
518
519 // Navigate to a page that disallows scripts via CSP and has an iframe that
520 // tries to load an invalid URL, which results in an error page.
521 GURL error_url("http://invalid.foo/");
522 content::NavigationHandleObserver observer(web_contents, error_url);
523 ui_test_utils::NavigateToURL(browser(), url);
524 EXPECT_TRUE(observer.has_committed());
525 EXPECT_TRUE(observer.is_error());
526
527 // The error page should not inherit the CSP directive that blocks all
528 // scripts from the parent frame, so this script should be allowed to
529 // execute. Since ExecuteScript will execute the passed-in script regardless
530 // of CSP, use a javascript: URL which does go through the CSP checks.
531 content::RenderFrameHost* error_host =
532 ChildFrameAt(web_contents->GetMainFrame(), 0);
533 std::string location;
534 EXPECT_TRUE(ExecuteScriptAndExtractString(
535 error_host,
536 "location='javascript:domAutomationController.send(location.href)';",
537 &location));
538 EXPECT_EQ(location, content::kUnreachableWebDataURL);
539
540 // The error page should have a unique origin.
541 std::string origin;
542 EXPECT_TRUE(ExecuteScriptAndExtractString(
543 error_host, "domAutomationController.send(document.origin);", &origin));
544 EXPECT_EQ("null", origin);
545}
546
547// Test that web pages can't navigate to an error page URL, either directly or
548// via a redirect, and that web pages can't embed error pages in iframes.
549IN_PROC_BROWSER_TEST_F(ChromeNavigationBrowserTest,
550 NavigationToErrorURLIsDisallowed) {
551 content::WebContents* web_contents =
552 browser()->tab_strip_model()->GetActiveWebContents();
553 GURL url(embedded_test_server()->GetURL("/title1.html"));
554 ui_test_utils::NavigateToURL(browser(), url);
555 EXPECT_EQ(url, web_contents->GetLastCommittedURL());
556
557 // Try navigating to the error page URL and make sure it is canceled and the
558 // old URL remains the last committed one.
559 GURL error_url(content::kUnreachableWebDataURL);
560 EXPECT_TRUE(ExecuteScript(web_contents,
561 "location.href = '" + error_url.spec() + "';"));
562 content::WaitForLoadStop(web_contents);
563 EXPECT_EQ(url, web_contents->GetLastCommittedURL());
564
565 // Now try navigating to a URL that tries to redirect to the error page URL,
566 // and make sure the redirect is blocked. Note that DidStopLoading will
567 // still fire after the redirect is canceled, so TestNavigationObserver can
568 // be used to wait for it.
569 GURL redirect_to_error_url(
570 embedded_test_server()->GetURL("/server-redirect?" + error_url.spec()));
571 content::TestNavigationObserver observer(web_contents);
572 EXPECT_TRUE(ExecuteScript(
573 web_contents, "location.href = '" + redirect_to_error_url.spec() + "';"));
574 observer.Wait();
575 EXPECT_EQ(url, web_contents->GetLastCommittedURL());
576
577 // Also ensure that a page can't embed an iframe for an error page URL.
578 EXPECT_TRUE(ExecuteScript(web_contents,
579 "var frame = document.createElement('iframe');\n"
580 "frame.src = '" + error_url.spec() + "';\n"
581 "document.body.appendChild(frame);"));
582 content::WaitForLoadStop(web_contents);
583 content::RenderFrameHost* subframe_host =
584 ChildFrameAt(web_contents->GetMainFrame(), 0);
585 // The new subframe should remain blank without a committed URL.
586 EXPECT_TRUE(subframe_host->GetLastCommittedURL().is_empty());
587}
588
589// This test ensures that navigating to a page that returns an error code and
590// an empty document still shows Chrome's helpful error page instead of the
591// empty document.
592IN_PROC_BROWSER_TEST_F(ChromeNavigationBrowserTest,
593 EmptyDocumentWithErrorCode) {
594 GURL url(embedded_test_server()->GetURL("/empty_with_404.html"));
595 content::WebContents* web_contents =
596 browser()->tab_strip_model()->GetActiveWebContents();
597
598 // Wait for the navigation to complete. The empty document should trigger
599 // loading of the 404 error page, so check that the last committed entry was
600 // indeed for the error page.
601 content::TestNavigationObserver observer(web_contents);
602 EXPECT_TRUE(
603 ExecuteScript(web_contents, "location.href = '" + url.spec() + "';"));
604 observer.Wait();
605 EXPECT_FALSE(observer.last_navigation_succeeded());
606 EXPECT_EQ(url, web_contents->GetLastCommittedURL());
607 EXPECT_TRUE(
608 IsLastCommittedEntryOfPageType(web_contents, content::PAGE_TYPE_ERROR));
609
610 // Verify that the error page has correct content. This needs to wait for
611 // the error page content to be populated asynchronously by scripts after
612 // DidFinishLoad.
613 while (true) {
614 std::string content;
615 EXPECT_TRUE(ExecuteScriptAndExtractString(
616 web_contents,
617 "domAutomationController.send("
618 " document.body ? document.body.innerText : '');",
619 &content));
620 if (content.find("HTTP ERROR 404") != std::string::npos)
621 break;
622 base::RunLoop run_loop;
623 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
624 FROM_HERE, run_loop.QuitClosure(), TestTimeouts::tiny_timeout());
625 run_loop.Run();
626 }
627}
628
Alex Moshchukd252c192017-07-17 22:03:48629class SignInIsolationBrowserTest : public ChromeNavigationBrowserTest {
630 public:
631 SignInIsolationBrowserTest()
632 : https_server_(net::EmbeddedTestServer::TYPE_HTTPS) {}
633 ~SignInIsolationBrowserTest() override {}
634
Alex Moshchuk95e8906d2017-07-21 01:06:23635 virtual void InitFeatureList() {
Alex Moshchukd252c192017-07-17 22:03:48636 feature_list_.InitAndEnableFeature(features::kSignInProcessIsolation);
Alex Moshchuk95e8906d2017-07-21 01:06:23637 }
638
639 void SetUp() override {
640 InitFeatureList();
Alex Moshchukd252c192017-07-17 22:03:48641 https_server_.ServeFilesFromSourceDirectory("chrome/test/data");
642 ASSERT_TRUE(https_server_.InitializeAndListen());
643 ChromeNavigationBrowserTest::SetUp();
644 }
645
646 void SetUpCommandLine(base::CommandLine* command_line) override {
647 // Override the sign-in URL so that it includes correct port from the test
648 // server.
649 command_line->AppendSwitchASCII(
650 ::switches::kGaiaUrl,
651 https_server()->GetURL("accounts.google.com", "/").spec());
652
653 // Ignore cert errors so that the sign-in URL can be loaded from a site
654 // other than localhost (the EmbeddedTestServer serves a certificate that
655 // is valid for localhost).
656 command_line->AppendSwitch(switches::kIgnoreCertificateErrors);
657
658 ChromeNavigationBrowserTest::SetUpCommandLine(command_line);
659 }
660
661 void SetUpOnMainThread() override {
662 host_resolver()->AddRule("*", "127.0.0.1");
663 https_server_.StartAcceptingConnections();
664 ChromeNavigationBrowserTest::SetUpOnMainThread();
665 }
666
667 net::EmbeddedTestServer* https_server() { return &https_server_; }
668
Alex Moshchuk95e8906d2017-07-21 01:06:23669 bool HasSyntheticTrial(const std::string& trial_name) {
670 std::vector<std::string> synthetic_trials;
671 variations::GetSyntheticTrialGroupIdsAsString(&synthetic_trials);
672 std::string trial_hash =
673 base::StringPrintf("%x", metrics::HashName(trial_name));
674
675 for (auto entry : synthetic_trials) {
676 if (base::StartsWith(entry, trial_hash, base::CompareCase::SENSITIVE))
677 return true;
678 }
679
680 return false;
681 }
682
683 bool IsInSyntheticTrialGroup(const std::string& trial_name,
684 const std::string& trial_group) {
685 std::vector<std::string> synthetic_trials;
686 variations::GetSyntheticTrialGroupIdsAsString(&synthetic_trials);
687 std::string expected_entry = base::StringPrintf(
688 "%x-%x", metrics::HashName(trial_name), metrics::HashName(trial_group));
689
690 for (auto entry : synthetic_trials) {
691 if (entry == expected_entry)
692 return true;
693 }
694
695 return false;
696 }
697
698 const std::string kSyntheticTrialName = "SignInProcessIsolationActive";
699
700 protected:
Alex Moshchukd252c192017-07-17 22:03:48701 base::test::ScopedFeatureList feature_list_;
Alex Moshchuk95e8906d2017-07-21 01:06:23702
703 private:
Alex Moshchukd252c192017-07-17 22:03:48704 net::EmbeddedTestServer https_server_;
705
706 DISALLOW_COPY_AND_ASSIGN(SignInIsolationBrowserTest);
707};
708
709// This test ensures that the sign-in origin requires a dedicated process. It
710// only ensures that the corresponding base::Feature works properly;
711// IsolatedOriginTest provides the main test coverage of origins whitelisted
712// for process isolation. See https://crbug.com/739418.
713IN_PROC_BROWSER_TEST_F(SignInIsolationBrowserTest, NavigateToSignInPage) {
714 const GURL first_url =
715 embedded_test_server()->GetURL("google.com", "/title1.html");
716 const GURL signin_url =
717 https_server()->GetURL("accounts.google.com", "/title1.html");
718 ui_test_utils::NavigateToURL(browser(), first_url);
719 content::WebContents* web_contents =
720 browser()->tab_strip_model()->GetActiveWebContents();
721 scoped_refptr<content::SiteInstance> first_instance(
722 web_contents->GetMainFrame()->GetSiteInstance());
723
724 // Make sure that a renderer-initiated navigation to the sign-in page swaps
725 // processes.
726 content::TestNavigationManager manager(web_contents, signin_url);
727 EXPECT_TRUE(
728 ExecuteScript(web_contents, "location = '" + signin_url.spec() + "';"));
729 manager.WaitForNavigationFinished();
730 EXPECT_NE(web_contents->GetMainFrame()->GetSiteInstance(), first_instance);
731}
Alex Moshchuk95e8906d2017-07-21 01:06:23732
733// The next four tests verify that the synthetic field trial is set correctly
734// for sign-in process isolation. The synthetic field trial should be created
735// when browsing to the sign-in URL for the first time, and it should reflect
736// whether or not the sign-in isolation base::Feature is enabled, and whether
737// or not it is force-enabled from the command line.
738IN_PROC_BROWSER_TEST_F(SignInIsolationBrowserTest, SyntheticTrial) {
739 EXPECT_FALSE(HasSyntheticTrial(kSyntheticTrialName));
740
741 ui_test_utils::NavigateToURL(
742 browser(), https_server()->GetURL("foo.com", "/title1.html"));
743 EXPECT_FALSE(HasSyntheticTrial(kSyntheticTrialName));
744
745 GURL signin_url(
746 https_server()->GetURL("accounts.google.com", "/title1.html"));
747
748 // This test class uses InitAndEnableFeature, which overrides the feature
749 // settings as if it came from the command line, so by default, browsing to
750 // the sign-in URL should create the synthetic trial with ForceEnabled.
751 ui_test_utils::NavigateToURL(browser(), signin_url);
752 EXPECT_TRUE(IsInSyntheticTrialGroup(kSyntheticTrialName, "ForceEnabled"));
753}
754
755// This test class is used to check the synthetic sign-in trial for the Enabled
756// group. It creates a new field trial (with 100% probability of being in the
757// group), and initializes the test class's ScopedFeatureList using it, being
758// careful to not override it using the command line (which corresponds to
759// ForceEnabled).
760class EnabledSignInIsolationBrowserTest : public SignInIsolationBrowserTest {
761 public:
762 EnabledSignInIsolationBrowserTest() {}
763 ~EnabledSignInIsolationBrowserTest() override {}
764
765 void InitFeatureList() override {}
766
767 void SetUpOnMainThread() override {
768 const std::string kTrialName = "SignInProcessIsolation";
769 const std::string kGroupName = "FooGroup"; // unused
770 scoped_refptr<base::FieldTrial> trial =
771 base::FieldTrialList::CreateFieldTrial(kTrialName, kGroupName);
772
773 std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
774 feature_list->RegisterFieldTrialOverride(
775 features::kSignInProcessIsolation.name,
776 base::FeatureList::OverrideState::OVERRIDE_ENABLE_FEATURE, trial.get());
777
778 feature_list_.InitWithFeatureList(std::move(feature_list));
779 SignInIsolationBrowserTest::SetUpOnMainThread();
780 }
781
Alex Moshchuk9cf0ac12017-10-25 21:26:19782 void SetUpCommandLine(base::CommandLine* command_line) override {
783 // This test creates and tests its own field trial group, so it needs to
784 // disable the field trial testing config, which might define an
785 // incompatible trial name/group.
786 command_line->AppendSwitch(
787 variations::switches::kDisableFieldTrialTestingConfig);
788 SignInIsolationBrowserTest::SetUpCommandLine(command_line);
789 }
790
Alex Moshchuk95e8906d2017-07-21 01:06:23791 DISALLOW_COPY_AND_ASSIGN(EnabledSignInIsolationBrowserTest);
792};
793
794IN_PROC_BROWSER_TEST_F(EnabledSignInIsolationBrowserTest, SyntheticTrial) {
795 EXPECT_FALSE(HasSyntheticTrial(kSyntheticTrialName));
796 EXPECT_FALSE(IsInSyntheticTrialGroup(kSyntheticTrialName, "Enabled"));
797
798 GURL signin_url =
799 https_server()->GetURL("accounts.google.com", "/title1.html");
800 ui_test_utils::NavigateToURL(browser(), signin_url);
801 EXPECT_TRUE(IsInSyntheticTrialGroup(kSyntheticTrialName, "Enabled"));
802
803 // A repeat navigation shouldn't change the synthetic trial.
804 ui_test_utils::NavigateToURL(
805 browser(), https_server()->GetURL("accounts.google.com", "/title2.html"));
806 EXPECT_TRUE(IsInSyntheticTrialGroup(kSyntheticTrialName, "Enabled"));
807}
808
809// This test class is similar to EnabledSignInIsolationBrowserTest, but for the
810// Disabled group of the synthetic sign-in trial.
811class DisabledSignInIsolationBrowserTest : public SignInIsolationBrowserTest {
812 public:
813 DisabledSignInIsolationBrowserTest() {}
814 ~DisabledSignInIsolationBrowserTest() override {}
815
816 void InitFeatureList() override {}
817
818 void SetUpOnMainThread() override {
819 const std::string kTrialName = "SignInProcessIsolation";
820 const std::string kGroupName = "FooGroup"; // unused
821 scoped_refptr<base::FieldTrial> trial =
822 base::FieldTrialList::CreateFieldTrial(kTrialName, kGroupName);
823
824 std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
825 feature_list->RegisterFieldTrialOverride(
826 features::kSignInProcessIsolation.name,
827 base::FeatureList::OverrideState::OVERRIDE_DISABLE_FEATURE,
828 trial.get());
829
830 feature_list_.InitWithFeatureList(std::move(feature_list));
831 SignInIsolationBrowserTest::SetUpOnMainThread();
832 }
833
Alex Moshchuk9cf0ac12017-10-25 21:26:19834 void SetUpCommandLine(base::CommandLine* command_line) override {
835 // This test creates and tests its own field trial group, so it needs to
836 // disable the field trial testing config, which might define an
837 // incompatible trial name/group.
838 command_line->AppendSwitch(
839 variations::switches::kDisableFieldTrialTestingConfig);
840 SignInIsolationBrowserTest::SetUpCommandLine(command_line);
841 }
842
Alex Moshchuk95e8906d2017-07-21 01:06:23843 DISALLOW_COPY_AND_ASSIGN(DisabledSignInIsolationBrowserTest);
844};
845
846IN_PROC_BROWSER_TEST_F(DisabledSignInIsolationBrowserTest, SyntheticTrial) {
847 EXPECT_FALSE(IsInSyntheticTrialGroup(kSyntheticTrialName, "Disabled"));
848 GURL signin_url =
849 https_server()->GetURL("accounts.google.com", "/title1.html");
850 ui_test_utils::NavigateToURL(browser(), signin_url);
851 EXPECT_TRUE(IsInSyntheticTrialGroup(kSyntheticTrialName, "Disabled"));
852}
853
854// This test class is similar to EnabledSignInIsolationBrowserTest, but for the
855// ForceDisabled group of the synthetic sign-in trial.
856class ForceDisabledSignInIsolationBrowserTest
857 : public SignInIsolationBrowserTest {
858 public:
859 ForceDisabledSignInIsolationBrowserTest() {}
860 ~ForceDisabledSignInIsolationBrowserTest() override {}
861
862 void InitFeatureList() override {
863 feature_list_.InitAndDisableFeature(features::kSignInProcessIsolation);
864 }
865
866 DISALLOW_COPY_AND_ASSIGN(ForceDisabledSignInIsolationBrowserTest);
867};
868
869IN_PROC_BROWSER_TEST_F(ForceDisabledSignInIsolationBrowserTest,
870 SyntheticTrial) {
871 // Test subframe navigation in this case, since that should also trigger
872 // synthetic trial creation.
873 ui_test_utils::NavigateToURL(browser(),
874 https_server()->GetURL("a.com", "/iframe.html"));
875 content::WebContents* web_contents =
876 browser()->tab_strip_model()->GetActiveWebContents();
877 EXPECT_FALSE(IsInSyntheticTrialGroup(kSyntheticTrialName, "ForceDisabled"));
878 GURL signin_url =
879 https_server()->GetURL("accounts.google.com", "/title1.html");
880 EXPECT_TRUE(NavigateIframeToURL(web_contents, "test", signin_url));
881 EXPECT_TRUE(IsInSyntheticTrialGroup(kSyntheticTrialName, "ForceDisabled"));
882}
arthursonzognib43863ad2017-08-30 15:53:20883
884// Helper class. Track one navigation and tell whether a response from the
885// server has been received or not. It is useful for discerning navigations
886// blocked after or before the request has been sent.
887class WillProcessResponseObserver : public content::WebContentsObserver {
888 public:
889 explicit WillProcessResponseObserver(content::WebContents* web_contents,
890 const GURL& url)
891 : content::WebContentsObserver(web_contents), url_(url) {}
892 ~WillProcessResponseObserver() override {}
893
894 bool WillProcessResponseCalled() { return will_process_response_called_; }
895
896 private:
897 GURL url_;
898 bool will_process_response_called_ = false;
899
900 // Is used to set |will_process_response_called_| to true when
901 // NavigationThrottle::WillProcessResponse() is called.
902 class WillProcessResponseObserverThrottle
903 : public content::NavigationThrottle {
904 public:
905 WillProcessResponseObserverThrottle(content::NavigationHandle* handle,
906 bool* will_process_response_called)
907 : NavigationThrottle(handle),
908 will_process_response_called_(will_process_response_called) {}
909
910 const char* GetNameForLogging() override {
911 return "WillProcessResponseObserverThrottle";
912 }
913
914 private:
915 bool* will_process_response_called_;
916 NavigationThrottle::ThrottleCheckResult WillProcessResponse() override {
917 *will_process_response_called_ = true;
918 return NavigationThrottle::PROCEED;
919 }
920 };
921
922 // WebContentsObserver
923 void DidStartNavigation(content::NavigationHandle* handle) override {
924 if (handle->GetURL() == url_) {
925 handle->RegisterThrottleForTesting(
926 std::make_unique<WillProcessResponseObserverThrottle>(
927 handle, &will_process_response_called_));
928 }
929 }
930};
931
932// In HTTP/HTTPS documents, check that no request with the "ftp:" scheme are
933// submitted to load an iframe.
934// See https://crbug.com/757809.
935// Note: This test couldn't be a content_browsertests, since there would be
936// not handler defined for the "ftp" protocol in
937// URLRequestJobFactoryImpl::protocol_handler_map_.
938IN_PROC_BROWSER_TEST_F(ChromeNavigationBrowserTest, BlockLegacySubresources) {
939 net::SpawnedTestServer ftp_server(
940 net::SpawnedTestServer::TYPE_FTP,
941 base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
942 ASSERT_TRUE(ftp_server.Start());
943
944 GURL main_url_http(embedded_test_server()->GetURL("/iframe.html"));
945 GURL main_url_ftp(ftp_server.GetURL("iframe.html"));
946 GURL iframe_url_http(embedded_test_server()->GetURL("/simple.html"));
947 GURL iframe_url_ftp(ftp_server.GetURL("simple.html"));
948 GURL redirect_url(embedded_test_server()->GetURL("/server-redirect?"));
949
950 struct {
951 GURL main_url;
952 GURL iframe_url;
953 bool allowed;
954 } kTestCases[] = {
955 {main_url_http, iframe_url_http, true},
956 {main_url_http, iframe_url_ftp, false},
957 {main_url_ftp, iframe_url_http, true},
958 {main_url_ftp, iframe_url_ftp, true},
959 };
960 for (const auto test_case : kTestCases) {
961 // Blocking the request should work, even after a redirect.
962 for (bool redirect : {false, true}) {
963 GURL iframe_url =
964 redirect ? GURL(redirect_url.spec() + test_case.iframe_url.spec())
965 : test_case.iframe_url;
966 SCOPED_TRACE(::testing::Message()
967 << std::endl
968 << "- main_url = " << test_case.main_url << std::endl
969 << "- iframe_url = " << iframe_url << std::endl);
970
971 ui_test_utils::NavigateToURL(browser(), test_case.main_url);
972 content::WebContents* web_contents =
973 browser()->tab_strip_model()->GetActiveWebContents();
974 content::NavigationHandleObserver navigation_handle_observer(web_contents,
975 iframe_url);
976 WillProcessResponseObserver will_process_response_observer(web_contents,
977 iframe_url);
978 EXPECT_TRUE(NavigateIframeToURL(web_contents, "test", iframe_url));
979
980 if (test_case.allowed) {
981 EXPECT_TRUE(will_process_response_observer.WillProcessResponseCalled());
982 EXPECT_FALSE(navigation_handle_observer.is_error());
983 EXPECT_EQ(test_case.iframe_url,
984 navigation_handle_observer.last_committed_url());
985 } else {
986 EXPECT_FALSE(
987 will_process_response_observer.WillProcessResponseCalled());
988 EXPECT_TRUE(navigation_handle_observer.is_error());
989 EXPECT_EQ(net::ERR_ABORTED,
990 navigation_handle_observer.net_error_code());
991 }
992 }
993 }
994}
clamyb4f02242017-09-19 12:58:27995
996// Check that it's possible to navigate to a chrome scheme URL from a crashed
997// tab. See https://crbug.com/764641.
998IN_PROC_BROWSER_TEST_F(ChromeNavigationBrowserTest, ChromeSchemeNavFromSadTab) {
999 // Kill the renderer process.
1000 content::RenderProcessHost* process = browser()
1001 ->tab_strip_model()
1002 ->GetActiveWebContents()
1003 ->GetMainFrame()
1004 ->GetProcess();
1005 content::RenderProcessHostWatcher crash_observer(
1006 process, content::RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
1007 process->Shutdown(-1, true);
1008 crash_observer.Wait();
1009
1010 // Attempt to navigate to a chrome://... URL. This used to hang and never
1011 // commit in PlzNavigate mode.
1012 ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIVersionURL));
1013}
clamy8d8fe8332017-09-21 16:24:101014
1015// Check that a browser-initiated navigation to a cross-site URL that then
1016// redirects to a pdf hosted on another site works.
1017IN_PROC_BROWSER_TEST_F(ChromeNavigationBrowserTest, CrossSiteRedirectionToPDF) {
1018 net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
1019 https_server.AddDefaultHandlers(
1020 base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
1021 ASSERT_TRUE(https_server.Start());
1022
1023 GURL initial_url = embedded_test_server()->GetURL("/title1.html");
1024 GURL pdf_url = embedded_test_server()->GetURL("/pdf/test.pdf");
1025 GURL cross_site_redirecting_url =
1026 https_server.GetURL("/server-redirect?" + pdf_url.spec());
1027 ui_test_utils::NavigateToURL(browser(), initial_url);
1028 ui_test_utils::NavigateToURL(browser(), cross_site_redirecting_url);
1029 EXPECT_EQ(pdf_url, browser()
1030 ->tab_strip_model()
1031 ->GetActiveWebContents()
1032 ->GetLastCommittedURL());
1033}
Charles Harrison26b6c12e2017-11-04 06:30:461034
1035// TODO(csharrison): These tests should become tentative WPT, once the feature
1036// is enabled by default.
1037class NavigationConsumingTest : public ChromeNavigationBrowserTest {
1038 void SetUpCommandLine(base::CommandLine* cmd_line) override {
1039 ChromeNavigationBrowserTest::SetUpCommandLine(cmd_line);
1040 scoped_feature_.InitFromCommandLine("ConsumeGestureOnNavigation",
1041 std::string());
1042 }
1043 base::test::ScopedFeatureList scoped_feature_;
1044};
1045
1046// The fullscreen API is spec'd to require a user activation (aka user gesture),
1047// so use that API to test if navigation consumes the activation.
1048// https://fullscreen.spec.whatwg.org/#allowed-to-request-fullscreen
1049IN_PROC_BROWSER_TEST_F(NavigationConsumingTest,
1050 NavigationConsumesUserGesture_Fullscreen) {
1051 ui_test_utils::NavigateToURL(
1052 browser(),
1053 embedded_test_server()->GetURL("/navigation_consumes_gesture.html"));
1054 content::WebContents* contents =
1055 browser()->tab_strip_model()->GetActiveWebContents();
1056
1057 // Normally, fullscreen should work, as long as there is a user gesture.
1058 bool is_fullscreen = false;
1059 EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
1060 contents, "document.body.webkitRequestFullscreen();", &is_fullscreen));
1061 EXPECT_TRUE(is_fullscreen);
1062
1063 EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
1064 contents, "document.webkitExitFullscreen();", &is_fullscreen));
1065 EXPECT_FALSE(is_fullscreen);
1066
1067 EXPECT_TRUE(content::ExecuteScriptWithoutUserGestureAndExtractBool(
1068 contents, "document.body.webkitRequestFullscreen();", &is_fullscreen));
1069 EXPECT_FALSE(is_fullscreen);
1070
1071 // However, starting a navigation should consume the gesture. Fullscreen
1072 // should not work afterwards. Make sure the navigation is synchronously
1073 // started via click().
1074 std::string script = R"(
1075 document.getElementsByTagName('a')[0].click();
1076 document.body.webkitRequestFullscreen();
1077 )";
1078
1079 // Use the TestNavigationManager to ensure the navigation is not finished
1080 // before fullscreen can occur.
1081 content::TestNavigationManager nav_manager(
1082 contents, embedded_test_server()->GetURL("/title1.html"));
1083 EXPECT_TRUE(
1084 content::ExecuteScriptAndExtractBool(contents, script, &is_fullscreen));
1085 EXPECT_FALSE(is_fullscreen);
1086}
1087
1088// Similar to the fullscreen test above, but checks that popups are successfully
1089// blocked if spawned after a navigation.
1090IN_PROC_BROWSER_TEST_F(NavigationConsumingTest,
1091 NavigationConsumesUserGesture_Popups) {
1092 ui_test_utils::NavigateToURL(browser(),
1093 embedded_test_server()->GetURL("/links.html"));
1094 content::WebContents* contents =
1095 browser()->tab_strip_model()->GetActiveWebContents();
1096
1097 // Normally, a popup should open fine if it is associated with a user gesture.
1098 bool did_open = false;
1099 EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
1100 contents, "window.domAutomationController.send(!!window.open());",
1101 &did_open));
1102 EXPECT_TRUE(did_open);
1103
1104 // Starting a navigation should consume a gesture, but make sure that starting
1105 // a same-document navigation doesn't do the consuming.
1106 std::string same_document_script = R"(
1107 document.getElementById("ref").click();
1108 window.domAutomationController.send(!!window.open());
1109 )";
1110 EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
1111 contents, same_document_script, &did_open));
1112 EXPECT_TRUE(did_open);
1113
1114 // If the navigation is to a different document, the gesture should be
1115 // successfully consumed.
1116 std::string different_document_script = R"(
1117 document.getElementById("title1").click();
1118 window.domAutomationController.send(!!window.open());
1119 )";
1120 EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
1121 contents, different_document_script, &did_open));
1122 EXPECT_FALSE(did_open);
1123}