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