blob: 3dbe40c3ceed9c5801e6eebbefcd21df683d9939 [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"
Nasko Oskov78442ee2018-10-11 22:06:466#include "base/feature_list.h"
Gabriel Charette078e3662017-08-28 22:59:047#include "base/run_loop.h"
Lei Zhangfe5b86932019-02-01 17:26:598#include "base/strings/stringprintf.h"
Charlie Harrison650e11422018-12-04 00:37:269#include "base/test/metrics/histogram_tester.h"
Alex Moshchukd252c192017-07-17 22:03:4810#include "base/test/scoped_feature_list.h"
Alex Moshchuk71f485592017-08-16 16:20:0011#include "base/test/test_timeouts.h"
Reza.Zakerinasab875245c2018-02-27 17:09:0112#include "build/build_config.h"
naskoe4ebe0782016-10-27 16:52:1713#include "chrome/app/chrome_command_ids.h"
naskob2f82b82016-04-15 07:09:0714#include "chrome/browser/chrome_notification_types.h"
Nasko Oskov78442ee2018-10-11 22:06:4615#include "chrome/browser/extensions/chrome_test_extension_loader.h"
naskoe4ebe0782016-10-27 16:52:1716#include "chrome/browser/renderer_context_menu/render_view_context_menu_test_util.h"
Alex Moshchukb9810ce82019-03-29 23:46:5717#include "chrome/browser/tab_contents/navigation_metrics_recorder.h"
naskob2f82b82016-04-15 07:09:0718#include "chrome/browser/ui/browser.h"
afakhry4d116bd2016-11-29 17:25:2519#include "chrome/browser/ui/browser_commands.h"
naskob2f82b82016-04-15 07:09:0720#include "chrome/browser/ui/tabs/tab_strip_model.h"
Shivani Sharma883f5f32019-02-12 18:20:0121#include "chrome/browser/ui/toolbar/back_forward_menu_model.h"
Carlos IL798c47c8ce2018-11-26 17:30:4122#include "chrome/common/chrome_features.h"
Charlie Harrison650e11422018-12-04 00:37:2623#include "chrome/common/pref_names.h"
clamyb4f02242017-09-19 12:58:2724#include "chrome/common/url_constants.h"
naskob2f82b82016-04-15 07:09:0725#include "chrome/test/base/in_process_browser_test.h"
26#include "chrome/test/base/ui_test_utils.h"
Alex Moshchukd252c192017-07-17 22:03:4827#include "components/network_session_configurator/common/network_switches.h"
Charlie Harrison650e11422018-12-04 00:37:2628#include "components/prefs/pref_service.h"
Shivani Sharma93329102019-01-24 19:44:1829#include "components/ukm/test_ukm_recorder.h"
afakhry4d116bd2016-11-29 17:25:2530#include "components/url_formatter/url_formatter.h"
Alex Moshchukb9810ce82019-03-29 23:46:5731#include "components/variations/active_field_trials.h"
32#include "components/variations/hashing.h"
Charlie Harrison650e11422018-12-04 00:37:2633#include "content/public/browser/download_manager_delegate.h"
afakhry4d116bd2016-11-29 17:25:2534#include "content/public/browser/navigation_entry.h"
naskob2f82b82016-04-15 07:09:0735#include "content/public/browser/navigation_handle.h"
36#include "content/public/browser/notification_service.h"
Nasko Oskov78442ee2018-10-11 22:06:4637#include "content/public/browser/reload_type.h"
afakhry4d116bd2016-11-29 17:25:2538#include "content/public/browser/render_frame_host.h"
clamyb4f02242017-09-19 12:58:2739#include "content/public/browser/render_process_host.h"
Nasko Oskov28ebd5b2018-12-07 22:29:3340#include "content/public/browser/render_widget_host_view.h"
Alex Moshchuk07e1bb42019-03-08 04:44:0841#include "content/public/browser/site_isolation_policy.h"
naskob2f82b82016-04-15 07:09:0742#include "content/public/browser/web_contents_observer.h"
Alex Moshchukd252c192017-07-17 22:03:4843#include "content/public/common/content_features.h"
lgreycb827f612017-01-13 01:32:2444#include "content/public/common/content_switches.h"
naskoe4ebe0782016-10-27 16:52:1745#include "content/public/common/context_menu_params.h"
afakhry4d116bd2016-11-29 17:25:2546#include "content/public/common/url_constants.h"
naskob2f82b82016-04-15 07:09:0747#include "content/public/test/browser_test_utils.h"
Charlie Harrison650e11422018-12-04 00:37:2648#include "content/public/test/download_test_observer.h"
Alex Moshchuk71f485592017-08-16 16:20:0049#include "content/public/test/navigation_handle_observer.h"
naskob2f82b82016-04-15 07:09:0750#include "content/public/test/test_navigation_observer.h"
Nasko Oskov78442ee2018-10-11 22:06:4651#include "content/public/test/url_loader_interceptor.h"
52#include "extensions/test/test_extension_dir.h"
Alex Moshchukd252c192017-07-17 22:03:4853#include "google_apis/gaia/gaia_switches.h"
naskoe4ebe0782016-10-27 16:52:1754#include "net/dns/mock_host_resolver.h"
Shivani Sharma93329102019-01-24 19:44:1855#include "services/metrics/public/cpp/ukm_builders.h"
Nasko Oskov78442ee2018-10-11 22:06:4656#include "services/network/public/cpp/features.h"
Alex Moshchuke256d562019-04-26 21:43:5757#include "testing/gmock/include/gmock/gmock.h"
Julie Jeongeun Kim184d78a62019-03-01 02:10:1558#include "third_party/blink/public/mojom/web_feature/web_feature.mojom-shared.h"
naskob2f82b82016-04-15 07:09:0759
Alex Moshchuke256d562019-04-26 21:43:5760using ::testing::IsEmpty;
61using ::testing::UnorderedElementsAre;
62
naskob2f82b82016-04-15 07:09:0763class ChromeNavigationBrowserTest : public InProcessBrowserTest {
64 public:
Alexei Svitkine8724ea502019-06-14 21:51:4665 ChromeNavigationBrowserTest() {
Shivani Sharma93329102019-01-24 19:44:1866 scoped_feature_list_.InitAndEnableFeature(ukm::kUkmFeature);
Shivani Sharma93329102019-01-24 19:44:1867 }
Alexei Svitkine8724ea502019-06-14 21:51:4668 ~ChromeNavigationBrowserTest() override {}
Shivani Sharma93329102019-01-24 19:44:1869
naskob2f82b82016-04-15 07:09:0770 void SetUpCommandLine(base::CommandLine* command_line) override {
lgreycb827f612017-01-13 01:32:2471 // Backgrounded renderer processes run at a lower priority, causing the
72 // tests to take more time to complete. Disable backgrounding so that the
73 // tests don't time out.
74 command_line->AppendSwitch(switches::kDisableRendererBackgrounding);
75
Nasko Oskov28ebd5b2018-12-07 22:29:3376 embedded_test_server()->ServeFilesFromSourceDirectory("content/test/data");
Alex Moshchukb9810ce82019-03-29 23:46:5777 ASSERT_TRUE(embedded_test_server()->InitializeAndListen());
naskob2f82b82016-04-15 07:09:0778 }
79
Charlie Harrison650e11422018-12-04 00:37:2680 void SetUpOnMainThread() override {
81 host_resolver()->AddRule("*", "127.0.0.1");
Alex Moshchukb9810ce82019-03-29 23:46:5782 embedded_test_server()->StartAcceptingConnections();
Charlie Harrison650e11422018-12-04 00:37:2683 }
84
Shivani Sharma93329102019-01-24 19:44:1885 void PreRunTestOnMainThread() override {
86 InProcessBrowserTest::PreRunTestOnMainThread();
87 test_ukm_recorder_ = std::make_unique<ukm::TestAutoSetUkmRecorder>();
88 }
89
naskob2f82b82016-04-15 07:09:0790 void StartServerWithExpiredCert() {
91 expired_https_server_.reset(
92 new net::EmbeddedTestServer(net::EmbeddedTestServer::TYPE_HTTPS));
93 expired_https_server_->SetSSLConfig(net::EmbeddedTestServer::CERT_EXPIRED);
Alan Cuttera9a96c52019-03-28 07:15:3994 expired_https_server_->AddDefaultHandlers(GetChromeTestDataDir());
naskob2f82b82016-04-15 07:09:0795 ASSERT_TRUE(expired_https_server_->Start());
96 }
97
98 net::EmbeddedTestServer* expired_https_server() {
99 return expired_https_server_.get();
100 }
101
Shivani Sharma93329102019-01-24 19:44:18102 std::unique_ptr<ukm::TestAutoSetUkmRecorder> test_ukm_recorder_;
103
naskob2f82b82016-04-15 07:09:07104 private:
105 std::unique_ptr<net::EmbeddedTestServer> expired_https_server_;
Shivani Sharma93329102019-01-24 19:44:18106 base::test::ScopedFeatureList scoped_feature_list_;
naskob2f82b82016-04-15 07:09:07107
108 DISALLOW_COPY_AND_ASSIGN(ChromeNavigationBrowserTest);
109};
110
Yi Gu8dbecfc2018-10-22 20:12:21111#if defined(OS_LINUX) || defined(OS_CHROMEOS)
112// Fails on chromium.memory/Linux Chromium OS ASan LSan:
113// https://crbug.com/897879
114#define MAYBE_TransientEntryPreservedOnMultipleNavigationsDuringInterstitial \
115 DISABLED_TransientEntryPreservedOnMultipleNavigationsDuringInterstitial
116#else
117#define MAYBE_TransientEntryPreservedOnMultipleNavigationsDuringInterstitial \
118 TransientEntryPreservedOnMultipleNavigationsDuringInterstitial
119#endif
120
afakhry4d116bd2016-11-29 17:25:25121// Tests that viewing frame source on a local file:// page with an iframe
122// with a remote URL shows the correct tab title.
123IN_PROC_BROWSER_TEST_F(ChromeNavigationBrowserTest, TestViewFrameSource) {
124 // The local page file:// URL.
125 GURL local_page_with_iframe_url = ui_test_utils::GetTestUrl(
126 base::FilePath(base::FilePath::kCurrentDirectory),
127 base::FilePath(FILE_PATH_LITERAL("iframe.html")));
128
129 // The non-file:// URL of the page to load in the iframe.
130 GURL iframe_target_url = embedded_test_server()->GetURL("/title1.html");
131 ui_test_utils::NavigateToURL(browser(), local_page_with_iframe_url);
132 content::WebContents* web_contents =
133 browser()->tab_strip_model()->GetActiveWebContents();
134
135 content::TestNavigationObserver observer(web_contents);
136 ASSERT_TRUE(content::ExecuteScript(
137 web_contents->GetMainFrame(),
138 base::StringPrintf("var iframe = document.getElementById('test');\n"
139 "iframe.setAttribute('src', '%s');\n",
140 iframe_target_url.spec().c_str())));
141 observer.Wait();
142
143 content::RenderFrameHost* frame =
144 content::ChildFrameAt(web_contents->GetMainFrame(), 0);
145 ASSERT_TRUE(frame);
146 ASSERT_NE(frame, web_contents->GetMainFrame());
147
148 content::ContextMenuParams params;
149 params.page_url = local_page_with_iframe_url;
150 params.frame_url = frame->GetLastCommittedURL();
afakhry4d116bd2016-11-29 17:25:25151 TestRenderViewContextMenu menu(frame, params);
152 menu.Init();
153 menu.ExecuteCommand(IDC_CONTENT_CONTEXT_VIEWFRAMESOURCE, 0);
154 ASSERT_EQ(browser()->tab_strip_model()->count(), 2);
155 content::WebContents* new_web_contents =
156 browser()->tab_strip_model()->GetWebContentsAt(1);
157 ASSERT_NE(new_web_contents, web_contents);
158 WaitForLoadStop(new_web_contents);
159
160 GURL view_frame_source_url(content::kViewSourceScheme + std::string(":") +
161 iframe_target_url.spec());
162 EXPECT_EQ(url_formatter::FormatUrl(view_frame_source_url),
163 new_web_contents->GetTitle());
164}
165
Nasko Oskovdeb6c7ea2017-11-30 18:18:11166// Base class for ctrl+click tests, which contains all the common functionality
167// independent from which process the navigation happens in. Each subclass
168// defines its own expectations depending on the conditions of the test.
169class CtrlClickProcessTest : public ChromeNavigationBrowserTest {
lukaszaf206da92017-04-20 23:26:51170 protected:
Nasko Oskovdeb6c7ea2017-11-30 18:18:11171 virtual void VerifyProcessExpectations(
172 content::WebContents* main_contents,
173 content::WebContents* new_contents) = 0;
Nasko Oskovdeb6c7ea2017-11-30 18:18:11174
lukaszaf206da92017-04-20 23:26:51175 // Simulates ctrl-clicking an anchor with the given id in |main_contents|.
Nasko Oskovdeb6c7ea2017-11-30 18:18:11176 // Verifies that the new contents are in the correct process and separate
177 // BrowsingInstance from |main_contents|. Returns contents of the newly
lukaszaf206da92017-04-20 23:26:51178 // opened tab.
179 content::WebContents* SimulateCtrlClick(content::WebContents* main_contents,
180 const char* id_of_anchor_to_click) {
181 // Ctrl-click the anchor/link in the page.
182 content::WebContents* new_contents = nullptr;
183 {
184 content::WebContentsAddedObserver new_tab_observer;
185#if defined(OS_MACOSX)
186 const char* new_tab_click_script_template =
187 "simulateClick(\"%s\", { metaKey: true });";
188#else
189 const char* new_tab_click_script_template =
190 "simulateClick(\"%s\", { ctrlKey: true });";
191#endif
192 std::string new_tab_click_script = base::StringPrintf(
193 new_tab_click_script_template, id_of_anchor_to_click);
194 EXPECT_TRUE(ExecuteScript(main_contents, new_tab_click_script));
195
196 // Wait for a new tab to appear (the whole point of this test).
197 new_contents = new_tab_observer.GetWebContents();
198 }
199
Nasko Oskovdeb6c7ea2017-11-30 18:18:11200 // Verify that the new tab has the right contents and is in the tab strip.
lukaszaf206da92017-04-20 23:26:51201 EXPECT_TRUE(WaitForLoadStop(new_contents));
lukaszaf206da92017-04-20 23:26:51202 EXPECT_LT(1, browser()->tab_strip_model()->count()); // More than 1 tab?
Nasko Oskovdeb6c7ea2017-11-30 18:18:11203 CHECK_NE(TabStripModel::kNoTab,
204 browser()->tab_strip_model()->GetIndexOfWebContents(new_contents));
lukaszaf206da92017-04-20 23:26:51205 GURL expected_url(embedded_test_server()->GetURL("/title1.html"));
206 EXPECT_EQ(expected_url, new_contents->GetLastCommittedURL());
207
Nasko Oskovdeb6c7ea2017-11-30 18:18:11208 VerifyProcessExpectations(main_contents, new_contents);
lukaszaf206da92017-04-20 23:26:51209
lukaszaf206da92017-04-20 23:26:51210 {
211 // Double-check that main_contents has expected window.name set.
212 // This is a sanity check of test setup; this is not a product test.
213 std::string name_of_main_contents_window;
214 EXPECT_TRUE(ExecuteScriptAndExtractString(
215 main_contents, "window.domAutomationController.send(window.name)",
216 &name_of_main_contents_window));
217 EXPECT_EQ("main_contents", name_of_main_contents_window);
218
219 // Verify that the new contents doesn't have a window.opener set.
lukaszabe2f0da2017-04-25 00:43:00220 bool window_opener_cast_to_bool = true;
lukaszaf206da92017-04-20 23:26:51221 EXPECT_TRUE(ExecuteScriptAndExtractBool(
222 new_contents, "window.domAutomationController.send(!!window.opener)",
223 &window_opener_cast_to_bool));
224 EXPECT_FALSE(window_opener_cast_to_bool);
225
Nasko Oskovdeb6c7ea2017-11-30 18:18:11226 VerifyBrowsingInstanceExpectations(main_contents, new_contents);
lukaszaf206da92017-04-20 23:26:51227 }
228
229 return new_contents;
230 }
lukaszabe2f0da2017-04-25 00:43:00231
232 void TestCtrlClick(const char* id_of_anchor_to_click) {
233 // Navigate to the test page.
234 GURL main_url(embedded_test_server()->GetURL(
235 "/frame_tree/anchor_to_same_site_location.html"));
236 ui_test_utils::NavigateToURL(browser(), main_url);
237
238 // Verify that there is only 1 active tab (with the right contents
239 // committed).
240 EXPECT_EQ(0, browser()->tab_strip_model()->active_index());
241 content::WebContents* main_contents =
242 browser()->tab_strip_model()->GetWebContentsAt(0);
243 EXPECT_EQ(main_url, main_contents->GetLastCommittedURL());
244
245 // Test what happens after ctrl-click. SimulateCtrlClick will verify
Nasko Oskovdeb6c7ea2017-11-30 18:18:11246 // that |new_contents1| is in the correct process and separate
247 // BrowsingInstance from |main_contents|.
lukaszabe2f0da2017-04-25 00:43:00248 content::WebContents* new_contents1 =
249 SimulateCtrlClick(main_contents, id_of_anchor_to_click);
250
Nasko Oskovdeb6c7ea2017-11-30 18:18:11251 // Test that each subsequent ctrl-click also gets the correct process.
lukaszabe2f0da2017-04-25 00:43:00252 content::WebContents* new_contents2 =
253 SimulateCtrlClick(main_contents, id_of_anchor_to_click);
lukaszabe2f0da2017-04-25 00:43:00254 EXPECT_FALSE(new_contents1->GetSiteInstance()->IsRelatedSiteInstance(
255 new_contents2->GetSiteInstance()));
Nasko Oskovdeb6c7ea2017-11-30 18:18:11256 VerifyProcessExpectations(new_contents1, new_contents2);
257 }
Lukasz Anforowiczaf2f33572018-01-17 14:05:08258
259 private:
260 void VerifyBrowsingInstanceExpectations(content::WebContents* main_contents,
261 content::WebContents* new_contents) {
262 // Verify that the new contents cannot find the old contents via
263 // window.open. (i.e. window.open should open a new window, rather than
264 // returning a reference to main_contents / old window).
265 std::string location_of_opened_window;
266 EXPECT_TRUE(ExecuteScriptAndExtractString(
267 new_contents,
268 "w = window.open('', 'main_contents');"
269 "window.domAutomationController.send(w.location.href);",
270 &location_of_opened_window));
271 EXPECT_EQ(url::kAboutBlankURL, location_of_opened_window);
272 }
Nasko Oskovdeb6c7ea2017-11-30 18:18:11273};
274
275// Tests that verify that ctrl-click results 1) open up in a new renderer
276// process (https://crbug.com/23815) and 2) are in a new BrowsingInstance (e.g.
277// cannot find the opener's window by name - https://crbug.com/658386).
278class CtrlClickShouldEndUpInNewProcessTest : public CtrlClickProcessTest {
279 protected:
280 void VerifyProcessExpectations(content::WebContents* main_contents,
281 content::WebContents* new_contents) override {
282 // Verify that the two WebContents are in a different process, SiteInstance
283 // and BrowsingInstance from the old contents.
284 EXPECT_NE(main_contents->GetMainFrame()->GetProcess(),
285 new_contents->GetMainFrame()->GetProcess());
286 EXPECT_NE(main_contents->GetMainFrame()->GetSiteInstance(),
287 new_contents->GetMainFrame()->GetSiteInstance());
288 EXPECT_FALSE(main_contents->GetSiteInstance()->IsRelatedSiteInstance(
289 new_contents->GetSiteInstance()));
290 }
lukaszaf206da92017-04-20 23:26:51291};
292
293IN_PROC_BROWSER_TEST_F(CtrlClickShouldEndUpInNewProcessTest, NoTarget) {
lukaszabe2f0da2017-04-25 00:43:00294 TestCtrlClick("test-anchor-no-target");
295}
lukaszaf206da92017-04-20 23:26:51296
lukaszabe2f0da2017-04-25 00:43:00297IN_PROC_BROWSER_TEST_F(CtrlClickShouldEndUpInNewProcessTest, BlankTarget) {
298 TestCtrlClick("test-anchor-with-blank-target");
299}
lukaszaf206da92017-04-20 23:26:51300
lukaszabe2f0da2017-04-25 00:43:00301IN_PROC_BROWSER_TEST_F(CtrlClickShouldEndUpInNewProcessTest, SubframeTarget) {
302 TestCtrlClick("test-anchor-with-subframe-target");
lukaszaf206da92017-04-20 23:26:51303}
304
Nasko Oskovdeb6c7ea2017-11-30 18:18:11305// Similar to the tests above, but verifies that the new WebContents ends up in
306// the same process as the opener when it is exceeding the process limit.
307// See https://crbug.com/774723.
308class CtrlClickShouldEndUpInSameProcessTest : public CtrlClickProcessTest {
309 public:
310 void SetUpCommandLine(base::CommandLine* command_line) override {
311 CtrlClickProcessTest::SetUpCommandLine(command_line);
312 content::IsolateAllSitesForTesting(command_line);
313 content::RenderProcessHost::SetMaxRendererProcessCount(1);
314 }
315
Nasko Oskovdeb6c7ea2017-11-30 18:18:11316 protected:
317 void VerifyProcessExpectations(content::WebContents* contents1,
318 content::WebContents* contents2) override {
319 // Verify that the two WebContents are in the same process, though different
320 // SiteInstance and BrowsingInstance from the old contents.
321 EXPECT_EQ(contents1->GetMainFrame()->GetProcess(),
322 contents2->GetMainFrame()->GetProcess());
323 EXPECT_EQ(contents1->GetMainFrame()->GetSiteInstance()->GetSiteURL(),
324 contents2->GetMainFrame()->GetSiteInstance()->GetSiteURL());
325 EXPECT_FALSE(contents1->GetSiteInstance()->IsRelatedSiteInstance(
326 contents2->GetSiteInstance()));
327 }
Nasko Oskovdeb6c7ea2017-11-30 18:18:11328};
329
330IN_PROC_BROWSER_TEST_F(CtrlClickShouldEndUpInSameProcessTest, NoTarget) {
331 TestCtrlClick("test-anchor-no-target");
332}
333
334IN_PROC_BROWSER_TEST_F(CtrlClickShouldEndUpInSameProcessTest, BlankTarget) {
335 TestCtrlClick("test-anchor-with-blank-target");
336}
337
338IN_PROC_BROWSER_TEST_F(CtrlClickShouldEndUpInSameProcessTest, SubframeTarget) {
339 TestCtrlClick("test-anchor-with-subframe-target");
340}
341
naskoe4ebe0782016-10-27 16:52:17342class ChromeNavigationPortMappedBrowserTest : public InProcessBrowserTest {
343 public:
344 ChromeNavigationPortMappedBrowserTest() {}
345 ~ChromeNavigationPortMappedBrowserTest() override {}
346
347 void SetUpCommandLine(base::CommandLine* command_line) override {
348 ASSERT_TRUE(embedded_test_server()->Start());
349
350 // Use the command line parameter for the host resolver, so URLs without
351 // explicit port numbers can be mapped under the hood to the port number
352 // the |embedded_test_server| uses. It is required to test with potentially
353 // malformed URLs.
354 std::string port =
Raul Tambrefff51b752019-02-04 13:09:47355 base::NumberToString(embedded_test_server()->host_port_pair().port());
naskoe4ebe0782016-10-27 16:52:17356 command_line->AppendSwitchASCII(
357 "host-resolver-rules",
358 "MAP * 127.0.0.1:" + port + ", EXCLUDE 127.0.0.1*");
359 }
360
361 private:
362 DISALLOW_COPY_AND_ASSIGN(ChromeNavigationPortMappedBrowserTest);
363};
364
365// Test to verify that a malformed URL set as the virtual URL of a
366// NavigationEntry will result in the navigation being dropped.
367// See https://crbug.com/657720.
368IN_PROC_BROWSER_TEST_F(ChromeNavigationPortMappedBrowserTest,
369 ContextMenuNavigationToInvalidUrl) {
370 GURL initial_url = embedded_test_server()->GetURL("/title1.html");
371 GURL new_tab_url(
372 "www.foo.com::/server-redirect?https%3A%2F%2Fptop.only.wip.la%3A443%2Fhttp%2Fbar.com%2Ftitle2.html");
373
374 // Navigate to an initial page, to ensure we have a committed document
375 // from which to perform a context menu initiated navigation.
376 ui_test_utils::NavigateToURL(browser(), initial_url);
377 content::WebContents* web_contents =
378 browser()->tab_strip_model()->GetActiveWebContents();
379
380 // This corresponds to "Open link in new tab".
381 content::ContextMenuParams params;
382 params.is_editable = false;
Blink Reformat1c4d759e2017-04-09 16:34:54383 params.media_type = blink::WebContextMenuData::kMediaTypeNone;
naskoe4ebe0782016-10-27 16:52:17384 params.page_url = initial_url;
385 params.link_url = new_tab_url;
386
387 content::WindowedNotificationObserver tab_added_observer(
388 chrome::NOTIFICATION_TAB_ADDED,
389 content::NotificationService::AllSources());
390
391 TestRenderViewContextMenu menu(web_contents->GetMainFrame(), params);
392 menu.Init();
393 menu.ExecuteCommand(IDC_CONTENT_CONTEXT_OPENLINKNEWTAB, 0);
394
395 // Wait for the new tab to be created and for loading to stop. The
396 // navigation should not be allowed, therefore there should not be a last
397 // committed URL in the new tab.
398 tab_added_observer.Wait();
399 content::WebContents* new_web_contents =
400 browser()->tab_strip_model()->GetWebContentsAt(
401 browser()->tab_strip_model()->count() - 1);
402 WaitForLoadStop(new_web_contents);
403
404 // If the test is unsuccessful, the return value from GetLastCommittedURL
405 // will be the virtual URL for the created NavigationEntry.
406 // Note: Before the bug was fixed, the URL was the new_tab_url with a scheme
407 // prepended and one less ":" character after the host.
408 EXPECT_EQ(GURL(), new_web_contents->GetLastCommittedURL());
409}
nasko7058e5de2017-04-18 23:05:30410
Charlie Reis0aa576042018-10-05 21:22:26411// Ensure that a failed navigation in a new tab will not leave an invalid
412// visible URL, which may be formatted in an unsafe way in the omnibox.
413// See https://crbug.com/850824.
414IN_PROC_BROWSER_TEST_F(ChromeNavigationBrowserTest,
415 ClearInvalidPendingURLOnFail) {
416 GURL initial_url = embedded_test_server()->GetURL(
417 "/frame_tree/invalid_link_to_new_window.html");
418
419 // Navigate to a page with a link that opens an invalid URL in a new window.
420 ui_test_utils::NavigateToURL(browser(), initial_url);
421 content::WebContents* main_contents =
422 browser()->tab_strip_model()->GetActiveWebContents();
423
424 // Simulate a click on the link and wait for the new window.
425 content::WebContentsAddedObserver new_tab_observer;
426 EXPECT_TRUE(ExecuteScript(main_contents, "simulateClick()"));
427 content::WebContents* new_contents = new_tab_observer.GetWebContents();
428
429 // The load in the new window should fail.
430 EXPECT_FALSE(WaitForLoadStop(new_contents));
431
432 // Ensure that there is no pending entry or visible URL.
433 EXPECT_EQ(nullptr, new_contents->GetController().GetPendingEntry());
434 EXPECT_EQ(GURL(), new_contents->GetVisibleURL());
435}
436
nasko7058e5de2017-04-18 23:05:30437// A test performing two simultaneous navigations, to ensure code in chrome/,
438// such as tab helpers, can handle those cases.
439// This test starts a browser-initiated cross-process navigation, which is
440// delayed. At the same time, the renderer does a synchronous navigation
441// through pushState, which will create a separate navigation and associated
442// NavigationHandle. Afterwards, the original cross-process navigation is
443// resumed and confirmed to properly commit.
444IN_PROC_BROWSER_TEST_F(ChromeNavigationBrowserTest,
445 SlowCrossProcessNavigationWithPushState) {
446 const GURL kURL1 = embedded_test_server()->GetURL("/title1.html");
447 const GURL kPushStateURL =
448 embedded_test_server()->GetURL("/title1.html#fragment");
449 const GURL kURL2 = embedded_test_server()->GetURL("/title2.html");
450
451 content::WebContents* web_contents =
452 browser()->tab_strip_model()->GetActiveWebContents();
453
454 // Navigate to the initial page.
455 ui_test_utils::NavigateToURL(browser(), kURL1);
456
457 // Start navigating to the second page.
458 content::TestNavigationManager manager(web_contents, kURL2);
459 content::NavigationHandleCommitObserver navigation_observer(web_contents,
460 kURL2);
461 web_contents->GetController().LoadURL(
462 kURL2, content::Referrer(), ui::PAGE_TRANSITION_LINK, std::string());
463 EXPECT_TRUE(manager.WaitForRequestStart());
464
465 // The current page does a PushState.
466 content::NavigationHandleCommitObserver push_state_observer(web_contents,
467 kPushStateURL);
468 std::string push_state =
469 "history.pushState({}, \"title 1\", \"" + kPushStateURL.spec() + "\");";
470 EXPECT_TRUE(ExecuteScript(web_contents, push_state));
471 content::NavigationEntry* last_committed =
472 web_contents->GetController().GetLastCommittedEntry();
473 EXPECT_TRUE(last_committed);
474 EXPECT_EQ(kPushStateURL, last_committed->GetURL());
475
476 EXPECT_TRUE(push_state_observer.has_committed());
477 EXPECT_TRUE(push_state_observer.was_same_document());
478 EXPECT_TRUE(push_state_observer.was_renderer_initiated());
479
480 // Let the navigation finish. It should commit successfully.
481 manager.WaitForNavigationFinished();
482 last_committed = web_contents->GetController().GetLastCommittedEntry();
483 EXPECT_TRUE(last_committed);
484 EXPECT_EQ(kURL2, last_committed->GetURL());
485
486 EXPECT_TRUE(navigation_observer.has_committed());
487 EXPECT_FALSE(navigation_observer.was_same_document());
488 EXPECT_FALSE(navigation_observer.was_renderer_initiated());
489}
Alex Moshchukd252c192017-07-17 22:03:48490
Alex Moshchuk71f485592017-08-16 16:20:00491// Check that if a page has an iframe that loads an error page, that error page
492// does not inherit the Content Security Policy from the parent frame. See
493// https://crbug.com/703801. This test is in chrome/ because error page
494// behavior is only fully defined in chrome/.
495IN_PROC_BROWSER_TEST_F(ChromeNavigationBrowserTest,
496 ErrorPageDoesNotInheritCSP) {
497 GURL url(
498 embedded_test_server()->GetURL("/page_with_csp_and_error_iframe.html"));
499 content::WebContents* web_contents =
500 browser()->tab_strip_model()->GetActiveWebContents();
501
502 // Navigate to a page that disallows scripts via CSP and has an iframe that
503 // tries to load an invalid URL, which results in an error page.
504 GURL error_url("http://invalid.foo/");
505 content::NavigationHandleObserver observer(web_contents, error_url);
506 ui_test_utils::NavigateToURL(browser(), url);
507 EXPECT_TRUE(observer.has_committed());
508 EXPECT_TRUE(observer.is_error());
509
510 // The error page should not inherit the CSP directive that blocks all
511 // scripts from the parent frame, so this script should be allowed to
512 // execute. Since ExecuteScript will execute the passed-in script regardless
513 // of CSP, use a javascript: URL which does go through the CSP checks.
514 content::RenderFrameHost* error_host =
515 ChildFrameAt(web_contents->GetMainFrame(), 0);
516 std::string location;
517 EXPECT_TRUE(ExecuteScriptAndExtractString(
518 error_host,
519 "location='javascript:domAutomationController.send(location.href)';",
520 &location));
521 EXPECT_EQ(location, content::kUnreachableWebDataURL);
522
523 // The error page should have a unique origin.
524 std::string origin;
525 EXPECT_TRUE(ExecuteScriptAndExtractString(
Philip Jägenstedt67302a22018-09-14 09:58:05526 error_host, "domAutomationController.send(self.origin);", &origin));
Alex Moshchuk71f485592017-08-16 16:20:00527 EXPECT_EQ("null", origin);
528}
529
530// Test that web pages can't navigate to an error page URL, either directly or
531// via a redirect, and that web pages can't embed error pages in iframes.
532IN_PROC_BROWSER_TEST_F(ChromeNavigationBrowserTest,
533 NavigationToErrorURLIsDisallowed) {
534 content::WebContents* web_contents =
535 browser()->tab_strip_model()->GetActiveWebContents();
536 GURL url(embedded_test_server()->GetURL("/title1.html"));
537 ui_test_utils::NavigateToURL(browser(), url);
538 EXPECT_EQ(url, web_contents->GetLastCommittedURL());
539
540 // Try navigating to the error page URL and make sure it is canceled and the
541 // old URL remains the last committed one.
542 GURL error_url(content::kUnreachableWebDataURL);
543 EXPECT_TRUE(ExecuteScript(web_contents,
544 "location.href = '" + error_url.spec() + "';"));
545 content::WaitForLoadStop(web_contents);
546 EXPECT_EQ(url, web_contents->GetLastCommittedURL());
547
Alex Moshchuk71f485592017-08-16 16:20:00548 // Also ensure that a page can't embed an iframe for an error page URL.
549 EXPECT_TRUE(ExecuteScript(web_contents,
550 "var frame = document.createElement('iframe');\n"
551 "frame.src = '" + error_url.spec() + "';\n"
552 "document.body.appendChild(frame);"));
553 content::WaitForLoadStop(web_contents);
554 content::RenderFrameHost* subframe_host =
555 ChildFrameAt(web_contents->GetMainFrame(), 0);
556 // The new subframe should remain blank without a committed URL.
557 EXPECT_TRUE(subframe_host->GetLastCommittedURL().is_empty());
Charlie Reis56b51232019-02-27 03:16:02558
559 // Now try navigating to a URL that tries to redirect to the error page URL
Charlie Reis535885e2019-03-16 07:29:27560 // and make sure the navigation is ignored. Note that DidStopLoading will
561 // still fire, so TestNavigationObserver can be used to wait for it.
Charlie Reis56b51232019-02-27 03:16:02562 GURL redirect_to_error_url(
563 embedded_test_server()->GetURL("/server-redirect?" + error_url.spec()));
564 content::TestNavigationObserver observer(web_contents);
565 EXPECT_TRUE(ExecuteScript(
566 web_contents, "location.href = '" + redirect_to_error_url.spec() + "';"));
567 observer.Wait();
Charlie Reis535885e2019-03-16 07:29:27568 EXPECT_EQ(url, web_contents->GetLastCommittedURL());
Charlie Reis56b51232019-02-27 03:16:02569 EXPECT_EQ(
Charlie Reis535885e2019-03-16 07:29:27570 content::PAGE_TYPE_NORMAL,
Charlie Reis56b51232019-02-27 03:16:02571 web_contents->GetController().GetLastCommittedEntry()->GetPageType());
Charlie Reis535885e2019-03-16 07:29:27572 // Check the pending URL is not left in the address bar.
573 EXPECT_EQ(url, web_contents->GetVisibleURL());
Alex Moshchuk71f485592017-08-16 16:20:00574}
575
576// This test ensures that navigating to a page that returns an error code and
577// an empty document still shows Chrome's helpful error page instead of the
578// empty document.
579IN_PROC_BROWSER_TEST_F(ChromeNavigationBrowserTest,
580 EmptyDocumentWithErrorCode) {
581 GURL url(embedded_test_server()->GetURL("/empty_with_404.html"));
582 content::WebContents* web_contents =
583 browser()->tab_strip_model()->GetActiveWebContents();
584
585 // Wait for the navigation to complete. The empty document should trigger
586 // loading of the 404 error page, so check that the last committed entry was
587 // indeed for the error page.
588 content::TestNavigationObserver observer(web_contents);
589 EXPECT_TRUE(
590 ExecuteScript(web_contents, "location.href = '" + url.spec() + "';"));
591 observer.Wait();
592 EXPECT_FALSE(observer.last_navigation_succeeded());
593 EXPECT_EQ(url, web_contents->GetLastCommittedURL());
594 EXPECT_TRUE(
595 IsLastCommittedEntryOfPageType(web_contents, content::PAGE_TYPE_ERROR));
596
597 // Verify that the error page has correct content. This needs to wait for
598 // the error page content to be populated asynchronously by scripts after
599 // DidFinishLoad.
600 while (true) {
601 std::string content;
602 EXPECT_TRUE(ExecuteScriptAndExtractString(
603 web_contents,
604 "domAutomationController.send("
605 " document.body ? document.body.innerText : '');",
606 &content));
607 if (content.find("HTTP ERROR 404") != std::string::npos)
608 break;
609 base::RunLoop run_loop;
610 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
611 FROM_HERE, run_loop.QuitClosure(), TestTimeouts::tiny_timeout());
612 run_loop.Run();
613 }
614}
615
Nasko Oskov78442ee2018-10-11 22:06:46616// Test for https://crbug.com/866549#c2. It verifies that about:blank does not
617// commit in the error page process when it is redirected to.
Guido Urdanetac87ad342019-07-04 11:07:35618// Flaky on Linux. See https://crbug.com/981295.
619#if defined(OS_LINUX)
620#define MAYBE_RedirectErrorPageReloadToAboutBlank \
621 DISABLED_RedirectErrorPageReloadToAboutBlank
622#else
623#define MAYBE_RedirectErrorPageReloadToAboutBlank \
624 RedirectErrorPageReloadToAboutBlank
625#endif
Nasko Oskov78442ee2018-10-11 22:06:46626IN_PROC_BROWSER_TEST_F(ChromeNavigationBrowserTest,
Guido Urdanetac87ad342019-07-04 11:07:35627 MAYBE_RedirectErrorPageReloadToAboutBlank) {
Nasko Oskov78442ee2018-10-11 22:06:46628 content::WebContents* web_contents =
629 browser()->tab_strip_model()->GetActiveWebContents();
630 GURL url(embedded_test_server()->GetURL("a.com", "/title1.html"));
631 std::unique_ptr<content::URLLoaderInterceptor> url_interceptor =
632 content::URLLoaderInterceptor::SetupRequestFailForURL(
633 url, net::ERR_DNS_TIMED_OUT);
634
635 // Start off with navigation to a.com, which results in an error page.
636 {
637 content::TestNavigationObserver observer(web_contents);
638 ui_test_utils::NavigateToURL(browser(), url);
639 EXPECT_FALSE(observer.last_navigation_succeeded());
640 EXPECT_EQ(url, observer.last_navigation_url());
641 EXPECT_EQ(GURL(content::kUnreachableWebDataURL),
642 web_contents->GetMainFrame()->GetSiteInstance()->GetSiteURL());
643 }
644
645 // Install an extension, which will redirect all navigations to a.com URLs to
646 // about:blank. In general, web servers cannot redirect to about:blank, but
647 // extensions with webRequest API permissions can.
648 extensions::TestExtensionDir test_extension_dir;
649 test_extension_dir.WriteManifest(
650 R"({
651 "name": "Redirect a.com to about:blank",
652 "manifest_version": 2,
653 "version": "0.1",
654 "permissions": ["webRequest", "webRequestBlocking", "*://a.com/*"],
655 "background": { "scripts": ["background.js"] }
656 })");
657 test_extension_dir.WriteFile(
658 FILE_PATH_LITERAL("background.js"),
659 R"(chrome.webRequest.onBeforeRequest.addListener(function(d) {
660 console.log("onBeforeRequest: ", d);
661 return {redirectUrl:"about:blank"};
662 }, {urls: ["*://a.com/*"]}, ["blocking"]);
663 )");
664 extensions::ChromeTestExtensionLoader extension_loader(browser()->profile());
665 extension_loader.LoadExtension(test_extension_dir.UnpackedPath());
666
667 // Remove the interceptor to allow a reload to succeed, which the extension
668 // will intercept and redirect. The navigation should complete successfully
669 // and commit in a process that is different than the error page one.
670 url_interceptor.reset();
671 {
672 content::TestNavigationObserver observer(web_contents);
673 EXPECT_TRUE(ExecuteScript(web_contents, "location.reload();"));
674 observer.Wait();
675 EXPECT_TRUE(observer.last_navigation_succeeded());
676 EXPECT_EQ(GURL(url::kAboutBlankURL), observer.last_navigation_url());
677 EXPECT_NE(GURL(content::kUnreachableWebDataURL),
678 web_contents->GetMainFrame()->GetSiteInstance()->GetSiteURL());
679 }
680}
681
Alex Moshchukd252c192017-07-17 22:03:48682class SignInIsolationBrowserTest : public ChromeNavigationBrowserTest {
683 public:
684 SignInIsolationBrowserTest()
685 : https_server_(net::EmbeddedTestServer::TYPE_HTTPS) {}
686 ~SignInIsolationBrowserTest() override {}
687
Alex Moshchuk95e8906d2017-07-21 01:06:23688 void SetUp() override {
Alex Moshchukd252c192017-07-17 22:03:48689 https_server_.ServeFilesFromSourceDirectory("chrome/test/data");
690 ASSERT_TRUE(https_server_.InitializeAndListen());
691 ChromeNavigationBrowserTest::SetUp();
692 }
693
694 void SetUpCommandLine(base::CommandLine* command_line) override {
695 // Override the sign-in URL so that it includes correct port from the test
696 // server.
697 command_line->AppendSwitchASCII(
698 ::switches::kGaiaUrl,
699 https_server()->GetURL("accounts.google.com", "/").spec());
700
701 // Ignore cert errors so that the sign-in URL can be loaded from a site
702 // other than localhost (the EmbeddedTestServer serves a certificate that
703 // is valid for localhost).
704 command_line->AppendSwitch(switches::kIgnoreCertificateErrors);
705
706 ChromeNavigationBrowserTest::SetUpCommandLine(command_line);
707 }
708
709 void SetUpOnMainThread() override {
Alex Moshchukd252c192017-07-17 22:03:48710 https_server_.StartAcceptingConnections();
711 ChromeNavigationBrowserTest::SetUpOnMainThread();
712 }
713
714 net::EmbeddedTestServer* https_server() { return &https_server_; }
715
Alex Moshchuk95e8906d2017-07-21 01:06:23716 private:
Alex Moshchukd252c192017-07-17 22:03:48717 net::EmbeddedTestServer https_server_;
718
719 DISALLOW_COPY_AND_ASSIGN(SignInIsolationBrowserTest);
720};
721
722// This test ensures that the sign-in origin requires a dedicated process. It
Alex Moshchuk36417aa2018-06-13 18:01:12723// only ensures that the sign-in origin is added as an isolated origin at
724// chrome/ layer; IsolatedOriginTest provides the main test coverage of origins
725// whitelisted for process isolation. See https://crbug.com/739418.
Alex Moshchukd252c192017-07-17 22:03:48726IN_PROC_BROWSER_TEST_F(SignInIsolationBrowserTest, NavigateToSignInPage) {
727 const GURL first_url =
728 embedded_test_server()->GetURL("google.com", "/title1.html");
729 const GURL signin_url =
730 https_server()->GetURL("accounts.google.com", "/title1.html");
731 ui_test_utils::NavigateToURL(browser(), first_url);
732 content::WebContents* web_contents =
733 browser()->tab_strip_model()->GetActiveWebContents();
734 scoped_refptr<content::SiteInstance> first_instance(
735 web_contents->GetMainFrame()->GetSiteInstance());
736
737 // Make sure that a renderer-initiated navigation to the sign-in page swaps
738 // processes.
739 content::TestNavigationManager manager(web_contents, signin_url);
740 EXPECT_TRUE(
741 ExecuteScript(web_contents, "location = '" + signin_url.spec() + "';"));
742 manager.WaitForNavigationFinished();
743 EXPECT_NE(web_contents->GetMainFrame()->GetSiteInstance(), first_instance);
744}
Alex Moshchuk95e8906d2017-07-21 01:06:23745
arthursonzognib43863ad2017-08-30 15:53:20746// Helper class. Track one navigation and tell whether a response from the
747// server has been received or not. It is useful for discerning navigations
748// blocked after or before the request has been sent.
749class WillProcessResponseObserver : public content::WebContentsObserver {
750 public:
751 explicit WillProcessResponseObserver(content::WebContents* web_contents,
752 const GURL& url)
753 : content::WebContentsObserver(web_contents), url_(url) {}
754 ~WillProcessResponseObserver() override {}
755
756 bool WillProcessResponseCalled() { return will_process_response_called_; }
757
758 private:
759 GURL url_;
760 bool will_process_response_called_ = false;
761
762 // Is used to set |will_process_response_called_| to true when
763 // NavigationThrottle::WillProcessResponse() is called.
764 class WillProcessResponseObserverThrottle
765 : public content::NavigationThrottle {
766 public:
767 WillProcessResponseObserverThrottle(content::NavigationHandle* handle,
768 bool* will_process_response_called)
769 : NavigationThrottle(handle),
770 will_process_response_called_(will_process_response_called) {}
771
772 const char* GetNameForLogging() override {
773 return "WillProcessResponseObserverThrottle";
774 }
775
776 private:
777 bool* will_process_response_called_;
778 NavigationThrottle::ThrottleCheckResult WillProcessResponse() override {
779 *will_process_response_called_ = true;
780 return NavigationThrottle::PROCEED;
781 }
782 };
783
784 // WebContentsObserver
785 void DidStartNavigation(content::NavigationHandle* handle) override {
786 if (handle->GetURL() == url_) {
787 handle->RegisterThrottleForTesting(
788 std::make_unique<WillProcessResponseObserverThrottle>(
789 handle, &will_process_response_called_));
790 }
791 }
792};
793
794// In HTTP/HTTPS documents, check that no request with the "ftp:" scheme are
795// submitted to load an iframe.
796// See https://crbug.com/757809.
797// Note: This test couldn't be a content_browsertests, since there would be
Mike West80462a12018-11-27 16:05:06798// no handler defined for the "ftp" protocol in
arthursonzognib43863ad2017-08-30 15:53:20799// URLRequestJobFactoryImpl::protocol_handler_map_.
Arthur Sonzognid61d2be2018-06-06 09:04:27800IN_PROC_BROWSER_TEST_F(ChromeNavigationBrowserTest, BlockLegacySubresources) {
Alan Cuttera9a96c52019-03-28 07:15:39801 net::SpawnedTestServer ftp_server(net::SpawnedTestServer::TYPE_FTP,
802 GetChromeTestDataDir());
arthursonzognib43863ad2017-08-30 15:53:20803 ASSERT_TRUE(ftp_server.Start());
804
805 GURL main_url_http(embedded_test_server()->GetURL("/iframe.html"));
arthursonzognib43863ad2017-08-30 15:53:20806 GURL iframe_url_http(embedded_test_server()->GetURL("/simple.html"));
807 GURL iframe_url_ftp(ftp_server.GetURL("simple.html"));
808 GURL redirect_url(embedded_test_server()->GetURL("/server-redirect?"));
809
810 struct {
811 GURL main_url;
812 GURL iframe_url;
813 bool allowed;
814 } kTestCases[] = {
815 {main_url_http, iframe_url_http, true},
816 {main_url_http, iframe_url_ftp, false},
arthursonzognib43863ad2017-08-30 15:53:20817 };
818 for (const auto test_case : kTestCases) {
819 // Blocking the request should work, even after a redirect.
820 for (bool redirect : {false, true}) {
821 GURL iframe_url =
822 redirect ? GURL(redirect_url.spec() + test_case.iframe_url.spec())
823 : test_case.iframe_url;
824 SCOPED_TRACE(::testing::Message()
825 << std::endl
826 << "- main_url = " << test_case.main_url << std::endl
827 << "- iframe_url = " << iframe_url << std::endl);
828
829 ui_test_utils::NavigateToURL(browser(), test_case.main_url);
830 content::WebContents* web_contents =
831 browser()->tab_strip_model()->GetActiveWebContents();
832 content::NavigationHandleObserver navigation_handle_observer(web_contents,
833 iframe_url);
834 WillProcessResponseObserver will_process_response_observer(web_contents,
835 iframe_url);
836 EXPECT_TRUE(NavigateIframeToURL(web_contents, "test", iframe_url));
837
838 if (test_case.allowed) {
839 EXPECT_TRUE(will_process_response_observer.WillProcessResponseCalled());
840 EXPECT_FALSE(navigation_handle_observer.is_error());
841 EXPECT_EQ(test_case.iframe_url,
842 navigation_handle_observer.last_committed_url());
843 } else {
844 EXPECT_FALSE(
845 will_process_response_observer.WillProcessResponseCalled());
846 EXPECT_TRUE(navigation_handle_observer.is_error());
847 EXPECT_EQ(net::ERR_ABORTED,
848 navigation_handle_observer.net_error_code());
849 }
850 }
851 }
852}
clamyb4f02242017-09-19 12:58:27853
854// Check that it's possible to navigate to a chrome scheme URL from a crashed
855// tab. See https://crbug.com/764641.
856IN_PROC_BROWSER_TEST_F(ChromeNavigationBrowserTest, ChromeSchemeNavFromSadTab) {
857 // Kill the renderer process.
858 content::RenderProcessHost* process = browser()
859 ->tab_strip_model()
860 ->GetActiveWebContents()
861 ->GetMainFrame()
862 ->GetProcess();
863 content::RenderProcessHostWatcher crash_observer(
864 process, content::RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
Wez0abfbf512018-03-03 01:54:45865 process->Shutdown(-1);
clamyb4f02242017-09-19 12:58:27866 crash_observer.Wait();
867
868 // Attempt to navigate to a chrome://... URL. This used to hang and never
869 // commit in PlzNavigate mode.
870 ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIVersionURL));
871}
clamy8d8fe8332017-09-21 16:24:10872
873// Check that a browser-initiated navigation to a cross-site URL that then
874// redirects to a pdf hosted on another site works.
875IN_PROC_BROWSER_TEST_F(ChromeNavigationBrowserTest, CrossSiteRedirectionToPDF) {
876 net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
Alan Cuttera9a96c52019-03-28 07:15:39877 https_server.AddDefaultHandlers(GetChromeTestDataDir());
clamy8d8fe8332017-09-21 16:24:10878 ASSERT_TRUE(https_server.Start());
879
880 GURL initial_url = embedded_test_server()->GetURL("/title1.html");
881 GURL pdf_url = embedded_test_server()->GetURL("/pdf/test.pdf");
882 GURL cross_site_redirecting_url =
883 https_server.GetURL("/server-redirect?" + pdf_url.spec());
884 ui_test_utils::NavigateToURL(browser(), initial_url);
885 ui_test_utils::NavigateToURL(browser(), cross_site_redirecting_url);
886 EXPECT_EQ(pdf_url, browser()
887 ->tab_strip_model()
888 ->GetActiveWebContents()
889 ->GetLastCommittedURL());
890}
Charles Harrison26b6c12e2017-11-04 06:30:46891
Mustaq Ahmedefa963a2018-11-12 15:28:57892// Check that clicking on a link doesn't carry the transient user activation
893// from the original page to the navigated page (crbug.com/865243).
894IN_PROC_BROWSER_TEST_F(ChromeNavigationBrowserTest,
895 WindowOpenBlockedAfterClickNavigation) {
896 // Navigate to a test page with links.
897 ui_test_utils::NavigateToURL(browser(),
898 embedded_test_server()->GetURL("/links.html"));
899
900 // Click to navigate to title1.html.
901 content::WebContents* main_contents =
902 browser()->tab_strip_model()->GetActiveWebContents();
903 content::TestNavigationObserver observer(main_contents);
904 ASSERT_TRUE(ExecuteScript(main_contents,
905 "document.getElementById('title1').click();"));
906 observer.Wait();
907
908 // Make sure popup attempt fails due to lack of transient user activation.
909 bool opened = false;
910 EXPECT_TRUE(content::ExecuteScriptWithoutUserGestureAndExtractBool(
911 main_contents, "window.domAutomationController.send(!!window.open());",
912 &opened));
913 EXPECT_FALSE(opened);
914
915 EXPECT_EQ(embedded_test_server()->GetURL("/title1.html"),
916 main_contents->GetLastCommittedURL());
917 EXPECT_EQ(1, browser()->tab_strip_model()->count());
918}
919
Charlie Harrison650e11422018-12-04 00:37:26920IN_PROC_BROWSER_TEST_F(ChromeNavigationBrowserTest,
Charlie Harrison8065ffe22019-02-21 14:50:00921 OpenerNavigation_DownloadPolicy_Disallowed) {
Charlie Harrison650e11422018-12-04 00:37:26922 browser()->profile()->GetPrefs()->SetBoolean(prefs::kPromptForDownload,
923 false);
924 ui_test_utils::NavigateToURL(
925 browser(), embedded_test_server()->GetURL("a.com", "/title1.html"));
926
927 // Open a popup.
928 bool opened = false;
929 content::WebContents* opener =
930 browser()->tab_strip_model()->GetActiveWebContents();
931 const char* kScriptFormat =
932 "window.domAutomationController.send(!!window.open('%s'));";
Charlie Harrison8c113a32019-01-07 16:08:29933 GURL popup_url = embedded_test_server()->GetURL("b.com", "/title1.html");
Charlie Harrison650e11422018-12-04 00:37:26934 content::TestNavigationObserver popup_waiter(nullptr, 1);
935 popup_waiter.StartWatchingNewWebContents();
936 EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
937 opener, base::StringPrintf(kScriptFormat, popup_url.spec().c_str()),
938 &opened));
939 EXPECT_TRUE(opened);
940 popup_waiter.Wait();
941 EXPECT_EQ(2, browser()->tab_strip_model()->count());
942
943 // Using the popup, navigate its opener to a download.
944 base::HistogramTester histograms;
945 content::WebContents* popup =
946 browser()->tab_strip_model()->GetActiveWebContents();
947 EXPECT_NE(popup, opener);
Nasko Oskov6e845752018-12-15 00:24:55948 WaitForLoadStop(popup);
Charlie Harrison8065ffe22019-02-21 14:50:00949
950 content::ConsoleObserverDelegate console_observer(
951 opener,
952 "Navigating a cross-origin opener to a download (*) is deprecated*");
953 opener->SetDelegate(&console_observer);
954 EXPECT_TRUE(content::ExecuteScript(
955 popup,
956 "window.opener.location ='data:html/text;base64,'+btoa('payload');"));
957
958 console_observer.Wait();
959 histograms.ExpectBucketCount(
960 "Blink.UseCounter.Features",
961 blink::mojom::WebFeature::kOpenerNavigationDownloadCrossOrigin, 1);
962
963 // Ensure that no download happened.
964 std::vector<download::DownloadItem*> download_items;
965 content::DownloadManager* manager =
966 content::BrowserContext::GetDownloadManager(browser()->profile());
967 manager->GetAllDownloads(&download_items);
968 EXPECT_TRUE(download_items.empty());
969}
970
971// Opener navigations from a same-origin popup should be allowed.
972IN_PROC_BROWSER_TEST_F(ChromeNavigationBrowserTest,
973 OpenerNavigation_DownloadPolicy_Allowed) {
974 browser()->profile()->GetPrefs()->SetBoolean(prefs::kPromptForDownload,
975 false);
976 ui_test_utils::NavigateToURL(
977 browser(), embedded_test_server()->GetURL("a.com", "/title1.html"));
978
979 // Open a popup.
980 bool opened = false;
981 content::WebContents* opener =
982 browser()->tab_strip_model()->GetActiveWebContents();
983 const char* kScriptFormat =
984 "window.domAutomationController.send(!!window.open('%s'));";
985 GURL popup_url = embedded_test_server()->GetURL("a.com", "/title1.html");
986 content::TestNavigationObserver popup_waiter(nullptr, 1);
987 popup_waiter.StartWatchingNewWebContents();
988 EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
989 opener, base::StringPrintf(kScriptFormat, popup_url.spec().c_str()),
990 &opened));
991 EXPECT_TRUE(opened);
992 popup_waiter.Wait();
993 EXPECT_EQ(2, browser()->tab_strip_model()->count());
994
995 // Using the popup, navigate its opener to a download.
996 base::HistogramTester histograms;
997 content::WebContents* popup =
998 browser()->tab_strip_model()->GetActiveWebContents();
999 EXPECT_NE(popup, opener);
1000 WaitForLoadStop(popup);
1001
Charlie Harrison650e11422018-12-04 00:37:261002 content::DownloadTestObserverInProgress observer(
1003 content::BrowserContext::GetDownloadManager(browser()->profile()),
1004 1 /* wait_count */);
Charlie Harrison8065ffe22019-02-21 14:50:001005 EXPECT_TRUE(content::ExecuteScript(
Charlie Harrison650e11422018-12-04 00:37:261006 popup,
1007 "window.opener.location ='data:html/text;base64,'+btoa('payload');"));
1008 observer.WaitForFinished();
Charlie Harrison8065ffe22019-02-21 14:50:001009
Charlie Harrison8c113a32019-01-07 16:08:291010 histograms.ExpectBucketCount(
1011 "Blink.UseCounter.Features",
Charlie Harrison8065ffe22019-02-21 14:50:001012 blink::mojom::WebFeature::kOpenerNavigationDownloadCrossOrigin, 0);
Charlie Harrison650e11422018-12-04 00:37:261013
1014 // Delete any pending download.
1015 std::vector<download::DownloadItem*> download_items;
1016 content::DownloadManager* manager =
1017 content::BrowserContext::GetDownloadManager(browser()->profile());
1018 manager->GetAllDownloads(&download_items);
1019 for (auto* item : download_items) {
1020 if (!item->IsDone())
1021 item->Cancel(true);
1022 }
1023}
1024
Nasko Oskov28ebd5b2018-12-07 22:29:331025// Test which verifies that a noopener link/window.open() properly focus the
1026// newly opened tab. See https://crbug.com/912348.
1027IN_PROC_BROWSER_TEST_F(ChromeNavigationBrowserTest,
1028 NoopenerCorrectlyFocusesNewTab) {
1029 content::WebContents* main_contents =
1030 browser()->tab_strip_model()->GetActiveWebContents();
1031
1032 // Navigate to a test page with links.
1033 {
1034 content::TestNavigationObserver observer(main_contents);
1035 ui_test_utils::NavigateToURL(
1036 browser(),
1037 embedded_test_server()->GetURL("/click-noreferrer-links.html"));
1038 observer.Wait();
1039 EXPECT_TRUE(observer.last_navigation_succeeded());
1040 }
1041
1042 // Click a link with noopener that navigates in a new window.
1043 content::WebContents* link_web_contents = nullptr;
1044 {
1045 ui_test_utils::WindowedTabAddedNotificationObserver tab_added_observer(
1046 content::NotificationService::AllSources());
1047 EXPECT_TRUE(
1048 content::ExecJs(main_contents, "clickSameSiteNoOpenerTargetedLink();"));
1049 tab_added_observer.Wait();
1050 link_web_contents = tab_added_observer.GetTab();
1051 }
1052
1053 EXPECT_NE(main_contents, link_web_contents);
1054 EXPECT_TRUE(link_web_contents->GetRenderWidgetHostView()->HasFocus());
1055
1056 // Execute window.open() with noopener.
1057 content::WebContents* open_web_contents = nullptr;
1058 {
1059 ui_test_utils::WindowedTabAddedNotificationObserver tab_added_observer(
1060 content::NotificationService::AllSources());
1061 EXPECT_TRUE(content::ExecJs(
1062 main_contents, content::JsReplace("window.open($1, 'bar', 'noopener');",
1063 embedded_test_server()->GetURL(
1064 "a.com", "/title1.html"))));
1065 tab_added_observer.Wait();
1066 open_web_contents = tab_added_observer.GetTab();
1067 }
1068
1069 EXPECT_NE(main_contents, open_web_contents);
1070 EXPECT_NE(link_web_contents, open_web_contents);
1071 EXPECT_TRUE(open_web_contents->GetRenderWidgetHostView()->HasFocus());
1072}
1073
Shivani Sharma93329102019-01-24 19:44:181074// Tests the ukm entry logged when the navigation entry is marked as skippable
1075// on back/forward button on doing a renderer initiated navigation without ever
1076// getting a user activation.
1077IN_PROC_BROWSER_TEST_F(ChromeNavigationBrowserTest,
1078 NoUserActivationSetSkipOnBackForward) {
1079 GURL skippable_url(embedded_test_server()->GetURL("/title1.html"));
1080 ui_test_utils::NavigateToURL(browser(), skippable_url);
1081
1082 GURL redirected_url(embedded_test_server()->GetURL("/title2.html"));
Shivani Sharma883f5f32019-02-12 18:20:011083
1084 // Navigate to a new document from the renderer without a user gesture.
1085 content::WebContents* main_contents =
1086 browser()->tab_strip_model()->GetActiveWebContents();
1087 content::TestNavigationObserver observer(main_contents);
1088 EXPECT_TRUE(ExecuteScriptWithoutUserGesture(
1089 main_contents, "location = '" + redirected_url.spec() + "';"));
1090 observer.Wait();
1091 EXPECT_EQ(redirected_url, main_contents->GetLastCommittedURL());
Shivani Sharma93329102019-01-24 19:44:181092
1093 // Verify UKM.
1094 using Entry = ukm::builders::HistoryManipulationIntervention;
1095 const auto& ukm_entries =
1096 test_ukm_recorder_->GetEntriesByName(Entry::kEntryName);
1097 EXPECT_EQ(1u, ukm_entries.size());
1098 test_ukm_recorder_->ExpectEntrySourceHasUrl(ukm_entries[0], skippable_url);
Shivani Sharma883f5f32019-02-12 18:20:011099
1100 // Verify the metric where user tries to go specifically to a skippable entry
1101 // using long press.
1102 base::HistogramTester histogram;
1103 std::unique_ptr<BackForwardMenuModel> back_model(
1104 std::make_unique<BackForwardMenuModel>(
1105 browser(), BackForwardMenuModel::ModelType::kBackward));
1106 back_model->set_test_web_contents(main_contents);
1107 back_model->ActivatedAt(0);
1108 histogram.ExpectBucketCount(
1109 "Navigation.BackForward.NavigatingToEntryMarkedToBeSkipped", true, 1);
Shivani Sharma93329102019-01-24 19:44:181110}
1111
1112// Same as above except the navigation is cross-site.
1113IN_PROC_BROWSER_TEST_F(ChromeNavigationBrowserTest,
1114 NoUserActivationSetSkipOnBackForwardCrossSite) {
1115 GURL skippable_url(embedded_test_server()->GetURL("/title1.html"));
1116 ui_test_utils::NavigateToURL(browser(), skippable_url);
1117
1118 GURL redirected_url(
1119 embedded_test_server()->GetURL("foo.com", "/title2.html"));
1120 {
1121 // Navigate to a new document from the renderer without a user gesture.
1122 content::WebContents* main_contents =
1123 browser()->tab_strip_model()->GetActiveWebContents();
1124 content::TestNavigationObserver observer(main_contents);
1125 EXPECT_TRUE(ExecuteScriptWithoutUserGesture(
1126 main_contents, "location = '" + redirected_url.spec() + "';"));
1127 observer.Wait();
1128 EXPECT_EQ(redirected_url, main_contents->GetLastCommittedURL());
1129 }
1130
1131 // Verify UKM.
1132 using Entry = ukm::builders::HistoryManipulationIntervention;
1133 const auto& ukm_entries =
1134 test_ukm_recorder_->GetEntriesByName(Entry::kEntryName);
1135 EXPECT_EQ(1u, ukm_entries.size());
1136 test_ukm_recorder_->ExpectEntrySourceHasUrl(ukm_entries[0], skippable_url);
1137}
1138
Makoto Shimazue9c808f2018-04-10 01:23:591139// TODO(csharrison): These tests should become tentative WPT, once the feature
1140// is enabled by default.
Charlie Harrison25d683972018-06-28 22:27:341141using NavigationConsumingTest = ChromeNavigationBrowserTest;
Charles Harrison26b6c12e2017-11-04 06:30:461142
Makoto Shimazue9c808f2018-04-10 01:23:591143// The fullscreen API is spec'd to require a user activation (aka user gesture),
1144// so use that API to test if navigation consumes the activation.
1145// https://fullscreen.spec.whatwg.org/#allowed-to-request-fullscreen
1146IN_PROC_BROWSER_TEST_F(NavigationConsumingTest,
1147 NavigationConsumesUserGesture_Fullscreen) {
1148 ui_test_utils::NavigateToURL(
1149 browser(),
1150 embedded_test_server()->GetURL("/navigation_consumes_gesture.html"));
1151 content::WebContents* contents =
1152 browser()->tab_strip_model()->GetActiveWebContents();
1153
1154 // Normally, fullscreen should work, as long as there is a user gesture.
1155 bool is_fullscreen = false;
1156 EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
1157 contents, "document.body.webkitRequestFullscreen();", &is_fullscreen));
1158 EXPECT_TRUE(is_fullscreen);
1159
1160 EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
1161 contents, "document.webkitExitFullscreen();", &is_fullscreen));
1162 EXPECT_FALSE(is_fullscreen);
1163
Makoto Shimazue9c808f2018-04-10 01:23:591164 // However, starting a navigation should consume the gesture. Fullscreen
1165 // should not work afterwards. Make sure the navigation is synchronously
1166 // started via click().
1167 std::string script = R"(
1168 document.getElementsByTagName('a')[0].click();
1169 document.body.webkitRequestFullscreen();
1170 )";
1171
1172 // Use the TestNavigationManager to ensure the navigation is not finished
1173 // before fullscreen can occur.
1174 content::TestNavigationManager nav_manager(
1175 contents, embedded_test_server()->GetURL("/title1.html"));
1176 EXPECT_TRUE(
1177 content::ExecuteScriptAndExtractBool(contents, script, &is_fullscreen));
1178 EXPECT_FALSE(is_fullscreen);
1179}
1180
1181// Similar to the fullscreen test above, but checks that popups are successfully
1182// blocked if spawned after a navigation.
Charles Harrison26b6c12e2017-11-04 06:30:461183IN_PROC_BROWSER_TEST_F(NavigationConsumingTest,
1184 NavigationConsumesUserGesture_Popups) {
1185 ui_test_utils::NavigateToURL(browser(),
1186 embedded_test_server()->GetURL("/links.html"));
1187 content::WebContents* contents =
1188 browser()->tab_strip_model()->GetActiveWebContents();
1189
1190 // Normally, a popup should open fine if it is associated with a user gesture.
1191 bool did_open = false;
1192 EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
1193 contents, "window.domAutomationController.send(!!window.open());",
1194 &did_open));
1195 EXPECT_TRUE(did_open);
1196
1197 // Starting a navigation should consume a gesture, but make sure that starting
1198 // a same-document navigation doesn't do the consuming.
1199 std::string same_document_script = R"(
1200 document.getElementById("ref").click();
1201 window.domAutomationController.send(!!window.open());
1202 )";
1203 EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
1204 contents, same_document_script, &did_open));
1205 EXPECT_TRUE(did_open);
1206
1207 // If the navigation is to a different document, the gesture should be
1208 // successfully consumed.
1209 std::string different_document_script = R"(
1210 document.getElementById("title1").click();
1211 window.domAutomationController.send(!!window.open());
1212 )";
1213 EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
1214 contents, different_document_script, &did_open));
1215 EXPECT_FALSE(did_open);
1216}
Charlie Harrison25d683972018-06-28 22:27:341217
1218// Regression test for https://crbug.com/856779, where a navigation to a
1219// top-level, same process frame in another tab fails to focus that tab.
1220IN_PROC_BROWSER_TEST_F(NavigationConsumingTest, TargetNavigationFocus) {
1221 content::WebContents* opener =
1222 browser()->tab_strip_model()->GetActiveWebContents();
1223 ui_test_utils::NavigateToURL(
1224 browser(), embedded_test_server()->GetURL("/link_with_target.html"));
1225
1226 {
1227 content::TestNavigationObserver new_tab_observer(nullptr, 1);
1228 new_tab_observer.StartWatchingNewWebContents();
1229 ASSERT_TRUE(ExecuteScript(
1230 opener, "document.getElementsByTagName('a')[0].click();"));
1231 new_tab_observer.Wait();
1232 }
1233
1234 content::WebContents* new_contents =
1235 browser()->tab_strip_model()->GetActiveWebContents();
1236 EXPECT_NE(new_contents, opener);
1237
1238 // Re-focusing the opener and clicking again should re-focus the popup.
1239 opener->GetDelegate()->ActivateContents(opener);
1240 EXPECT_EQ(opener, browser()->tab_strip_model()->GetActiveWebContents());
1241 {
1242 content::TestNavigationObserver new_tab_observer(new_contents, 1);
1243 ASSERT_TRUE(ExecuteScript(
1244 opener, "document.getElementsByTagName('a')[0].click();"));
1245 new_tab_observer.Wait();
1246 }
1247 EXPECT_EQ(new_contents, browser()->tab_strip_model()->GetActiveWebContents());
1248}
Shivani Sharma298d12852019-01-22 20:04:031249
Shivani Sharma4e799c72019-03-28 18:22:571250using HistoryManipulationInterventionBrowserTest = ChromeNavigationBrowserTest;
Shivani Sharma298d12852019-01-22 20:04:031251
1252// Tests that chrome::GoBack does nothing if all the previous entries are marked
1253// as skippable and the back button is disabled.
1254IN_PROC_BROWSER_TEST_F(HistoryManipulationInterventionBrowserTest,
1255 AllEntriesSkippableBackButtonDisabled) {
1256 // Create a new tab to avoid confusion from having a NTP navigation entry.
1257 GURL skippable_url(embedded_test_server()->GetURL("/title1.html"));
1258 ui_test_utils::NavigateToURLWithDisposition(
1259 browser(), skippable_url, WindowOpenDisposition::NEW_FOREGROUND_TAB,
1260 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
1261
1262 content::WebContents* main_contents =
1263 browser()->tab_strip_model()->GetActiveWebContents();
1264
1265 // Navigate to a new document from the renderer without a user gesture.
1266 GURL redirected_url(embedded_test_server()->GetURL("/title2.html"));
1267 content::TestNavigationManager manager(main_contents, redirected_url);
1268 EXPECT_TRUE(ExecuteScriptWithoutUserGesture(
1269 main_contents, "location = '" + redirected_url.spec() + "';"));
1270 manager.WaitForNavigationFinished();
1271 ASSERT_EQ(redirected_url, main_contents->GetLastCommittedURL());
1272 ASSERT_EQ(2, main_contents->GetController().GetEntryCount());
1273
1274 // Attempting to go back should do nothing.
1275 ASSERT_FALSE(chrome::CanGoBack(browser()));
1276 chrome::GoBack(browser(), WindowOpenDisposition::CURRENT_TAB);
1277 ASSERT_EQ(redirected_url, main_contents->GetLastCommittedURL());
1278
1279 // Back command should be disabled.
1280 EXPECT_FALSE(chrome::IsCommandEnabled(browser(), IDC_BACK));
1281}
1282
1283// Tests that chrome::GoBack is successful if there is at least one entry not
1284// marked as skippable and the back button should be enabled.
1285IN_PROC_BROWSER_TEST_F(HistoryManipulationInterventionBrowserTest,
1286 AllEntriesNotSkippableBackButtonEnabled) {
1287 // Navigate to a URL in the same tab. Note that at the start of the test this
1288 // tab already has about:blank.
1289 GURL skippable_url(embedded_test_server()->GetURL("/title1.html"));
1290 ui_test_utils::NavigateToURL(browser(), skippable_url);
1291
1292 content::WebContents* main_contents =
1293 browser()->tab_strip_model()->GetActiveWebContents();
1294
1295 // Navigate to a new document from the renderer without a user gesture.
1296 GURL redirected_url(embedded_test_server()->GetURL("/title2.html"));
1297 content::TestNavigationManager manager(main_contents, redirected_url);
1298 EXPECT_TRUE(ExecuteScriptWithoutUserGesture(
1299 main_contents, "location = '" + redirected_url.spec() + "';"));
1300 manager.WaitForNavigationFinished();
1301 ASSERT_EQ(redirected_url, main_contents->GetLastCommittedURL());
1302 ASSERT_EQ(3, main_contents->GetController().GetEntryCount());
1303
1304 // Back command should be enabled.
1305 EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_BACK));
1306
1307 // Attempting to go back should skip |skippable_url| and go to about:blank.
1308 ASSERT_TRUE(chrome::CanGoBack(browser()));
1309 chrome::GoBack(browser(), WindowOpenDisposition::CURRENT_TAB);
1310 content::WaitForLoadStop(main_contents);
1311 ASSERT_EQ(GURL("about:blank"), main_contents->GetLastCommittedURL());
1312}
Alex Moshchuk07e1bb42019-03-08 04:44:081313
Shivani Sharma985474f2019-05-23 21:36:471314// Tests that a main frame hosting pdf does not get skipped because of history
1315// manipulation intervention (crbug.com/965434).
1316IN_PROC_BROWSER_TEST_F(HistoryManipulationInterventionBrowserTest,
1317 PDFDoNotSkipOnBackForward) {
1318 GURL pdf_url(embedded_test_server()->GetURL("/pdf/test.pdf"));
1319 ui_test_utils::NavigateToURL(browser(), pdf_url);
1320
1321 GURL url(embedded_test_server()->GetURL("/title2.html"));
1322
1323 // Navigate to a new document from the renderer without a user gesture.
1324 content::WebContents* main_contents =
1325 browser()->tab_strip_model()->GetActiveWebContents();
1326 content::TestNavigationObserver observer(main_contents);
1327 EXPECT_TRUE(ExecuteScriptWithoutUserGesture(
1328 main_contents, "location = '" + url.spec() + "';"));
1329 observer.Wait();
1330 EXPECT_EQ(url, main_contents->GetLastCommittedURL());
1331
1332 // Even though pdf_url initiated a navigation without a user gesture, it will
1333 // not be skipped since it is a pdf.
1334 // Going back should be allowed and should navigate to pdf_url.
1335 EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_BACK));
1336
1337 ASSERT_TRUE(chrome::CanGoBack(browser()));
1338 chrome::GoBack(browser(), WindowOpenDisposition::CURRENT_TAB);
1339 content::WaitForLoadStop(main_contents);
1340 ASSERT_EQ(pdf_url, main_contents->GetLastCommittedURL());
1341}
1342
Alex Moshchuk07e1bb42019-03-08 04:44:081343// This test class turns on the mode where sites where the user enters a
1344// password are dynamically added to the list of sites requiring a dedicated
1345// process. It also disables strict site isolation so that the effects of
1346// password isolation can be observed.
1347class SiteIsolationForPasswordSitesBrowserTest
1348 : public ChromeNavigationBrowserTest {
Alex Moshchukb9810ce82019-03-29 23:46:571349 public:
Alexei Svitkine8724ea502019-06-14 21:51:461350 SiteIsolationForPasswordSitesBrowserTest() {
1351 feature_list_.InitWithFeatures({features::kSiteIsolationForPasswordSites},
1352 {features::kSitePerProcess});
1353 }
1354
Alex Moshchuke256d562019-04-26 21:43:571355 std::vector<std::string> GetSavedIsolatedSites() {
1356 return GetSavedIsolatedSites(browser()->profile());
1357 }
1358
1359 std::vector<std::string> GetSavedIsolatedSites(Profile* profile) {
1360 PrefService* prefs = profile->GetPrefs();
1361 auto* list = prefs->GetList(prefs::kUserTriggeredIsolatedOrigins);
1362 std::vector<std::string> sites;
1363 for (const base::Value& value : list->GetList())
1364 sites.push_back(value.GetString());
1365 return sites;
1366 }
1367
Alex Moshchukb9810ce82019-03-29 23:46:571368 bool HasSyntheticTrial(const std::string& trial_name) {
1369 std::vector<std::string> synthetic_trials;
1370 variations::GetSyntheticTrialGroupIdsAsString(&synthetic_trials);
1371 std::string trial_hash =
1372 base::StringPrintf("%x", variations::HashName(trial_name));
1373 auto it =
1374 std::find_if(synthetic_trials.begin(), synthetic_trials.end(),
1375 [trial_hash](const auto& trial) {
1376 return base::StartsWith(trial, trial_hash,
1377 base::CompareCase::SENSITIVE);
1378 });
1379 return it != synthetic_trials.end();
1380 }
1381
1382 bool IsInSyntheticTrialGroup(const std::string& trial_name,
1383 const std::string& trial_group) {
1384 std::vector<std::string> synthetic_trials;
1385 variations::GetSyntheticTrialGroupIdsAsString(&synthetic_trials);
1386 std::string expected_entry =
1387 base::StringPrintf("%x-%x", variations::HashName(trial_name),
1388 variations::HashName(trial_group));
1389 return std::find(synthetic_trials.begin(), synthetic_trials.end(),
1390 expected_entry) != synthetic_trials.end();
1391 }
1392
Alex Moshchukdbead202019-05-24 02:26:411393 const std::string kSiteIsolationSyntheticTrialName = "SiteIsolationActive";
1394 const std::string kOOPIFSyntheticTrialName = "OutOfProcessIframesActive";
Alex Moshchukb9810ce82019-03-29 23:46:571395 const std::string kSyntheticTrialGroup = "Enabled";
1396
Alex Moshchuk07e1bb42019-03-08 04:44:081397 protected:
Alex Moshchukb9810ce82019-03-29 23:46:571398 void SetUpCommandLine(base::CommandLine* command_line) override {
1399 ChromeNavigationBrowserTest::SetUpCommandLine(command_line);
1400
1401 // This simulates a whitelist of isolated sites.
1402 std::string origin_list =
1403 embedded_test_server()->GetURL("isolated1.com", "/").spec() + "," +
1404 embedded_test_server()->GetURL("isolated2.com", "/").spec();
1405 command_line->AppendSwitchASCII(switches::kIsolateOrigins, origin_list);
Alex Moshchuke256d562019-04-26 21:43:571406
1407 // Allow HTTPS server to be used on sites other than localhost.
1408 command_line->AppendSwitch(switches::kIgnoreCertificateErrors);
Alex Moshchukb9810ce82019-03-29 23:46:571409 }
1410
Alex Moshchuk07e1bb42019-03-08 04:44:081411 private:
1412 base::test::ScopedFeatureList feature_list_;
1413};
1414
1415// Verifies that a site gets process-isolated after a password is typed on a
1416// page from that site.
1417IN_PROC_BROWSER_TEST_F(SiteIsolationForPasswordSitesBrowserTest,
1418 SiteIsIsolatedAfterEnteringPassword) {
1419 // This test requires dynamic isolated origins to be enabled.
1420 if (!content::SiteIsolationPolicy::AreDynamicIsolatedOriginsEnabled())
1421 return;
1422
1423 GURL url(embedded_test_server()->GetURL("sub.foo.com",
1424 "/password/password_form.html"));
1425 ui_test_utils::NavigateToURL(browser(), url);
1426 content::WebContents* contents =
1427 browser()->tab_strip_model()->GetActiveWebContents();
1428
1429 // foo.com should not be isolated to start with. Verify that a cross-site
1430 // iframe does not become an OOPIF.
Alex Moshchukdc3560cb2019-04-17 22:05:071431 EXPECT_FALSE(
1432 contents->GetMainFrame()->GetSiteInstance()->RequiresDedicatedProcess());
Alex Moshchuk07e1bb42019-03-08 04:44:081433 std::string kAppendIframe = R"(
1434 var i = document.createElement('iframe');
1435 i.id = 'child';
1436 document.body.appendChild(i);)";
1437 EXPECT_TRUE(ExecJs(contents, kAppendIframe));
1438 GURL bar_url(embedded_test_server()->GetURL("bar.com", "/title1.html"));
1439 EXPECT_TRUE(NavigateIframeToURL(contents, "child", bar_url));
1440 content::RenderFrameHost* child = ChildFrameAt(contents->GetMainFrame(), 0);
1441 EXPECT_FALSE(child->IsCrossProcessSubframe());
1442
1443 // Fill a form and submit through a <input type="submit"> button.
1444 content::TestNavigationObserver observer(contents);
1445 std::string kFillAndSubmit =
1446 "document.getElementById('username_field').value = 'temp';"
1447 "document.getElementById('password_field').value = 'random';"
1448 "document.getElementById('input_submit_button').click()";
1449 EXPECT_TRUE(content::ExecJs(contents, kFillAndSubmit));
1450 observer.Wait();
1451
Alex Moshchukdc3560cb2019-04-17 22:05:071452 // Since there were no script references from other windows, we should've
1453 // swapped BrowsingInstances and put the result of the form submission into a
1454 // dedicated process, locked to foo.com. Check that a cross-site iframe now
1455 // becomes an OOPIF.
1456 EXPECT_TRUE(
1457 contents->GetMainFrame()->GetSiteInstance()->RequiresDedicatedProcess());
1458 EXPECT_TRUE(ExecJs(contents, kAppendIframe));
1459 EXPECT_TRUE(NavigateIframeToURL(contents, "child", bar_url));
1460 child = ChildFrameAt(contents->GetMainFrame(), 0);
1461 EXPECT_TRUE(child->IsCrossProcessSubframe());
1462
1463 // Open a fresh tab (also forcing a new BrowsingInstance), navigate to
1464 // foo.com, and verify that a cross-site iframe becomes an OOPIF.
Alex Moshchuk07e1bb42019-03-08 04:44:081465 AddBlankTabAndShow(browser());
1466 EXPECT_EQ(2, browser()->tab_strip_model()->count());
1467 content::WebContents* new_contents =
1468 browser()->tab_strip_model()->GetActiveWebContents();
1469 EXPECT_NE(new_contents, contents);
1470
1471 ui_test_utils::NavigateToURL(browser(), url);
1472 EXPECT_TRUE(ExecJs(new_contents, kAppendIframe));
1473 EXPECT_TRUE(NavigateIframeToURL(new_contents, "child", bar_url));
1474 content::RenderFrameHost* new_child =
1475 ChildFrameAt(new_contents->GetMainFrame(), 0);
1476 EXPECT_TRUE(new_child->IsCrossProcessSubframe());
1477}
Alex Moshchukb9810ce82019-03-29 23:46:571478
1479// This test checks that the synthetic field trial is activated properly after
1480// a navigation to an isolated origin commits in a main frame.
1481IN_PROC_BROWSER_TEST_F(SiteIsolationForPasswordSitesBrowserTest,
1482 SyntheticTrialFromMainFrame) {
1483 content::WebContents* web_contents =
1484 browser()->tab_strip_model()->GetActiveWebContents();
1485
1486 NavigationMetricsRecorder* recorder =
1487 content::WebContentsUserData<NavigationMetricsRecorder>::FromWebContents(
1488 web_contents);
1489 recorder->EnableSiteIsolationSyntheticTrialForTesting();
1490
Alex Moshchukdbead202019-05-24 02:26:411491 EXPECT_FALSE(HasSyntheticTrial(kSiteIsolationSyntheticTrialName));
1492 EXPECT_FALSE(HasSyntheticTrial(kOOPIFSyntheticTrialName));
Alex Moshchukb9810ce82019-03-29 23:46:571493
1494 // Browse to a page with some iframes without involving any isolated origins.
1495 GURL unisolated_url(embedded_test_server()->GetURL(
1496 "a.com", "/cross_site_iframe_factory.html?a(b,c(a))"));
1497 ui_test_utils::NavigateToURL(browser(), unisolated_url);
Alex Moshchukdbead202019-05-24 02:26:411498 EXPECT_FALSE(HasSyntheticTrial(kSiteIsolationSyntheticTrialName));
Alex Moshchukb9810ce82019-03-29 23:46:571499
1500 // Now browse to an isolated origin.
1501 GURL isolated_url(
1502 embedded_test_server()->GetURL("isolated1.com", "/title1.html"));
1503 ui_test_utils::NavigateToURL(browser(), isolated_url);
Alex Moshchukdbead202019-05-24 02:26:411504 EXPECT_TRUE(IsInSyntheticTrialGroup(kSiteIsolationSyntheticTrialName,
1505 kSyntheticTrialGroup));
1506
1507 // The OOPIF synthetic trial shouldn't be activated, since the isolated
1508 // oriign page doesn't have any OOPIFs.
1509 EXPECT_FALSE(
1510 IsInSyntheticTrialGroup(kOOPIFSyntheticTrialName, kSyntheticTrialGroup));
Alex Moshchukb9810ce82019-03-29 23:46:571511}
1512
Alex Moshchukdbead202019-05-24 02:26:411513// This test checks that the synthetic field trials for both site isolation and
1514// encountering OOPIFs are activated properly after a navigation to an isolated
1515// origin commits in a subframe.
Alex Moshchukb9810ce82019-03-29 23:46:571516IN_PROC_BROWSER_TEST_F(SiteIsolationForPasswordSitesBrowserTest,
1517 SyntheticTrialFromSubframe) {
1518 content::WebContents* web_contents =
1519 browser()->tab_strip_model()->GetActiveWebContents();
1520
1521 NavigationMetricsRecorder* recorder =
1522 content::WebContentsUserData<NavigationMetricsRecorder>::FromWebContents(
1523 web_contents);
1524 recorder->EnableSiteIsolationSyntheticTrialForTesting();
1525
Alex Moshchukdbead202019-05-24 02:26:411526 EXPECT_FALSE(HasSyntheticTrial(kSiteIsolationSyntheticTrialName));
1527 EXPECT_FALSE(HasSyntheticTrial(kOOPIFSyntheticTrialName));
Alex Moshchukb9810ce82019-03-29 23:46:571528
1529 // Browse to a page with an isolated origin on one of the iframes.
1530 GURL isolated_url(embedded_test_server()->GetURL(
1531 "a.com", "/cross_site_iframe_factory.html?a(b,c,isolated2,d)"));
1532 ui_test_utils::NavigateToURL(browser(), isolated_url);
Alex Moshchukdbead202019-05-24 02:26:411533 EXPECT_TRUE(IsInSyntheticTrialGroup(kSiteIsolationSyntheticTrialName,
1534 kSyntheticTrialGroup));
Alex Moshchukb9810ce82019-03-29 23:46:571535 EXPECT_TRUE(
Alex Moshchukdbead202019-05-24 02:26:411536 IsInSyntheticTrialGroup(kOOPIFSyntheticTrialName, kSyntheticTrialGroup));
Alex Moshchukb9810ce82019-03-29 23:46:571537}
Alex Moshchuke256d562019-04-26 21:43:571538
1539// Verifies that persistent isolated sites survive restarts. Part 1.
1540IN_PROC_BROWSER_TEST_F(SiteIsolationForPasswordSitesBrowserTest,
1541 PRE_IsolatedSitesPersistAcrossRestarts) {
1542 // There shouldn't be any saved isolated origins to start with.
1543 EXPECT_THAT(GetSavedIsolatedSites(), IsEmpty());
1544
1545 // Isolate saved.com and saved2.com persistently.
1546 GURL saved_url(embedded_test_server()->GetURL("saved.com", "/title1.html"));
1547 content::SiteInstance::StartIsolatingSite(browser()->profile(), saved_url);
1548 GURL saved2_url(embedded_test_server()->GetURL("saved2.com", "/title1.html"));
1549 content::SiteInstance::StartIsolatingSite(browser()->profile(), saved2_url);
1550
1551 // Check that saved.com utilizes a dedicated process in future navigations.
1552 // Open a new tab to force creation of a new BrowsingInstance.
1553 AddBlankTabAndShow(browser());
1554 ui_test_utils::NavigateToURL(browser(), saved_url);
1555 content::WebContents* contents =
1556 browser()->tab_strip_model()->GetActiveWebContents();
1557 EXPECT_TRUE(
1558 contents->GetMainFrame()->GetSiteInstance()->RequiresDedicatedProcess());
1559
1560 // Check that saved.com and saved2.com were saved to disk.
1561 EXPECT_THAT(GetSavedIsolatedSites(),
1562 UnorderedElementsAre("http://saved.com", "http://saved2.com"));
1563}
1564
1565// Verifies that process-isolated sites persist across restarts. Part 2.
1566// This runs after Part 1 above and in the same profile. Part 1 has already
1567// added "saved.com" as a persisted isolated origin, so this part verifies that
1568// it requires a dedicated process after restart.
1569IN_PROC_BROWSER_TEST_F(SiteIsolationForPasswordSitesBrowserTest,
1570 IsolatedSitesPersistAcrossRestarts) {
1571 // Check that saved.com and saved2.com are still saved to disk.
1572 EXPECT_THAT(GetSavedIsolatedSites(),
1573 UnorderedElementsAre("http://saved.com", "http://saved2.com"));
1574
1575 // Check that these sites utilize a dedicated process after restarting, but a
1576 // non-isolated foo.com URL does not.
1577 GURL saved_url(embedded_test_server()->GetURL("saved.com", "/title1.html"));
1578 GURL saved2_url(embedded_test_server()->GetURL("saved2.com", "/title2.html"));
1579 GURL foo_url(embedded_test_server()->GetURL("foo.com", "/title3.html"));
1580 ui_test_utils::NavigateToURL(browser(), saved_url);
1581 content::WebContents* contents =
1582 browser()->tab_strip_model()->GetActiveWebContents();
1583 EXPECT_TRUE(
1584 contents->GetMainFrame()->GetSiteInstance()->RequiresDedicatedProcess());
1585 ui_test_utils::NavigateToURL(browser(), saved2_url);
1586 EXPECT_TRUE(
1587 contents->GetMainFrame()->GetSiteInstance()->RequiresDedicatedProcess());
1588 ui_test_utils::NavigateToURL(browser(), foo_url);
1589 EXPECT_FALSE(
1590 contents->GetMainFrame()->GetSiteInstance()->RequiresDedicatedProcess());
1591}
1592
1593// Verify that trying to isolate a site multiple times will only save it to
1594// disk once.
1595IN_PROC_BROWSER_TEST_F(SiteIsolationForPasswordSitesBrowserTest,
1596 IsolatedSiteIsSavedOnlyOnce) {
1597 GURL saved_url(embedded_test_server()->GetURL("saved.com", "/title1.html"));
1598 content::SiteInstance::StartIsolatingSite(browser()->profile(), saved_url);
1599 content::SiteInstance::StartIsolatingSite(browser()->profile(), saved_url);
1600 content::SiteInstance::StartIsolatingSite(browser()->profile(), saved_url);
1601 EXPECT_THAT(GetSavedIsolatedSites(),
1602 UnorderedElementsAre("http://saved.com"));
1603}
1604
1605// Check that Incognito doesn't inherit saved isolated origins from its
1606// original profile, and that any isolated origins added in Incognito don't
1607// affect the original profile.
1608IN_PROC_BROWSER_TEST_F(SiteIsolationForPasswordSitesBrowserTest,
1609 IncognitoWithIsolatedSites) {
1610 // Isolate saved.com and verify it's been saved to disk.
1611 GURL saved_url(embedded_test_server()->GetURL("saved.com", "/title1.html"));
1612 content::SiteInstance::StartIsolatingSite(browser()->profile(), saved_url);
1613 EXPECT_THAT(GetSavedIsolatedSites(),
1614 UnorderedElementsAre("http://saved.com"));
1615
1616 // Create an incognito browser and browse to saved.com. Verify that it's
1617 // *not* isolated in incognito.
1618 //
1619 // TODO(alexmos): This might change in the future if we decide to inherit
1620 // main profile's isolated origins in incognito. See
1621 // https://crbug.com/905513.
1622 Browser* incognito = CreateIncognitoBrowser();
1623 ui_test_utils::NavigateToURL(incognito, saved_url);
1624 content::WebContents* contents =
1625 incognito->tab_strip_model()->GetActiveWebContents();
1626 EXPECT_FALSE(
1627 contents->GetMainFrame()->GetSiteInstance()->RequiresDedicatedProcess());
1628
1629 // Add an isolated site in incognito, and verify that while future
1630 // navigations to this site in incognito require a dedicated process,
1631 // navigations to this site in the main profile do not require a dedicated
1632 // process, and the site is not persisted for either the main or incognito
1633 // profiles.
1634 GURL foo_url(embedded_test_server()->GetURL("foo.com", "/title1.html"));
1635 content::SiteInstance::StartIsolatingSite(incognito->profile(), foo_url);
1636
1637 AddBlankTabAndShow(incognito);
1638 ui_test_utils::NavigateToURL(incognito, foo_url);
1639 contents = incognito->tab_strip_model()->GetActiveWebContents();
1640 EXPECT_TRUE(
1641 contents->GetMainFrame()->GetSiteInstance()->RequiresDedicatedProcess());
1642
1643 AddBlankTabAndShow(browser());
1644 ui_test_utils::NavigateToURL(browser(), foo_url);
1645 contents = browser()->tab_strip_model()->GetActiveWebContents();
1646 EXPECT_FALSE(
1647 contents->GetMainFrame()->GetSiteInstance()->RequiresDedicatedProcess());
1648
1649 EXPECT_THAT(GetSavedIsolatedSites(browser()->profile()),
1650 testing::Not(testing::Contains("http://foo.com")));
1651 EXPECT_THAT(GetSavedIsolatedSites(incognito->profile()),
1652 testing::Not(testing::Contains("http://foo.com")));
1653}
1654
1655// Verify that serving a Clear-Site-Data header does not clear saved isolated
1656// sites. Saved isolated sites should only be cleared by user-initiated
1657// actions.
1658IN_PROC_BROWSER_TEST_F(SiteIsolationForPasswordSitesBrowserTest,
1659 ClearSiteDataDoesNotClearSavedIsolatedSites) {
1660 // Start an HTTPS server, as Clear-Site-Data is only available on HTTPS URLs.
1661 net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
1662 https_server.AddDefaultHandlers(GetChromeTestDataDir());
1663 ASSERT_TRUE(https_server.Start());
1664
1665 // Isolate saved.com and verify it's been saved to disk.
1666 GURL saved_url(https_server.GetURL("saved.com", "/clear_site_data.html"));
1667 content::SiteInstance::StartIsolatingSite(browser()->profile(), saved_url);
1668 EXPECT_THAT(GetSavedIsolatedSites(),
1669 UnorderedElementsAre("https://saved.com"));
1670
1671 // Navigate to a URL that serves a Clear-Site-Data header for cache, cookies,
1672 // and DOM storage. This is the most that a Clear-Site-Data header could
1673 // clear, and this should not clear saved isolated sites.
1674 ui_test_utils::NavigateToURL(browser(), saved_url);
1675 EXPECT_THAT(GetSavedIsolatedSites(),
1676 UnorderedElementsAre("https://saved.com"));
1677}